Understanding the Structure of a jQuery Script

Some mainstream languages (which shall go unnamed) contain a monolithic “standard library,” which really isn’t so standard. Rather than using a standard library with a common denominator set of tools, several additional modules are added. This results in unnecessarily large downloads, wasted resources, and functionality that you may never use. On the other hand, the creators of jQuery very thoughtfully kept out these kinds of “add on” modules, and kept the jQuery core small and compact. It is, however, extensible through the plugin system, which is covered in Chapter 12.

The jQuery core function, sometimes also referred to as a factory object, is referenced as either jQuery() or, more commonly, by its alias $(). If you recall from the JavaScript primer, this is a completely valid name for a variable. In this case, the variable has the type of “function.” This function accepts either a selector string, a string of raw HTML, a DOM element, an existing jQuery object, or no argument at all. The function returns a jQuery object which also has several methods attached to it, for example, $.ajax() or $.each(). More on these later.

Typically, your scripts will follow the pattern shown in the following code snippet. Remember to include the jQuery JavaScript file before any other dependent code.

<!DOCTYPE html>

<html>

<head>

<script src=”jquery.js”></script>

<script >

… jquery code here

</script>

</head>

<body>

<!–

tags here, no embedded javascript here

–>

</body>

</html>

The doctype declaration, as always, is placed at the beginning of the HTML file, even before the html tag, to indicate the document definition type (DTD). In this book, you will always use the HTML 5 doctype, which is very simply:

<!DOCTYPE html>

Most of the time when you use jQuery, you’ll follow the pattern of selecting a DOM element, or set of DOM elements, performing some operation or manipulation on the selected element(s). Select and manipulate, rinse and repeat. The basic call to jQuery is

$(selector);

where selector is a string-enclosed expression for matching DOM elements. The selector format is the same used with CSS, so you can carry over your existing knowledge of CSS to jQuery. For example, # matches elements by their id attribute and . matches by CSS classes. For example, to get a div with the ID feed use the following:

