How andSelf() improves find()

We have seen how the jQuery methods filter() and find() differ. Now we see how to improve find() combining it to another useful method, andSelf(), that works smoothly with it.

I want to draw a box around my unsorted lists, and also around the included links. To do that, I can write this JavaScript oneliner:
$('ul').find('a').andSelf().css('border', '1px solid blue');
I select all the ULs in my document, than I find all the included A elements, and I join the two sets by calling andSelf(). Finally I call css() specifying that I want to put a thin blue line border around them.

Go to the full post

Choosing between filter and find

The .filter() and .find() jQuery methods look similar, and it could happen to mix them up. Still there is substantial difference between them, .filter() modifies the current set of elements, reducing it by applying the specified rule, while .find() operates on the children of the current set, returning a completely different set of elements.

Say that we are working on an HTML page containing a few lists, and we want to do something on some list items, the LI elements marked with a specific class, and we want to work on the links defined in any list item.

In the first case we'll use the .filter() method, since we want to refine the existing selection, for the latter .find() is the right choice, being our aim to select a new set elements among the children of the original set.

Here is a JavaScript code fragment:
var $li = $("li"); // 1

var $liK = $li.filter('.k'); // 2
console.log($liK, $liK.length);

var $a = $('a'); // 3
var $liA = $li.find('a'); // 4
var $LiA2 = $('a', $('li')); // 5
var $LiA3 = $('li a'); // 6
console.log($a, $a.length, " -", $liA, $liA.length, " -", $liA2, $liA2.length, " -", $liA3, $liA3.length);
1. Selecting all the LI elements in the current document.
2. Restricting the original set to the LI elements having class='k' as attribute.
3. All the anchor elements in the document.
4. Find the anchor elements children of LI elements.
5. Same result of (4), asking to jQuery to get all the A elements children of a LI.
6. Same of (4) and (5), and in this case probably the preferred way to the result.

Go to the full post

Selecting DOM elements

Selecting DOM elements of a given type in a document is a simple task, and we can easily do it using standard JavaScript functionality. Nevertheless, jQuery makes it even simpler.

Here is the code to get all the LI elements in the current document, both in plain JavaScript, and using jQuery:
var li = document.getElementsByTagName("li"); // 1
var $li = $("li"); // 2

console.log("li: ", li, li.length);
console.log("$li: ", $li, $li.length);
1. The getElementsByTagName() method returns a NodeList, a structure that is array-ish but does not derive from Array. It sports a property, length, that contains the number of element contained, and lets the user access each of them through the [] operator. An out of bound request is resolved to null.
2. A call to jQuery factory function returns a jQuery object that, for what we care here, is not different from a NodeList object, but it is enriched by extra-information and functionality, that could be useful in more a demanding context.

Go to the full post

When this does not work, use that

There is an issue in "this", the JavaScript keyword identifying the current object.
It works fine in an object member functions (AKA methods) but not in their inner functions. An easy way to bypass the problem requires us to create a member variable, that is often called "that" (or "self", but it is usually considered a weaker option).

Does it remember you an Abbott & Costello skit, "who's on first?", or it is just me? Anyway, an example should help clarifying the matter.

Say that we want to have an object, named calculator, keeping an internal status and providing a couple of methods, opA() and opB(), to perform some obscure calculations. The first operation is not too complicated, but opB() requires some messy stuff to be done, and we think that it would be a good idea to organize it defining an inner function that, among the other things, calls a free function.

It should be all not too complex to do, still we have to deal with the above mentioned issue.
var elaborate = (function(x) { // 1
    var cache = 0;

    return function(x) {
        cache += x;
        return cache;
    }
}());

var calculator = {
    status: 0,
    opA: function(x) { // 2
        this.status += x;
    },
    opB: function() { // 3
        var that = this; // 4
        var somethingComplicated = function() {
//            this.status += elaborate(this.status); // 5
            that.status += elaborate(that.status); // 6
        };
        
        somethingComplicated(); // 7
    }

    calculator.opA(3);
    calculator.opA(4);
    calculator.opB();
    console.log(calculator.status);
};
1. I defined elaborate() as a closure, so that it could keep its own status. See details in a previous post, static variable by closure.
2. This first method is trivial. It gets a parameter in input (assumed to be a numeric value), and adds it to the object property (status). To access the object property the keyword "this" is used. Not an issue here, for the object methods, the bind between "this" and the object itself is correctly done by JavaScript.
3. More complications here. In opB() we define a function, somethingComplicated(), that calls elaborate(), the closure defined in (1). The issue is that we can't use "this" in the body of somethingComplicated(), because "this", at that point, refers to the global scope or is undefined (if we "use strict" JavaScript, as we should).
4. "this" don't work as we would like in inner functions, but we can patch this behavior defining a local variable in the function, often called "that", that stores the value of "this" so to do as a bridge to the inner function.
5. As said above, this line doesn't work. "this" is undefined ("use strict") or points to the global scope. Hardly what you usually need.
6. This line saves the day. We use "that" to get access of the unavailable "this".
7. So we can happily call our somethingComplicated() inner method.

Go to the full post

Strictly or loosely false

Being Javascript a loosely typed language, comparing a value for its truthiness could lead to an unexpected behavior if you, well, do not expect it.

To perform a strict checking, you should use the strict comparison operator "triple equals", and you should be aware that by default the loose "double equals" operator is used.

There is a bunch of values that are loosely evaluate as false (friendly known as "falsy"):
var myUndef, // undefined
    myNull = null,
    myFalse = false,
    myEmpty = '', // empty string
    myZero = 0, // numeric zero
    myNan = parseInt('not a number'); // parsing a non numeric string returns NaN
    
