Book Image

jQuery Design Patterns

By : Thodoris Greasidis
Book Image

jQuery Design Patterns

By: Thodoris Greasidis

Overview of this book

jQuery is a feature-rich JavaScript library that makes HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a variety of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript. jQuery solves the problems of DOM manipulation, event detection, AJAX calls, element selection and document queries, element attribute and data management, as well as object management utilities. This book addresses these problems and shows you how to make the best of jQuery through the various design patterns available. The book starts off with a refresher to jQuery and will then take you through the different design patterns such as facade, observer, publisher/subscriber, and so on. We will also go into client-side templating techniques and libraries, as well as some plugin development patterns. Finally, we will look into some best practices that you can use to make the best of jQuery.
Table of Contents (18 chapters)
jQuery Design Patterns
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
Index

The Iterator Pattern


The key concept of the Iterator Pattern is the use of a function with the single responsibility to traverse a collection and provide access to its items. This function is known as the iterator and provides a way to access the items of the collection, without exposing implementation specifics and the underlying data structure used by the collection object.

Iterators provide a level of encapsulation regarding the way the iteration occurs, decoupling the iteration over the items of a collection from the implementation logic of their consumers.

Note

For more information on the Single Responsibility principle, you can visit http://www.oodesign.com/single-responsibility-principle.html.

How the Iterator Pattern is used by jQuery

As we saw earlier in this chapter, the jQuery core $() function returns an Array-like object that wraps a collection of page elements and it also provides an iterator function to traverse it and access each element individually. It actually goes one step further and provides a generic helper method jQuery.each() that can iterate over arrays, Array-like objects, and also object properties.

A more technical description can be found in jQuery API documentation page at http://api.jquery.com/jQuery.each/, where the description of jQuery.each() reads as follows:

A generic iterator function, which can be used to seamlessly iterate over both objects and arrays. Arrays and Array-like objects with a length property (such as a function's arguments object) are iterated by numeric index, from 0 to length-1. Other objects are iterated via their named properties.

The jQuery.each() helper function is used internally in several places of the jQuery source code. One of its uses is iterating over the items of a jQuery object and applying manipulations on each of them, as the Composite Pattern suggests. A simple search for the keyword .each( reveals 56 matches.

Note

As of writing this book, the latest stable version is v2.2.0 and this was used for the above statistics.

We can easily trace its implementation in jQuery's source, either by searching for "each:" (note that there are two occurrences) or using the jQuery Source Viewer and searching for "jQuery.each()" (like we did earlier in this chapter):

each: function( obj, callback ) {
  var length, i = 0;

  if ( isArrayLike( obj ) ) {
    length = obj.length;
    for ( ; i < length; i++ ) {
      if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
        break;
      }
    }
  } else {
    for ( i in obj ) {
      if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
        break;
      }
    }
   }

  return obj;
}

This helper function is also accessible on any jQuery object by using the same prototypical inheritance that we saw earlier for methods such as .append(). You can easily find the code that does exactly this, by searching for "jQuery.fn.each()" in jQuery Source Viewer or directly searching jQuery source code for each: (note that there are two occurrences):

each: function( callback ) {
  return jQuery.each( this, callback );
}

Using the method version of ".each()" enables us to directly iterate over the elements of a jQuery collection object with a more convenient syntax.

The example code that follows showcases how the two flavors of .each() can be used in our code:

// using the helper function on an array
$.each([3, 5, 7], function(index){
    console.log(this + 1);
});
// using the method on a jQuery object
$('.boxContainer .box').each(function(index) {
    console.log('I\'m box #' + (index + 1)); // index is zero-based
});

When executed, the preceding code will log the following on the browser's console:

How it pairs with the Composite Pattern

Since the Composite Pattern encapsulates a collection of items into a single object and the Iterator Pattern can be used to iterate over an abstracted data structure, we can easily characterize these two patterns as complementary.

Where can it be used

The Iterator Pattern can be used in our applications to abstract the way we access items from a data structure. For example, let's suppose we need to retrieve all the items that are greater than 4 from the following tree structure:

var collection = { 
    nodeValue: 7, 
    left: { 
        nodeValue: 4, 
        left: 2, 
        right: { 
            nodeValue: 6, 
            left: 5, 
            right: 9 
        } 
    }, 
    right: { 
        nodeValue: 9, 
        left: 8 
    } 
}; 

Let's now implement our iterator function. Since tree data structures can have nesting, we end up with the following recursive implementation:

function iterateTreeValues(node, callback) { 
    if (node === null || node === undefined) { 
        return; 
    } 

    if (typeof node === 'object') { 
        if ('left' in node) { 
            iterateTreeValues(node.left, callback); 
        } 
        if ('nodeValue' in node) { 
            callback(node.nodeValue); 
        } 
        if ('right' in node) { 
            iterateTreeValues(node.right, callback); 
        } 
    } else { 
        // its a leaf, so the node is the value 
        callback(node); 
    } 
} 

Finally, we end up with an implementation that looks as follows:

var valuesArray = []; 
iterateTreeValues(collection, function(value) { 
    if (value > 4) { 
        valuesArray.push(value); 
    } 
}); 
console.log(valuesArray);

When executed, the preceding code will log the following on the browser's console:

► Array [ 5, 6, 9, 7, 8, 9 ]

We can clearly see that the iterator simplified our code. We no longer bother with the implementation specifics of the data structure used every time we need to access some items that fulfill certain criteria. Our implementation works on top of the generic API that the iterator exposes, and our implementation logic appears in the callback that we provide to the iterator.

This encapsulation allows us to decouple our implementation from the data structure used, given that an iterator with the same API will be available. For instance, in this example, we can easily change the data structure used to a sorted binary tree or a simple array and preserve our implementation logic the same.