A word of warning

The code we generated to retrieve templates from the server does come with a caveat. It takes time for the browser to get the template from the client. Sometimes, it may take a second or two, and at times even more.

How do we handle the case where we want to theme something and the template hasn't yet completely loaded?

There are two options:

1. Implement a default local theme that can be used when the server hasn't sent a template back.

2. Use a timer (setTimeout()), callback, or another similar mechanism to delay and give the server time to respond.

In the next chapter, when we look at AJAX in more detail, we will see some additional jQuery functionality that could be used to make the loadTemplate() function more robust. Rewriting that function might eliminate the need for precautions like this. We might also consider rewriting the template feature to use synchronous, rather than asynchronous, requests for templates. However, this could become a performance bottleneck.

Both of these options can be used in conjunction. Here's the sample function that illustrates how we might use both:

var max_wait = 3000; // 3 seconds var attempt = 0; function addNode() { var wait = 200; var node = {

title: "New Node", content: "JavaScript created this node!", nodeUrl: 'http://drupal.org'

if (TplHtml.template.node) {

Drupal.attachBehaviors();

else if (attempt * wait < max_wait) { ++attempt;

setTimeout(addNode, wait); console.log("delaying");

var txt = Drupal.theme('defaultNode', node);

Drupal.attachBehaviors();

This is a variation of the addNode() testing function we looked at before. There are two new variables, max_wait and attempt, which are in a broader scope than the function and will persist across function calls. The first one—max_wait — sets the maximum amount of time that this script will wait for the server to load the template. The second one —attempt — is a counter that will record the number of attempts made to use the template.

These will make more sense in a moment.

The important code is the big if/else-if/else conditional. Here's how it works.

It first checks to see if the TplHtml.template.node template exists. If it does, then we know that the template must have been loaded already. We can then go on and do our theming by using the function we created earlier.

If the template does not exist, we check the else if condition:

else if (attempt * wait < max_wait) { ++attempt;

setTimeout(addNode, wait); console.log("delaying");

Here, we check to make sure that we still have time to check for the template. The wait variable, set early in the addNode() function, is the amount of time between checks. We can multiply attempt and wait to see how long we've been trying to use the template. Of course, the first time this is run, it will be 0. We haven't delayed at all as of now.

Using this method, we can account for cases when the remote server is unavailable. If the server takes too long to respond, a default template is I used. One drawback of using a callback (an alternative to this method) is I that there is no way to gracefully handle server failures.

If we make it to the inside of the else if condition, we know that the template isn't loaded and we still have time to wait for it to be loaded. So here's what we do:

• Increment the attempt counter: ++attempt.

• Register a timeout function (setTimeout(addNode, wait)). This tells the JavaScript runtime to wait for wait milliseconds (200 in our case) and then call the addNode() method. Essentially, this function is registering itself as the callback.

• For debugging purposes (this is a test function, after all), we are logging this to the Firebug console so we can tell that it is in a waiting state.

If this condition takes effect, the application will wait before trying to theme and display the content.

However, if the server hasn't retrieved our template by max_wait, then the else block of the conditional will be executed. In this case, a different theming function will be called:

var txt = Drupal.theme(,defaultNode', node);

This fictional theme (we haven't written a function for it) would hold a default theme implementation for a node theme. This would be an implementation that doesn't rely on a template retrieved from the server.

The example here illustrates one way of working around timing issues with our AJAX-based template system.

At this point we have finished our last project, and also the chapter.

The focus of this chapter was on the JavaScript theming system. We began by looking at the tools included in the drupal.js library. We then moved on and built our own themes. From there, we looked at the JavaScript theming module, examining some of the themes and user interface tools that it provides. Finally, we implemented our own template system, which was based on HTML, CSS, and JavaScript.

This chapter rounds out our look at drupal.js. In the remaining chapters of the book, we will make frequent use of the features we covered in this, and the previous two chapters. The next chapter will cover AJAX using jQuery and Drupal. There, we will see how much we can gain by adding more client-server interaction to our scripts.

» If we expect long delays and need to notify the user, we may use a throbber as a visual device to indicate the waiting state. We will discuss this in Chapter 8.

0 0

Post a comment