Mobile Ajax And The Frost Ajax Library

By Rocco Georgi

14th December 2011: This article is obsolete

This article is obsolete/out of date, so should no longer be treated as a current or reliable source of information. The official Frost page (http://frostlib.org) no longer seems functional.

Introduction

This article is a short introduction to the tricky topic of creating Ajax-powered web sites and applications on mobile and other alternative devices. Below I will discuss how Mobile Ajax is different from desktop Ajax, what its special problems and limitations are and the possible solutions that exist. One solution presented is the Frost Ajax Library, a useful tool in developing Ajax-powered services for mobile devices - an example of using Frost is given. This article is for web developers who want to create Ajax sites that work across alternative browsing devices, not just the desktop.

Assumed knowledge

If you've mastered the basics of HTML, JavaScript and the XMLHttpRequest object, you'll understand this article fine. Further helpful knowledge might be DOM scripting, CSS and some experience with Ajax libraries and/or frameworks (such as prototype, jQuery, dojo, YUI etc,) but these are not mandatory.

Some terms and definitions

Mobile Ajax has become a buzzword of its own - I'm not sure if I like it or not. On one hand I like that there is a term to describe what we're talking about when referring to the area of creating Ajax-enhanced sites, but on the other hand it's not a clearly defined term and everybody has their own definition. Maybe it's time for a Wikipedia entry ... anybody?

I really don't claim to provide definitive definitions for anything, it's legitimate for everybody to have his or her own definition, however I want to define the following terms in order to level the playing field for the rest of this article:

  • Mobile Web: There is a huge discussion going on at the moment as to what this is. Personally I think we should be referring to "One Web"[1], but there are many different parts to this one web, and some parts of it are definitely aimed at mobile phones, and other alternative devices. That is what I would refer to as the Mobile Web and it encompasses different standards (e.g. XHTML-MP) and of course different web browsers, usually ones with constraints on standards support and bandwidth. Here I will therefore distinguish between mobile and desktop environments - for the web as well as specifically for Ajax.
  • Ajax: A technology based on JavaScript/ECMAScript, running in a web browser and providing a means of asynchronous communication between the client and a web server (you can choose to reload small chunks of the currrent web page without the need for a complete page refresh.) Ajax is a compound technology that requires several things, such as different methods to retrieve, manipulate and display data.
  • Mobile Ajax: This is pretty straightforward now, since it's combining the two above. Mobile Ajax is exactly the same technology as in desktop browsers. However there are some important differences: different browsers with different capabilities, different use cases due to limited resources on the devices as well as on the network and finally other, usually limited interaction possibilities between user and device.

Ajax in the mobile space can offer many improvements, because it can help to overcome problems like narrow bandwidths and usability issues. For example can it help load content faster by only reloading the necessary parts of a page, and also if you imagine a page scrolled down by several screen heights, retrieving info and showing it in this place does not require the user to scroll down to the end of the page again, which he would have to if the action required a page refresh.

Mobile Ajax has, since pre-2006[2], created a lot of hype[3] and more and more people are getting interested in it. This is shown by events like the W3C/OpenAjax Alliance-organized workshop[4], the OpenAjax Alliance Mobile Ajax Task-force[5], numerous conference talks and at least as many blog posts on the topic.

Leaving all the hype that often surrounds Mobile Ajax aside, it comes down to being one of many tools that can improve the user experience for mobile web users, despite it's limitations. Mobile Ajax is very fragmented due to many different browsers with many different capabilities and different JavaScript implementations. Therefore comparisons to other mobile technologies are usually heavily skewed and are close to comparing apples with oranges, especially when it comes to developing mobile applications.

The term Mobile Ajax is often also used to refer to technologies that consist of an installable program, usually based on Java/J2ME that provides a runtime to execute JavaScript and render HTML (or similar dialects). These technologies are usually used to implement widget engines and to enable developers to employ web standards (or similar markup) to create applications that run on the device. However they don't refer to themselves as web browsers, but as frameworks or platforms. Mojax[6] and the now deprecated Opera Platform[7] are examples of this.

Browser Constraints And Other Problems

Talking about constrained browsers, let's look at some of them. The below list contains all the important browsers that are able to provide some kind of web access and that are not available on the desktop. WML browsers are really out of focus, so we're looking at anything that can do XHTML/WAP 2.0[8]:

  • Pocket IE/IE Mobile (WM 2003, 5.0, 6.0)
  • OpenWave (>= Mercury)
  • Access Netfront (>= 3.4)
  • Nokia S60
  • Minimo (Mozilla)
  • Opera Mini and similar (proxy-based)

All these browsers are more or less capable of doing some Ajax, or if not, the next versions promise support for it. When I say "some" Ajax this means that the browser and its JavaScript engine are generally able to execute asynchronous calls to a server. However, since Ajax is a compound technology the available tools in the various different JavaScript implementations on different browsers can be totally different, usually because of a lack of standards support and DOM functionality.

Opera Mobile is one of the true mobile browsers, as it doesn't have many constraints/limitations and provides a very capable JavaScript implementation.

The basic things any browser that wants to do Ajax need to be capable of are as follows:

  1. Sending/retrieving data asynchronously (through a XMLHttpRequest object or ActiveX)
  2. Doing something once the data arrives back at the client (usually a callback function call)
  3. Displaying something in the client based on the data retrieved or just the data itself

Number 3 would involve using a collection of DOM functions to manipulate the document. Constrained browsers often lack sufficient DOM implementations and usually only a subset of the DOM specification is implemented. Another possibility is to use the non-standard but very well supported innerHTML, which can also be used to change pieces of content on a document in the client. In the mobile space innerHTML is often the only existing alternative to true DOM manipulation. Now for innerHTML to make really sense, usually you will want to use another DOM function along with it - getElementById(). Luckily this element of DOM functionality is pretty well supported - from experience, I have developed the following general rule of thumb: if the browser implements XHR then getElementById() should be supported as well and can therefore be used.

I also want to mention one of the major problems when dealing not only with Mobile Ajax, but the mobile web in general: network latency. Wireless networks can have huge latency times, often one or more seconds. This means that if you request a script or page on the server, it can take several seconds before the actual download of data happens. This is really annoying and a real problem for Mobile Ajax in general. Using Ajax however you overcome some other problems, as mentioned earlier (cutting down on page reloads to save bandwidth and browser rendering time and usability in long pages.) Fortunately all of these issues are already going away as both networks and devices become faster.

Running Ajax In Constrained Browsers

Let's get into some real examples - I'll start with a basic Ajax request. The task here is to call a server-side script once the user clicks on a link - the data returned by that script should be displayed below the link. Here's the markup for that:

<a href="no_ajax.html" onclick="return !getData();">request data</a>
<div id="datacontainer">data should go here</div>

This markup consists of a link and a container for the data to populate. The link's onclick attribute contains a bit of JavaScript, namely a function call that provides a return value which is negated. This return value is important for graceful degradation - the user gets to see the content the link points to whether Ajax is supported or not; if it is, then the content is shown on the same page, meaning a better user experience:

  • If getData() returns true (meaning it was able to do whatever it does) then the link's onclick returns false (since the return value of getData() is negated) and the link-click is intercepted, causing the browser not to follow the href attribute given in the link.
  • If getData() returns false (eg because a necessary JavaScript method was not found) then the return value "true" of the onclick attribute causes the link to be followed as if there had never been an onclick attribute.

This technique and some inspirations for the following JavaScript code are taken from an excellent book: "Bulletproof Ajax" by Jeremy Keith[9]. The getData() method looks like this:

function getData() {
  var xhr = false;
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    try {
      xhr = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
      try {
        xhr = new ActiveXObject("Microsoft.XMLHTTP");
      } catch(e) {
        xhr = false;
      }
    }
  }
  if(xhr) {
    xhr.onreadystatechange = function() {
      parseResponse(xhr);
    };
    xhr.open("GET", "somescript.php", true);
    xhr.send(null);
    document.getElementById("datacontainer").innerHTML = "...loading...";
    return true;
  } else {
    return false;
  }
}

