When you should NOT user jQuery.load function in your PhoneGap application

In most more complex PhoneGap applications developers split app contents into several files. When these are truly separate “screen” of application, and are accessible via normal <a href=""> links, everything is fine.

Problems arise, when you want to split contents of one “screen” into several files. For example to have tabs, where each tab content is stored in external separate file. In this case, content is loaded on tab’s tab (or preloaded during application init) using AJAX (which can be used to request local files as well).

If you rely on jQuery and want to use .load() or .ajax() function, read this post to avoid common pitfalls.

The general problem is, that jQuery’s .load() and .ajax() functions doesn’t handle request.status === 0 situation. It was reported, that on Android 2.x.x, when accessing local files, this status, not request.status === 200 is returned. This is outlined in details in Simon Mac Donald blog’s.

Therefore, very common request result manipulation (checking):

if(request.readyState === 4)
{
    if(request.status === 200)
    {
        //Do something...
    }
}

must be, in case of PhoneGap application (but only for accessing local files!) extended to:

if(request.readyState === 4)
{
    if(request.status === 200 || request.status === 0)
    {
        //Do something...
    }
}

Here is an example of function, using above extension, that loads contents of each Bootstrap’s tab pane upon application init:

$("div.tab-pane").each(function()
{
    var
        target = $(this),
        request = new XMLHttpRequest();
        
    request.open('GET', target.attr("data-url"), true);
    
    request.onreadystatechange = function()
    {
        if(request.readyState === 4)
        {
            if(request.status === 200 || request.status === 0)
            {
                target.html(request.responseText);
                                    
                console.log('File "' + target.attr("data-url") + '" loaded to #' + target.attr("id") + ' tab!');
            }
        }
    }
    
    request.send();
});

It should be called anywhere in application init process (specific init() function, ondeviceready handler, $(function($) etc.).

This example is using Twitter Bootstrap framework’s tab. To test it, place tabs definition similar to below, anywhere withing any of your HTML file:

<ul class="nav nav-tabs">
    
    <li class="active"><a href="#bootstrap" data-toggle="tab">Bootstrap</a></li>

    <li><a href="#javascript" data-toggle="tab">Javascript</a></li>

    <li><a href="#phonegap" data-toggle="tab">PhoneGap</a></li>
  
</ul>

<div class="tab-content">
    
    <div class="tab-pane active" id="bootstrap" data-url="_bootstrap.html">Please wait, loading...</div>

    <div class="tab-pane" id="javascript" data-url="_javascript.html">Please wait, loading...</div>

    <div class="tab-pane" id="phonegap" data-url="_phonegap.html">Please wait, loading...</div>
  
</div>

I’m using data-url attributes in this example to store URL of file containg each tab contents.

Further readings:

Leave a Reply