What is the minimum valid JSON?

The short, but entirely unhelpful, answer to this question is that… it depends; it depends on both what the language you are sending from, and receiving to, deems as the minimum valid JSON.

For example, if you are sending JSON between PHP and a browser (in either direction), the minimum valid JSON is a JSON literal. Between a browser and Ruby however, it is a JSON object (or array).

The reason for this lack of consensus is best explained by the “creator” of JSON himself; Douglas Crockford:

JSON is just a grammar, and the grammar includes numbers and strings. Uses of JSON must necessarily be more restrictive. RFC-4627 is one possible use, and was never intended to be the standard for JSON itself.

So yeah. You don’t just send or receive “JSON”. Technically, you receive a JSON formatted text which adheres to a particular format; commonly described in a standard. RFC-4627 is one of those. ECMA-404 is another. RFC-4627 defines a JSON array/ object as the minimum valid JSON, whilst ECMA-404 permits JSON literals (JSONValue‘s in the spec.) as well.

This is why you need to look at the documentation for the stringifer and parser you are using; to check what standard they adhere to.

To make things more confusing however, many JSON implementations do not perfectly adhere to a particular specification, and will add their own exceptions to their implementation. This is why JSON literals are accepted as valid JSON between PHP and browsers; as even though both technically adhere to RFC-4627, both also specifically add the exception that they also accept JSON literals as well as JSON object/arrays as the minimum JSON (relevant part of the ECMAScript 5 spec., relevant part of the PHP docs.).

With Ruby on Rails however, no exceptions exist; it adheres to RFC-4627 plain and simple. So whilst browsers can create and parse JSON texts which contain only literals, Ruby on Rails cannot parse or create them itself.


This post summarises the content of two answers on Stack Overflow; my own answer to ‘What is the minimum valid JSON’, and other answer by Jeremy Banks to ‘After the publication of ECMA-404, is ‘2’ or ‘”hello”‘ considered a valid JSON text?’.

Force www or non-www in Express/ Connect

Serving your website through either your domain prefixed by “www”, or by your domain directly (but not both) is important for SEO. For ease-of-use (i.e so as not to drive away users), it is common practice to redirect the domain you chose not to be the canonical domain to redirect to your canonical domain.

In Apache this is accomplished via your .htaccess file. No provisions exist to do this automatically in Connect or Express, but it is easy to add middleware to achieve this.

Basically, examine the host property of the request object, and call redirect on the response object to redirect to the canonical domain if necessary.

To force “www”:

var express = require('express'),
    app = express();

app.use(function (req, res, next) {
  if (req.host.indexOf("www.") !== 0) {
    res.redirect(301, req.protocol + "://www." + req.host + ":80" + req.originalUrl);
  } else {
    next();
  }
});

To force non-“www”:

var express = require('express'),
    app = express();

app.use(function (req, res, next) {
  var str = "www.";

  if (req.host.indexOf(str) === 0) {
    res.redirect(301, req.protocol + "://" + req.host.slice(str.length) + ":80" + req.originalUrl);
  } else {
    next();
  }
});

Notes:

  1. Do not forget to call next() in the event of a redirect not being needed.
  2. Ensure you are emitting a 301 (permanent redirect) rather than any other HTTP status code.
  3. Here’s an example of how I’ve used a variant of this code in practice in my own code (using the vhost module).
  4. If you’re running on port 80, you can remove the + ":80" + portion of the code within the redirect() call; if you’re running on a different port however, change “80” to be your port.

Submitting a form as an AJAX request using jQuery

It is often the case where you have a form in your HTML, and you want to submit either all or part of it via AJAX, rather than via standard HTTP GET/ POST.

You can easily do this in jQuery using the serialize() method, which, when called on a jQuery object containing either a form element or form controls (<input />‘s, <select>‘s etc.), will return a URL-encoded string.

Example HTML:

<form id="the-form">
    <input name="username" type="text" value="mattlunn" />
    <input name="password" type="password" value="pass1234" />
</form>

Example JavaScript:

alert($('#the-form').serialize()); // username=mattlunn&password=pass1234 

Try it yourself in this jsFiddle.

This URL-encoded string can be used directly as the GET query string, or as your POST body, so all that is left is to construct a jQuery AJAX request, passing this string as the content of the request:

jQuery.ajax({
    url: '/some/endpoint.php',
    method: 'GET',
    data: $('#the-form').serialize()
}).done(function (response) {
    // Do something with the response
}).fail(function () {
    // Whoops; show an error.
});

You might find this snippet of jQuery code a good starting point for implementing AJAX forms on your website. It copies the method and target from the <form /> control, and makes the AJAX request for you.

/**
 * Utility function to help submit forms/ form controls via AJAX.
 * @param selector: Optional. Parameter passed to find() to restrict which elements are serialized. Default is to return all elements
 * @param success: Required. A function to be executed when the AJAX request completes. Arguments are standard AJAX args. 'this' is the form.
 * @param error: Required. A function to be executed when the AJAX request fails. Arguments are standard AJAX args. 'this' is the form.
 */
jQuery.fn.ajaxify = function (selector, success, error) {
    // Handle the optional case of selector.
    if (arguments.length === 2) {
        error = success;
        success = selector;
        selector = undefined;
    }

    return this.on('submit', function (e) {
        // Copy the options from the '<form />' control.
        jQuery.ajax({
            url: this.action,
            method: this.method || 'GET',
            data: (typeof selector === 'undefined' ? $(this).serialize() : $(this).find(selector).serialize())
        }).done(jQuery.proxy(success, this)).fail(jQuery.proxy(error, this));

        e.preventDefault(); // Don't forget to stop the form from being submitted the "normal" way.
    });
};