As you can see, getData() calls parseResponse() (that's the callback function) whenever the onreadystatechange property of the xhr object changes. getData() always returns either true or false, so the link will either get executed, or not. parseResponse() then puts the returned data into the container using innerHTML. The source for that looks like this:

function parseResponse(request) {
  if (request.readyState == 4) {
    if (request.status == 200 || request.status == 304) {
      var data = request.responseText;
      document.getElementById("datacontainer").innerHTML = data;
    }
  }
}

This is very basic stuff - probably one of the most basic ways to do some Ajax; the good thing here though is that it will work on pretty much all devices that can do Ajax, even the limited ones on mobile phones. The minimum requirements are XHR/ActiveX, getElementById() and innerHTML - and that's exactly what the core of the Frost library needs too. This is what we'll discuss next.

Using Frost To Do The Same

The Frost Ajax library is a tool for Ajax development on constrained browsers, such as those on mobile phones or gaming consoles. Frost provides you with JavaScript functions that can be used in mobile web applications to do Ajax and related things. The underlying approach is to be very minimalist in functionality and file size. Frost aims to output only the JavaScript code that can actually be used by the browser running the script, which means some server-side browser detection is involved. The server-side parts of Frost are currently available in PHP, but some people have already expressed interest in porting them to Java and Ruby.

The way Frost basically works is pretty straightforward:

  • You include Frost in your page, usually using a script tag's src attribute (you point to a server-side script)
  • You add some Frost function calls here and there in your markup or scripts (cf. example below)
  • When the page is requested by a browser, Frost tries to detect the browser using it's user agent string
  • Frost outputs JavaScript code depending on the browser's capabilities
  • If a browser does not have the necessary capabilities to run the Ajax, the Frost functions return false, so you can execute fallback functions
  • if Frost doesn't know a browser and it's capabilities, it outputs a universal version of the JavaScript, one that most likely will work

As a result Frost outputs very little code to known browsers and more in depth but more robust code to unknown ones.

Frost consists of a core library that will be extended by contributors in the future; you can configure which of the contributions should be contained in the library at inclusion time . Since Frost contains a server-side component you can either include an external script directly from the Frost site or you can install the whole thing on your own server and handle browser-detection etc. yourself - in this case you can also include the JavaScript output of the library directly in the XHTML document, which can help to overcome latency issues.

Frost is still under development and not officially released yet. However you can play around with a pre-release version available at http://frostlib.org. Your feedback is always appreciated.

Getting back to our simple Ajax example from above, if you wanted to use the Frost Ajax Library to do the same thing, things would look quite similar:

<a href="no_ajax.html" onclick="return !f('urltoid',['somescript.php', 'datacontainer2']);">request data</a>
<div id="datacontainer">data should go here</div>

That's a tad more code than before, but it's also more universal. Basically the f() function is the only public function Frost provides and it's a wrapper for all the functions in Frost. The parameters of this function are the Frost function name, here: urltoid, and an array of arguments for this function, in this case the id of the container the data should be displayed in. f() always returns either true or false, so in case something goes wrong, the browser can always expose the link's href instead.

You can check out how this works in reality in your own mobile browser by pointing it to http://frostlib.org/demo/ - this page contains both versions of the example and also shows the debug output of Frost. The page works with fully-functional mobile browsers like Opera Mobile, and also constrained mobile browsers like Opera Mini 4, IE and Minimo - all tested on Windows Mobile 5. it also works on the PlayStation 3 and Wii web browsers.

Frost's debug output shows you everything that's going on within the library. This should help developers in their development efforts, because especially on mobile devices there's almost no way to debug JavaScript code, except by alert()ing everything, which quickly gets very tedious. Debug can of course easily be disabled in production environments, in this case the server-side component in Frost strips out all debug-related code from the JavaScript that is outputted.

If you look into the source of the example page, you'll see that Frost is included there as an external script like this:

<script type="text/javascript" src="frost/frost.php?debug=1"></script>

As you can see, the src attribute points to a PHP script, frost.php, that gets passed an argument: debug=1 - this turns debugging output on. On the server the PHP script referenced here uses a JavaScript file as its input and strips out anything the browser cannot deal with. If you're curious how the underlying JavaScript code on the server looks like, check out http://frostlib.org/demo/frost/frost.js - that's the complete source of the JavaScript part of the library.

Aside from providing a universal set of functions for as many browsers as possible, one major goal of Frost is to provide you with a small file size to save on loading times. However, to achieve the same functionality as the simple Ajax demo, Frost actually needs more space than the 0.7kB above - that's simply because Frost provides a lot of other functionality. The full Frost source is around 1.9kB...still really small for a JavaScript library.

The advantages of using Frost

So why use Frost when I just can do it myself like shown above? There are some good reasons:

  • You don't want to keep rewriting the same code over and over again - that's no big deal in this case, but what if you need more functionality, and what if you don't know what browser you're serving the page to?
  • You want to cut down on irrelevant code for each browser - e.g. you can check if the XHR object or the ActiveX exists and then serve it just the appropriate content it can use
  • You want debugging support - it is useful to know what's going on in the background, and constant alert()s can be annoying, time consuming, and affect results
  • You want to handle offline states - guess what happens when you load the page, then go offline and then click the link? It depends on the browser and the device. The best thing that could happen is for the connection to be restored automatically, but that doesn't happen a lot. What usually happens is that the check for xhr.onreadystatechange waits forever because the state simply doesn't change. Too bad we already returned true in getData() when the link was not executed - it means you're stuck and nothing happens. Frost handles callbacks a bit differently and can therefore have time-outs for XHR requests, so in case nothing happens for a while, the request will time-out and Frost can then execute any JavaScript function you specify, eg show a message informing the user that the request failed, and then return to the previoud page.
  • You want to show something is going on in the background - typically some kind of spinning animation is shown while the Ajax request runs in the background, so the user knows something is going on. Frost can swap a predefined image on the page with a loading animation whenever an XHR request is happening; a text-based animation is also being worked on at this moment.

The current Frost core library weights in at 1.9kB and offers all of these points except for debugging. If you enable debugging, which is only necessary for development environments, you're looking at 3.2kB.

So why is Frost still not released? As mentioned before, Frost tries to minimize the JavaScript file size by outputting only the JavaScript code that can actually be used by the browser running the script, so some kind of browser detection and a database of browser-related capabilities is necessary. That's one of the reasons why there's not a final release of Frost available yet - we are still working on the testing setup that will test a browser's capabilities and populate the database. It is planned to export this data to and also use data from projects like WURFL[10] or DDWG[11]. The brand new Frost site at http://frostlib.org and the evolving community around it will help to resolve those issues quickly. By the end of the year we should have a working release. For now, please check out the pre-release version on the site! Also you might want to join the just recently set up mailing list covering Ajax in WURFL.[12]

Summary

Mobile Ajax is a nice thing to have, it will become much more important with the further emergence of more capable phones. On the mobile the same best practices apply as on the desktop for using Ajax - you should use it as an enhancement, but not force your users to rely on it - let it degrade gracefully. Content adaptation has become a common technology in mobile development and deployment, so why not do the same for Ajax?

If I would have to give a forecast of the future I would say we'll see Mobile Ajax evolve in many ways, as browsers become more capable and technological problems in dealing with Ajax go away. Soon there will be ways to access the device API, such as GPS or applications through JavaScript objects. Mobile widgets and offline handling will become widespread too. Ajax will be coupled with other technologies like SVG for example (imagine dynamic SVG graphics!)

On our blog at PavingWays[13], you can find further information about Mobile Ajax. People at dev.mobi[14] have also written some stuff on Mobile Ajax. Finally, an article by Chris Mills here on dev.opera.com[15] also covers Ajax capabilities of Opera Mini and explains pretty well why Ajax works, but not asynchronously.

References

[1] W3C One Web presentation
[2] Ajax on IE Mobile in 2005
[3] Ajit Jaokar on Mobile Ajax
[4] Mobile Ajax Workshop 2007
[5] Open Ajax Alliance Mobile Ajax Taskforce
[6] Mojax, Java based
[7] Opera Platform
[8] WAP 2.0 definition
[9] "Bulletproof Ajax" by Jeremy Keith
[10] WURFL project
[11] DDWG at W3C
[12] Ajax in WURFL (Yahoo! Group)
[13] Mobile Ajax Intro at PavingWays
[14] Mobile Ajax Intro at dev.mobi
[15] Chris Mills on Opera Mini and Ajax

a href=

--
Rocco Georgi is the Lead Developer of PavingWays. He has worked in the area of web development for more than seven years. With PavingWays Rocco specializes on bringing web applications to (mobile) devices.


This article is licensed under a Creative Commons Attribution, Non Commercial - Share Alike 2.5 license.

Comments

The forum archive of this article is still available on My Opera.

No new comments accepted.