Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
jQuery Design Patterns
jQuery Design Patterns

jQuery Design Patterns: Write Elegant, Structured and Efficient jQuery

eBook
$9.99 $35.99
Paperback
$43.99
Subscription
Free Trial
Renews at $19.99p/m

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Table of content icon View table of contents Preview book icon Preview Book

jQuery Design Patterns

Chapter 1. A Refresher on jQuery and the Composite Pattern

Until the Web 2.0 era started, the Web was just a document-based media and all it offered was just interconnecting different pages/documents and client-side scripting that was mostly limited to form validation. By 2005, Gmail and Google Maps were released, and JavaScript proved itself as a language used by big enterprises to create large-scale applications and provide rich user interface interactions.

Even though JavaScript has had very few changes since its original release, there was a tremendous change in the expectations that the Enterprise world had about what web pages should be capable of doing. Since then, web developers were required to deliver complex user interactions and, finally, the term "web application" appeared on the market. As a result, it started to become obvious that they should create some code abstractions, define some best practices, and adopt all the applicable Design Patterns that computer science had to offer. The wide adoption of JavaScript for enterprise-grade applications helped the evolution of the language, which with the EcmaScript2015/EcmaScript6 (ES6) specification was expanded in a way that allowed even more Design Patterns to be easily utilized.

In August 2006, the jQuery library was first released by John Resig at http://jquery.com, as an effort to create a convenient API to locate DOM elements. Since then, it has been an integral part of a web developer's toolkit. jQuery in its core uses several Design Patterns and tries to urge their use to the developer through the methods that it provides. The Composite Pattern is one of them and it is exposed to the developer through the very core jQuery() method, which is used for DOM traversal, one of the highlights of the jQuery library.

In this chapter, we will:

  • Have a refresher on DOM scripting using jQuery
  • Introduce the Composite Pattern
  • See how the Composite Pattern is used by jQuery
  • Discuss the gains offered by jQuery over plain JavaScript DOM manipulations
  • Introduce the Iterator Pattern
  • Use the Iterator Pattern in an example application

jQuery and DOM scripting

By DOM scripting, we refer to any procedure that alters or manipulates the elements of a web page after it has been loaded by the browser. The DOM API is a JavaScript API that was standardized in 1998 and it provides to web developers a collection of methods that allow the manipulation of the DOM tree elements that the browser creates after loading and parsing the web page's HTML code.

Note

For more information on the Document Object Mode (DOM) and its APIs, you can visit https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction.

By utilizing the DOM API in their JavaScript code, web developers can manipulate the DOM's nodes and add new elements or remove existing elements from the page. The primary use case for DOM scripting was initially limited to client-side form validation, but as the years passed and JavaScript gained the trust of the Enterprise world, more complex user interactions started to be implemented.

The initial version of the jQuery library was first released in August 2006 and it tried to ease the way the web developers were traversing and manipulating the DOM tree. One of its main goals was to provide abstractions that resulted in shorter, easier-to-read, and less error-prone code, while also ensuring cross-browser interoperability.

These core principles that jQuery follows are clearly visible in its homepage, where it presents itself as:

...a fast, small, and feature-rich JavaScript library. It makes things like HTML document traversal and manipulation, event handling, animation, and Ajax much simpler with an easy-to-use API that works across a multitude of browsers. With a combination of versatility and extensibility, jQuery has changed the way that millions of people write JavaScript.