The above function can be used like so;

jQuery(document).ready(function ($) {
    $('form').ajaxify(function (response) {
        // Handle a successful submission
    }, function (xhr, error) {
        // Handle an error'd submission
    })
});

If you’re interested in reading further, you may want to check out the definition for a “successful control”; as only these types of elements will be contained in the string returned by serialize(). Furthermore, you may also want to checkout the jQuery plugin “forms”, which is a plugin designed to bring unobtrusive AJAX to your forms.

jQuery delay() not working for you?

jQuery’s delay() function causes more than its fair share of problems over on Stack Overflow. You often see people trying to use delay() to delay something like* setting a CSS property (via css()), and then wondering why their CSS property updated immediately; irrespective of their use of delay().

$('#some-element').delay(5000).css("backgroundColor", "red"); // this won't work

*: Other common problems originate from trying to perform DOM manipulation (via the likes of append(), after() etc, or the setting of HTML/ values (via html(),text() or val()).

The short answer is to basically use setTimeout() instead. The long answer involves looking more into how jQuery queues these requests, and finding out exactly what delay() does…

Why it doesn’t work…

When you call delay(5000), what you’re actually doing is calling delay(5000, "fx") as the function has an optional second parameter (the queue name you wish to delay operation of) which defaults to fx. The various effects methods (fadeOut(), animate() etc.) all use this queue which is why delay() has an effect on them.

However nothing else in jQuery does (by default at least, but we’ll get to that part shortly). That is to say that calls to any manipulation functions (html(), append(), css() etc.) will completely ignore your delay() call, because they’re are all executed immediately, and not queued at all.

How you can fix it…

The recommendation here is to use setTimeout() instead; your code will end up looking like this:

setTimeout(function () {
    $("#some-element").css("backgroundColor", "red");
}, 5000);

However, if you wish to use delay(), you can use the queue() function to queue something. The signature of the queue() function is as follows;

queue([queueName,] functionToBeExecuted(next));

That is to say, the first argument is the name of the queue you wish to add to (which defaults to fx when not specified), and the second argument is the function you wish to queue. That function gets passed one parameter, which you must call when your function has finished doing whatever it needs to do; this is to ensure the next elements in the queue get executed as well.

Therefore we end up doing something like this;

$('#some-element').delay(5000, "my-queue").queue("my-queue", function (next) {
    $(this).css("backgroundColor", "red");
    next();
});

Note that in the above example, we’ve specifically avoided the fx queue; the changing of the background-color is not related to fx at all, so we shouldn’t abuse the use of that queue. Having said that, there are times when queuing to the fx queue is useful; such as when you want to perform an action after a list of effects have completed;

$("#some-element").fadeIn(200).animate({
    padding: "+=50"
}, 1500).delay(1000).queue(function (next) {
    $(this).css("backgroundColor", "red");
    next();
});

Of course, if we wanted to be very explicit about which queues we were using, it’d look something like this:

$("#some-element").fadeIn(200).animate({
    padding: "+=50"
}, 1500).delay(1000, "fx").queue("fx", function (next) {
    $(this).css("backgroundColor", "red");
    next();
});

For further reading after finishing the article, consider reading the delay() documentation or the Stack Overflow question that triggered me writing this article!

Event Delegation with jQuery

This is the last in a series of posts on bubbling, delegation and how to delegate events with jQuery. You should already have read the articles What does event bubbling mean and Event Delegation in JavaScript, or have a grasp on their topics.

Event Delegation with jQuery

At the end of the last post, we had a table with hundreds of rows. Each row contained a <a /> to which we wanted to attach a click handler to. We added a single handler to the <table/> element (we delegated the event handler to it) to capture the event.

The correct way to delegate an event handler to the <table> for a click on the <a /> in jQuery would be;

$('#the-table').on('click', 'a', function (e) {
    alert('You clicked row #' + $(this).closest('tr').prop('rowIndex')); 

    e.preventDefault();
});

See it in action here. In words, we capture the element we wish to delegate the event to ($('#the-table')) and call the on() method on it. The event type is the first parameter (click), and the second parameter is a selector which pinpoints the descendant(s) we wish to handle events for (a). The third parameter is the event handler.

Inside the event handler, this is the element the event occurred on (e.g. the <a /> that was clicked). Inside the Event object;

  1. e.target is the element the event occurred on (the same value as this).
  2. e.delegateTarget is the element the event is delegated to (the <table /> element).

Note that jQuery has the same caveat as normal JavaScript when delegating an event to an element; the element you’re delegating to (the table in this case) must exist in the DOM at the time you attach the event.

Controlling Event Bubbling with jQuery

A developer can prevent an event bubbling any further up the list of ancestors if they want to.

To do this, call the stopPropagation() on the event object passed to an event handler. This will execute all other event handlers bound to the current element, but will not propagate up the DOM. You can see this in action here. Even though we’ve bound a click handler to all elements in the ancestor chain, you only see alerts for the a, span and h1, as the h1 handler prevents the event bubbling further.

stopImmediatePropagation() will also prevent the event propagating, but it’ll also stop any other event handlers bound to the current element from firing.

You can check whether an event’s had it’s propagation stopped via the isPropagationStopped() method and isImmediatePropagationStopped() methods.

Another way a developer can stop the event propagating is by returning false from an event handler. This is equivilant to calling stopPropagation() and preventDefault(). I personally recommend against using this shortcut, as it’s use can cause confusion; instead use the methods themselves to make your code more meaningful.