jQuery Function Toggle Plugin

Already some while ago, I created a jQuery plugin which I call jQuery Function Toggle.

The idea is that upon successive events (e.g. consecutive clicks), the plugin loops through functions and executes one for each event.

Example:

The function funcToggle() basically provides the same interface as bind(), with the difference that it accepts more than one function.

The source code is available on GitHub.

How to return data from an Ajax call?

That is another question that is frequently asked on stackoverflow.com.

The short answer: You can’t (if you don’t want to give the benefits of Ajax a miss).

Ajax

What does Ajax stand for? It stands for Asynchronous JavaScript And XML and the important word here is asynchronous.

Fetching the data from the server is not done in the normal program control flow, but parallel to it.

That is why, in one way or another, you specify a callback that handles the response from the server when it is available.

Callbacks?

One could say the philosophy about callbacks is: Don’t call us, we call you. You are not waiting for a function to return a value, but you provide another function that gets called as soon as this value is available.

So instead of doing

var val = foo();
// do some processing with val here

you do

function callback(val) {
    // do some processing with val here
}

foo(callback);

This might change your the control flow and it can be tricky to convert non-callback code to callback, but it is quite powerful too. Typically, one would put all the code that has to process val into the callback.

Getting Ajax into the game

Here is a telephone analogy: Imagine you are calling one of your colleagues (friends, fellow students, …) and ask him to do a job for you that takes some time (let’s say picking something up from somewhere). Now what would you do? Would you wait on the phone until the other person returns (e.g. waiting for an hour)? Or would you rather say: “Ey, know what? Call me back when you have my stuff. (Here is my number:…)”?

Some people seem to think that JavaScript is waiting for the call to finish (waiting on the phone) and wonder why code like

function foo() {
    var result;
   $.get("<some url>", function(data) {
       result = data;
   });
   return result;
}

var val = foo();
// do some processing with val here

does not work (I’m using jQuery in this example, $.get() just makes an GET Ajax request to <some url> and executes the callback passed as second parameter).

It is because JavaScript does not wait until the Ajax request is finished. When the function is called, it will call $.get(), which will setup and send the Ajax request, but returns immediately. Then the function foo returns, before the callback passed to $.get() is even called. I.e. the assignment result = data; was not executed yet and the function returns undefined.

In order to fix this, all the logic that should operate with val has to be put into the callback:

function foo(callback) { 
    $.get("<some url>", callback); 
}

foo(function(val){
    // do some processing with val here
});

To be fair

There is a way to make the previously not-working code work. Ajax requests can be set up to be not asynchronous (is it a Jax request then? Or Sjax?). I.e. the execution will halt and continue once the response from the server was received.
That said, this should be avoided by all means (there might be some edge cases where it is ok but it is not the normal case). One of the big advantages of Ajax is the asynchronicity. Depending on how long it takes to get the response, using a synchronous request might freeze the user interface and you gain nothing but annoyed users.

Good Code (from xkcd.com)

Good Code (from xkcd.com)

JavaScript, JSON objects and object literal notation

This is my crusade against the inconsiderate usage of the term JSON object in the context of JavaScript.

JSON objects in the context of JSON

Yes, JSON objects exist in JSON, and they are well defined:

JSON object

Where value can be:

  • a string ("string")
  • a number (42)
  • another object ({"key": ...})
  • an array ([42, "string", {...}, ...])
  • true
  • false
  • null

So this is a valid JSON string with a JSON object:

'{"foo": "bar", "baz": 0}'

JSON objects and object literal notation in JavaScript

Some people think, the object literal notation in JavaScript and JSON objects are the same and use the latter to describe the former. But that is wrong. The syntax for JSON objects is just a subset of the possible syntax for JavaScript objects. The object literal notation was just the model for JSON.

This is not a JSON object:

var foo =  {foo: "bar", baz: 0};

because it would not even be valid JSON (keys must be enclosed in double quotes).

But neither is this one:

var foo = {"foo": "bar", "baz": 0};

because it is still just object literal notation. Talking about JSON here would be misleading. JSON is a data exchange format.

It would be valid talk about a JSON object in this case:

 var foo = '{"foo": "bar", "baz": 0}';

because now we are talking about a string that contains JSON and a JSON object.

The JSON object in JavaScript

Using the term JSON object for object literal notation seems to be even more wrong considering that there actually exists a JSON object in JavaScript. At least in the newer browser. It is an object, available via the global variable JSON and provides the methods

  • JSON.parse to decode JSON data into JavaScript objects
  • JSON.stringify to encode JavaScript object into JSON data (if possible)

Bottom line

Don’t use the term JSON object to describe JavaScript objects defined with object literal notation. It is misleading and confusing.


Further information:

PHP and JSONP

Since PHP 5.2, with json_decode, we have an easy way to decode JSON data. But sometimes, the only data we can get is actually JSONP, that is JSON data wrapped in a function call like:

callback({/*.. JSON data .. */});

It is not difficult to use some string functions to remove this “overhead”. Here is an example implementation of jsonp_decode (which offers the same interface as json_decode):

function jsonp_decode($jsonp, $assoc = false) { 
    // PHP 5.3 adds "depth" as third parameter to json_decode
    if($jsonp[0] !== '[' && $jsonp[0] !== '{') { // we have JSONP
        $jsonp = substr($jsonp, strpos($jsonp, '('));
    }
    return json_decode(trim($jsonp,'();'), $assoc);
}