The abstracted APIs that jQuery provided from the beginning, and the way that different Design Patterns were orchestrated, led to wide acceptance among the web developers. As a result, the jQuery library is referenced by more than 60% of the most visited websites worldwide, according to several sources such as BuiltWith.com (http://trends.builtwith.com/javascript/jQuery).

Manipulating the DOM using jQuery

To have a refresher on jQuery, we will go through an example web page that does some simple DOM manipulations. In this example, we will load a simply structured page that initially looks like the following figure:

Manipulating the DOM using jQuery

We will use some jQuery code to change the page's content and layout and, in order to make its effects clearly visible, we will set it to run about 700 milliseconds after the page has loaded. The result of our manipulations will look like the following figure:

Manipulating the DOM using jQuery

Now let's review the HTML code required for the preceding example:

<!DOCTYPE html> 
<html> 
  <head> 
    <title>DOM Manipulations</title> 
    <link rel="stylesheet" type="text/css" href="dom-manipulations.css">
  </head> 
  <body> 
    <h1 id="pageHeader">DOM Manipulations</h1> 

    <div class="boxContainer"> 
      <div> 
        <p class="box"> 
          Doing DOM Manipulations is easy with JS! 
        </p> 
      </div> 
      <div> 
        <p class="box"> 
          Doing DOM Manipulations is easy with JS! 
        </p> 
      </div> 
      <div> 
        <p class="box"> 
          Doing DOM Manipulations is easy with JS! 
        </p> 
      </div> 
    </div> 

    <p class="box"> 
      Doing DOM Manipulations is easy with JS! 
    </p> 
    <p class="box"> 
      Doing DOM Manipulations is easy with JS! 
    </p>

    <script type="text/javascript" src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
    <script type="text/javascript" src="jquery-dom-manipulations.js"></script>
  </body>
</html>

The CSS code used is quite simple, containing only three CSS classes as follows:

.box {
    padding: 7px 10px;
    border: solid 1px #333;
    margin: 5px 3px;
    box-shadow: 0 1px 2px #777;
}

.boxsizer {
    float: left;
    width: 33.33%;
}

.clear { clear: both; }

The preceding code results in a page looking like the first figure when opened in a browser and before our JavaScript code is executed. In the preceding CSS code, we first defined some basic styles for the box, boxsizer, and clear CSS classes. The box class styles the associated elements found in the page by using some padding, a thin border, some margin around, and a small shadow below the elements in order to make them look like a box. The boxsizer class will make the elements that use it to take just 1/3rd of the width of their parent element and create a three-column layout. Finally, the clear class will be used on an element as a break point for the column layout so that all the elements that follow will be positioned below it. The boxsizer and clear classes are not initially used by any element defined in the HTML code, but will be used after the DOM manipulations that we will do in JavaScript.

In the <body> element of our HTML, we initially define an <h1> heading element with ID pageHeader so that it is easily selectable through JavaScript. Right below it, we define five paragraph elements (<p>) with the box class, having the first three of them wrapped inside the three <div> elements and then inside another <div> element with the boxContainer class.

Reaching our two <script> tags, we first include a reference to the jQuery library from jQuery CDN. For more information, you can visit http://code.jquery.com/. In the second <script> tag, we reference the JavaScript file with the required code, for this example, which looks as follows:

setTimeout(function() {
    $('#pageHeader').css('font-size', '3em');

    var $boxes = $('.boxContainer .box');
    $boxes.append(
      '<br /><br /><i>In case we need simple things</i>.');
    $boxes.parent().addClass('boxsizer');

    $('.boxContainer').append('<div class="clear">');
}, 700);

All our code is wrapped inside a setTimeout call to delay its execution, according to the use case described earlier. The first parameter of the setTimeout function call is an anonymous function that will be executed after a timer of 700 milliseconds has expired, as defined in the second argument.

At the first line of our anonymous callback function, we use the jQuery $() function to traverse the DOM and locate the element with the ID pageHeader, and use the css() method to increase its font-size to 3em. Next we provide a more complex CSS selector to the $() function, to locate all the elements with the box class that are descendants of the element with the boxContainer class, and then store the result in a variable named $boxes.

Tip

Variable naming conventions

It is a common practice among developers to use naming conventions for variables that hold objects of a certain type. Using such conventions not only helps you remember what the variable is holding, but also makes your code easier to understand by other developers of your team. Among jQuery developers, it is common to use variable names starting with a "$" sign when the variable stores the result of the $() function (also know as a jQuery collection object).

After we get a hold of the box elements that we are interested in, we append two breaking spaces and some extra text in italics, at the end of each of them. Then, we use the $boxes variable and traverse the DOM tree one level up, using the parent() method. The parent() method returns a different jQuery object holding the parent <div> elements of our initially selected boxes and then we chain a call to the addClass() method to assign them the boxsizer CSS class.

Tip

If you need to traverse all the parent nodes of a selected element, you can use the $.fn.parents() method. If you just need to find the first ancestor element that matches a given CSS selector, consider using the $.fn.closest() method instead.

Finally, since the boxsizer class uses floats to achieve the three-column layout, we need to clear the floats in the boxContainer. Once again, we traverse the DOM using the simple .boxContainer CSS selector and the $() function. Then, we call the .append() method to create a new <div> element with the .clear CSS class and insert it at the end of the boxContainer.

After 700 milliseconds, our jQuery code will have finished, resulting in the three-column layout as shown earlier. In its final state, the HTML code of our boxContainer element will look as follows:

<div class="boxContainer"> 
  <div class="boxsizer"> 
    <p class="box"> 
      Doing DOM Manipulations is easy with JS! 
      <br><br><i>In case we need simple things</i>. 
    </p> 
  </div> 
  <div class="boxsizer"> 
    <p class="box"> 
      Doing DOM Manipulations is easy with JS! 
      <br><br><i>In case we need simple things</i>. 
    </p> 
  </div> 
  <div class="boxsizer"> 
    <p class="box"> 
      Doing DOM Manipulations is easy with JS! 
      <br><br><i>In case we need simple things</i>. 
    </p> 
  </div> 
  <div class="clear"></div> 
</div> 

Method Chaining and Fluent Interfaces

Actually, in the preceding example, we can also go one step further and combine all three box-related code statements into just one, which looks something as follows:

$('.boxContainer .box') 
  .append('<br /><br /><i>In case we need simple things</i>.') 
  .parent() 
  .addClass('boxsizer');

This Syntax Pattern is called Method Chaining and it is highly recommended by jQuery and the JavaScript community in general. Method Chaining is part of the Object Oriented Implementation Pattern of Fluent Interfaces where each method relays its instruction context to the subsequent one.

Most jQuery methods that apply on a jQuery object also return the same or a new jQuery element collection object. This allows us to chain several methods, not only resulting in a more readable and expressive code but also reducing the required variable declarations.

The Composite Pattern

The key concept of the Composite Pattern is to enable us to treat a collection of objects in the same way as we treat a single object instance. Manipulating a composition by using a method on the collection will result in applying the manipulation to each part of it. Such methods can be applied successfully, regardless of the number of elements that are part of the composite collection, or even when the collection contains no elements.

Also, the objects of a composite collection do not necessarily have to provide the exact same methods. The Composite Object can either expose only the methods that are common among the objects of the collection, or can provide an abstracted API and appropriately handle the method differentiations of each object.

Let's continue by exploring how the intuitive API that jQuery exposes is highly influenced from the Composite Pattern.

How the Composite Pattern is used by jQuery

The Composite Pattern is an integral part of jQuery's architecture and is applied from the very core $() function itself. Each call to the $() function creates and returns an element collection object, which is often simply referred as a jQuery object. This is exactly where we see the first principle of the Composite Patterns; in fact, instead of returning a single element, the $() function returns a collection of elements.

The jQuery object returned is an Array-like object that acts as a wrapper object and carries the collection of the retrieved elements. It also exposes a number of extra properties as follows:

  • The length of the retrieved element collection
  • The context that the object was constructed
  • The CSS selector that was used on the $() function call
  • A prevObject property in case we need to access the previous element collection after chaining a method call

Tip

Simple Array-like object definition

An Array-like object is a JavaScript object { } that has a numeric length property and the respective number of properties, with sequential numeric property names. In other words, an Array-like object that has the length == 2 property is expected to also have two properties defined, "0" and "1". Given the above properties, Array-like objects allow you to access their content using simple for loops, by utilizing JavaScript's Bracket Property Accessor's syntax:

for (var i = 0; i < obj.length; i++) { 
  console.log(obj[i]); 
}

We can easily experiment with the jQuery objects returned from the $() function and inspect the properties described above, by using the developer tools of our favorite browser. To open the developer tools on most of them, we just need to press F12 on Windows and Linux or Cmd + Opt + I on Mac, and right after that, we can issue some $() calls in the console and click on the returned objects to inspect their properties.

In the following figure, we can see what the result of the $('#pageHeader') call, which we used in the example earlier, looks like in Firefox Developer Tools:

How the Composite Pattern is used by jQuery

The result of the $('.boxContainer .box') call looks as follows:

How the Composite Pattern is used by jQuery

The fact that jQuery uses Array-like objects as a wrapper for the returned elements allows it to expose some extra methods that apply on the collection returned. This is achieved through prototypical inheritance of the jQuery.fn object, resulting in each jQuery object also having access to all the methods that jQuery provides. This completes the Composite Pattern, which provides methods that, when applied to a collection, are appropriately applied to each of its members. Because jQuery uses Array-like objects with prototypical inheritance, these methods can be easily accessed as properties on each jQuery object, as shown in the example in the beginning of the chapter: $('#pageHeader').css('font-size', '3em');. Moreover, jQuery adds some extra goodies to its DOM manipulating code, following the goal of smaller and less error-prone code. For example, when using the jQuery.fn.html() method to change the inner HTML of a DOM node that already contains child elements, jQuery first tries to remove any data and event handlers that are associated with the child elements, before removing them from the page and appending the provided HTML code.

Let's take a look at how jQuery implements these collection-applicable methods. For this task, we can either download and view the source code from the GitHub page of jQuery (https://github.com/jquery/jquery/releases), or we can use a tool such as the jQuery Source Viewer that is available at http://james.padolsey.com/jquery.

Note

Depending on the version you are using, you might get different results to some degree. The most recent stable jQuery version that was released and used as a reference while writing this book, was v2.2.0.

One of the simplest methods to demonstrate how methods that apply to collections are implemented, is jQuery.fn.empty(). You can easily locate its implementation in jQuery's source code by searching for "empty:" or using the jQuery Source Viewer and searching for "jQuery.fn.empty". Using either one of the ways will bring us to the following code:

empty: function() { 
  var elem, i = 0; 

  for ( ; ( elem = this[ i ] ) != null; i++ ) {
    if ( elem.nodeType === 1 ) { 
      // Prevent memory leaks 
      jQuery.cleanData( getAll( elem, false ) ); 

      // Remove any remaining nodes 
      elem.textContent = ""; 
    } 
  } 

  return this; 
}

As you can see, the code is not complex at all. jQuery iterates over all the items of the collection object (referred to as this since we are inside the method implementation) by using a plain for loop. For each item of the collection, that is, an Element Node, it clears any data-* property values using the jQuery.cleanData() helper function, and right after this, it clears its content by setting it to an empty string.

Note

For more information on the different specified Node Types, you can visit https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType.

Comparing the benefits over the plain DOM API

To clearly demonstrate the benefits that the Composite Pattern provides, we will rewrite our initial example without the abstractions that jQuery offers. By using just plain JavaScript and the DOM API, we can write an equivalent code that looks as follows:

setTimeout(function() { 
  var headerElement = document.getElementById('pageHeader'); 
  if (headerElement) { 
    headerElement.style.fontSize = '3em'; 
  } 
  var boxContainerElement = document.getElementsByClassName('boxContainer')[0]; 
  if (boxContainerElement) { 
    var innerBoxElements = boxContainerElement.getElementsByClassName('box'); 
    for (var i = 0; i < innerBoxElements.length; i++) { 
      var boxElement = innerBoxElements[i]; 
      boxElement.innerHTML +='<br /><br /><i>In case we need simple things</i>.'; 
      boxElement.parentNode.className += ' boxsizer'; 
    } 
    var clearFloatDiv = document.createElement('div'); 
    clearFloatDiv.className = 'clear'; 
    boxContainerElement.appendChild(clearFloatDiv); 
  } 
}, 700);

Once again, we use setTimeout with an anonymous function and set 700 milliseconds as the second parameter. Inside the function itself, we use document.getElementById to retrieve elements that are known to have a unique ID in the page, and later document.getElementsByClassName when we need to retrieve all the elements that have a specific class. We also use boxContainerElement.getElementsByClassName('box') to retrieve all the elements with the box class that are descendants of the element with the boxContainer class.

The most obvious observation is that, in this case, we needed 18 lines of code in order to achieve the same results. For comparison, when using jQuery, we only needed 9 lines of code, that's half the number of lines of code compared to the later implementation. Using the jQuery $() function with a CSS selector was an easier way to retrieve the elements that we needed, and it also ensures compatibility with browsers that do not support the getElementsByClassName() method. However, there are more benefits than just the code line count and the improved readability. As an implementer of the Composite Pattern, the $() function always retrieves element collections, making our code more uniform when compared to the differentiated handling of each getElement* method we used. We use the $() function in exactly the same way, regardless of whether we just want to retrieve an element with a unique ID or a number of elements with a specific class.

As an extra benefit of returning Array-like objects, jQuery can also provide more convenient methods to traverse and manipulate the DOM, such as those we saw in our first example, .css(), .append() and .parent(), which are accessible as properties of the returned object. Additionally, jQuery also offers methods that abstract more complex use cases such as .addClass() and .wrap() that have no equivalent methods available as part of the DOM API.

Since the returned jQuery collection objects do not differ in anything other than the elements they wrap, we can use any method of the jQuery API in the same way. As we saw earlier, these methods apply to each element of the retrieved collection, regardless of the element count. As a result, we do not need a separate for loop to iterate over each retrieved element and apply our manipulations individually; instead, we apply our manipulations (for example, .addClass()) directly to the collection object.

To continue providing the same execution safety guaranties in the later example, we also need to add some extra if statements to check for null values. This is required because, for example, if the headerElement is not found, an error will occur and the rest of the lines of code will never be executed. Someone could argue that these checks, such as if (headerElement) and if (boxContainerElement), are not required in this example and can be omitted. This might appear to be correct in this example, but actually this is among the top reasons for errors while developing large-scale applications, where elements are created, inserted, and removed from the DOM tree continuously. Unfortunately, programmers in all languages and target platforms tend to first write their implementation logic and fill such checks at a later time, often after they get an error when testing their implementation.

Following the Composite Pattern, even an empty jQuery collection object (one that contains no retrieved elements) is still a valid collection object, where we can safely apply any method that jQuery provides. As a result, we do not need the extra if statements to check whether a collection actually contains any element before applying a method such as .css(), just for the sake of avoiding a JavaScript runtime error.

Overall, the abstractions that jQuery offers by using the Composite Pattern lead to fewer lines of code, which is more readable, uniform, and with fewer typo-prone lines (compare typing $('#elementID') versus document.getElementById('elementID')).

Using the Composite Pattern to develop applications

Now that we have seen how jQuery uses the Composite Pattern in its architecture and also did a comparison on the benefits it provided, let's try to write an example use case of our own. We will try to cover all concepts that we have seen earlier in this chapter. We will structure our Composite to be an Array-like object, operate on totally different structured objects, provide a Fluent API to allow chaining, and have methods that apply on all the items of the collection.

A sample use case

Let's say that we have an application that at some point needs to perform operations on numbers. On the other hand, the items that it needs to operate on come from different sources and are not uniform at all. To make this example interesting, let's suppose that one source of data provides plain numbers and another one provides objects with a specific property that holds the number we are interested in:

var numberValues = [2, 5, 8]; 

var objectsWithValues = [ 
    { value: 7 }, 
    { value: 4 }, 
    { value: 6 }, 
    { value: 9 } 
];

The objects returned by the second source of our use case could have a more complex structure and probably some extra properties. Such changes wouldn't differentiate our example implementation in any way, since when developing a Composite we are only interested in providing a uniform handling over the common parts between the targeted items.

The Composite Collection Implementation

Let's proceed and define the Constructor Function and the prototype that will describe our Composite Collection Object:

function ValuesComposite() { 
    this.length = 0; 
} 

ValuesComposite.prototype.append = function(item) { 
    if ((typeof item === 'object' && 'value' in item) || 
        typeof item === 'number') { 
        this[this.length] = item; 
        this.length++; 
    } 

    return this; 
}; 

ValuesComposite.prototype.increment = function(number) { 
    for (var i = 0; i < this.length; i++) { 
        var item = this[i]; 
        if (typeof item === 'object' && 'value' in item) { 
            item.value += number; 
        } else if (typeof item === 'number') { 
            this[i] += number; 
        } 
    } 

    return this; 
}; 

ValuesComposite.prototype.getValues = function() { 
    var result = []; 
    for (var i = 0; i < this.length; i++) { 
        var item = this[i]; 
        if (typeof item === 'object' && 'value' in item) { 
            result.push(item.value); 
        } else if (typeof item === 'number') { 
            result.push(item); 
        } 
    } 
    return result; 
};

The ValuesComposite() constructor function in our example is quite simple. When invoked with the new operator, it returns an empty object with a length property equal to zero, representing that the collection it wraps is empty.

Note

For more information on the Prototype-based programming model of JavaScript, visit https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript.

We first need to define a way that will enable us to populate our composite collection objects. We defined the append method that checks whether the provided parameter is one of the types that it can handle; in this case, it appends the parameter on the Composite Object on the next available numeric property and increments the length property value. For example, the first appended item, whether it is an object with a value property or a plain number, will be exposed to the "0" property of the Composite Object and will be accessible with the Bracket Property Accessor's syntax as myValuesComposition[0].

The increment method is presented as a simple example method that can manipulate such collections by operating over all the collection items. It accepts a numeric value as a parameter and then appropriately handles it by adding it to each item of our collection, based on their type. Since our composite is an Array-like object, increment uses a for loop to iterate over all the collection items and either increases the item.value (in case the item is an object) or the actual numeric value stored (when the collection item stored is a number). In the same manner, we can continue and implement other methods that will, for example, enable us to multiply the collection items with a specific number.

In order to allow chaining the methods of our Composite Object, all the methods of the prototype need to return a reference to the instance of the object. We achieve this goal by simply adding a return this; statement as the last line for all the methods that manipulate the collection, such as append and increment. Keep in mind that methods such as getValues that do not manipulate the collection but are used to return a result, by definition, can't be chained to relay the collection object instance to subsequent method calls.

Finally, we implement the getValues method as a convenient way to retrieve the actual numeric values of all the items in our collection. Similar to the increment method, the getValues method abstracts away the handling between the different item types of our collection. It iterates over the collection items, extracts each numeric value, and appends them to a result array that it returns to its caller.

An example execution

Let's now see an actual example that will use the Composite Object we just implemented:

var valuesComposition = new ValuesComposite(); 

for (var i = 0; i < numberValues.length; i++) { 
    valuesComposition.append(numberValues[i]); 
} 

for (var i = 0; i < objectsWithValues.length; i++) { 
    valuesComposition.append(objectsWithValues[i]); 
}

valuesComposition.increment(2) 
    .append(1) 
    .append(2) 
    .append({ value: 3 }); 

console.log(valuesComposition.getValues()); 

When the preceding code is executed in a browser, by writing the code either in an existing page or directly in the browser's console, it will log a result that looks as follows:

► Array [ 4, 7, 10, 9, 6, 8, 11, 1, 2, 3 ]

We are using our data sources such as the numberValues and objectsWithValues variables that were shown earlier. The preceding code iterates over both of them and appends their items to a newly created Composite Object instance. We then proceed by incrementing the values of our composite collection by 2. Right after this, we chain the three item insertions using append, with the first two appending numeric values and the third appending an object with a value property. Finally, we use the getValues method in order to get an array with all the numeric values of our collection and log it in our browser's console.

Alternative implementations

Keep in mind that a Composite does not need to be an Array-like object, but is commonly preferred since JavaScript makes it easy to create such an implementation. Additionally, Array-like implementations also have the benefit of allowing us to iterate over the collection items using a simple for loop.

On the other hand, in case an Array-like object is not preferred, we can easily use a property on the Composite Object to hold our collection items. For example, this property can be named as items and be used to store and access the items of the collection inside our methods using this.items.push(item) and this.items[i], respectively.

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 the Iterator Pattern is used by jQuery

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.

Summary

In this chapter, we had a refresher on JavaScript's DOM Scripting API and jQuery. We were introduced to the Composite Pattern and saw how it is used by the jQuery library. We saw how the Composite Pattern simplifies our workflow after we rewrote our example page without using jQuery, and later showcased an example of using the Composite Pattern in our applications. Finally, we were introduced to the Iterator Pattern and saw how well it pairs when used along with the Composite Pattern.

Now that we have completed our introduction on how the Composite Pattern plays an important role in the way we use jQuery methods every day, we can move on to the next chapter where we will showcase the Observer Pattern and the convenient way to utilize it in our pages using jQuery.

Left arrow icon Right arrow icon

Key benefits

  • Learn about the observer pattern and the deferred observer pattern, two of the most popular design patterns that handle custom events
  • Advance your jQuery skills by learning about patterns such as divide and conquer, facade, and builder and factory to handle complex results
  • This step-by-step guide to applying micro-patterns and optimizing jQuery applications will help you get the best performance in a production environment

Description

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.

Who is this book for?

This book is for existing jQuery Developers or new developers who want to get an understanding of the “correct way” to build jQuery applications, using best practices and industry standard patterns.

What you will learn

  • Respond to user actions
  • Achieve greater flexibility and code decoupling
  • Have a central point for emitting and receiving application level events
  • Structure the application into small independent modules
  • Abstract complex APIs
  • Isolate the procedure of generating complex parts of the application
  • Efficiently orchestrate asynchronous procedures using jQuery Deferred and Promises
  • Utilize the most widely-used client-side templating libraries for more complex use cases
Estimated delivery fee Deliver to Japan

Standard delivery 10 - 13 business days

$8.95

Premium delivery 3 - 6 business days

$34.95
(Includes tracking information)

Product Details

Country selected
Publication date, Length, Edition, Language, ISBN-13
Publication date : Feb 26, 2016
Length: 246 pages
Edition : 1st
Language : English
ISBN-13 : 9781785888687
Tools :

What do you get with Print?

Product feature icon Instant access to your digital eBook copy whilst your Print order is Shipped
Product feature icon Paperback book shipped to your preferred address
Product feature icon Download this book in EPUB and PDF formats
Product feature icon Access this title in our online reader with advanced features
Product feature icon DRM FREE - Read whenever, wherever and however you want
OR
Modal Close icon
Payment Processing...
tick Completed

Shipping Address

Billing Address

Shipping Methods
Estimated delivery fee Deliver to Japan

Standard delivery 10 - 13 business days

$8.95

Premium delivery 3 - 6 business days

$34.95
(Includes tracking information)

Product Details

Publication date : Feb 26, 2016
Length: 246 pages
Edition : 1st
Language : English
ISBN-13 : 9781785888687
Tools :

Packt Subscriptions

See our plans and pricing
Modal Close icon
$19.99 billed monthly
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Simple pricing, no contract
$199.99 billed annually
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts
$279.99 billed in 18 months
Feature tick icon Unlimited access to Packt's library of 7,000+ practical books and videos
Feature tick icon Constantly refreshed with 50+ new titles a month
Feature tick icon Exclusive Early access to books as they're written
Feature tick icon Solve problems while you work with advanced search and reference features
Feature tick icon Offline reading on the mobile app
Feature tick icon Choose a DRM-free eBook or Video every month to keep
Feature tick icon PLUS own as many other DRM-free eBooks or Videos as you like for just $5 each
Feature tick icon Exclusive print discounts

Frequently bought together


Stars icon
Total $ 104.98
jQuery Design Patterns
$43.99
ASP.NET jQuery Cookbook (Second Edition)
$60.99
Total $ 104.98 Stars icon
Banner background image

Table of Contents

12 Chapters
1. A Refresher on jQuery and the Composite Pattern Chevron down icon Chevron up icon
2. The Observer Pattern Chevron down icon Chevron up icon
3. The Publish/Subscribe Pattern Chevron down icon Chevron up icon
4. Divide and Conquer with the Module Pattern Chevron down icon Chevron up icon
5. The Facade Pattern Chevron down icon Chevron up icon
6. The Builder and Factory Patterns Chevron down icon Chevron up icon
7. Asynchronous Control Flow Patterns Chevron down icon Chevron up icon
8. Mock Object Pattern Chevron down icon Chevron up icon
9. Client-side Templating Chevron down icon Chevron up icon
10. Plugin and Widget Development Patterns Chevron down icon Chevron up icon
11. Optimization Patterns Chevron down icon Chevron up icon
Index Chevron down icon Chevron up icon

Customer reviews

Rating distribution
Full star icon Full star icon Full star icon Full star icon Full star icon 5
(5 Ratings)
5 star 100%
4 star 0%
3 star 0%
2 star 0%
1 star 0%
B. S. Oluwa Apr 14, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
Absolutely well written and explains a lot of the patterns used in the industry linked directly to jQuery's implementation. Breaks down key concepts and has a very fluid flow of information with the examples implemented in the book. Nice easy read too. Thanks Thodoris Greasidis.BSO
Amazon Verified review Amazon
Amazon Customer Jul 20, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
After reading the book, i have to confess that i feel much more comfortable when dealing with front-end issues.The author, following a great flow in every single chapter, provides you the way you have to think before startingto develop the front-end part of your web application.Included, you will find "ready-to-run" parts of code which will help you easily endorse the best practices using jQuery.To conclude, i find the book a must-read for every web developer who wants to learn how to set things up the right waywith the power of jQuery.
Amazon Verified review Amazon
Christopher Varakliotis Jun 28, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
This book is a great resource for those looking to deepen their knowledge of jQuery and Javascript.Though the topics covered could be considered fairly advanced, the author does an excellent job explaining how and where the various patterns and techniques can be used, giving practical examples and in many cases going out of his way to shed light on the internals of jQuery, which is great if you are concerned about performance, or just curious about how things such as method overloading are implemented.Best practices for creating jQuery plugins could not be absent from this book, as expected, and are followed again by simple-to-follow examples and boilerplate code.The book does not stop at covering jQuery patterns however: hot topics such as ES6, memory management, DOM manipulation performance & client side templating are also covered.All in all, this a must read for any web developer. It will help you use jQuery in a more effective and productive way, and -given that many of the lessons learned by this book apply to other programming environments as well- become better at the craft of producing code.
Amazon Verified review Amazon
Amazon Customer Jun 27, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
I found this book to be an exceptionally useful tool for the web developers who want to upgrade their jQuery skills.The text covers everything you need to know in design patterns in order to tackle common problems and help you write clean and maintainable code. It is perfect for people with some basic knowledge of jQuery who want to build large scale web applications.The coding examples are extremely useful and concise.
Amazon Verified review Amazon
Amazon Customer Jun 26, 2016
Full star icon Full star icon Full star icon Full star icon Full star icon 5
The contents of the book are very easy to consume and digest, thus focusing in providing suggestions and examples for various considerations and requirements of real world application development. It’s as explanatory as it should be and never made me skip a paragraph.If you are an experienced software developer working on the server side and back-end systems and fan of best practices and design patterns (like me), want to make your web products better by adding some presentation logic and interactivity on the client, the right way, then this book is highly recommended. If you have worked with javascript & jQuery, but want to quickly start writing high quality, well-structured, controllable code without using a more sophisticated javascript framework, then this book will give exactly you what you want and expect.It’s not about jQuery, but rather on how jQuery should be used in the real world of modular, extendable and maintainable application programming. I especially enjoyed references to Asynchronous Control and Plugins designing.I also think that this book should be a first reference to young programmers who opt for front-end development and want to get involved with more advanced frameworks.It certainly made me appreciate frond-end development more than I could expect.
Amazon Verified review Amazon
Get free access to Packt library with over 7500+ books and video courses for 7 days!
Start Free Trial

FAQs

What is the delivery time and cost of print book? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela
What is custom duty/charge? Chevron down icon Chevron up icon

Customs duty are charges levied on goods when they cross international borders. It is a tax that is imposed on imported goods. These duties are charged by special authorities and bodies created by local governments and are meant to protect local industries, economies, and businesses.

Do I have to pay customs charges for the print book order? Chevron down icon Chevron up icon

The orders shipped to the countries that are listed under EU27 will not bear custom charges. They are paid by Packt as part of the order.

List of EU27 countries: www.gov.uk/eu-eea:

A custom duty or localized taxes may be applicable on the shipment and would be charged by the recipient country outside of the EU27 which should be paid by the customer and these duties are not included in the shipping charges been charged on the order.

How do I know my custom duty charges? Chevron down icon Chevron up icon

The amount of duty payable varies greatly depending on the imported goods, the country of origin and several other factors like the total invoice amount or dimensions like weight, and other such criteria applicable in your country.

For example:

  • If you live in Mexico, and the declared value of your ordered items is over $ 50, for you to receive a package, you will have to pay additional import tax of 19% which will be $ 9.50 to the courier service.
  • Whereas if you live in Turkey, and the declared value of your ordered items is over € 22, for you to receive a package, you will have to pay additional import tax of 18% which will be € 3.96 to the courier service.
How can I cancel my order? Chevron down icon Chevron up icon

Cancellation Policy for Published Printed Books:

You can cancel any order within 1 hour of placing the order. Simply contact customercare@packt.com with your order details or payment transaction id. If your order has already started the shipment process, we will do our best to stop it. However, if it is already on the way to you then when you receive it, you can contact us at customercare@packt.com using the returns and refund process.

Please understand that Packt Publishing cannot provide refunds or cancel any order except for the cases described in our Return Policy (i.e. Packt Publishing agrees to replace your printed book because it arrives damaged or material defect in book), Packt Publishing will not accept returns.

What is your returns and refunds policy? Chevron down icon Chevron up icon

Return Policy:

We want you to be happy with your purchase from Packtpub.com. We will not hassle you with returning print books to us. If the print book you receive from us is incorrect, damaged, doesn't work or is unacceptably late, please contact Customer Relations Team on customercare@packt.com with the order number and issue details as explained below:

  1. If you ordered (eBook, Video or Print Book) incorrectly or accidentally, please contact Customer Relations Team on customercare@packt.com within one hour of placing the order and we will replace/refund you the item cost.
  2. Sadly, if your eBook or Video file is faulty or a fault occurs during the eBook or Video being made available to you, i.e. during download then you should contact Customer Relations Team within 14 days of purchase on customercare@packt.com who will be able to resolve this issue for you.
  3. You will have a choice of replacement or refund of the problem items.(damaged, defective or incorrect)
  4. Once Customer Care Team confirms that you will be refunded, you should receive the refund within 10 to 12 working days.
  5. If you are only requesting a refund of one book from a multiple order, then we will refund you the appropriate single item.
  6. Where the items were shipped under a free shipping offer, there will be no shipping costs to refund.

On the off chance your printed book arrives damaged, with book material defect, contact our Customer Relation Team on customercare@packt.com within 14 days of receipt of the book with appropriate evidence of damage and we will work with you to secure a replacement copy, if necessary. Please note that each printed book you order from us is individually made by Packt's professional book-printing partner which is on a print-on-demand basis.

What tax is charged? Chevron down icon Chevron up icon

Currently, no tax is charged on the purchase of any print book (subject to change based on the laws and regulations). A localized VAT fee is charged only to our European and UK customers on eBooks, Video and subscriptions that they buy. GST is charged to Indian customers for eBooks and video purchases.

What payment methods can I use? Chevron down icon Chevron up icon

You can pay with the following card types:

  1. Visa Debit
  2. Visa Credit
  3. MasterCard
  4. PayPal
What is the delivery time and cost of print books? Chevron down icon Chevron up icon

Shipping Details

USA:

'

Economy: Delivery to most addresses in the US within 10-15 business days

Premium: Trackable Delivery to most addresses in the US within 3-8 business days

UK:

Economy: Delivery to most addresses in the U.K. within 7-9 business days.
Shipments are not trackable

Premium: Trackable delivery to most addresses in the U.K. within 3-4 business days!
Add one extra business day for deliveries to Northern Ireland and Scottish Highlands and islands

EU:

Premium: Trackable delivery to most EU destinations within 4-9 business days.

Australia:

Economy: Can deliver to P. O. Boxes and private residences.
Trackable service with delivery to addresses in Australia only.
Delivery time ranges from 7-9 business days for VIC and 8-10 business days for Interstate metro
Delivery time is up to 15 business days for remote areas of WA, NT & QLD.

Premium: Delivery to addresses in Australia only
Trackable delivery to most P. O. Boxes and private residences in Australia within 4-5 days based on the distance to a destination following dispatch.

India:

Premium: Delivery to most Indian addresses within 5-6 business days

Rest of the World:

Premium: Countries in the American continent: Trackable delivery to most countries within 4-7 business days

Asia:

Premium: Delivery to most Asian addresses within 5-9 business days

Disclaimer:
All orders received before 5 PM U.K time would start printing from the next business day. So the estimated delivery times start from the next day as well. Orders received after 5 PM U.K time (in our internal systems) on a business day or anytime on the weekend will begin printing the second to next business day. For example, an order placed at 11 AM today will begin printing tomorrow, whereas an order placed at 9 PM tonight will begin printing the day after tomorrow.


Unfortunately, due to several restrictions, we are unable to ship to the following countries:

  1. Afghanistan
  2. American Samoa
  3. Belarus
  4. Brunei Darussalam
  5. Central African Republic
  6. The Democratic Republic of Congo
  7. Eritrea
  8. Guinea-bissau
  9. Iran
  10. Lebanon
  11. Libiya Arab Jamahriya
  12. Somalia
  13. Sudan
  14. Russian Federation
  15. Syrian Arab Republic
  16. Ukraine
  17. Venezuela