Ajax

In Chapter 3, we added an Ajax request to the News application, transforming the application from a static data reader to a dynamic application serving up new stories from multiple feeds in the background. There is a huge difference in user experience when your application can let the user know that something new exists and present it to her immediately.

You aren’t required to use the Prototype functions. You can use the XMLHttpRequest object directly, and you will be required to if your data protocols are SOAP-based or if they are anything other than simple XML, JSON, or text-based web services. There are many references for XMLHttpRequest if you’d like to explore this more directly. Any fundamental JavaScript reference will give you an overview, but for more in-depth information, look for Ajax-specific references such as Anthony Holdener’s Ajax: The Definitive Guide (O’Reilly). For a more basic introduction, you can review the tutorial at https://developer.mozilla.org/en/XMLHttpRequest, which, while focused on Firefox, is nonetheless a good introduction to XMLHttpRequest.

The Ajax class functions, which are a basic feature of the Prototype JavaScript library, are included with webOS because they encapsulate the lifecycle of an XMLHttpRequest object and handlers into a few simple functions. The next few pages will explore these functions to show you how Prototype can help you integrate dynamic data into your application.

Note

Palm webOS applications are run from file:// URLs and thus aren’t restricted by the single-origin policy that makes mixing services from different websites difficult.

Ajax Request

Back in Chapter 3, we added an Ajax.Request object to News to sync the web feeds to the device, but didn’t describe the object or the return handling in any detail. Ajax.Request manages the complete Ajax lifecycle, with support for callbacks at various points to allow you to insert processing within the lifecycle where you need to. In Chapter 3, we used updateFeedRequest to initiate the Ajax request:

// updateFeedRequest - function called to setup and make a feed request
updateFeedRequest: function(currentFeed) {
    Mojo.Log.info("URL Request: ", currentFeed.url);

    var request = new Ajax.Request(currentFeed.url, {
        method: "get",
        evalJSON: "false",
        onSuccess: this.updateFeedSuccess.bind(this),
        onFailure: this.updateFeedFailure.bind(this)
    });
},

An Ajax.Request is created using the new operator, the only way that a request can be generated, and initiates an XMLHttpRequest as soon as it is created. In this case, a get request is initiated on the URL defined in currentFeed.url, and two callbacks are defined for success or failure of the request. You can also make post requests and define other callbacks, which map to the request lifecycle shown in Table 6-3.

Table 6-3. Ajax.Request callbacks by lifecycle stage

Callback

Lifecycle stage

onCreate

Created

onUninitialized

Created

onLoading

Initialized

onLoaded

Request Sent

onInteractive

Response being received (per packet)

on###, onSuccess, onFailure

Response Received

onComplete

Response Received

To clarify:

onCreate

Is available only to responders and is not available as a property of Ajax.Request.

on###

When specified (where ### is an HTTP status code, such as on 403), it is invoked in place of onSuccess in the case of a success status, or onFailure in the case of a failure status.

onComplete

Is called only after the previous potential callback—either onSuccess or onFailure (if specified)—is called.

Ajax requests are asynchronous by default, one of the virtues of Ajax. While Ajax.Request supports an override, the synchronous XMLHttpRequest has been disabled in webOS. Since the UI and applications run as part of a common process, this is necessary to preserve UI responsiveness. It may be supported in a later release when there is concurrency support.

There are more Ajax.Request options available. Ajax.Request is covered thoroughly in most Prototype references, including the Prototype 1.6 API reference available at http://www.prototypejs.org/api.

Ajax Response

An Ajax.Response object is passed as the first argument to any callback. In our sample, we have used the HTTP status codes under the status property and the responseText and responseXML properties. Table 6-4 provides a summary of the full list of properties.

Table 6-4. Ajax.Response properties

Property

Type

Description

readyState

Integer

Current lifecycle state:

0 = Uninitialized

1 = Initialized

2 = Request Sent

3 = Interactive

4 = Complete

status

Integer

HTTP status code for the request

statusText

String

HTTP status text corresponding to the code

responseText

String

Text body of the response

responseXML

XML or Document

If content type is application/xml, then XML body of the response; null otherwise

responseJSON

Object

If content type is application/json, then JSON body of the response; null otherwise

headerJSON

Object

Sometimes JSON is returned in the X-JSON header instead of response text; if not, this property is null

request

Object

Original request object

transport

Object

Actual XMLHttpRequest object

We haven’t discussed JSON specifically, but it is an increasingly important tool for developers. Prototype includes some powerful JSON tools in Ajax.Request, which supports automatic conversion of JSON data and headers. If you’re handling structured data, you should look at JSON, particularly for data interchange.

More Ajax

Prototype includes some additional functions for consolidating listeners for Ajax callbacks, called responders, and for updating DOM elements directly from an Ajax request.

Ajax responders

If you’re doing multiple Ajax requests, you might find it useful to set up responders for common callbacks rather than setting callbacks with each request. This is particularly applicable to error handlers or activity indicators. The following example shows the use of setup responders to manage a spinner during feed updates and to handle Ajax request failures:

Ajax.Responders.register({
   onCreate: function()  {
       spinnerModel.value = true;
       this.controller.modelChanged(spinnerModel, this);
   }.bind(this),

   onSuccess: function(response)  {
       spinnerModel.value = false;
       this.controller.modelChanged(spinnerModel, this);
       this.process.Update(response);
   }.bind(this),

   onFailure: function(response) {
       this.spinnerModel.value = false;
       this.controller.modelChanged(spinnerModel, this);
       var status = response.status;
       Mojo.Log.info("Invalid URL - Status returned: ", status);
       Mojo.Controller.errorDialog("Invalid feed - http failure: "+status);
   }.bind(this)
});

In this sample code, each responder is defined using the callback property and a function literal. The first, onCreate, is available only to responders and not in an Ajax.Request object. It starts the spinner, while the other two, onSuccess and onFailure, stop it while performing some appropriate postprocessing.

Responders can be unregistered, but you would need to avoid using function literals when you register them, as the previous example did. The responders would need to be defined first, then registered and unregistered with a reference to that definition.

Ajax.Updater and Ajax.PeriodicalUpdater

Ajax.Updater and Ajax.PeriodicalUpdater each make an Ajax request and update the contents of a DOM container or element with the response text. Ajax.Updater will perform an update request once, while Ajax.PeriodicalUpdater will perform the requests repeatedly, with a delay option to extend the interval between updates when responses are unchanged. Note that Ajax.PeriodicalUpdater uses JavaScript timers and won’t wake the device.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.36.56