jQuery includes a number of utility methods that perform advanced operations on jQuery objects or that supplement the JavaScript language to provide features that are usually present in programming languages. You might never need any of these methods, but they are used internally by jQuery, and making them publicly available means that you can save time and effort when you come across an odd problem that the jQuery team has already solved.
Some of these methods are applied to jQuery objects, and some are called against the main jQuery function, which I have illustrated using the $ notation (described in Chapter 5). Table 33-1 provides the summary for this chapter.
In Chapter 10, I showed you how you could use the jQuery effects queue to manage a chain of effects to apply to a set of elements. In fact, the effects queue is just one queue and the feature is a general-purpose one you can use more widely. Table 33-2 restates the queue-related methods, tweaked for general-purpose use.
When you use these methods without specifying a queue name, jQuery defaults to fx
, which is the queue for visual effects. You can use any other queue name to create a queue of functions.
When applying jQuery queues to general use, you use the clearQueue
method instead of the stop
method. Stop has special support for jQuery effects that are not appropriate for broader use. Listing 33-1 provides an example of using a general-purpose queue.
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<script src="jquery-1.7.js" type="text/javascript"></script>
<link rel="stylesheet" type="text/css" href="styles.css"/>
<script type="text/javascript">
$(document).ready(function() {
var elems = $('input'),
elems.queue("gen", function(next) {
$(this).val(100).css("border", "thin red solid");
next();
});
elems.delay(1000, "gen");
elems.queue("gen", function(next) {
$(this).val(0).css("border", "");
$(this).dequeue("gen");
});
$("<button>Process Queue</button>").appendTo("#buttonDiv")
.click(function(e) {
elems.dequeue("gen");
e.preventDefault();
})
});
</script>
</head>
<body>
<h1>Jacqui's Flower Shop</h1>
<form method="post">
<div id="oblock">
<div class="dtable">
<div id="row1" class="drow">
<div class="dcell">
<img src="astor.png"/><label for="astor">Astor:</label>
<input name="astor" value="0" required />
</div>
<div class="dcell">
<img src="daffodil.png"/><label for="daffodil">Daffodil:</label>
<input name="daffodil" value="0" required />
</div>
<div class="dcell">
<img src="rose.png"/><label for="rose">Rose:</label>
<input name="rose" value="0" required />
</div>
</div>
<div id="row2"class="drow">
<div class="dcell">
<img src="peony.png"/><label for="peony">Peony:</label>
<input name="peony" value="0" required />
</div>
<div class="dcell">
<img src="primula.png"/><label for="primula">Primula:</label>
<input name="primula" value="0" required />
</div>
<div class="dcell">
<img src="snowdrop.png"/><label for="snowdrop">Snowdrop:</label>
<input name="snowdrop" value="0" required />
</div>
</div>
</div>
</div>
<div id="buttonDiv"><button type="submit">Place Order</button></div>
</form>
</body>
</html>
In this example, I add three functions to a queue called gen
that operates on the input
elements in the document. First, I use the val
method to set all of the input values to 100
and the css
method to add a border. Second, I use the delay method to add a 1-second delay to the queue. Finally, I use the val
and css
methods to reset the input
elements to their original state.
I also added a button to the document that calls the dequeue
method. Unlike with the effects queue, you are responsible for starting queue processing yourself. You can see the effect in Figure 33-1.
The functions that you place in the queue work in the same way as for the events queue and, as before, you are responsible for either calling the dequeue
method or invoking the function that is passed as an argument. I tend to use the function argument—just because I often forget to specify the queue name when calling the dequeue
method, which means that my queue grinds to a halt.
Of course, you don't have to trigger one queued function from another. You can rely on an external trigger to dequeue
each item, such as the user pressing the button I added to the document. Listing 33-2 shows how you can do this.
...
<script type="text/javascript">
$(document).ready(function() {
$('input').queue("gen", function() {
$(this).val(100).css("border", "thin red solid");
}).queue("gen", function() {
$(this).val(0).css("border", "");
}).queue("gen", function() {
$(this).css("border", "thin blue solid");
$('#dequeue').attr("disabled", "disabled");
});
$("<button id=dequeue>Dequeue Item</button>").appendTo("#buttonDiv")
.click(function(e) {
$('input').dequeue("gen");
e.preventDefault();
});
});
</script>
...
In this script, I chained the queue
calls together and added a function that sets a border on the selected elements and disables the button
element. You must press the button
to process each item in the queue—here is no automated chaining. You can see the sequence in Figure 33-2.
jQuery provides a number of useful methods for working with arrays. These methods are described in Table 33-3. For the most part, there are better ways of working with HTMLElement
arrays—you can just use the standard jQuery methods for handling and filtering elements. For other kinds of arrays, these methods can be helpful.
The grep
method allows you to find all of the elements in an array that are matched by a filter function. Listing 33-3 provides a demonstration of this method.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
var filteredArray = $.grep(flowerArray, function(elem, index) {
return elem.indexOf("p") > -1;
});
for (var i = 0; i < filteredArray.length; i++) {
console.log("Filtered element: " + filteredArray[i]);
}
});
</script>
...
The filter function is passed two arguments. The first is the element in the array, and the second is the array index of that element. This function is called for each item in the array and you return true
if you want the current item to be included in the filtered results.
In this example, I use the grep
method on an array of strings, filtering out those that don't contain the letter p
. I write the contents of the filtered array to the console, producing the following results:
Filtered element: peony
Filtered element: primula
Filtered element: snowdrop
You can supply an additional argument to the grep
method. If this argument is true
, the filtering process is inverted and the result contains the elements that the function filtered out. Listing 33-4 shows the effect of this argument.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
var filteredArray = $.grep(flowerArray, function(elem, index) {
return elem.indexOf("p") > -1;
}, true);
for (var i = 0; i < filteredArray.length; i++) {
console.log("Filtered element: " + filteredArray[i]);
}
});
</script>
...
This change produces the following results:
Filtered element: astor
Filtered element: daffodil
Filtered element: rose
The inArray
method lets you establish whether an array contains a specified value. The method returns the index of the item if it is in the array and -1
otherwise. Listing 33-5 demonstrates the inArray
method.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
console.log("Array contains rose: " + $.inArray("rose", flowerArray));
console.log("Array contains lily: " + $.inArray("lily", flowerArray));
});
</script>
...
This script checks to see if the array of flowers contains rose
and lily
. The results are as follows:
Array contains rose: 2
Array contains lily: -1
The map
method lets you use a function to project the contents of an array or a map object into a new array, using a function to determine how each item is represented in the result. Listing 33-6 shows the use of the map
method with an array.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
var result = $.map(flowerArray, function(elem, index) {
return index + ": " + elem;
});
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
});
</script>
...
This mapping function is executed for each item in the array and is passed the item and its index in the array as arguments. The result from the function is included in the array returned by the map
method. In this script, I transform each item in the array by concatenating the value with its index, producing the following results:
0: astor
1: daffodil
2: rose
3: peony
4: primula
5: snowdrop
You can use the map
method to selectively project an array. There will be no corresponding item in the result if you don't return a value from the function for the item being processed. Listing 33-7 shows how you can selectively project from an array.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
var result = $.map(flowerArray, function(elem, index) {
if (elem != "rose") {
return index + ": " + elem;
}
});
for (var i = 0; i < result.length; i++) {
console.log(result[i]);
}
});
</script>
...
Results are generated for all of the array values except rose
, which gives rise to the following results:
The merge
method concatenates two arrays, as demonstrated in Listing 33-8.
...
<script type="text/javascript">
$(document).ready(function() {
var flowerArray = ["astor", "daffodil", "rose", "peony", "primula", "snowdrop"];
var additionalFlowers = ["carnation", "lily", "orchid"];
$.merge(flowerArray, additionalFlowers);
for (var i = 0; i < flowerArray.length; i++) {
console.log(flowerArray[i]);
}
});
</script>
...
The items from the second array are appended to the first array, and the array specified by the first argument is modified by the merge process. The script in the example produces the following results:
astor
daffodil
rose
peony
primula
snowdrop
carnation
lily
orchid
The unique
method sorts an array of HTMLElement
objects into the order in which they appear in the document and removes any duplicate elements. Listing 33-9 shows how you can use this method.
...
<script type="text/javascript">
$(document).ready(function() {
var selection = $('img[src*=rose], img[src*=primula]').get();
$.merge(selection, $('img[src*=astor]'));
$.merge(selection, $('img'));
$.unique(selection);
for (var i =0; i < selection.length; i++) {
console.log("Elem: " + selection[i].src);
}
});
</script>
...
The sorting process is done in-place, meaning that the array you pass as the argument to the unique
method is modified. In this example, I created an array of HTMLElement
objects that contain duplicates and that are not in document order, and then I applied the unique
method.
jQuery provides a set of methods that are useful for determining the nature of a JavaScript object. These methods are described in Table 33-4.
Most of these methods are very simple. You pass an object to the method, which returns true
if the object is of the type that the method detects and false
otherwise. As a simple demonstration, Listing 33-10 contains an example using the isFunction
method.
...
<script type="text/javascript">
$(document).ready(function() {
function myFunc() {
console.log("Hello!");
}
console.log("IsFunction: " + $.isFunction(myFunc));
console.log("IsFunction: " + $.isFunction("hello"));
});
</script>
...
In this example, I use the isFunction
method to test two objects. The results are as follows:
IsFunction: true
IsFunction: false
The type
method is slightly different in that it returns the base JavaScript type of an object. The result will be one of the following strings:
boolean
number
string
function
array
date
regexp
object
Listing 33-11 shows the use of the type
method.
...
<script type="text/javascript">
$(document).ready(function() {
function myFunc() {
console.log("Hello!");
}
var jq = $('img'),
var elem = document.getElementById("row1");
console.log("Type: " + $.type(myFunc));
console.log("Type: " + $.type(jq));
console.log("Type: " + $.type(elem));
});
</script>
...
In this script, I use the type method on a function, a jQuery
object, and an HTMLElement
object. The results are as follows:
Type: function
Type: object
Type: object
jQuery defines a number of utility methods that can be useful for working with various kinds of data. These methods are described in Table 33-5.
The serialize
and serializeArray
methods are convenient ways to extract the details from a set of form elements in a way that is useful for regular or Ajax form submissions. Listing 33-12 shows both methods in use.
...
<script type="text/javascript">
$(document).ready(function() {
$("<button>Serialize</button>").appendTo("#buttonDiv").click(function(e) {
var formArray = $('form').serializeArray();
console.log("JSON: " + JSON.stringify(formArray))
var formString = $('form').serialize();
console.log("String: " + formString)
e.preventDefault();
});
});
</script>
...
In this example, I serialize the form elements in the document using both methods and write the results to the console. The serializeArray
method returns a JavaScript array that contains one object for each form element in the document. These objects have two properties: the name
property contains the value of the name
attribute of the element, and the value
property contains the element's value. Here is the output from the example document:
[{"name":"astor","value":"1"},{"name":"daffodil","value":"0"},
{"name":"rose","value":"0"},{"name":"peony","value":"0"},
{"name":"primula","value":"2"},{"name":"snowdrop","value":"0"}]
By contrast, the serialize method creates an encoded string, as follows:
astor=1&daffodil=0&rose=0&peony=0&primula=2&snowdrop=0
The parseJSON
and parseXML
methods are especially useful when dealing with the results of Ajax requests. For most web applications, JSON has taken over as the data format of choice, for the reasons I outlined in Chapter 14. XML is still used, but I find myself using this XML data only when integrating new applications with legacy back-end systems. Listing 33-13 shows the parseJSON
method in use.
...
<script type="text/javascript">
$(document).ready(function() {
$("<button>Serialize</button>").appendTo("#buttonDiv").click(function(e) {
var jsonData = '{"name": "Adam Freeman", "city": "London", "country": "UK"}'
var dataObject = $.parseJSON(jsonData)
for (var prop in dataObject) {
console.log("Property: " + prop + " Value: " + dataObject[prop])
}
e.preventDefault();
});
});
</script>
...
In this example, I define a simple JSON string and use the parseJSON
method to convert it into a JavaScript object. I then enumerate the properties in the object and their values to the console, producing the following output:
Property: name Value: Adam Freeman
Property: city Value: London
Property: country Value: UK
The trim
method removes all of the whitespace from the start and end of string. This includes spaces, tabs, and newlines. This is a feature that most programming languages support as part of their core handling of character data, but which is missing from JavaScript for some reason. Listing 33-14 shows the trim
method in use.
...
<script type="text/javascript">
$(document).ready(function() {
$("<button>Serialize</button>").appendTo("#buttonDiv").click(function(e) {
var sourceString = "
This string contains whitespace ";
console.log(">" + sourceString + "<")
var resultString = $.trim(sourceString);
console.log(">" + resultString + "<")
e.preventDefault();
});
});
</script>
...
In this example, I use the trim
method and write the original and trimmed strings to the console, producing the following results:
>
This string contains whitespace <
>This string contains whitespace<
A number of jQuery methods don't neatly fit into another category, but they can still be very useful. These are described in Table 33-6.
The contains
method lets you check to see if one element contains another. Both arguments are expressed as HTMLElement
objects, and the method returns true
if the element represented by the first argument contains the element represented by the second argument. Listing 33-15 provides a demonstration of the contains
method.
...
<script type="text/javascript">
$(document).ready(function() {
$('img').hover(function(e) {
var elem = document.getElementById("row1");
if ($.contains(elem, this)) {
$(e.target).css("border", e.type == "mouseenter" ?
"thick solid red" : "");
}
});
});
</script>
...
In this script, I obtain an HTMLElement
object using the DOM API and check to see that it contains the element passed to an event handler method. If it does, I set a border for the element that triggered the event.
Tip This method only works on HTMLElement
objects. If you want to perform the same check on jQuery
objects, consider using the find
method, which I describe in Chapter 6.
The proxy
method allows you to create a function whose this
variable is always an object that you specify. Listing 33-16 shows how the proxy method can be used.
...
<script type="text/javascript">
$(document).ready(function() {
$('img').hover($.proxy(handleMouse, $('img').eq(0)));
function handleMouse(e) {
$(this).css("border", e.type == "mouseenter" ? "thick solid red" : "");
}
});
</script>
...
This example contains a function called handleMouse
that sets the border on the element represented by the this
variable in response to mouse events. I used the proxy
function to create a wrapper around the handleMouse
function, which ensures that the value of this is always set to the first img
element in the document. The effect of using the proxy
method is that regardless of which img
element triggers the mouse event, the border is always applied to the first img
element.
Tip This method is not widely used—not least because only the this
variable is changed. As a consequence, the proxy
method has no real effect if you are in the habit of using the Event.target
property to find out which element triggered the event, for example.
In this chapter, I described the jQuery utility methods—an eclectic set of helpful functions that can be used to perform advanced operations on jQuery objects or that supplement the JavaScript language features to provide support that programmers commonly need. These are the kinds of methods you are glad exist when you need them, but you can safely forget about them for most web application projects.
52.15.38.176