And example implementation for creating a JSONP string:

function jsonp_encode($value, $function_name = 'cb') { 
    // 5.3 adds "options" as second parameter to json_encode
    return sprintf('%s(%s);', trim($function_name, '();'), json_encode($value));
}

Update:

The code is now available on GitHub.

JavaScript: About loops, functions and closures

On stackoverflow.com, nearly every day (at least it feels like so) I find questions about why some JavaScript code gives unexpected results - and the reason is almost always the same.

Let me take you on a short journey about loops, functions and closures.

The loop

A for loop in JavaScript (JS) seems to be the same as a for loop in C or Java, but it is not. It is actually more like in PHP. But that is another topic.

The most important thing to know about loops in JS is that they do not create a scope. JS does not have block scope, only function scope. What does this mean?

Consider the following snippet:

function foo() {
    var bar = 1;
   for(var i = 0; i < 42; i++) {
       var baz = i;
   }
   /* more code */
}

It is clear that bar will be available in the whole function. But baz (and i) will be too! There is only one difference: Until the first iteration of the loop, baz will have the value undefined. After the loop, it will have the value 41 (and i will be 42).

So any variable you declare anywhere in a function will be available everywhere in the function. But it will only have a value after one was assigned to it.

Lets continue.

The function

Functions are powerful in JS. Because they are first-class citizens, you can pass them around like any other value. Therefore you can also create functions inside functions and return them, e.g.:

function foo() {
    return function(x) {
        return 42*x;
    }
}

Which brings us to the next point.

Closures

Closures are nothing else then functions defined in other functions that are passed to some other context. They are called closures because they close over the local variables of the function they are defined in (i.e. they have access to the other functions scope).
Again an example:

function foo(x) {
    return function() {
        return 42*x;
    }
}

This time, x defined as parameter of foo, and var bar = foo(2)(); would return 84. The inner function, the function that is returned by foo has access to x.

Aggregation

Why is all this important? Because it gives those people who want to create functions inside loops and that depend on loop variables a hard time. Consider this snippet which assignes an click handler to various elements:

// elements is an array of 3 DOM elements
var values = ['foo', 'bar', 'baz'];

for(var i = 0, l = elements.length; i < l; i++) {
    var data = values[i];
    elements[i].onclick = function() {
        alert(data);
    };
}

What is the value they elements will alert when they are clicked? It will be the same for all, namely baz. Here is the reason again: By the time, the event handler is called, the for has already finished. JS has no block scope, i.e. all the handlers share a reference to the same data variable. After the loop, this value will be values[2] which is baz. You can also think this way: Every variable declaration in a function creates one place in the memory to store the data. In the for this data is just changed over and over again, the position in the memory stays the same. Every event handler access the same position in the memory.

How to solve this?

The only solution is to introduce another scope that “captures” the current value of data. JS only has function scope. So we have to introduce another function. We could do something like:

function createEventHandler(x) {
    return function() {
        alert(x);
    }
}

for(var i = 0, l = elements.length; i < l; i++) {
    var data = values[i];
    elements[i].onclick = createEventHandler(data);
}

This works, because the value of data will be stored in the local scope of createEventHandler and this function is executed newly in every iteration.

This can be written shorter using immediate executing functions:

for(var i = 0, l = elements.length; i < l; i++) {
    var data = values[i];
    elements[i].onclick = (function(x) {
           function() {
               alert(x);
           };
    }(data));
}

This might look special but it really is no. It is just substituting the createEventHandler by the function definition.


Further information:

How to detect when HTML5’s history.pushState() is called?

That was the question I had and galambalazs helped me to solve this question on stackoverflow.com.


Problem description and background:

The latest version of my Firefox add-on (FloatNotes), also listens to the event hashchange, which is raised when the fragment-identifier of the URL is changed. As you may know, this technique is used in Ajax-enabled websites (like Google Mail) to make URLs be part of the browsing history without reloading the page. So the idea is that if the hash has changed, the user actually visits another page.

Now, with HTML5, the window.history object gets new methods which take the previous mentioned idea further: pushState and replaceState. As the name suggests, pushState adds a new URL to existing history stack and (if the protocol and host stay the same) does not trigger a reload of the page. Most browsers will display the new URL in the address bar too so it really looks like you clicked a normal link, but the content is loaded via Ajax. You can test this using Firefox 4 or Chrome 8 and Facebook.

The problem is that calling pushState does generate any event (like changing the hash did) so loading of new content cannot be detected anymore.


The solution

I first tried to replace the whole history object with a custom object, but that did not work (probably window.history is readonly). Then galambalazs proposed to just replace the pushState method. Here is his code:

(function(history){
    var pushState = history.pushState;
    history.pushState = function(state) {
        if (typeof history.onpushstate == "function") {
            history.onpushstate({state: state});
        }
        // ... whatever else you want to do
        // maybe call onhashchange e.handler
        return pushState.apply(history, arguments);
    }
})(window.history);

So whenever the pushState method is called, you can trigger your own event handler.

It is a hack, but until an event is raised by default, this seems to be the only way to get notified when history.pushState() is called.