if(myUndef || myNull || myFalse || myEmpty || myZero || myNan) // 1
    console.log('Unexpected');

try {
    if(myNotExisting) // 2
        console.log('Unexpected');
}
catch(e) {
    console.log(e);
}

if('false') { // 3
    console.log('Misleading');
}
1. All these values (undefined, false, empty string, zero, NaN) are loosely equals to the boolean false value, so the next line is not executed.
2. This variable was even not declared, checking it results in an exception of type ReferenceError.
3. The string 'false' is not converted to the boolean false value, and it is evaluated to true.

Go to the full post

Hello jQuery

If you are developing JavaScript's for a web application that should run in the wild, you know the pain of writing code that should run on large part of the available browsers. A common approach is delegating to a library the bore of taking care of the details, better if it has the side effect of providing a high level interface. A popular choice in this field is represented by jQuery, recently released in its 1.8 version.

Writing an Hello jQuery application is pretty easy.

Firstly, you'd better get the library on your local machine. You can fetch it following the instructions in Download jQuery.

Actually you could avoid this step and refer to a publicly available copy of it, see CDN hosted jQuery for details. Whichever strategy you follow, you should ensure your script gets access to the jQuery library. In my case, I have simply put the js file in the same directory of the html that you can see below.

My hello page pops up an alert with greetings after the HTML page is fully loaded. It is not much, but this ensures that the jQuery library is properly linked:
<html>
<head>
    <meta charset="UTF-8">
    <title>Hello jQuery</title>
    <script src="jquery-1.8.0.js"></script> <!-- 1 -->
    <script>
        $(function(){ // 2
            alert("Hello from jQuery");
        });
    </script>
</head>
    <body>
        <h1>A JavaScript/jQuery powered page</h1>
    </body>
</html>
1. I ask to the browser to go and load the jQuery library. I have put it in the current folder, so I specify just its name. In production code, it would almost certainly be somewhere else.
2. I called a function named $ (just the single character "dollar"), passing to it an anonymous function that calls the alert() function. This is quite an implicit way of calling the jQuery ready event handler. Maybe it looks more clear if I rewrite it in this way:
jQuery(document).ready(function() {
    alert("Hello from jQuery");
});
The dollar sign is a mere synonym for the jQuery() function. And, if you dig in the jquery.js code, you'll find out that passing a function to jQuery is a shortcut for calling the document ready event handler.

Putting our call to alert() in the jQuery ready() body, we ensure that it is called only after the DOM document associated to the current HTML page is fully loaded.

Go to the full post

String and regular expressions

The JavaScript String class has a few methods that could be used with RegExp. Here is a breaf introduction to them: split(), search(), match(), and replace().

split

Regular expressions make String.split() more flexible:
"1, 2, 3".split(", "); // 1
"1 ,  2 ,3".split(/\s*,\s*/); // 2
1. This is how is commonly called split(). If we are sure on how the separator is, it works fine, and returns an array of three elements containg just the numbers. But what if we have no control on the blanks? And we could have no blanks, or many of them, around a comma? You usually won't be happy with the result.
2. This is the solution. A comma is the real separator, and any blank around it is eaten out.

search()

Passing a RegExp to search() on a specified string, we get back an integer representing the index of the first match, or minus one if there is no match:
"JavaScript".search(/script/); // 1
"JavaScript".search(/Script/); // 2
"JavaScript".search(/script/i); // 3
"Here is 1 for you, 3 for me, 42 for the others.".search(/\d+/g); // 4
1. The search is by default case sensitive, so the pattern here is not found, and the function call returns -1.
2. The match is found starting on 4.
3. We can override the default, saying that we want to perform a case-insensitive search, specifying the "i" flag after the pattern. This function call returns 4.
4. The global option makes no sense in this context, and it is silently ignored. The returned value is the position of the first match, 8.

match()

The match() behavior is quite articulate. Its output should be interpreted differently accordingly to the provided input. Seeing it in action should clarify what I mean:
var s = "Here is 1 for you, 3 for me, 42 for the others.";
s.match(/\d+/); // 1
s.match(/\d+/g); // 2
"My email address is someone@not.existing.zzz".match(/(\S*)@(\S*)/);
1. We ask to match() to return just the first subsequence matching the specified pattern, in this case a string of one or more digits. It returns a vector containing one element, "1".
2. Global matching, a vector is returned containing all the matching elements, in this case three strings, "1", "3", and "42".
3. The RegExp represents an email address, first part is the sequence of not-blank characters before the "at" symbol; second part is what is after it, till we get a blank. Notice that we asked match() to capture $1 and $2 as left and right side of the "at". In this case match() returns an array containing in first position the full matching element, and in the next positions $1, $2, ...

replace()

This function returns a copy of the original string where, if the RegExp is found, it is replaced by the second parameter passed:
"... javaScript ... javascript ... Javascript ...".replace(/javascript/gi, "JavaScript"); // 1
"I want to have 'doublequotes' in this string!".replace(/'([^']*)'/g, '"$1"'); // 2
1. Notice the two flags associated to the RegExp, specifying that we are preforming a global and case insensitive search. All the three JavaScript variation in the string are found and replaced by the string passed as second argument to the function.
2. What we are saying here is: search for each {g option} sequence starting with a single quote {'}, followed by any number {*} of any character but a single quote {[^']} and a single quote, and call $1 the subexpression in the round parenthesis. Then replace what you have found with a double quote, the $1 subexpression, and another double quote.

Go to the full post