Miscellaneous utility functions

This section will explore the set of utility functions that are pretty much a category on their own. We’ll start with one that doesn’t seem to do much.

Doing nothing

jQuery defines a utility function that does nothing, literally. This function could have been named $.uselessFunctionThatDoesNothing(), but that’s a tad long, so it’s named $.noop(). It’s defined with the following syntax.

Function syntax: $.noop
$.noop()
Does nothing
Parameters
none
Returns
undefined

Hmmm, a function that is passed nothing, does nothing, and returns undefined. What’s the point?

Do you recall that many jQuery methods are passed parameters or option values that are optional function callbacks? $.noop() serves as a handy default for those callbacks when the user doesn’t supply one.

Testing for containment

When you want to test one element for containment within another, jQuery provides the $.contains() utility function.

Function syntax: $.contains
$.contains(container, contained)
Tests if one element is contained within another in the DOM hierarchy
Parameters
container(Element) The DOM element being tested as containing another element
contained(Element) The DOM element being tested for containment
Returns
true if the contained element is contained within the container; false otherwise

Hey, wait a minute! Doesn’t this sound familiar? Indeed, we discussed the has() method back in lesson 2, to which this function bears a striking resemblance.

This function, used frequently internally to jQuery, is most useful when you already have references to the DOM elements to be tested and there’s no need to take on the overhead of creating a jQuery collection.

To see this method in action, consider the following markup:

<div id="wrapper">
   <p id="description">Some text</p>
</div>
<div id="empty"></div>

If you execute the following two statements

console.log($.contains(
   document.getElementById('wrapper'),
   document.getElementById('description')
));
console.log($.contains(
   document.getElementById('empty'),
   document.getElementById('description')
));

you’ll obtain the following result on the console:

true
false

The reason is that the element having description as its ID is a descendant of the element having wrapper as its ID, but not of the one whose ID is empty.

This section and the previous one were simple to digest. Now turn your attention to one of the more esoteric utility functions—one that lets you have a pronounced effect on how event listeners are called.

Prebinding function contexts

As you’ve seen throughout our examination of jQuery, functions and their contexts play an important role in jQuery-using code. The context of a function—what’s pointed to by this—is determined by how the function is invoked and not how it’s defined (see the appendix if you want to review this concept). When you want to call a particular function and explicitly control what the function context will be, you can use JavaScript’s call() or apply() method to invoke the function.

But what if you’re not the one calling the function? What if, for example, the function is a callback? In that case, you’re not the one invoking the function so you can’t use the previously mentioned methods to affect the setting of the function context.

jQuery provides a utility function by which you can prebind an object to a function so that when the function is invoked, the bound object will become the function context. This utility function is named $.proxy(), and its syntax is as follows.

Function syntax: $.proxy
$.proxy(function, proxy[, argument, …, argument])
$.proxy(proxy, property[, argument, …, argument])
Takes a function and returns a new one that will have a particular context
Function syntax: $.proxy (continued)
Parameters
function(Function) The function whose context will be changed
proxy(Object) The object to which the context (this) of the function should be set
argument(Any) An argument to pass to the function referenced in the function parameter
property(String) The name of the function whose context will be changed (should be a property of the proxy object)
Returns
The new function whose context is set to the proxy object

Bring up the example in the file lesson-9/$.proxy.html and you’ll see the display shown in figure 9.7.

Figure 9.7. The $.proxy example page will help you see the difference between normal and proxied callbacks.

In this example page you have a Test button, whose ID is test-button, which you store in a variable as follows:

var $button = $('#test-button');

When the Normal radio button is clicked, a click handler is established on the Test button and its container:

$button.click(customLog);

The customLog() handler shows on the screen the ID of the function context (whatever is referred to by this):

function customLog() {
   $('#log').prepend(
     '<li>' + this.id + '</li>'
   );
}

When the button is clicked, you’d expect the established handler to have as the function context the element upon which it was established: the Test button. The result of clicking the Test button is shown in figure 9.8.

Figure 9.8. The result of the $.proxy example page when using the normal handler

But when the Proxied radio button is clicked, the handler is established as follows:

$button.click($.proxy(customLog, $('#control-panel').get(0)));

This establishes the same handler as before, except that the handler function has been passed through the $.proxy() utility function, prebinding an object to the handler. In this case you bind the element with the ID of control-panel. The bound object doesn’t have to be an element—in fact, most often it won’t be. We chose it for this example because it makes the object easy to identify via its ID.

Now, when you click the Test button, you obtain the result shown in figure 9.9, which proves how the function context has been forced to be the object that you bound to the handler with $.proxy().

Figure 9.9. This example shows the effects of prebinding an object to the click handler for the Test button.

This ability is useful for providing data to a callback that it might not normally have access to via closures or other means.

The most common use case for $.proxy() is when you want to bind a method of an object as a handler and have the method’s owning object established as the handler’s function context exactly as if you had called the method directly. Consider an object such as this:

var obj = {
  id: 'obj',
  hello: function() { alert('Hi there! I am ' + this.id); }
};

If you were to call the hello() method via obj.hello(), the function context (this) would be obj. But if you establish the function as a handler like so,

$(whatever).click(obj.hello);

you’ll find that the function context is the current bubbling element, not obj. And if your handler relies on obj, you’re rather screwed. You can get out of this predicament by using $.proxy() to force the function context to be obj with the following statement:

$(whatever).click($.proxy(obj.hello, obj));

Alternatively, using the second signature of the function, you can achieve the same goal with

$(whatever).click($.proxy(obj, 'hello'));

where obj is the object to which the context (this) of the function should be set and the string "hello" represents the name of the function that belongs to obj, whose context will be changed.

Be aware that going this route means that you won’t have any way of knowing the current bubble element of the event propagation—the value normally established as the function context.

Evaluating expressions

Although the use of eval() isn’t recommended by many developers, there are times when it’s useful (take a look at the code of the Parsing Functions Lab page for an example).

The problem is that eval() executes in the current context. When writing plugins and other reusable scripts, you might want to ensure that the evaluation always takes place in the global context. Enter the $.globalEval() utility function.

Function syntax: $.globalEval
$.globalEval(code)
Evaluates the passed JavaScript code in the global context
Parameters
code(String) The JavaScript code to be evaluated
Returns
The evaluation of the JavaScript code

We’ll wrap up our investigation of the utility functions with one that you’ll use when learning how to write jQuery plugins but that you might use in other situations, too.

Throwing exceptions

Under some circumstances you’ll want to throw an error in a function or a plugin you’ve authored. For example, you may want to throw an error if a developer passes to your plugin an unexpected parameter. For this purpose, jQuery provides a utility function called $.error().

Function syntax: $.error
$.error(string)
Takes a string and throws an exception containing it
Parameters
string(String) A string specifying the message to send out
Returns
undefined

This method exists primarily for plugin developers who wish to override it and provide a better display (or more information) for the error messages. A simple example of use of this function is the following:

function isPrime(number) {
   if (typeof number !== 'number') {
      $.error('The argument provided is not a number');
   }
   // Remaining code here...
}

We’ll use this function again when we discuss how to develop plugins for jQuery, but that’s another lesson.


by

Tags:

Comments

Leave a Reply

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