JavaScript
  Home arrow JavaScript arrow Page 3 - Distributed Events and the Browser-Server ...
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
JAVASCRIPT

Distributed Events and the Browser-Server Dialogue
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 3
    2006-10-26

    Table of Contents:
  • Distributed Events and the Browser-Server Dialogue
  • Decisions about Distributed Events
  • Real-World Examples of Distributed Events
  • Introducing a watchlist

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Distributed Events and the Browser-Server Dialogue - Real-World Examples of Distributed Events


    (Page 3 of 4 )

     

    ActiveMQ Servlet Adaptor

    ActiveMQ (http://activemq.codehaus.org/) is an open source implementation of Java Messaging Service (JMS) (http://java.sun.com/products/jms/), an official Sun standard for enterprise messaging. As such, it provides a way to pass Java objects and strings between different processes, and includes a publish-subscribe mechanism allowing a process to subscribe for all messages in a particular "topic."

    Normally, the processes run server side, but using a servlet adaptor, ActiveMQ effectively gives the web app, through JavaScript, full ability to send and receive messages.

    MapBuilder

    MapBuilder (http://mapbuilder.sourceforge.net) is a framework for mapping web sites, heavily influenced by MVC. The model holds application data such as current maps, positions, and dimensions. The configuration process wires each model to a number of interested widgets, all of which receive notifications when the model has changed.

    Dojo Events Library

    Dojo (http://dojotoolkit.org/download) is a comprehensive framework aiming to simplify JavaScript development. One thing it does is enhance JavaScript's standard event management. This includes publish-subscribe functionality. You register one or more functions as publishers and one or more functions as subscribers. When a publisher function is called, all of the subscriber functions will also be called.

    LivePage Library

    LivePage (http://twisted.sourceforge.net/TwistedDocs-1.2.0/howto/livepage.html), mentioned in HTTP Streaming (Chapter 6) examples, is a framework based around Distributed Events.

    Code Refactoring: AjaxPatterns Distributed Events Wiki Demo

    The Basic Wiki Demo (http://ajaxify.com/run/wiki) has a single callback function that serves two purposes: to parse the incoming message and to display it to the user. That's okay for a simple application, but what if we want to scale up the display operation by displaying different messages in different ways or performing some action when a single message has changed? It won't be a great surprise that Distributed Events are one way to make the browser script more modular, and this refactoring shows how.

    Refactoring to an event mechanism

    The first refactoring lays the groundwork for a richer message handling by introducing an event mechanism. There are some minor user-interface differences, for coding convenience. For example, instead of a single "synchronize" point, downloading and uploading are split into independent timing mechanisms; there's no more background color change while waiting for a message to upload; and a One-Second Spotlight (Chapter 16) effect now occurs when a message has updated, to compensate for the loss of color change. Also, note that a different version of ajaxCaller is used, which allows a callback object to be specified in addition to a callback function.

    A model object has been introduced to track the state of each message and to play the role of an event manager, notifying listeners of changes. One type of listener receives notification of any new messages. The other type receives notification of updates to a specific message. New message listeners are held in a single array. Update listeners are held in an array of arrays, with all subscribers to a particular message held in an array that's keyed on the message ID:

      newMessageListeners: new Array(),
      messageUpdateListenersById: new Array(),

      addNewMessageListener: function(listener) {
        this.newMessageListeners.push(listener);
      },
      addMessageUpdateListener: function(messageId, listener) {
        var listeners = this.messageUpdateListenersById[messageId];
        listeners.push(listener);
      },

    Notification then works by iterating through the collection of relevant listeners:

      notifyNewMessageListeners: function(newMessage) {
          for (i=0; i<this.newMessageListeners.length; i++) {
            this.newMessageListeners[i](newMessage);
         
    }
      },
      notifyMessageUpdateListeners: function(updatedMessage) {
       
    var listenersToThisMessage =        
          this.messageUpdateListenersById[updatedMessage.id];
        for (i=0; i<listenersToThisMessage.length; i++) {
          listenersToThisMessage[i](updatedMessage);
        }
      }

    How do these events arise? The model object must be started manually and will then peri odically poll the server:

      start: function() {    
        this.requestMessages();
        setInterval(this.requestMessages, DOWNLOAD_INTERVAL);
      }
      ...
      requestMessages: function() {    

        ajaxCaller.getXML("content.php?messages", messageModel.onMessagesLoaded);   },

    As before, the server provides an XML Message (Chapter 9) describing all messages. The model steps through each message in the XML, constructing an equivalent JavaScript object. If the message ID is unknown, the new message listeners are notified, and an array of update listeners is also created for this new message. If the message differs from the cur rent message with the same ID, it's changed, so all the update listeners are notified. Recall that the message update notification is fine-grained: only listeners to a particular message ID are notified; hence the extraction of a message-specific list of listeners.

      onMessagesLoaded: function(xml, callingContext) {
        var incomingMessages = xml.getElementsByTagName("message");    
        for (var messageCount=0; messageCount<incomingMessages.length;
             messageCount++) {
         var messageNode = incomingMessages[messageCount];
         var content = this.getChildValue(messageNode, "content");
         content = (content==null ? "" : unescape(content));
         var incomingMessage = {
          
    id: this.getChildValue(messageNode, "id"),
           lastAuthor: this.getChildValue(messageNode, "lastAuthor"),       
           ranking: this.getChildValue(messageNode, "ranking"),
           content: content
         };
         var currentMessage = this.messagesById[incomingMessage.id];
         if (!currentMessage) {       

           this.messageUpdateListenersById[incomingMessage.id]=new Array();        
           this.notifyNewMessageListeners(incomingMessage);
         } else if (!this.messagesEqual(incomingMessage, currentMessage)) {
           this.notifyMessageUpdateListeners(incomingMessage);
         }
         this.messagesById[incomingMessage.id] = incomingMessage;
        }
      },
      getChildValue: function(parentNode, childName) {
        var childNode = parentNode.getElementsByTagName(childName)[0];
       
    return childNode.firstChild == null ? null : childNode.firstChild.nodeValue;
      },
      messagesEqual: function(message1, message2) {    

        return    message1.lastAuthor == message2.lastAuthor
               && message1.ranking == message2.ranking
               && message1.content == message2.content;
     
    }

    A new messagesDiv object has also been created to encapsulate the message-handling logic. On startup, it subscribes for notification of new messages. For each message, it performs a similar function to what was previously done on each update: it creates all the message information and appends to the page, along with a newly introduced visual effect (cour tesy of Scriptaculous; see http://script.aculo.us).

      start: function() {     
        messageModel.addNewMessageListener(this.onNewMessage);
      },
      ...
      onNewMessage: function(message) {
        var messageArea = document.createElement("textarea");    
        messageArea.className = "messageArea";     messageArea.id = message.id;    
        messageArea.serverMessage = message;     ...
        messageDiv.appendChild(lastAuthor);
        messageDiv.appendChild(messageArea);
        ...
        $("messages").appendChild(messageDiv);     Effect.Appear(messageDiv);
        ...
     
    }

    The messageDiv has another responsibility: it must update the display when a message has updated. Thus, it registers itself as a listener on each message. The easiest way to do this is upon adding each new message:

      onNewMessage: function(message) {
        ...     
        messageModel.addMessageUpdateListener(message.id, function(message) {
         
    var messageDiv = $("messageDiv" + message.id);
          var lastAuthor = messageDiv.childNodes[0];
          var messageArea = messageDiv.childNodes[1];
          if (messageArea.hasFocus) {
           
            return;
          }
          lastAuthor.innerHTML = message.id + "."
           
    + "<em>" + message.lastAuthor + "</em>"+"."
           
    + message.ranking;      
          messageArea.value = message.content;       Effect.Appear(messageDiv);
       
    });
      },

    Compared to the previous version, we're now only redrawing a message when it's actually changed. Using an event mechanism has helped to separate the logic out. Now, it's the messageDiv itself that decides how it will look after a message comes in, which is much more sane than the message-receiving callback making that decision.

    More JavaScript Articles
    More By O'Reilly Media


       · This article is an excerpt from the book "Ajax Design Patterns," published by...
     

    Buy this book now. This article is excerpted from chapter 10 of the book Ajax Design Patterns, written by Michael Mahemoff (O'Reilly, 2006; ISBN: 0596101805). Check it out today at your favorite bookstore. Buy this book now.

    JAVASCRIPT ARTICLES

    - More on JavaScript Array Objects
    - Methods of the DOM Location Object
    - The DOM Location Object Properties
    - Handling Remote Files with JavaScript Click ...
    - Using Click Interceptions with a Database-Dr...
    - Using JavaScript Click Interceptions in an I...
    - Using Click Interceptions with JavaScript
    - QuickSort in Action
    - Quicksort
    - Using Mod_Security to Protect Your Server
    - Detecting and Countering Server Intrusions
    - Securing Your Web Server
    - Building a Secure Web Server
    - Protecting the Server
    - Book Review: Learning the Yahoo! User Interf...


     
    Best Practices for Windows Vista Migration Presentation
    Dell and Microsoft recently held a series of face-to-face seminars entitled, &qu....

     
    Creating a Culture for Code Reuse
    If you oversee development teams you know that like it or not proprietary and ex....

     
    Keys to Web Application Acceleration: Advances in Delivery Systems
    Accelerate Web apps by up to 5x. Ensure significantly faster access to the Web a....

     
    Optimizing Application Monitoring
    Tired of finding out from your customers that you're offline? This white paper e....

     
    Solaris to Solaris Migration -- Migrating applications from Sun SPARC to Dell PowerEdge R900
    This comprehensive Migration Guide reviews the approach that Principled Technolo....

     





    © 2003-2009 by Developer Shed. All rights reserved. DS Cluster 6 hosted by Hostway
    Stay green...Green IT