Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Ajax In Action (2006).pdf
Скачиваний:
63
Добавлен:
17.08.2013
Размер:
8.36 Mб
Скачать

Using the framework with network requests

237

 

 

6.5 Using the framework with network requests

In chapter 5 we introduced the ContentLoader object as a common encapsulation for network traffic. We can make use of our notification framework to provide status reports on any data request that we make automatically. Let’s scope out the requirements first.

When a request is made to the server, we would like to indicate that it is in progress, with a low-priority notification. To differentiate network requests from other low-level notifications, we would like to use a different icon. We have the image of the earth from our planetary viewer example in chapters 4 and 5, so let’s use that.

When the network request completes, we would like the notification to be cleared and replaced by a low-level notification if everything went okay or by a medium-level notification if there was an error.

To implement this, we simply need to create Message objects at appropriate points in the lifecycle of the request, such as when the request is fired, when it completes or errors, and so on. The modified code for our ContentLoader object is given in listing 6.9.

Listing 6.9 ContentLoader with notifications

net.ContentLoader=function( ... ){ ... }; net.ContentLoader.msgId=1; net.ContentLoader.prototype={

loadXMLDoc:function(url,method,params,contentType){ if (!method){

method="GET";

}

if (!contentType && method=="POST"){ contentType='application/x-www-form-urlencoded';

}

if (window.XMLHttpRequest){ this.req=new XMLHttpRequest();

} else if (window.ActiveXObject){

this.req=new ActiveXObject("Microsoft.XMLHTTP");

}

if (this.req){ try{

var loader=this; this.req.onreadystatechange=function(){

loader.onReadyState.call(loader);

}

this.req.open(method,url,true); if (contentType){

this.req.setRequestHeader('Content-Type', contentType);

238CHAPTER 6

The user experience

 

}

 

b Notify request has started

 

this.notification=new msg.Message(

 

"net00"+net.ContentLoader.msgId,

 

 

"loading "+url,

 

 

 

msg.PRIORITY_LOW.id,

 

 

 

-1,

 

 

 

"img/ball-earth.gif"

 

 

 

);

 

 

 

net.ContentLoader.msgId++;

 

 

 

this.req.send(params);

 

 

}catch (err){

 

 

 

this.onerror.call(this);

 

 

}

 

 

 

}

 

 

 

},

 

 

 

onReadyState:function(){

 

 

var

req=this.req;

 

 

var

ready=req.readyState;

 

 

if (ready==net.READY_STATE_COMPLETE){

 

var httpStatus=req.status;

 

 

if (httpStatus==200 || httpStatus==0){

 

 

this.onload.call(this);

c Clear initial notification

 

this.notification.clear();

}else{

 

 

 

this.onerror.call(this);

 

 

}

 

 

 

}

 

 

 

},

 

 

 

defaultError:function(){

d Notify on error

var msgTxt="error fetching data!" +"<ul><li>readyState:"+this.req.readyState +"<li>status: "+this.req.status

+"<li>headers: "+this.req.getAllResponseHeaders() +"</ul>";

if (this.notification){ this.notification.clear();

}

this.notification=new msg.Message( "net_err00"+net.ContentLoader.msgId, msgTxt,msg.PRIORITY_DEFAULT.id

);

net.ContentLoader.msgId++;

}

};

Using the framework with network requests

239

 

 

When we make a network request using loadXMLDoc(), we create a low-level notification band attach a reference to it to the ContentLoader object. Note that we set the lifetime to -1, so that the notification won’t expire by itself.

In the onReadyState() method, we clear the notification if everything has gone well c. In the case of an error, we call the defaultError() method, which now generates a notification of its own d. The message for this notification uses HTML markup to create a richer report than plain text could.

Listing 6.10 demonstrates an example page using this modified ContentLoader.

Listing 6.10 Notifications sample page

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>

<head>

<title>Notifications test</title>

<link rel=stylesheet type="text/css" href="msg.css"/>

<script type="text/javascript" src="x/x_core.js"></script> <script type="text/javascript" src="extras-array.js"></script> <script type="text/javascript" src="styling.js"></script> <script type="text/javascript" src="msg.js"></script>

<script type="text/javascript" src="net_notify.js"></script> <script type="text/javascript">

window.onload=function(){

msg.render('msgbar');

}

var msgId=1;

function submitUrl(){

 

 

var url=document.getElementById('urlbar').value;

b Make request

var loader=new net.ContentLoader(url,notifyLoaded);

}

 

to server

function notifyLoaded(){

c Notify that resource is loaded

var doneMsg=new msg.Message(

"done00"+msgId,

 

 

"loaded that resource you asked for: "+this.url, msg.PRIORITY_LOW.id

);

msgId++;

msg.render('msgbar');

}

</script>

</head>

240CHAPTER 6

The user experience

<body>

<div class='content'>

<p>here is some content. This is what the web application is up to when not being bugged silly by all these messages and notifications and stuff. <p>Type in a URL in the box below (from the

same domain, see Chapter 7), and hit 'submit'. A souped-up contentloader that understands the notification system will be invoked.

<input id='urlbar' type='text'/> 

<a href='javascript:submitUrl()'>submit</a> </div>

<div id='msgbar' class='msgbar'></div> </body>

</html>

The page (as seen in figures 6.6 and 6.7) renders a simple HTML form into which the user can type URLs. Clicking the submit link will attempt to load that URL b and fire the notifyLoaded() callback function if successful. notifyLoaded() doesn’t actually do anything with the resource, other than report that it has fetched it by creating another Message object c.

Note that the behavior on a successful request is not written into the framework but provided by a custom onload handler function. This allows the framework to be adapted to differing requirements. In the example in listing 6.9, we have hard-coded the default behavior in case of error. In a real application, every network failure may not be sufficiently important to warrant a big in-your-face dialog. We leave it as an exercise for the reader to add a parameter to the ContentLoader to denote the urgency of the notification required on failure (or else provide an overridden onError handler with a gentler notification policy).

Figure 6.6

A successfully loaded resource will be displayed as a tooltip on the status bar.