-
Notifications
You must be signed in to change notification settings - Fork 44
Client side processing
For rapid development, the GSN web interface uses many pieces of existing javascript code which are in the js folder. The following files are part of the webapp:
- jquery-latest.pack.js: The main jQuery library. The version in use comes from the svn as some needed fixes were not available in the latest version.
- jquery-dom.js: An extension to jQuery which allows easy DOM creation written like $.DIV("class":"test","content");
- jquery.history.js: An extension to jQuery to manage the hash part of the location url (index.html#hash). It is used to allow the page to be fully static html while at the same time still support the browser back button and bookmarking of a specific part of the page.
- dimensions.js: An extension to jQuery to know the page's width and height. Used only in fullmap.html in order to have the container with vsboxes of the right size.
- datepicker.js: Customized extension of jquery used for the datetime helper.
- jquery-tooltip.js: A plugin to have better tooltips than the browser default behaviour which is used for descriptions.
- gsn.js: Our core javascript code. Explanations in the next subsection.
Almost all of gsn JavaScript code is regrouped inside gsn.js. It is written using a JavaScript Object Notation and use a GSN object to reduce the risk of conflicts with any future addition of JavaScript code. vsName, the name of the virtual sensor (text) is considered as unique, which explains why it is so much used as a parameter. Most of the ajax calls go to the /gsn servlet. The data part uses the /data servlet for retrieving data. Binary and image are accessed through the /field servlet and webinput upload goes to the /upload servlet.
Here is a brief explanation of the core variables and functions:
- GSN.context: defines which page of gsn is being displayed (home, data, map or fullmap).
- GSN.load(): initializes a page load (begin, tab click & back button).
- GSN.msgcallback(): callback method when the webupload iframe finishes.
- GSN.nav(page): click on the top navigation bar.
- GSN.menu(vsName): click on the virtual sensor on the left bar.
- GSN.loaded: is true after the first load of XML info which calls GSN.init().
- GSN.init(): initializes the gsn title and the left side menu.
- GSN.updatenb: a counter to prevent multiple instances of GSN.updateall().
- GSN.updateall(): Ajax call to update all the sensor displays on the page and the map.
- GSN.addandupdate(vsName): adds a vsbox if it doesn't exist, bring it to front and update it.
The virtual sensor information (dynamic, static and structure) are regrouped in a div box called the vsbox. This div has the class .vsbox and .vsbox-the virtual sensor name. They will be put in the container specified by GSN.vsbox.container.
Here are the function of the GSN.vsbox.* part:
- GSN.vsbox.container: the container to put the vsbox (default "#vs").
- GSN.vsbox.add(vsName): creates an empty vsbox.
- GSN.vsbox.bringToFront(vsName): brings a vsbox at the beginning of the container.
- GSN.vsbox.update(vs): updates and shows all the data of the vsbox.
- GSN.vsbox.remove(vsName): removes the vsbox from the container.
- GSN.vsbox.toggle(...): to manage the click on tab.
All the functionality used to display the virtual sensor on the google map is regrouped in the GSN.map.* part. Here is the core functionality:
- GSN.map.loaded: ss true after the initialisation of the google map.
- GSN.map.markers : array containing the displayed markers.
- GSN.map.highlighted : the index of the focused marker or null.
- GSN.map.highlightedmarker : the green marker.
- GSN.map.init(): initializes the google map.
- GSN.map.userchange(): callback after any map change (zoom and map move) and vs toggle to update #hash of URL.
- GSN.map.zoomend(..): callback after any zoom change, used for the tricked followed marker.
- GSN.map.trickhighlighted(): followed marker and top of the others.
- GSN.map.autozoomandcenter(): auto-zoom and center on the visible sensors.
- GSN.map.addMarker(vsName,lat,lon): adds a vs marker on the map.
- GSN.map.markerIsVisible(vsName): returns if a marker is visible.
- GSN.map.toggleAllMarkers(): toggles all markers (visible or not).
- GSN.map.toggleMarker(vsName): toggles marker (visible or not).
- GSN.map.updateMarker(vsName,lat,lon): updates a vs marker position on the map.
- GSN.map.followMarker(vsName): highlights a marker, stops it if called with null name.
- GSN.map.showAllMarkers(): zoom out to see all markers.
The functionality in the data webpage is regrouped in the GSN.data.* part and was only bugfixed and slightly improved. The remaining GSN.util.* functions are basic formatting piece of code that don't need any explanations at all.
- An IE only bug caused problems, because Ajax request in IE are locally cached like any normal http request. Therefore, the webapp wasn't refreshing even if the Javascript was working fine and making ajax calls. It was easily resolved by adding to the XML API servlet various http headers (Expires, Cache-Control,..) to avoid any caching at all.
The code around GSN.map.trickhighlighted() can look quite suspicious. Why so much code and diverse variables just to highlight a marker on Google map? Changing from one type of marker to another does not require all this. It could have been made easier, but then when you zoom out you might not see the highlighted marker if it is surrounded by many other markers. It is due because Google map does not allow to specify the z-index of a marker and automatically order them by their latitude. Thus the marker with the lowest latitude will be shown on top of the others one.
This behaviour can be changed by using a trick which is to use a marker with an offsetted latitude and an offsetted marker image which will always be at a lower latitude than the other markers. Thus always be on top of them. It is offsetted depending of the zoom level and the normal marker height. With this trick, the highlighted marker is popping out of crowd as shown on the left side image.
The only drawback of this technique is that it might look weird sometime because of the shape of the marker. As the right side image shows, the spike of the highlighted market is on top of the one bellow. Anyway it isn't that frequent and the benefits when zoomed out in a dense area of marker are worth it.
When a web application uses ajax techniques, one of the key features of the browsing experience is broken: the URL. With ajax calls made without a page load, the state of the current web page is not related to the URL anymore. It breaks the back button feature of any browser, and even worse, the current web page cannot be bookmarked properly. As those feature are essential to a website, it is necessary to find a way to mimic them. The solution is to use the hash part of the URL : http://server.com/index.html#hash. The hash part is easily modified through javascript without a page load and is considered as a page change by every browser which means that the back button feature works. In addition, an URL with a hash part can be bookmarked and, with some javascript initialization, can restore the webpage in the same state than when it was bookmarked. This was implemented using a jQuery extension as some tricky javascript code is required to make this functionality compatible with Internet Explorer.
For example, a URL in the gsn webapp when browsing the map part might look like the following:
http://localhost:22001/#map,lt=38.17343267903539,lo=-121.9537353515625,z=8,vs=gpsvs:gps2:memorymonitorvs
Such a URL is fully bookmarkable and will initialize the webapp at the same state which allows people to share URL in order to show specific sensors. It is decomposed into several parameters which represent:
- map: which context/part of the webapp (could be home, data or map)
- lt=38.17343267903539: latitude of the map when not in automatic mode
- lo=-121.9537353515625: longitude of the map when not in automatic mode
- z=8: zoom level of the map when not in automatic mode
- vs=gpsvs:gps2:memorymonitorvs: shown virtual sensors when some are hidden
Nevertheless, the URL can become quite long with all these parameters inside it. However, it is not a problem as Internet Explorer supports URL lengths up to 2048 characters. The alternative web browsers (FireFox, Opera & Safari) are even better and support up to 100000 characters.