Ajax, hashes & history

jQuery Mobile's navigation model

A "page" in jQuery Mobile consists of an element (usually a div) with a data-role attribute set to "page", within which there generally tends to be div elements with roles of "header", "content", and "footer", each containing common markup, forms, and custom jQuery Mobile widgets.

The basic workflow with page loading is as follows: first, a page is requested with a normal HTTP request, and subsequent "pages" are then requested and injected into that page's DOM. Because of this, the DOM may have a number of "pages" in it at a time, each of which can be re-visited by linking to its ID attribute.

When a url is initially requested, there may be one or more "pages" in the response, and only the first one will be shown. The advantage of storing more than one "page" is that it allows you to pre-fetch static pages that are likely to be visited.

Ajax-driven page navigation

All navigation within jQuery Mobile is based on changes and updates to location.hash. Whenever possible, page changes will use a smooth transition between the current "page" and the next, whether it is either already present in the DOM, or is automatically loaded via Ajax.

Hash values created by jQuery Mobile are normalized as full paths relative to the URL of the first "real" page that was loaded. The hash is always maintained as a valid URL, so any "page" in jQuery mobile can be bookmarked or referenced in a link. To retrieve a non-hash-based URL, simply remove the # from the address and refresh the page.

In general, hash changes are created whenever a link is clicked in jQuery mobile. When a link is clicked, jQuery mobile will make sure the link is referencing a local URL, and if so, it'll prevent the link's default click behavior from occurring and request the referenced url via Ajax instead. When the page returns successfully, it will set the location.hash to the new page's relative url.

Within the framework, page changes - both for pages already in the DOM and for pages that need to be loaded via Ajax - use the $.changePage function. $.changePage contains all of the logic for finding pages to transition to and from, and how to handle various response conditions such as a page not found. $.changePage can be called externally and accepts the following arguments (to, transition, back, changeHash). The to argument can accept either a string (such as a file url or local element's ID), an array (in which the first array item is any local page you'd like to transition from, and the second array item is the to page), or an object (with expected properties: url, type ("get" or "post"), and data (for serialized parameters)), the latter of which is useful for loading pages that expect form data. The transition argument accepts a string representing a named transition, such as "slide". The back argument accepts a boolean representing whether the transition should go forward or in reverse. Lastly, the changeHash argument accepts a boolean for whether you'd like the url to be updated upon a successful page change.

The $.changePage function is used in a number of places in jQuery Mobile. For example, when a link is clicked, its href attribute is normalized and then $.changePage handles the rest. When forms are submitted, jQuery Mobile simply gathers a few of the form's attributes, serializes its data, and once again, $.changePage is used to handle the submission and response. Also, links that create dialogs use $.changePage to open a referenced page without updating the hash, which is useful for keeping dialogs out of history tracking.

Another key ingredient to jQuery Mobile's page navigation model is the base element, which is injected into the head and modified on every page change to ensure that any assets (css,images,js,etc) referenced on that page will be requested from a proper path. In browsers that don't support dynamic updates to the base element (such as Firefox 3.6), jQuery Mobile loops through all of the referenced assets on the page and prefixes their href and src attributes with the base path.

Hash changes that occur independently of a click, such as when a user clicks the back button, are handled through the hashchange event, which is bound to the window object using Ben Alman's hashchange special event plugin (included in jQuery Mobile). When a hash change occurs (and also when the first page loads), the hashchange event handler will send the location.hash to the $.changePage function, which in turn either loads or reveals the referenced page.

Once the referenced page is present in the DOM, the $.changePage function applies a transition between the current active page and the new page. Page transitions happen through adding and removing classes that apply CSS animations. For example, in a slide-left transition, the exiting page is given the classes "slideleft" and "out", and the entering page is given the classes "slideleft" and "in", as well as a class of "ui-page-active" to mark it as the new "active" page being viewed. When the animation is complete, the "in" and "out" classes are removed, and the exited page loses its "ui-page-active" class.

Developer explanation of base url management:

jQuery Mobile manages http requests using a combination of generated absolute URL paths and manipulating a generated <base> element's href attribute. The combination of these two approaches allows us to create URLs that contain full path information for loading pages, and a base element to properly direct asset requests made by those loaded pages (such as images and stylesheets).

jQuery Mobile core contains 4 internal functions for manipulating a base url to be used in normalizing relative http requests:

These are called at certain times during page requests and transitions: On DOM ready, during the initial page load, a <base> element is created and appended to the <head> of the page. Immediately after that, resetBaseURL() is called to set the <base> element's href to location.pathname.

Whenever a link with a relative URL is clicked, the $.changePage function will prefixed that link's href with the value of getBaseURL(), which creates a full path to that file, relative to the document.

Changing the hash value triggers the hashchange event handler, which first calls resetBaseURL(), and makes an Ajax request to the value of the hash (which is already a full path, requiring no base url). After that request is sent, setBaseURL() is called, which resets the <base> element's href attribute to the value of getBaseURL() and allows any references to images, stylesheets, and scripts within that page to be requested with a proper base path.

Auto-generated pages and sub-hash urls

Some plugins may choose to dynamically break a page's content into separate navigable pages, which can then be reached via deep links. One example of this would be the Listview plugin, which will break a nested UL (or OL) into separate pages, which are each given an ID so they can be linked to like any normal "page" in jQuery Mobile. However, in order to link to these pages, the page that generates them must first be requested from the server. To make this work, pages that are auto-generated by plugins use the following special ID structure: <div id="page.html&subpageidentifier">

So, for example, a page generated by the listview plugin may have an ID like this: id="artists.html&ui-page=listview-1"

When a page is requested, jQuery Mobile knows to split the URL at "&ui-page" and make an HTTP request to the portion of the URL before that key. In the case of the listview example mentioned above, the URL would look like this: http://example.com/artists.html&ui-page=listview-1 ...and jQuery Mobile would request artists.html, which would then generate its sub-pages, creating the div with id="artists.html&ui-page=listview-1", which it will then display as the active page.

Note that the ID of the element contains the full URL path, not just the portion after &ui-page=. This allows jQuery Mobile to use a single consistent mechanism that matches URLs to page IDs.

Cases when Ajax navigation will not be used

Under certain conditions, normal http requests will be used instead of Ajax requests. One case where this is true is when linking to pages on external websites. You can also specify that a normal http request be made through the following link attributes:

Form submissions

Form submissions are handled automatically through the navigation model as well. Visit the forms section for more information.

Known limitations

The non-standard environment created by jQuery Mobile's page navigation model introduces some conditions for which you should be aware when building pages: