
Although Oz Weather is a fully functional app, as usual I feel driven to improve it further. So what is the next step? It is to improve the speed and efficiency (and hence user experience) by moving towards a purer AJAX implementation, and using whatever data compression is possible in delivering the data to the browser.
The existing application renders the page from PHP, and then uses javascript to update the time values on the page at regular intervals. The rendered page also includes the following meta tag in its header.
<meta http-equiv="Refresh" content="600" />
This forces a page refresh every 600 seconds (10 minutes), to ensure a fairly small time lag between data availability and the user’s view.
The ideal I wish to achieve is to render the initial page layout purely as HTML, and then deliver the weather data via AJAX as needed ie. using a javascript timer to decide when the data content needs to be refreshed, instead of requiring a reload of the entire page. Consequently, apart from the initial page load, no further html needs to be delivered.
The first step was to create a PHP data query module, delivering the data in JSON format. For future flexibility (and readability), I also added an XML format option, of which a truncated example follows.
<?xml version="1.0"?> <forecast> <numdays>2</numdays> <day1> <date>2008-08-25</date> <dayname>Monday</dayname> <min>8</min> <max>18</max> <icon>34</icon> <desc>Fine. Partly cloudy.</desc> </day1> <day2> <date>2008-08-26</date> <dayname>Tuesday</dayname> <min>8</min> <max>20</max> <icon>32</icon> <desc>Fine. Mostly sunny.</desc> </day2> </forecast>
The next step was to create the HTML page with null data, with all data-bearing divs identified with appropriate id values. And then to write the javascript required to place the data query, and then populate the divs with the returned data values. All of this is relatively straight-forward with the use of statements like the following.
document.getElementByID('temp_max').innerHTML=JSONObj.forecast.day[iday].max;
This all worked as expected. However, a few unforeseen problems arose, in particular relating to the –webkit-marquee CSS behaviour (also referred to in an earlier blog post). The problem is that the marquee behaviour only appears to work when the div using marquee in its CSS style is first rendered ie. when the page is first loaded or refreshed. But with the new AJAX version, no page reload occurs, even when the user selects a new city to display. Also, even altering the contents of the div doesn’t re-trigger the marquee motion. Eventually, though I found a workaround. The trick is to clone the div, and then replace the original div in the DOM model with the newly created clone. Sample code follows.
function refreshMarquee(element)
{
var pclone = element.cloneNode(true);
var parent = element.parentNode;
parent.replaceChild(pclone, element);
return false;
}
refreshMarquee(document.getElementById('weather_description'));
Note that the cloneNode call requires its “deepBoolean” parameter to be set to “true” in order to copy the text value from the source node.
Another issue is how to force a data refresh every 10 minutes without a manual page reload. This is fairly straight-forward with the use of setTimeout function calls used recursively, which I was already using at 10 second intervals to update the time since observations were made. However, as this is an iPhone application, it is likely that users will view the page, then close the browser, and perhaps come backs hours or days later and reopen the browser still viewing the same page. Of course the javascript would have stopped running, and the timer code would simply restart without realising that there had been a suspension, and the data would thus remain out-of-date until the remainder of the timer period eventually expired – which could be up to 10 minutes. The solution here is to set up a start-time variable, and frequently check how much time has elapsed since then. In this case, after the page is resumed from dormancy, then next check will immediately reveal that the data needs an update… problem solved!
All desired changes having been made, the html, javascript and css files were converted to include php wrappers to allow gzip compression, and then a benchmark comparison was made with the previous PHP intensive version. Hmmm – it seems almost nothing gained on load, despite all the compression, due to the need for the AJAX data query to run (owquery2.php) after the initial HTML load – but obviously substantial gains for subsequent updates without reload.
One nagging problem remains. Despite trying at least half a dozen coding variants based around “window.scrollTo(0,1)” the url bar refuses to retract after the initial page load. There is no problem at all in getting it to retract after an AJAX data refresh, and I suspect it has something to do with the AdMob javascript that is rendering the ad banner at the top of the page – but at this stage still not sure exactly what.
Hopefully I will be able to post my solution in a future blog entry.