[gnome-devel-docs] Tutorials: weather application example for JavaScript



commit af181462fa91b74127287e8a2c2164c84d0fd318
Author: Susanna Huhtanen <ihmis suski gmail com>
Date:   Mon Mar 12 16:04:05 2012 +0100

    Tutorials: weather application example for JavaScript

 platform-demos/C/media/weatherAppJs.png   |  Bin 0 -> 18008 bytes
 platform-demos/C/weatherApp.js.page       |   49 ++++++
 platform-demos/C/weatherAppMain.js.page   |  234 +++++++++++++++++++++++++++++
 platform-demos/C/weatherAutotools.js.page |  150 ++++++++++++++++++
 platform-demos/C/weatherGeonames.js.page  |  153 +++++++++++++++++++
 5 files changed, 586 insertions(+), 0 deletions(-)
---
diff --git a/platform-demos/C/media/weatherAppJs.png b/platform-demos/C/media/weatherAppJs.png
new file mode 100644
index 0000000..ea038d1
Binary files /dev/null and b/platform-demos/C/media/weatherAppJs.png differ
diff --git a/platform-demos/C/weatherApp.js.page b/platform-demos/C/weatherApp.js.page
new file mode 100644
index 0000000..9aa1990
--- /dev/null
+++ b/platform-demos/C/weatherApp.js.page
@@ -0,0 +1,49 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="guide" style="task"
+      id="weatherApp.js">
+  <info>
+    <link type="guide" xref="index#js"/>
+    <revision version="0.1" date="2012-03-09" status="stub"/>
+
+    <credit type="author copyright">
+      <name>Susanna Huhtanen</name>
+      <email>ihmis suski gmail com</email>
+      <years>2012</years>
+    </credit>
+
+    <desc> How to plan an application that uses asynchronous calls. Asynchronous calls will be presented through a weather application.
+    </desc>    
+
+  </info>
+
+  <title>4 Weather Application</title>
+  <synopsis>
+    <p>In this guide well construct a weather application using asynchronous calls. Weather information in this example is fetched from geonames.org and the application is using the <link href= "http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code:_E";>ICAO codes </link> to place your weather request. To write and run all the code examples yourself, you need an editor to write code in, Terminal and GNOME 3 or higher installed into your computer. In this guide we we'll go through the following parts:</p>
+      
+    <list>
+      <item><p> <link xref="#planningUi">Planning the graphical user interface</link></p></item>
+      <item><p> <link xref="#asynchronous">Asynchronous calls</link></p></item>
+      <item><p> <link xref="#main">The main program file</link></p></item>
+      <item><p> <link xref="#main">Local library GeoNames</link></p></item>
+      <item><p> <link xref="#main">Autotools and Icons</link></p></item>
+    </list> 
+  </synopsis>
+  
+  <p>After reading this tutorial, you should see this in your screen:</p>
+  <media type="image" mime="image/png" src="media/weatherAppJs.png"/>
+
+  <section id ="planningUi">
+    <title>Planning the graphical user interface</title>
+    <p> Structuring an application for GNOME 3 means you will be using <link href="http://developer.gnome.org/platform-overview/stable/gtk";>GTK+</link>. The most important thing is to remember that the main window will only accept one widget. You must plan your structure accordingly (this example is using Gtk.Grid). A useful method is to draw out the main window and place every widget needed inside that box. By looking at an image of your future application it is easier to tell what are the relations between widgets. For example Gtk.Grid places your widgets in relation to other widgets, so after the first widget is in place, placing widgets can be done in relation to any widget on the grid. </p>
+  </section>
+  <section id ="Asynchronous">
+    <title>Asynchronous calls</title>
+    <p> With many programming languages, all operations are run synchronously - you tell the program to do something, and it will wait until that action completes before proceeding. This is however bad for
+    graphical user interfaces, as then the whole application will be frozen while the program waits for
+    the operation. Going asynchronous (async) helps here. With async calls, your UI won't be blocked with any requests. Async calls make your application more flexible and better equipped to handle situations when calls take more time than expected or for some reason get jammed. Async calls can be used for example file system I/O and for slower calculations in the background.   </p>
+    <p>    In this example we have to get data from geonames.org. While we do that we want the rest of our program to continue. If we wouldn't get any information from geonames.org for the lack of internet connection and this would be a synchronous application we would never  get to the point where our main_quit() is processed correctly and the application would have to killed from Terminal.  </p>
+  </section>
+  <section id="main">
+    <title>The different parts of the program</title>
+  </section>
+</page>
diff --git a/platform-demos/C/weatherAppMain.js.page b/platform-demos/C/weatherAppMain.js.page
new file mode 100644
index 0000000..2b19617
--- /dev/null
+++ b/platform-demos/C/weatherAppMain.js.page
@@ -0,0 +1,234 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="topic" style="task"
+      id="weatherAppMain.js">
+  <info>
+    <link type="guide" xref="weatherApp.js#main" group="#first"/>
+    <revision version="0.1" date="2012-03-09" status="stub"/>
+
+    <credit type="author copyright">
+      <name>Susanna Huhtanen</name>
+      <email>ihmis suski gmail com</email>
+      <years>2012</years>
+    </credit>
+
+    <desc></desc>
+  </info>
+
+  <title>The main program file</title>
+  <synopsis>
+    <p>In this part of the guide well construct the main program file of the weather application. To write and run all the code examples yourself, you need an editor to write code in, Terminal and GNOME 3 or higher installed into your computer. In this part we we'll go through the following parts:</p> 
+    <list>
+      <item><p> <link xref="#script">Script for running the application</link> </p></item>
+      <item><p> <link xref="#imports">Libraries to import</link> </p></item>
+      <item><p> <link xref="#mainwindow">Creating the main window for the application</link> </p></item>
+      <item><p> <link xref="#widgets">Adding a grid and all the necessary widgets to it</link></p></item>
+      <item><p> <link xref="#asynccall">Requesting the weather information asynchronously</link></p></item>
+      <item><p> <link xref="#connectingbuttons">Connecting signals to button and entry."></link></p></item>
+      <item><p> <link xref="#weatherapp.js">weatherapp.js</link></p></item>
+    </list> 
+  </synopsis>
+  <section id="script">
+    <title>Script for running the application</title>
+    <code mime="text/javascript" style="numbered"><![CDATA[
+  #!/usr/bin/gjs]]></code>
+    <p>  This line tells how to run the script. It needs to be the first line of the code and it needs to be executable. To get the execution rights go to Terminal and run in right folder: chmod +x scriptname. Or you can use the graphical filemanager. Just go to the right folder where your code is, right click you code file, choose properties, click the permissions tab and check the box for allow executing file as a program  
+    </p>
+  </section>
+  
+  <section id="imports">
+    <title>Libraries to import</title>
+    <code mime="text/javascript" style="numbered"><![CDATA[
+var Gtk = imports.gi.Gtk;
+const WeatherService = imports.geonames;]]></code>
+    <p>In order to have a working program we need to import a GObject Introspection -library to our use. For working UI, we need Gtk. Gtk is imported in the beginning so we have it in our use everywhere. We also import our own local JavaScript library geonames to our use here.</p>
+    </section>
+
+   <section id="mainwindow">
+    <title>Creating the main window for the application</title> 
+    <code mime="text/javascript" style="numbered"><![CDATA[
+// Initialize the gtk
+Gtk.init(null, 0);
+//create your window, name it and connect the x to quit function. Remember that window is a taken word
+var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL});
+weatherwindow.title = "Todays weather";
+//Window only accepts one widget and a title. Further structure with Gtk.boxes of similar
+weatherwindow.connect("destroy", function(){Gtk.main_quit()});
+
+weatherwindow.show_all();
+//and run it
+Gtk.main();]]></code>
+  </section>
+  <section id="widgets">
+  <title>Adding a grid and all the necessary widgets to it</title>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+var grid = new Gtk.Grid();
+weatherwindow.add(grid);
+
+//We initialize the icon here, but deside the file later in geonames.js.
+var weatherIcon = new Gtk.Image();
+
+//Set some labels to your window
+var label1 = new Gtk.Label({label: ""});
+var label2 = new Gtk.Label({label: "Looking in the sky..."});   
+var label3 = new Gtk.Label({label: ""});
+
+var entry = new Gtk.Entry();
+entry.set_width_chars(4);
+entry.set_max_length(4);
+var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "});
+var button1 = new Gtk.Button({label: "search!"});
+
+grid.attach(label4, 2, 1, 1, 1);
+grid.attach_next_to(label1,label4,3,1,1);
+grid.attach_next_to(label2,label1,3,1,1);
+grid.attach_next_to(label3,label2,3,1,1);
+grid.attach_next_to(entry,label4,1,1,1);
+grid.attach_next_to(button1,entry,1,1,1);
+grid.attach_next_to(weatherIcon,label2,1,1,1)
+]]></code>
+    <p>In this section we create the grid we are going to use for positioning the widgets. All the buttons, labels and entrys are initialized and placed on the grid. As seen from the placing of the different widgets, they don't need to be related only to one widget. At this point some of the labels don't have any content. The content for those widgets is applied later. If you run the application at this stage, you have the UI ready, but the widgets are not connected to anything. For this we need to first build the weather searching local library, and then get the information we need asynchronously. When we have our local library ready we can connect it to the necessary widgets.</p>
+  </section>
+ 
+     <section id="asynccall">
+  <title>Requesting the weather information asynchronously</title>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+function getWeatherForStation() {
+  var station = entry.get_text();
+
+  var GeoNames = new WeatherService.GeoNames(station); //"EFHF";
+
+  GeoNames.getWeather(function(error, weather) {
+    //this here works bit like signals. This code will be run when we have weather.
+    if (error) { 
+      label2.set_text("Suggested ICAO station does not exist Try EFHF");
+    return; }
+    weatherIcon.file = GeoNames.getIcon(weather);
+    
+    label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees.");
+    if (weather.weatherObservation.weatherCondition !== "n/a"){
+      label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky.");
+      }
+    else {
+      label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky.");
+    }
+    label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s")
+    // ...
+  });
+}
+]]></code>
+  <p>This function is dedicated for calling for the weather information and updating labels and icons accordingly. In the beginning of the function we get the user input for the search. So here for the first time we use our own library and assign it to variable GeoNames. While assigning WeatherService we give it the station. The firs thing we do with GeoNames is to request weather. Everything after GeoNames.getWeather(function(error, weather) happens only if we either get an error message or weather information. If either doesn't come, the rest of the program works as normal, so main_Quit works.</p>
+  </section>
+  
+  <section id="connectingbuttons">
+  <title>Connecting signals to button and entry.</title>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+entry.connect("key_press_event", function(widget, event) {
+  if (entry.get_text().length === 4) {
+    // Enough is enough
+    getWeatherForStation();
+  }
+  return false;
+});
+
+button1.connect("clicked", function(){
+  getWeatherForStation();
+});]]></code>
+  <p>And finally we have the connections that make the whole application run as it should. We connect both the entry and the button to do the same thing, getting the weather. So it doesn't matter weather you press enter of click the search button.</p>
+  </section>  
+  
+  <section id ="weatherapp.js">
+  <title>Weatherapp.js</title>
+  <p> Weatherapp.js file looks like this:</p>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+#!/usr/bin/gjs
+//The previous line is a hash bang tells how to run the script.
+// Note that the script has to be executable (run in terminal in the right folder: chmod +x scriptname)
+
+var Gtk = imports.gi.Gtk;
+
+const WeatherService = imports.geonames;
+//Bring your own library from same folder (as set in GJS_PATH). If using autotools .desktop will take care of this
+
+// Initialize the gtk
+Gtk.init(null, 0);
+//create your window, name it and connect the x to quit function. Remember that window is a taken word
+var weatherwindow = new Gtk.Window({type: Gtk.WindowType.TOPLEVEL});
+weatherwindow.title = "Todays weather";
+//Window only accepts one widget and a title. Further structure with Gtk.boxes of similar
+weatherwindow.connect("destroy", function(){Gtk.main_quit()});
+//We initialize the icon here, but deside the file later in geonames.js.
+
+var weatherIcon = new Gtk.Image();
+
+//Set some labels to your window
+var label1 = new Gtk.Label({label: ""});
+var label2 = new Gtk.Label({label: "Looking in the sky..."});   
+var label3 = new Gtk.Label({label: ""});
+
+var grid = new Gtk.Grid();
+weatherwindow.add(grid);
+
+var entry = new Gtk.Entry();
+entry.set_width_chars(4);
+entry.set_max_length(4);
+var label4 = new Gtk.Label({label: "Enter ICAO station for weather: "});
+var button1 = new Gtk.Button({label: "search!"});
+
+//some weather
+
+entry.connect("key_press_event", function(widget, event) {
+  // FIXME: Get weather on enter (key 13)
+  if (entry.get_text().length === 4) {
+    // Enough is enough
+    getWeatherForStation();
+  }
+  return false;
+});
+
+button1.connect("clicked", function(){
+  getWeatherForStation();
+});
+
+function getWeatherForStation() {
+  var station = entry.get_text();
+
+  var GeoNames = new WeatherService.GeoNames(station); //"EFHF";
+
+  GeoNames.getWeather(function(error, weather) {
+    //this here works bit like signals. This code will be run when we have weather.
+    if (error) { 
+      label2.set_text("Suggested ICAO station does not exist Try EFHF");
+    return; }
+    weatherIcon.file = GeoNames.getIcon(weather);
+    
+    label1.set_text("Temperature is " + weather.weatherObservation.temperature + " degrees.");
+    if (weather.weatherObservation.weatherCondition !== "n/a"){
+      label2.set_text("Looks like there is " + weather.weatherObservation.weatherCondition + " in the sky.");
+      }
+    else {
+      label2.set_text("Looks like there is " + weather.weatherObservation.clouds + " in the sky.");
+    }
+    label3.set_text("Windspeed is " + weather.weatherObservation.windSpeed + " m/s")
+    // ...
+  });
+}
+
+grid.attach(label4, 2, 1, 1, 1);
+grid.attach_next_to(label1,label4,3,1,1);
+grid.attach_next_to(label2,label1,3,1,1);
+grid.attach_next_to(label3,label2,3,1,1);
+grid.attach_next_to(entry,label4,1,1,1);
+grid.attach_next_to(button1,entry,1,1,1);
+grid.attach_next_to(weatherIcon,label2,1,1,1)
+weatherwindow.show_all();
+//and run it
+Gtk.main();
+]]></code>
+  <p>Running until you have all the autotools files ready. :</p>
+
+  <screen> <output style="prompt">$ </output><input> GJS_PATH=`pwd` gjs weatherapp.js</input></screen>
+  <p> Use this command on terminal while developing your modules. When calling your program in this manner it knows where to find your custom JSlibraries, in this case geonames.js.
+  </p>
+
+  </section>
+</page>
diff --git a/platform-demos/C/weatherAutotools.js.page b/platform-demos/C/weatherAutotools.js.page
new file mode 100644
index 0000000..5961f8e
--- /dev/null
+++ b/platform-demos/C/weatherAutotools.js.page
@@ -0,0 +1,150 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="topic" style="task"
+      id="weatherAutotools.js">
+  <info>
+    <link type="guide" xref="weatherApp.js#main" group="#last"/>
+    <revision version="0.1" date="2012-03-09" status="stub"/>
+
+    <credit type="author copyright">
+      <name>Susanna Huhtanen</name>
+      <email>ihmis suski gmail com</email>
+      <years>2012</years>
+    </credit>
+
+    <desc></desc>
+  </info>
+
+  <title>Autotools and Icons</title>
+  <synopsis>
+    <p>In this part of the guide well construct the autotools and custom icons needed for weather application to be a seamless part of your desktop. To write and run all the code examples yourself, you need an editor to write code in, Terminal and GNOME 3 or higher installed into your computer. In this guide we we'll go through the following parts:</p>
+      
+    <list>
+      <item><p><link xref="#autotools"> Autotools</link></p></item>
+      <item><p><link xref="#icons">Custom icons for your application</link></p></item>
+    </list> 
+  </synopsis>
+  
+
+
+  <section id ="autotools">
+  <title>Autotools and necessary files</title>
+  <p>Having more than one file in your folder makes using autotools a bit tricky. You need the .desktop file, autogen.sh, Makefile.am, configure.ac and as a new file: myapp.sh.in file. Hacking the autotools file is a complicated field. More information can be found in many different sources, <link href="http://en.wikipedia.org/wiki/GNU_build_system";>the wikipedia article</link> provides a good overwiev on the subject.  
+  </p> 
+    <list>
+      <item><p>weatherapp.desktop</p></item>
+      <item><p>weatherapp.sh.in</p></item>
+      <item><p>Makefile.am</p></item>
+      <item><p>configure.ac</p></item>
+      <item><p>autogen.sh</p></item>          
+    </list>
+    <p>weatherapp.desktop</p>
+    <code mime="text/.desktop" style="numbered"><![CDATA[
+[Desktop Entry]
+Version=1.0
+Encoding=UTF-8
+Name=Weather app
+Comment=Weather showing application
+Exec=weatherapp.sh
+Icon=application-default-icon
+Terminal=false
+Type=Application
+StartupNotify=true
+Categories=GNOME;GTK;Utility;]]></code>
+    <p>The thing to notice in this file is that the Exec line will make this .desktop file work only after running all the other makefiles. Weatherapp.sh is a small shell script created with the weatherapp.sh.in.</p>
+
+    <p>weatherapp.sh.in</p>
+    <code mime="text/sh.in" style="numbered"><![CDATA[
+#!/bin/sh
+export GJS_PATH= bindir@
+gjs @bindir@/weatherapp.js]]></code>
+    <p>This file is a template to the file Makefile will do to be run from .desktop.</p>
+
+    <p>Makefile.am</p>
+    <code mime="text/am" style="numbered"><![CDATA[
+# The actual runnable program is set to the SCRIPTS primitive. Prefix bin_ tells where to copy this
+bin_SCRIPTS = weatherapp.js geonames.js weatherapp.sh
+# List of files to be distributed
+EXTRA_DIST=  \
+    $(bin_SCRIPTS) \
+    $(private_icons)	\
+	  $(NULL)
+
+CLEANFILES =
+
+# The desktop files    
+desktopdir = $(datadir)/applications
+desktop_DATA =weatherapp.desktop
+
+# convenience command for doing Makefile variable substitutions in non-Makefile
+# files (scripts, service files, etc.)
+do_subst = sed -e 's|@abs_top_srcdir[ ]|$(abs_top_srcdir)|g' \
+               -e 's|@abs_top_builddir[ ]|$(abs_top_builddir)|g' \
+               -e 's|@localedir[ ]|$(localedir)|g' \
+               -e 's|@bindir[ ]|$(bindir)|g' \
+               -e 's|@libexecdir[ ]|$(libexecdir)|g' \
+	       -e 's|@pkglibdir[ ]|$(pkglibdir)|g' \
+	       -e 's|@pkgdatadir[ ]|$(pkgdatadir)|g' \
+	       -e 's|@have_libnotify[ ]|$(HAVE_LIBNOTIFY)|g' \
+	       -e 's|@have_libsoup[ ]|$(HAVE_LIBSOUP)|g' \
+	       -e 's|@have_cheese[ ]|$(HAVE_CHEESE)|g'
+
+weatherapp.sh: weatherapp.sh.in
+	$(AM_V_GEN) $(do_subst) $< > $@
+	chmod +x $@
+	
+CLEANFILES += weatherapp.sh
+EXTRA_DIST += weatherapp.sh.in
+
+#the application icon
+appicondir=$(datadir)/icons/hicolor/scalable/apps
+appicon_DATA=weather-icon.svg
+
+#icons in the application
+NULL =
+
+private_icons = \
+	weather-clear.svg \
+  weather-few-clouds.svg \
+  weather-fog.svg \
+  weather-icon.svg \
+  weather-overcast.svg \
+  weather-showers.svg \
+  weather-showers-scattered.svg \
+  weather-snow.svg \
+  $(NULL)
+  
+install-icons:
+	for icon in $(private_icons); do \
+		mkdir -p $(DESTDIR)$(pkgdatadir)/icons/; \
+		$(INSTALL_DATA) $(srcdir)/$$icon $(DESTDIR)$(pkgdatadir)/icons/; \
+	done
+	
+install-data-local: install-icons]]></code>
+    <p>This needs a bit more explaining. Compared to the HelloWorld Makefile.am this has changed quite a bit. Lets go through all the new blocks:</p>
+    <p>bin_scripts are the files that are needed to run your application. In thin case they are the first two files are the program itself and the third is the script that launches the application.</p>
+    <p>EXTRA_DIST are the files that are to be distributed</p>
+    <p>do_subst block is bits and pieces that need to be where they are</p>
+    <p>after the comment #icons in the application there are all the icons that are used by the program. For them to be useful you need to install the icons in correct places and that is done byt the install-icons: bit</p>
+
+    <p>configure.ac</p>
+    <code mime="text/ac" style="numbered"><![CDATA[
+dnl This file is processed by autoconf to create a configure script
+AC_INIT([Weather App], 1.0)
+AM_INIT_AUTOMAKE([1.10 no-define foreign])
+AC_CONFIG_FILES(Makefile)
+AC_OUTPUT]]></code>
+    <p>autohen.sh</p>
+    <code mime="text/sh" style="numbered"><![CDATA[
+#!/bin/sh
+# This will run autoconf, automake, etc. for us
+autoreconf --force --install]]></code>
+  </section>
+  <section id="icons">
+  <title>Custom icons for your application</title>
+  <p>When thinking about custom icons a good rule of thumb is: do you expect to see that icon used elsewhere or is it private to your app? If the first (e.g. the icons in the desktop file that are shown by the shell) then you need /usr/share/hicolor, otherwise (e.g. the weather icons of your app) /usr/share/$application/bla/bla</p>
+  <p>Using autotools you have to make some changes to your .desktop and Makefile.am files. In the desktop file you change the Icon's name  Icon=weather-icon. In the Makefile.am file you add these two lines to the end of your application #the application icon</p>
+  <p>appicondir=$(datadir)/icons/hicolor/scalable/apps</p>
+  <p>appicon_DATA=weather-icon.svg</p> 
+  </section>
+
+</page>
diff --git a/platform-demos/C/weatherGeonames.js.page b/platform-demos/C/weatherGeonames.js.page
new file mode 100644
index 0000000..e96d278
--- /dev/null
+++ b/platform-demos/C/weatherGeonames.js.page
@@ -0,0 +1,153 @@
+<page xmlns="http://projectmallard.org/1.0/";
+      type="topic" style="task"
+      id="weatherGeonames.js">
+  <info>
+    <link type="guide" xref="weatherApp.js#main"/>
+    <revision version="0.1" date="2012-03-09" status="stub"/>
+
+    <credit type="author copyright">
+      <name>Susanna Huhtanen</name>
+      <email>ihmis suski gmail com</email>
+      <years>2012</years>
+    </credit>
+
+    <desc></desc>
+  </info>
+
+  <title>Local library geoNames</title>
+  <synopsis>
+    <p>In this part of the guide well construct the local library geoNames using asynchronous calls. Weather information in this example is fetched from geonames.org and the application is using the <link href= "http://en.wikipedia.org/wiki/List_of_airports_by_ICAO_code:_E";>ICAO codes </link> to place your weather request. To write and run all the code examples yourself, you need an editor to write code in, Terminal and GNOME 3 or higher installed into your computer. In this guide we we'll go through the following parts:</p>
+      
+    <list>
+      <item><p> <link xref="#geonamesimports">Local library for getting the weather</link></p></item>
+      <item><p> <link xref="#geonamesfunction">Creating function geoNames</link></p></item>
+      <item><p> <link xref="#geonamesmethods">Methods for geoNames</link></p></item>
+      <item><p> <link xref="#geonames.js">geonames.js </link></p></item>
+    </list> 
+  </synopsis>
+ 
+  <section id="geonamesimports">
+  <title>Local library for getting the weather</title>
+  <p>For this we need a new file that will be our local library.</p>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+const Soup = imports.gi.Soup;
+const _httpSession = new Soup.SessionAsync();
+Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
+]]></code>
+  <p>In the first lines we'll import and initialize the libraries we need to use in this local library. Soup handles all the requests we have to make with http.</p>
+  </section>
+  
+  <section id="geonamesfunction">
+  <title>Creating function GeoNames</title>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+function GeoNames(station) {
+  this.station = station;
+}
+
+GeoNames.prototype = { 
+ 
+}
+]]></code>
+  <p>Here we create the function GeoNames that will handle getting weather for us. JavaScript allows us to create functions that have little inside at first and later expand them. This will be done inside the GeoNames.prototype curly braces{}</p>
+  </section>
+  
+  <section id="geonamesmethods">
+  <title>Methods for GeoNames</title>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+getWeather: function(callback) {
+    var request = Soup.Message.new('GET', 'http://api.geonames.org/weatherIcaoJSON?ICAO=' + this.station + '&username=demo');
+    _httpSession.queue_message(request, function(_httpSession, message) {
+      if (message.status_code !== 200) {
+        callback(message.status_code, null);
+        return;
+      }
+      var weatherJSON = request.response_body.data;
+      var weather = JSON.parse(weatherJSON);
+      callback(null, weather);
+      });
+}, 
+    
+getIcon: function(weather){
+    switch (weather.weatherObservation.weatherCondition){
+    case "drizzle":
+    case "light showers rain":
+    case "light rain":
+      return "weather-showers-scattered.svg";
+    case "rain":
+      return "weather-showers.svg";
+    case "light snow": 
+    case "snow grains":
+      return "weather-snow.svg"; 
+    }
+    switch (weather.weatherObservation.clouds){
+      case "few clouds":
+      case "scattered clouds":
+        return "weather-few-clouds.svg";
+      case "clear sky":
+        return "weather-clear.svg"
+      case "broken clouds":
+      case "overcast":
+        return "weather-overcast.svg";
+    }
+    return "weather-fog.svg";
+}
+]]></code>
+  <p>The first method for GeoNames is getWeather and the second getIcon. In getWeather we make a http request with soup, handle errors and then parse the information from the request to form we can use it. In getIcon we simply compare the results we got from getWeather to the switch we have in order to get the icon matching current weather. Now that we have our local library ready, it's time to make use of it.</p>
+  </section>
+  
+
+  <section id ="geonames.js">
+  <title>geonames.js</title>
+  <p>Here is the entire code for our local library. The main program file calls this asynchronously.</p>
+  <code mime="text/javascript" style="numbered"><![CDATA[
+const Soup = imports.gi.Soup;
+const _httpSession = new Soup.SessionAsync();
+Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
+
+function GeoNames(station) {
+  this.station = station;
+}
+
+GeoNames.prototype = { 
+  getWeather: function(callback) {
+    var request = Soup.Message.new('GET', 'http://api.geonames.org/weatherIcaoJSON?ICAO=' + this.station + '&username=demo');
+    _httpSession.queue_message(request, function(_httpSession, message) {
+      if (message.status_code !== 200) {
+        callback(message.status_code, null);
+        return;
+      }
+      var weatherJSON = request.response_body.data;
+      var weather = JSON.parse(weatherJSON);
+      callback(null, weather);
+      });
+    }, 
+    
+  getIcon: function(weather){
+    switch (weather.weatherObservation.weatherCondition){
+    case "drizzle":
+    case "light showers rain":
+    case "light rain":
+      return "weather-showers-scattered.svg";
+    case "rain":
+      return "weather-showers.svg";
+    case "light snow": 
+    case "snow grains":
+      return "weather-snow.svg"; 
+    }
+    switch (weather.weatherObservation.clouds){
+      case "few clouds":
+      case "scattered clouds":
+        return "weather-few-clouds.svg";
+      case "clear sky":
+        return "weather-clear.svg"
+      case "broken clouds":
+      case "overcast":
+        return "weather-overcast.svg";
+    }
+    return "weather-fog.svg";
+    }
+}
+}  ]]></code>
+  </section>
+
+</page>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]