Showing posts with label jQuery. Show all posts
Showing posts with label jQuery. Show all posts

Module pattern template

My current project makes use of different technologies, for presentation we rely on a mix of Java EE and JavaScript. We try not to mess around too much with the latter, and we strive to keep that code as readable as possible. For this reason we break the JavaScript code in modules that, ideally, are all written following the same template, so that it is easy for anyone in the team to put his hands on any piece of code available.

Here is an example of how we typically write a module.

As you will see, we use the well known module pattern, with a few specific variations:
var APP = APP || {}; // 1

APP.Module = (function(app, global, $) { // 2
  "use strict"; // 3

  var FIRM_NAME = 'XYZ'; // 4

  function Factory(options) { // 5
    var that = this; // 6

    if(!(this instanceof Factory)) { // 7
      return new Factory();
    }

    this.options = $.extend({ name: null }, options); // 8

    function _checkName() { // 9
      if(that.options.name) {
        console.log('In a private function, use that instead of this');
        return true;
      }
      else {
        return false;
      }
    }

    this.getName = function getName() { // 10
      return FIRM_NAME + (_checkName() ? ': ' + this.options.name : '');
    }

    return this; // 11
  }

  Factory.aFunction = function() { // 12
    if(this == Factory) {
      console.log('A static function has no access to instance variables');
    }
    else { // called by sayHello, see below
      console.log('Instance', this.options.name);
    }
  }

  Factory.prototype.sayHello = Factory.aFunction; // 13

  return Factory; // 14
}(APP, this, jQuery)); // 15
1. First thing, I define a namespace for all the modules. Or better, if APP is already defined, I use it as it is in the following code. Only if no APP is already available a create it from scratch.
2. In APP, I create a module named Module (usually it is a good idea choosing a better name). As you see, it is nothing more that an immediate function that receives in input three parameters, see the module last line (point 15.) to find out what they are.
3. The JavaScript code used is "strict".
4. This is a private variable (ideally, a constant) available to all the Module instances.
5. The Module's constructor. It accepts in input a variable used to set the internal object properties. In this case "options" contains just a single value, so it is an overkill not to use it. But usually options contains a large number of properties.
6. The infamous "this is that" pattern. Follow the link for more details.
7. Another well known JavaScript pattern. The constructor could be called improperly, with this check we avoid any unpleasant surprise.
8. We use jQuery, so to extends the "options" object passed to the constructor we use the jQuery .extend() function. Same functionality is provided by other frameworks, and it could also implemented with no special trouble by hands. The idea is that we want to ensure that our local "options" contains at least a property named "name". If the passed "options" has it, we will keep it, otherwise a new, empty one (or better, null), is created.
9. A private function. No one could access it outside its scope. Notice that inside it we have to use "that" to access the constructor "this".
10. A public function. It could be called from outside, and it has full access to the constructor and module properties.
11. As almost any constructor, at the end of its job it returns "this".
12. Sometimes it is useful to have a "static" (in the C++/Java sense) method in a module. Here is how we can emulate it. We can even use a trick (see 13.) to adapt this method so that it could also be called as a non-static function.
13. Here is the trick. We create a property in the Factory prototype, and we assign to it the static function. Neat.
14. Finally, the immediate function calls the constructor, so that the object is created.
15. We call the immediate function passing to it APP (the module's namespace), the current "this" (at this point it should be the global one), and jQuery (since we use it - you could pass your preferred framework instead, obviously. Or you could even pass many ones).

Here is a test usage for the above defined module:
var m1 = new APP.Module({name: 'John Smith'}); // 1
console.log(m1.getName());

var m2 = new APP.Module(); // 2
console.log(m2.getName());

APP.Module.aFunction(); // 3
console.log("Can't call a private function from outside:", m1._checkName === undefined);
console.log("Can't call an instance function from static context:", APP.Module.sayHello === undefined);
console.log("Can't call a static function from an object:", m1.aFunction === undefined);
m1.sayHello(); // 4
1. An object m1 is created, passing a name to the module.
2. Here we create an "anonymous" module, no name it is passed.
3. The static function is called on the module itself, it doesn't requires an actual instance.
4. But through that clever trick showed above on (13.) we can call the static function through an alias.

Go to the full post

Reading a JSON and looping on it

I have a JSON array of strings stored in a file, I want to read it from a JavaScript and use in someway its values. To simplify the file access, I am about to use the jQuery getJSON() function.

The JSON file, named numbers.json, contains something like this:
["Zero", "One", "Two", "Three"]

This JavaScript fragment gets asynchronously the file, and then dumps to the console any elements in the fetched JSON:
$.getJSON('numbers.json').done(function(numbers) {
  for(var i=0; i < numbers.length; ++i) {
    console.log(numbers[i]);
  }
});
Calling getJSON() we ask jQuery to fetch the content of the passed filename and, when done, calling the anonymous function passed as parameter to done(), putting in its input parameter, that I named numbers, the contained JSON. In the body of that anonymous function we have to deal with the fetched data. What I do there is simply looping on the array, and logging to the console each component.

Go to the full post

Three solutions to the loop problem

The lack of a block scope in JavaScript leads to what is often called The Infamous Loop Problem, where we try to use the (supposed) cycle variable in a for loop to set a callback function.

Conceptually, the solution is quite easy. The trouble is caused by the loop variable, that actually does not have a local scope, so we provide to it a local scope. In JavaScript we have only function scope, so a function would help us to find a way out.

The question is, which function? Whichever it is better for you in your context, I'd say. Let's see the three answers that I guess are more natural.

In the previous post I have written a buggy piece of code that was storing a few functions when looping on an array, an then, in another for loop, it called those functions. Now I modify it to let it work as I expected, following three different approaches.

Closure in loop

This is the most idiomatic solution using "pure" JavaScript. We wrap the code in the for loop around a closure, designed just to provide a local scope for the loop variable.
function doSomething(msg) {
    console.log(msg);
}

var messages = [ "hello", 42, { pi: 3.14 } ];
var buffer = [];

for(var i = 0; i < messages.length; ++i) {
    buffer[i] = (function(j) { // 1
        return function() { // 2
            doSomething(messages[j]);
        }
    })(i); // 3
}

// ...

for(var k = 0; k < buffer.length; ++k) {
    buffer[k]();
}
1. We put in buffer the function returned by a closure, here defined, that take as input a parameter, named j, that is assigned a value defined in (3).
2. The function returned by the closure is almost the same function we defined in the original code. The difference is that I don't use anymore the loop variable, but the closure parameter.
3. This is the core of the solution. I assigned to the closure parameter the loop variable, in this way the closure captures its current value, that now has a local scope, as required.

After a while, I guess this would look as the most natural approach, but if your JavaScript mileage is low, you could be find it a bit overwhelming. In this case, maybe you could be more at ease with the following variation.

Closure in the function

The idea is to move the closure from the for loop to the recipient function. I refactor the code above, rewriting the for loop and doSomething(), renamed doSomethingElse() for the sake of clarity.
function doSomethingElse(index) {
    return function() { // 1
        console.log(messages[index]);
    }
}

// ...

for(var i = 0; i < messages.length; ++i) {
    buffer[i] = doSomethingElse(i); // 2
}

// ...
1. The closure has been moved here. Notice that this function does not run any code, but returns a function.
2. Just a simple assignment!

This code is so much readable, but I am losing the connection between the loop (2) and the reason why I need a closure in (1). Someone who reads just doSomethingElse() would probably wonder why it returns a closure instead of doing directly its job.

jQuery.each()

If we use the jQuery library, we can get the advantages of both the previous solutions using the each() method.

We use the original doSomething() function, and we don't need a closure in the for loop, jQuery.each() is a function, so it provides its own scope.
$.each(messages, function(index, value) { // 1
    buffer[index] = function() { // 2
        doSomething(value);
    }
});
1. For each element in the messages array, we call a function where the first parameter is the current index, and value the message element currently accessed.
2. There's no need of a closure, we simply assign to the buffer element a function that calls doSomething(). The capturing of local values is performed by jQuery.each().

Go to the full post

Adding a DOM element

If you have to modify an existing DOM document in the fly by adding a HTML fragment, you can use the jQuery appendTo() method, that would simplify your job. Being jQuery smart enough to create a jQuery object from a HTML literal fragment, we can even operate on it before appending it.

To add a bottom line to an HTML page, I could write:
var fragment = $('<p><i>Bottom line</i></p>'); // 1
fragment.find('i').attr('class', 'z'); // 2
fragment.appendTo('body'); // 3
1. I create a P element containing an I element, containing some text.
2. Before actually adding it to my document, I can modify it. Here I get the I element and add to it an attribute, class='z'.
3. Finally, I add my fragment at the end of the BODY element.

There is no need of writing this code on three lines, I can squeeze it on just one, but I have to be careful:
$('<p><i>Bottom line</i></p>').find('i').attr('class', 'k').end().appendTo('body');
I need to call end() before appendTo(), otherwise I put to the document only the element returned by find(), and the paragraph would be lost.

Go to the full post

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

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