$(“div#feed”);

The next chapter covers selectors in-depth.

When using the jQuery object to either select elements or create new elements, it returns what’s known as a wrapper object. It’s called a wrapper object because you “wrap” jQuery functionality around a collection of DOM elements. A wrapper object is array-like, meaning you can index it with square brackets or check the number of elements using its .length property. I’ll use the .length property often to verify that a selector matched a set of elements. It’s easy to check out the .length property of a jQuery wrapper using the Firebug console.

When you call a jQuery method, such as .addClass(), it applies the method to all of the selected elements. There’s no need to iterate over the collection with a loop.

We’ve mentioned that the jQuery object contains several methods. Table 3-1 shows a sampling of just some of them.

jQuery is eco-friendly; it doesn’t pollute the namespace with globals except for jQuery and $. Although the $ alias might be used in other libraries, it’s highly unlikely that any other library uses jQuery as a variable.

1. Utility Functions

If you recall, functions are also objects. Hence, a function may have properties and its own methods. The jQuery object has several useful methods conveniently called utility methods. Methods exist for enhancing operations for arrays, objects, functions, and even data manipulation.

1.1. Objects

The plain-old JavaScript way of checking the type of an object is using the typeof()operator , which is sometimes inconsistent. In some instances typeof() returns an incorrect or unexpected value. Take for example typeof(null) — it returns object instead of null. Luckily, jQuery has a custom .type() method for these situations:

$.type(null); // returns null

$.type([]); // returns array

The .isEmptyObject() method is used to test whether an object contains any properties, including inherited properties, independent of object type:

$.isEmptyObject(“”); // returns true

$.isEmptyObject({}); // returns true

var mailman = {}; mailman.letters = 100;

$.isEmptyObject(mailman); // returns false

There’s a similar .isPlainObject() method. It also tests whether an object contains any properties, but must be of an Object instance. So an empty string will return false in this case:

$.isPlainObject(“”); // false

$.isPlainObject({}); // true

$.isPlainObject(new Object); // true

You mention, “OK, that’s great, but what else can I do with objects?” Glad you asked. You can also merge two or more objects with the .extend() method. More specifically, .extend() combines the properties of one or more objects into a target object. In the next example, objl receives the properties of obj2 and obj3:

var   objl = {“1″:”property 1”};

var   obj2 = {“2″:”property 2”};

var   obj3 = {“3″:”property 3”};

$.extend(obj1, obj2, obj3);

console.log(obj1[“3”]); // displays property 3

An interesting note about .extend() is that you can use it to clone JavaScript objects (this is different from the $.clone() method):

var clonedObject = $.extend({}, anObject);

$.extend() accepts an additional first argument for doing a deep merge of objects, in other words, a recursive copy. You can also use this to do a deep clone of objects as well:

var clonedObject = $.extend(true, {}, anObject);

1.2. Functions

jQuery has two utility methods for functions: .isFunction() and .noop(). As its name implies, .isFunction() tests whether an object is also a function. Make sure not to use parentheses in the function name. In the next example, .isFunction() is passed to itself. Because it is itself a function, it must return true.

$.isFunction({}); // false

$.isFunction($.isFunction); // true

$.isFunction($.isFunction()); // false, because of parenthesis

The .noop() method is a stub function; it doesn’t perform any operation. But, it’s still useful for moments when you’d like to pass an empty function as an argument, e.g., to install a new event that does nothing by default.

1.3. Array Operations

Similar to .isObject() and .isFunction(), you also have an .isArray() at your disposal. Besides checking whether an object is an array, you can turn an array-like object to a true array using .makeArray(). By converting an array-like object to an array, you lose its methods and properties. The following illustrates a simple usage of makeArray which converts a cloned version of jQuery into a standard Array.

// clone jQuery object

var clonedjq = $.extend(true, {}, $);

//returns “object”

$.type(clonedjq);

// convert to JS array

var jqArray = $.makeArray(clonedjq);

// returns “array”

$.type(jqArray);

jQuery also provides an additional convenience method for combining arrays called .merge(), which takes the elements from a second array and appends them to the elements of a first array, preserving the order of the elements of the two arrays:

var spooks = [“wraiths”, “vampires”, “lichs”];

var nums = [1,2,3];

var mergedArrays = $.merge(spooks, nums);

alert(mergedArrays); // displays: wraiths, vampires, lichs, 1, 2, 3

The next two methods are useful for working with the elements of an array. .inArray() checks for the existence of a value (in the array no less) and returns the index of the value if found. If the value isn’t in the array, -1 is returned. The $.unique() removes duplicate elements from an array of DOM elements. This following snippet demonstrates both methods:

<!DOCTYPE html>

<html>

<head>

</head>

<body>

<p></p>

<p></p>

<p></p>

<p class=”duplicate”></p>

<p class=”duplicate”></p>

<p class=”duplicate”></p>

<p></p>

<script

src=”http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js”>

</script>

<script>

$(document).ready(function(){

// select all paragraph elements

var paragraphs = $( “p” );

//returns 7

console.log( paragraphs.length );

//turn it into an array

paragraphs = $.makeArray( paragraphs );

//get elements of class duplicate and immediately convert them to an array

var dupes = $.makeArray($( “.duplicate” ))

//concat them into our paragraphs array

paragraphs = paragraphs.concat( dupes );

//returns 10

console.log( paragraphs.length );

//get rid of the dupes

paragraphs = $.unique( paragraphs );

//returns 7

console.log( paragraphs.length );

var index = $.inArray(“6”, paragraphs);

console.log(index); // returns -1

});

</script>

</body>

</html>

Code snippet is from in-array-and-unique.tx

Using a jQuery tag selector, you get all of the paragraph elements, then using .makeArray() you convert to a plain-old JavaScript array. You then use a jQuery class selector to get all elements of class “duplicate” and add them into our original paragraphs array. With that action, paragraphs now contain duplicate elements. Its total length is 10. Then using .unique() you get the set of paragraph elements without the duplicates. Its total length is now 7. Finally, you check for “6” in the list of paragraphs, which of course returns -1.

You can iterate through an array using an old-fashioned for loop, but as you’ve probably predicted, jQuery has an alternate method called .each(). This will work with objects, array-like objects, and arrays. $.each() is zero-based and accepts two arguments: the collection to iterate over and a callback function. The callback function accepts the arguments: the index currently operated on and the element value. The following code illustrates using $.each() to iterate over the members of a simple array:

<!DOCTYPE html>

<html>

<head>

<script type=”text/javascript” src=”jquery.js”></script>

<script type=”text/javascript”>

$.ready(function(){

var numArray = [1,2,3,4];

$.each(numArray, function(index, value){

value = value * 2;

console.log(“index is:”+index+” new value is:”+value);

});

});

</script>

</head>

<body>

</body>

</html>

Code snippet is from each.txt

The last jQuery utility method for working with arrays you’ll check out is .map(), which has a similar syntax to .each(), accepting an array or array-like object as its first argument and a callback function. The callback function — according to the jQuery docs, is a “. . . function to process each item against” — accepts one of the array elements and its current index.

<!DOCTYPE html>

<html>

<head>

<script type=”text/javascript” src=”jquery.js”></script>

<script type=”text/javascript”>

$.ready(function(){

var numArray = [42,1024,486,109821];

console.log(numArray);

var newArray = $.map(numArray, function(value, index){

return Math.sqrt(value).toFixed(4);

});

//logs [“6.4807”, “32.0000”, “22.0454”, “331.3925”]

console.log(newArray);

});

</script>

</head>

<body>

</body>

</html>

Code snippet is from map.txt

1.4. Data Structures

A queue is a “First In, First Out” data structure, meaning elements are added to the back and removed from the front. In jQuery, you can use $.queue() to maintain a list of functions. The default function queue is fx, the standard effects queue. In the fx context the power of queues is very clear. The following code sample illustrates a simplified animation queue. Our animation div slides up and then, when it’s finished, the next animation in the queue, the fadeln, runs.

$(‘#animation’).slideUp().fadeIn();

The $.queue supports the operations push and pop. To remove all functions from a queue, use .clearQueue(). Using the corresponding method .dequeue() you can remove an item from a queue and execute it. The following code sample shows a simplified example of a manual usage queue and dequeue. A second animation is added to the queue, and then is pulled off the stack and executed with dequeue.

<!DOCTYPE html>

<html>

<head>

<script type=’text/javascript src=’http://code.jquery.com/jquery-1.7.1.js’></script> 

<style type=’text/css’>

#animation {

width:200px;

height:200px;

background:#ccc;

}

</style>

<script type=’text/javascript’>

$.ready (function(){

$(“#animation”).show(“slow”);

$(“#animation”).queue(function () {

$(this).animate({width:’+=400’},1000);

$(this).dequeue();

});

});

</script>

</head>

<body>

<div id =”animation” style=”display:none”></div> </body>

</html>

Code snippet is from queue-and-dequeue.txt

1.5. Strings

There is just one utility method for working with strings: .trim(). JavaScript already contains a powerful mechanism for working with strings via its regular expressions, but its string objects don’t contain a built-in .trim() method. As the following code example illustrates, trimming removes the trailing and leading whitespaces from a string.

var phrase1 = “ 1. Either this wallpaper goes ”;
var phrase2 = “ or I go. ”;

// Last words of Oscar Wilde

var quote = $.trim(phrase1) + ” ” + $.trim(phrase2);

console.log(quote);

//logs 1. Either this wallpaper goes or I go.

2. Data

Ajax is a major part of the modern Web. The ability to wire data from client to server and back again, without a full page refresh, has resulted in a serious usability boon for modern web applications. Two of the most common data exchange formats are XML and JSON (JavaScript Object Notation). jQuery has the ability to parse both formats locally and over a URL with the .parseXML() and .parseJSON() methods. You learn about those later when you explore Ajax.

Arbitrary data can be attached to HTML element storage/retrieval. The utility method .data() is used for this purpose. .data() will be covered in detail in Chapter 6.

3. Other Useful Utility Methods

These last few utility methods don’t fit into any of the other categories: .contains(), .isWindow(), .isXMLDoc(), .now(), .support(), and .globalEval(). This section tackles each one.

3.1. Checking for Subnodes

The method .contains() checks to see if a DOM node is a child, or subnode, of another node. It expects two arguments — the possible container and the contained node:

$.contains($(“head”)[0], $(“title”)[0]); //

The jQuery wrapper is array-like, so to get the reference to the actual element, you’ll need to use the square brackets to retrieve the element references. The title tag is always a child of the head tag, and hence returns true.

3.2. Checking for Windows

Consider the situation were you have an iframe. In one of your operations you may want to distinguish between that iframe and the browser window. To do this use the .isWindow() method:

<!DOCTYPE html>

<html>

 <head>

<script type=”text/javascript” src=”jquery.js”></script>

<script type=”text/javascript”>

$.ready(function(){

var inlineFrame = $(“#frame”)[0];

$.isWindow(inlineFrame); // returns false

$.isWindow(window);  // returns true

});

</script>

</head>

<body>

<iframe id=”frame” src=”externalPage.html”></iframe>

</body>

</html>

3.3. Determining the Current Time

For checking the current time, use the $.now() shortcut, as its name implies. It’s a shortcut for (new Date).getTime(), and obviously it’s much easier to just write $.now().

3.4. Detecting Browser Features

You’ve probably heard that it’s better to detect browser features rather than detect browsers. Using the .support() method you can detect what features a browser supports. This function deprecates $.browser from earlier versions of jQuery. A good example of its use: if ($.support.ajax) { } to check if a browser supports Ajax requests (aka XMLHttpRequest object creation).

3.5. Evaluation in the Global Context

The last utility method we’ll look at is .globalEval(). You may recall the eval() expression, used to execute arbitrary JavaScript code:

// create a variable x, and initialize it to 0 after all DOM elements are loaded

$(function(){

eval(“var x = 0;”);

});

The execution context of eval is not global, but rather local. You may want the execution context for statements you’re evaluating to exist globally, for example when loading external JavaScript files. This is where .globalEval() comes into play:

// now in global context

$(function(){

$.globalEval(“var x = 0;”);

});

Table 3-2 summarizes all of the utility methods discussed.

Source: Otero Cesar, Rob Larsen (2012), Professional jQuery, John Wiley & Sons, Inc

Leave a Reply

Your email address will not be published. Required fields are marked *