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

518CHAPTER 13

Building stand-alone applications with Ajax

Figure 13.7

CSS applied to the footer

In figure 13.7, we see all of the properties that we applied to the divs. We applied widths, colors, font sizes, borders, padding, and much more. We can customize the CSS properties of these elements so they fit the needs and styles of any website theme or personal taste. The next thing we need to do is get content into our RSS reader!

13.3 Loading the RSS feeds

In this example, we will load files from multiple feeds. We will use our ContentLoader object to do the work, as we have throughout this book. In the first version, we use a series of global variables to quickly develop an RSS feed viewer.

13.3.1Global scope

Global variables allow for easy adjustments to our script so we do not have to change the functionality inside the for loops and timers. We will be able to adjust the contents of the global variables to make changes throughout the script and communicate between the different functions. We want to use global variables rather than local variables in this script so they can be shared and we don’t have to pass them from function to function. Later on in this chapter, when we refactor our script, you will see a solution that doesn’t use global variables; but for now, they keep our example simple.

One downfall to JavaScript is that there is no variable type for constants, so we are simulating the effect with global variables. However, global variables can be

Loading the RSS feeds

519

 

 

overwritten, so we must be careful when using them. The variables in listing 13.5 will not be overwritten at any time during the application.

Listing 13.5 Global constant variables

var flipLength = 5000; var timeColor = 100;

var strErrors = "<hr/>Error List: <br/>" var arrayRSSFeeds = new Array(

"http://radio.javaranch.com/news/rss.xml",

"http://radio.javaranch.com/pascarello/rss.xml",

"http://radio.javaranch.com/bear/rss.xml",

"http://radio.javaranch.com/lasse/rss.xml");

In listing 13.5, we assign the global variables that affect how our viewer performs. The first global variable, flipLength, determines how many milliseconds our current message is displayed before it is replaced with the next message. In this case, the value 5000 represents the total number of milliseconds between messages. Another timer variable is timeColor. This time span is the number of milliseconds between the coloring or fading steps in our script. The larger the number, the longer the transition takes to complete.

The next global variable that we use is strErrors. This line is the heading for any errors we encounter during the loading process. We can change the message or add style parameters to it. The last global variable that is going to affect the outcome of the script is the array, arrayRSSFeeds. In this array, we add the URLs of the RSS feeds that we want to access. In this case, we access four separate RSS feeds from JavaRanch.com’s radio blogs.

The next set of global variables that we declare, in listing 13.6, are used to communicate between our separate functions. These global variables hold the state of the RSS feeder. Their values change depending on the action that is being performed.

Listing 13.6 Global variables that maintain the state

var currentMessage = 0; var layerFront = 2;

var timerSwitch;

var bPaused = false;

var arrayMessage = new Array(); var intLoadFile = 0;

var bLoadedOnce = false;

520CHAPTER 13

Building stand-alone applications with Ajax

The first global variable that we instantiate in listing 13.6 is currentMessage. The variable currentMessage keeps track of the message that is being viewed. It can be considered a counter that is reset when it reaches the maximum number of records. The next global variable is layerFront, which holds the state of our layers. When we designed our RSS reader layout, we had two layers on top of each other. This variable is keeping track of the state of those layers.

The variable timerSwitch holds the timer object that determines when the next frame is going to be loaded. If the user pauses the feeder, we cancel this timer and change the state of our next variable, bPaused. The boolean value that bPaused holds allows us to determine the state of the timer: true if it is paused and false if it is running.

The global variable arrayMessage holds the formatted messages that we retrieved from the RSS items. The array is multidimensional and holds all the information we want to show. As stated earlier, the item elements in the RSS feed hold more information than we may need; therefore, we only grab the few items that interest us and store them in arrayMessage.

The last variable, intLoadFile, leads us into our next section of code. The variable is a counter, which holds the current file count that is being loaded from our array, arrayRSSFeeds, during the preloading process.

Now that all the global variables have been declared, we can see a global picture of where this project is heading. We preload the RSS feeds from an array of URLs. We use a counter to track the status of the preload process. During the preloading, we are only selecting the desired information from each XML file. After the preload process has finished, the messages are displayed with a fading transition to create a slideshow, which we can pause and manipulate. With the global variables that we declared, we are able to control the functionality of the script. This has led us to the starting point of the RSS preloader function.

13.3.2Ajax preloading functionality

One of the problems developers face with Ajax is how to preload multiple files without sending too many requests to the external websites and having them step all over each other. One solution is to use queuing, and that is what our Ajax ContentLoader does.

Making the repeated requests

The ContentLoader allows the queuing mechanism to fire the requests in an orderly fashion. In listing 13.7, we take our array (which was populated when the

Loading the RSS feeds

521

 

 

page was loaded in listing 13.5) that contains the URLs to our feeds and prepare them for our ContentLoader.

Listing 13.7 Preload JavaScript function

window.onload = function(){ var loader= new Array()

for(i=0;i<arrayRSSFeeds.length;i++){ loader[loader.length] = new

net.ContentLoader(arrayRSSFeeds[i],

BuildXMLResults,BuildError);

}

}

The code in listing 13.7 is fired with the onload event handler. As the page is loaded, we prepare an array variable, loader, to hold all the requests to the server. We loop through our array arrayRSSFeeds to obtain all of the URLs from which we want to obtain information. For each iteration, we increment our loader array to hold the new ContentLoader request. We pass in the URL of the feed, the function BuildXMLResults() that formats the content, and the function BuildError() that will be called if there is an error obtaining the feed. Now that we have begun the loading process, we need to format the returned XML feeds.

Adapting the function

When the request is made, it is going to call either BuildXMLResults() (if it was successful) or BuildError() (if it encountered any problems). BuildXMLResults() takes the XML feed and formats it into a usable format. BuildError() logs the error to the error list. Both functions update the status so we can see the progress of the loading. Listing 13.8 shows the implementation of this logic.

Listing 13.8 Formatting the XML results into a JavaScript array

function BuildXMLResults(){

var xmlDoc = this.req.responseXML.documentElement; var RSSTitle =

xmlDoc.getElementsByTagName('title')[0].firstChild.nodeValue; var xRows = xmlDoc.getElementsByTagName('item'); for(iC=0;iC<xRows.length;iC++){

intMessage = arrayMessage.length; arrayMessage[intMessage] = new Array( RSSTitle, xRows[iC].getElementsByTagName('title')[0]

.firstChild.nodeValue,

xRows[iC].getElementsByTagName('link')[0]

522CHAPTER 13

Building stand-alone applications with Ajax

.firstChild.nodeValue,

xRows[iC].getElementsByTagName('description')[0]

.firstChild.nodeValue);

}

UpdateStatus();

}

The function BuildXMLResults() in listing 13.8 retrieves the XML document by referencing our request object’s responseXML property. With the XML document stored in our local variable xmlDoc, we are able to obtain the RSS title information for the feed. To do this, we reference the title element tag and reference the first child node’s value.

We obtain the item elements and prepare to loop through the resulting array stored in xRows. By looping through the array, we are able to create a multidimensional array, storing it in the next position of our global array, arrayMessage. The global array holds the title of the RSS feed and the title, link, and description of the article. We build this multidimensional array for every item element stored in xRows. After we’ve finished traversing the document, we call the function UpdateStatus() (listing 13.9) to display the current state of the process to the user.

Listing 13.9 Function informing user of preloading functionality

function UpdateStatus(){ intLoadFile++;

if(intLoadFile < arrayRSSFeeds.length){ document.getElementById("divNews2").innerHTML =

"Loaded File " + intLoadFile + " of " + arrayRSSFeeds.length + strErrors;

}else if(intLoadFile >= arrayRSSFeeds.length && !bLoadedOnce){ document.getElementById("divNews2").innerHTML =

"Loading Completed" + strErrors; if(arrayMessage.length == 0){

alert("No RSS information was collected."); return false;

}

bLoadedOnce = true;

var timerX = setTimeout("ChangeView()",1500);

}

}

The function UpdateStatus() performs two services, as shown in listing 13.9. The first service displays the status of the preloader to the user. The second service determines if the slideshow has to be started. We first increment our global

Loading the RSS feeds

523

 

 

variable intLoadFile to update the file count. If intLoadFile is less than the total files we are to load, we display our loading status by setting the innerHTML of our top layer divNews2 with our output string.

If the file count is greater than or equal to the number of files in our array (and also the slideshow has not been started), then we can start the transitions. Before we can start the slideshow, we need to verify that we actually have data to show. We verify the data by checking the length of our formatted message array, arrayMessage. If there are no messages, we notify the user and exit the function by returning false.

If there is data to display, we set bLoadedOnce to true and call the function ChangeView() after a slight pause in time. The slight pause allows the user to read any error messages that we may have encountered. As mentioned previously, if the loader encountered a problem with loading the XML document, it calls our function BuildError() (see listing 13.10).

Listing 13.10 Function to handle the errors generated from the XMLHttpRequest

function BuildError(){

strErrors += "Error:" + "" + "<br/>"; UpdateStatus();

}

BuildError() allows us to display an error to the user. This tells the user that not all of the files were loaded. We just append the error to our global variable strErrors and call our UpdateStatus() function that we just developed to inform the user of the application’s current loading state. We can verify that our preloader works by saving the document and running the web page in our browser (figure 13.8).

When we test the viewer, we should see the status update on the screen. In figure 13.8, the preloader is loading file 2 of 4 and there have been no error messages. When all of the files have loaded, we should see that the files have been loaded successfully and there are no errors in the list. However, there is a JavaScript error indicated in our status bar since we still have not created our function ChangeView(). We’ll do that in the next section, but first we will create the crossbrowser fading transition effect.