October 8, 2011


HTML5 introduces lots of new and exciting things for web authors, among these are new APIs. Here are some of them.

An API to interact with the application cache, which is a set of cached resources.

You can do window.applicationCache to get the ApplicationCache object that applies to the active document of that window. More on application caches here.

DataTransfer API
The DataTransfer objects are used to expose the drag data store that underlies a drag-and-drop operation. More on drag and drop here.

Command API
A command is the abstraction behind menu items, buttons, and links. They are defined to have facets (label, hint, icon, etc.) and are exposed on elements using this API.

As of this writing, there is no proper definition to this. But we can assume it'll extend our client-side validation tool arsenal.

The History objects provide a representation of the pages in the session history of browsing contexts.

For example, you can go back (window.history.back()) and forward (window.history.forward()). More on session history here.

An API to interact with the <audio> and <video> elements.

You can do things like play (controller.play()) and pause (controller.pause()). More on media elements here.

Text Track API
An API to interact with the <audio> and <video> associated text tracks, like subtitles or captions.

You can get a media element and get a track from it like media.textTracks[0] (for the first one).
textTrack element has it's own API which can return things like the language, readyState, mode, etc. More on media elements here.

APIs for the text field selections
The input and textarea text elements define an API for handling their selection.

You can select everything in a text field with the select() function, or use selectionStart and selectionEnd to get the currently selected text.

By the way, this is not it. There are, of course, other interfaces and current elements that are being extended with new properties and functions.

Related specifications
Now I present to you:
  • Specs that were originally in the HTML5 spec, but were later moved out into their own.
  • Specs worked on by the Web Apps Working Group (in charge of HTML5).
  • Other related/interesting specs.

Canvas 2D Context
Defines the 2D Context for the HTML <canvas> element.

Clipboard API and events
Describes APIs for clipboard operations such as copy, cut and paste in web applications.

Editing APIs
Defines commands to edit HTML documents programmatically.

File API
This specification provides an API for representing file objects in web applications, as well as programmatically selecting them and accessing their data.

File API: Directories and System
This specification defines an API to navigate file system hierarchies.

File API: Writer
This specification defines an API for writing to files from web applications.

Defines two mechanisms for communicating between browsing contexts in HTML documents.

Indexed Database API
Formerly WebSimpleDB API, this document defines APIs for a database of records holding simple values and hierarchical objects.

Server-Sent Events
This specification defines an API for opening an HTTP connection for receiving push notifications from a server in the form of DOM events.

The Web Sockets API
This specification defines an API that enables Web pages to use the WebSocket protocol for two-way communication with a remote host.

Web Storage
This specification defines an API for persistent data storage of key-value pair data in Web clients.

Web Workers
This specification defines an API that allows Web application authors to spawn background workers running scripts in parallel to their main page. This allows for thread-like operation with message-passing as the coordination mechanism.

Enhances the XMLHttpRequest object with new features, such as cross-origin requests, progress events, and the handling of byte streams for both sending and receiving.

And, again, these are not it. There are other working groups in the W3C besides the Web Apps one, each one with specifications they're working on. It's crazy, I know, but hopefully this will give you an idea of what's coming. I strongly recommend you to research more about it and experiment.

Thanks for reading and let me know your comments.

September 11, 2011

CSS Selectors

Have you ever wondered:
  • How many selectors does CSS have?
  • Which selectors come from which version of CSS?
  • How does each selector work?

Me too! so here's what I found out with an example for each one.

E → an element of type E

/* selects any div element in the document */
E F → an F element descendant of an E element
div p

/* selects any p element that is a descendant of a div element */
E.warning → an E element whose class is "warning"

/* selects any element whose class is "banner" */
E#myid → an E element with ID equal to "myid".

/* selects an element with ID equal to "footer" */
E:link → an E element being the source anchor of a hyperlink of which the target is not yet visited

/* selects any unvisited a element */
E:visited → an E element being the source anchor of a hyperlink of which the target is already visited

/* selects any visited a element */
E:active → an E element currently being selected

/* selects any a element currently being selected */
E:first-line → the first formatted line of an E element

/* selects the first formatted line of any p element */
E:first-letter → the first formatted letter of an E element

/* selects the first formatted letter for any p element */
E, F → an element of type E and an element of type F
label, span

/* not really a selector, it's a way of grouping them */
According to the CSS 1 spec: "Anchor pseudo-classes have no effect on elements other than 'A'".

Also, CSS 1 and CSS 2.1 use a single colon to refer to the first-line pseudo-class (:first-line) but CSS 3 uses two colons (::first-line).

CSS 2.1
Includes all previous ones and adds these in:

* → any element

/* selects any element */
E > F → an F element child of an E element
div > p

/* selects any p elements that are direct children of a div element */
E:first-child → an E element, first child of its parent

/* selects a p element, the first child of its parent */
E:hover → an E element when it's hovered over

/* selects any a element when it's hovered over */
E:focus → an E element while it has the focus

/* selects any input element while it has the focus */
E:lang(fr) → an element of type E in language "fr"

/* selects any element which language matches french*/
E[foo] → an E element with a "foo" attribute

/* selects any img element with a title attribute */
E + F → an F element immediately preceded by an E element
div + span

/* selects any span element immediately preceded by a sibling div element */
E[foo="bar"] → an E element whose "foo" attribute value is exactly equal to "bar"

/* selects any p element whose class attribute is exactly equal to "example" */
E[foo~="bar"] → an E element whose "foo" attribute value is a list of whitespace-separated values, one of which is exactly equal to "bar"

/* selects any a element whose title attribute value is a list of
whitespace-separated values, one of which is exactly equal to "copyright" */
E[foo|="en"] → an E element whose "foo" attribute has a hyphen-separated list of values beginning (from the left) with "en"

/* selects any element whose lang attribute has a hyphen-separated list of
values beginning (from the left) with "en" */

Includes all previous ones and adds these in:

E[foo^="bar"] → an E element whose "foo" attribute value begins exactly with the string "bar"

/* selects any object element whose type attribute value begins with "image/" */
E[foo$="bar"] → an E element whose "foo" attribute value ends exactly with the string "bar"

/* selects any a element whose href attribute value ends with ".html" */
E[foo*="bar"] → an E element whose "foo" attribute value contains the substring "bar"

/* selects any p element whose title attribute value contains the
substring "hello" */
E:root → an E element, root of the document

/* selects the root of the document, i.e. the HTML element */
E:nth-child(n) → an E element, the n-th child of its parent

/* selects any tr element that is the third child of its parent */
E:nth-last-child(n) → an E element, the n-th child of its parent, counting from the last one

/* selects any tr element that is one of the two last rows of an HTML table */
E:nth-of-type(n) → an E element, the n-th sibling of its type

/* selects any p element with odd position */
E:nth-last-of-type(n) → an E element, the n-th sibling of its type, counting from the last one

/* selects any p element with even position, starting from the last */
E:last-child → an E element, last child of its parent
ol > li:last-child

/* selects any li element which is a last child of an ol element */
E:first-of-type → an E element, first sibling of its type

/* selects any dt element that is the first sibling of its type */
E:last-of-type → an E element, last sibling of its type

/* selects any td element that is the last sibling of its type */
E:only-child → an E element, only child of its parent

/* selects any tr element that is an only child */
E:only-of-type → an E element, only sibling of its type

/* selects any p element which is the only of its type in a parent */
E:empty → an E element that has no children (including text nodes)

/* selects any empty div element */
E:target → an E element being the target of the referring URI

/* selects any p element that is the target element of the referring URI */
E:enabled → a user interface element E which is enabled

/* selects any input element that is in a enabled state */
E:disabled → a user interface element E which is disabled

/* selects any input element that is in a disabled state */
E:checked → a user interface element E which is checked

/* selects any input element that is selected or is toggled "on" */
E:not(s) → an E element that does not match simple selector s

/* selects all button elements that are not disabled*/
E ~ F → an F element preceded by an E element
div ~ p

/* selects any p element that is a sibling to any div element */

Cascading Style Sheets, level 1
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1)
Selectors Level 3

August 12, 2011


In my last post I wrote about how to detect a JavaScript array, so I thought it would be a good idea to see how jQuery does it.

Here's the jQuery.isArray() method (in 1.6.2):
isArray: Array.isArray || function( obj ) {
    return jQuery.type(obj) === "array";
It uses the native Array.isArray() method if it exists, if not it will find out the type of whatever is passed in using the jQuery.type() method and see if that equals the string "array".

But come on, that's not much of a learning experience not to mention it makes for a pretty short blog post.

So instead, I looked into the jQuery.type() method to see how that works.

It looks something like this:
// Save a reference to some core methods
toString = Object.prototype.toString
// [[Class]] -> type pairs
class2type = {};
type: function( obj ) {
    return obj == null ?
        String( obj ) :
        class2type[ toString.call(obj) ] || "object";
// Populate the class2type map
    "Boolean Number String Function Array Date RegExp Object".split(" "),
    function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
(Distant pieces of code are separated with three dots.)

Breaking it down
  • Line 3 - A reference to the toString() method of Object
  • Line 6 - An internal object (map) that will contain all types as strings.
  • Line 15-19 - For each member in the array we're passing in, we'll create a property in the object and set its value to the name of the array member in lowercase.
  • Line 8-12 - The method will check if the argument passed in is null or undefined, if so, it will return the string "null" or "undefined" (by calling the String constructor without the new keyword, which is allowed for some constructors). If it's something else, we'll call the toString() method on the argument and look to see if the class2type object has a value for it, if not, we'll just return the string "object".

To give you a better overall picture, here's how the class2type object would look after page load:
var class2type = {
    "[object Array]": "array",
    "[object Boolean]": "boolean",
    "[object Date]": "date",
    "[object Function]": "function",
    "[object Number]": "number",
    "[object Object]": "object",
    "[object RegExp]": "regexp",
    "[object String]": "string"

That's why we call the toString() method of Object when we're looking for the property name. Remember how this method returns this sort of "[object Constructor]" string pattern?

So, if we did jQuery.type("hello") we'd actually be doing something like class2type["[object String]"], which would return the corresponding value "string"

And that's how the jQuery.type() method works.

It's not that complicated when you have an "Epiphany" section, huh?

jQuery.type() - jQuery API Documentation
jQuery 1.6.2 Source Code

July 21, 2011

How to detect a JavaScript array

"Piece of cafe" I bet you're thinking, oh I wish it were that easy.

But fear not, JavaScript does have the typeof operator (returns a string) which is very useful for type-checking:
var str = 'hello',
    num = 64,
    bool = false,
    func = function () {},

typeof str; // "string"
typeof num; // "number"
typeof bool; // "boolean"
typeof func; // "function"
typeof undef; // "undefined"
Like shown in the previous code, it works fine for most things. However, it's a little flawed:
var n = null,
    str = new String('hello'), // any wrapper function or custom constructor
    arr = [1, 2, 3];

typeof n; // "object", which is wrong
typeof str; // "object", which is correct but not very useful.
typeof arr; // "object", which is correct but not very useful.

constructor property
Every created object has a constructor property that points to the function that created the object's prototype. You can leverage that reference to do some accurate detections:
var str = new String('hello'),
    arr = [1, 2, 3],
    Person = function (name) {
        this.name = name;

obj = new Person('John');

obj.constructor === Person; // true
str.constructor === String; // true
arr.constructor === Array; // true
isArray method
ECMAScript 5 defines a new method for the Array function called isArray(). If it's not implemented by the browser you can define it like this:
if (!Array.hasOwnProperty('isArray')) {
    Array.isArray = function (value) {
        return Object.prototype.toString.call(value) === '[object Array]';
Invoking the toString() method of Object, gets us a string representation of the object, for arrays it's [object Array]:
var arr1 = [1, 2, 3],
    arr2 = new Array(1, 2, 3);

Array.isArray(arr1); // true
Array.isArray(arr2); // true
Array.isArray(new Number('12')); // false
Array.isArray({}); // false

typeof operator (MDC)
constructor property (MDC)

July 9, 2011

The this keyword in JavaScript

What does this mean?
Short answer, it depends.

In general terms, you could say that the this keyword, in JavaScript, refers to the function's context, how it's invoked. There are four ways in which a function can be invoked: method form, function form, constructor form and apply form.

Method form
If a function is invoked in the method form, this will be bound to the object that owns the function:
var myObj = {
    name: 'Chuck',
    sayName: function () {
        return 'Hello ' + this.name;

myObj.sayName(); // this refers to myObj, returns 'Hello Chuck'

Function form
This means taking a function value and calling it. In ECMAScript 3, this would be bound to the global object:
var myFunc = function () {
    return this.location.href;

myFunc(); // this refers to window (in browsers), returns the current URL
In ECMAScript 5 Strict Mode (almost fully supported), this was changed so that it would refer to undefined instead:
var myFunc = function () {
    'use strict';
    return this.location.href;

myFunc(); // error, this is undefined

Constructor form
A constructor is meant to be called using the new keyword, in this form, this will refer to the object being produced:
var MyConstructor = function (name) {
    this.name = name;
    this.sayName = function () {
        return 'Hello ' + this.name;

var myObj = new MyConstructor('Chuck');
myObj.name; // 'Chuck'
myObj.sayName(); // 'Hello Chuck'

Apply form
Functions are objects and, as most objects, they have methods. This form refers to using the function's methods apply() or call() to call a function. Both methods take whatever first argument you pass and bound this to it. They differ in the way they provide the arguments to the function being invoked.
The apply() method takes an array of arguments:
var myObj1 = {
    name: 'Chuck'
var myObj2 = {
    name: 'Charles'
var sayWelcome = function (location) {
    return 'Hello ' + this.name + '. Welcome to ' + location;

sayWelcome.apply(myObj1, ['New York']); // 'Hello Chuck. Welcome to New York'
sayWelcome.apply(myObj2, ['Toronto']); // 'Hello Charles. Welcome to Toronto'
The call() method takes a list of arguments separated by commas:
sayWelcome.call(myObj1, 'New York'); // 'Hello Chuck. Welcome to New York'
sayWelcome.call(myObj2, 'Toronto'); // 'Hello Charles. Welcome to Toronto'

The value of this depends on the calling form:
  • Method form: it's bound to the object containing the method.
  • Function form: it's bound to either the global object (ECMAScript 3), or to undefined in (ECMAScript 5 Strict Mode).
  • Constructor form: it's bound to the new object being constructed.
  • Apply form: it's bound to the first argument passed to apply() or call().

Crockford on JavaScript - Act III: Function the Ultimate

June 16, 2011

Why your Java math might be wrong

We all know that mathematical operations with decimals in JavaScript are no good. For instance:

alert(1.1 + 2.2); // should be 3.3, but the result is 3.3000000000000003

It turns out this is a cross to bare for pretty much any language that uses the IEEE-754 standard to implement a floating point number and that includes... *drums*... Java.

// Adding doubles
System.out.println(1.1 + 2.2); // 3.3000000000000003

// Adding floats
System.out.println(1.1f + 2.2f); // 3.3000002

So if you're doing these kinds of operations with float or double in Java you might be doing them wrong.

This is huge because an application that deals with money is almost certain to have to deal with decimals. You have to get it right or you'll be in a lot of trouble.

"People have a reasonable expectation that when you’re adding up their money you’re going to come up with the right result, and you don’t" - Douglas Crockford

float and double should never be used for currency or high precision operations.

The proper way to do this is using the BigDecimal class. Check out the documentation.

Let's try it again, this time using BigDecimal:

BigDecimal num1 = new BigDecimal(1.1);
BigDecimal num2 = new BigDecimal(2.2);
System.out.println(num1.add(num2)); // 3.30000000000000026645352591003756...etc.

Oh noes! what happened? I thought BigDecimal was supposed to solve all my problems.

Hold on, take another look at the code above. You'll notice we're constructing our BigDecimal objects using a... *drums*... double.

So? Well, that's the deal with float and double, it's why they should not be used in these operations. They cannot accurately represent numbers with decimals.

OK, how do we fix this? There's a constructor that takes a String argument (didn't you look at the documentation?). That's how we should always do it. Pass a String so you won't lose precision:

BigDecimal num3 = new BigDecimal("1.1");
BigDecimal num4 = new BigDecimal("2.2");
System.out.println(num3.add(num4)); // 3.3, finally

Perfect! now lawsuits won't be falling from the sky.

Thanks for reading and let me know your comments.

Representing money
Beware of floating point numbers

May 26, 2011

How to hide your JavaScript code

Billy Hoffman, author of "Ajax Security", has a very interesting talk about JavaScript named "The Evil Parts" where he talks about the "evil" things a person can accomplish using JavaScript.

One of the things he shows us are two functions, a dehydrate and a hydrate function. He uses them to hide/display malicious code, to "dehydrate" JavaScript, so the code is transformed into whitespace and tabs, therefore becoming invisible.
// to "dehydrate" a string of code
function dehydrate(s) {
    var r = new Array();
    for (var i = 0; i < s.length; i++) {
        for (var j = 6; j >= 0; j--) {
            if (s.charCodeAt(i) & (Math.pow(2, j))) {
                r.push(' ');
            } else {
    return r.join('');
// to "hydrate" a string of code
function hydrate(s) {
    var r = []; var curr = 0;
    while (s.charAt(curr) != '\n') {
        var tmp = 0;
        for (var i = 6; i >= 0; i--) {
            if (s.charAt(curr) == ' ') {
                tmp = tmp | (Math.pow(2, i));
    return r.join('');

So you dehydrate the code to hide it. And you hydrate it back and then eval it to execute it.
The code does become larger (x7 according to him) because it goes character by character transforming them, but hey, it's invisible code!

Give it a try, you know you want to.

Billy Hoffman - JavaScript: The Evil Parts

May 19, 2011

How many global variables are there?

We all know global variables in JavaScript are bad.

If you declare a bunch of variables/functions in the global namespace they become properties of the global object, in the browser that would be the window object.

So the other day I was thinking of a way to find out how many of them were in a page. So I came up with this script that you can run to find out:
(function (window) {
    var document = window.document,
        hasOwnProperty = Object.prototype.hasOwnProperty,
        globals = [],

    for (prop in window) {
        !hasOwnProperty.call(window, prop) && globals.push('@');

    div = document.getElementById('abc-js-globals') ||
    div.id = div.id || 'abc-js-globals';
    div.innerHTML = '<h2>Global Variables:</h2><ul>'
        + globals.join('') + '</ul>';


You can paste that in the Firebug/Inspector console and a list of the globals will show up at the end of the page.
The names that start with @ mean they are properties inherited from the prototype chain.

UPDATE: I changed the code to be slightly faster (I think). I guess that makes it version 1.1.

April 28, 2011


Do you want to know how the trim method works in jQuery? Today is lucky day.

Here's the code from the jQuery 1.5.2 source, I separated distant lines of code with three dots:
// Check if a string has a non-whitespace character in it
rnotwhite = /\S/,

// Used for trimming whitespace
trimLeft = /^\s+/,
trimRight = /\s+$/,
// Save a reference to some core methods
trim = String.prototype.trim,
// Use native String.trim function wherever possible
trim: trim ?
    function( text ) {
        return text == null ?
            "" :
            trim.call( text );
    } :

    // Otherwise use our own trimming functionality
    function( text ) {
        return text == null ?
            "" :
            text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
    trimLeft = /^[\s\xA0]+/;
    trimRight = /[\s\xA0]+$/;

Line 14 is where the ternary action to determine how $.trim will behave begins, all the way through line 26. Another way to look at it is this:
trim: trim ?
    function( text ) {
        // native trimming
    } :
    function( text ) {
        // jQuery trimming

You might find trim: trim hard to understand, but not when you look at the trim variable in line 11. Notice how jQuery stores an internal reference to the native trim method of strings. So, if we have native support for trimming, i.e. checking for truthy value in the trim variable, we go ahead and do it that way but not before checking for null or undefined.

If the browser doesn't have support, we'll check if the passed string is not null or undefined, if it is, we'll return a blank string (just like in the first case), otherwise we'll trim it. Let's see how.

We're calling the toString method on the passed string to, and this is a total guess, make sure we have a string to work with before attempting any operation.

Then we'll trim the left side of the string and after that the right side. The regular expressions for those (in lines 6 & 7) match, pretty much, every type of space you wouldn't want in your string. So, we make sure that the passed string doesn't have those, and if it does, we get rid of them by replacing them with a blank string.

We're just missing lines 2-3 and 28-32. rnotwhite matches a single character other than white space and lines 28-32 check if we should be checking for non-breaking spaces (A0 in hexadecimal) in our trimming, mostly because of IE like the comment says. If so, we need to redefine our trimLeft and trimRight to include matching the non-breaking space character.

Hopefully I'm right about some of this but if not, let me know in the comments.

Thanks for reading.

jQuery 1.5.2 source code
jQuery API - jQuery.trim()

April 21, 2011


The other day I was re-watching (haha, learning through repetition) "11 More Things I Learned from the jQuery Source" and this time I was quite amazed when Paul Irish talked about parseJSON. And the reason was the way jQuery makes the JSON object, it's clever, it's very clever.

Let me show you. Here's jQuery's 1.5.2 parseJSON method:
parseJSON: function( data ) {
    if ( typeof data !== "string" || !data ) {
        return null;

    // Make sure leading/trailing whitespace is removed (IE can't handle it)
    data = jQuery.trim( data );

    // Make sure the incoming data is actual JSON
    // Logic borrowed from http://json.org/json2.js
    if ( rvalidchars.test(data.replace(rvalidescape, "@")
        .replace(rvalidtokens, "]")
        .replace(rvalidbraces, "")) ) {

        // Try to use the native JSON parser first
        return window.JSON && window.JSON.parse ?
            window.JSON.parse( data ) :
            (new Function("return " + data))();

    } else {
        jQuery.error( "Invalid JSON: " + data );

Let's dissect that:
  • Lines 2-4 are just checking you pass a string and its not empty.
  • Line 7 explains itself.
  • Lines 11-13 is a regular expression evaluation to make sure we have valid JSON.

The interesting part, in this case, is the return statement:
return window.JSON && window.JSON.parse ?
    window.JSON.parse( data ) :
    (new Function("return " + data))();

If the browser has native JSON support, use that. If not, and this is the interesting part, we'll do (new Function("return " + data))()

But what does that mean? I'm glad you asked.
  • We're calling the Function constructor, which will return a Function object (function reference) and immediately invoke it.
  • The Function constructor takes an "n" number of arguments that will become the function's parameters, being the last one the body of the function. We're passing only one parameter, meaning "return " + data will become the function's body.
  • What does the constructed function do then? Considering data is a JSON string it becomes rather obvious now. It returns a JavaScript object.
See? I told you it was clever, no need for eval() this way.

Thanks for reading and let me know your comments.

11 More Things I Learned From The jQuery Source by Paul Irish
Function - MDN

April 19, 2011

Beware of Assholes

What is an asshole?
  • Someone who either intentionally or unintentionally infuriates/demeans/damages their peers/superiors/underlings.
  • There are two flavors: Temporary and Certified assholes. A temporary asshole is someone who is probably having a bad day or a bad moment. Certified assholes are persistently nasty and destructive jerks.

Why are they dangerous?
  • Remember how they can damage people? well, at times that includes clients and customers.
  • They undermine organizational performance.
  • Asshole poisoning is a contagious disease that anyone can catch. Once you unleash disdain, anger and contempt or someone else unleashes it on you, it spreads like wildfire.

What should you care?
  • The total costs of assholes are HIGH. From loss of motivation, higher stress and turnover to legal and HR management costs like inside and outside counsel.
  • If you sap the energy out of people, you may be sucking the life out of your career.
  • When people feel mistreated and dissatisfied with their jobs, they are unwilling to do extra work to help their organization.
  • Writing, displaying and repeating words about treating people with respect, but allowing or encouraging the opposite behavior, is worse than useless. The organization and its leaders are seen as hypocrites, which fuels cynicism and scorn.
  • Organizations that drive in compassion and drive out fear attract superior talent, share ideas more freely, have less dysfunctional internal competition, and trump the external competition.

What should you do?
  • Adopt The No Asshole Rule.
  • Have yourself tested.
  • Get rid of assholes fast.
  • Treat certified assholes as incompetent employees.
  • Model and teach constructive confrontation.
  • Improve your hiring process. Recruiters tend to hire candidates who look and act like his or her favorite person on the planet- him or herself. Assholes will hire assholes.
  • Be like Google. Like Google, not "be" Google. They have a "Don't be evil" motto. The company works to screen them out in hiring, and nasty people suffer during performance evaluations and aren't promoted to management positions.

"The No Asshole Rule" by Robert I. Sutton is a must-read for anyone looking to make a difference in their workplace. It is a very entertaining book and quite a learning experience.

This post contains information found in:
The No Asshole Rule: Building a Civilized Workplace and Surviving One That Isn't

March 28, 2011

HTMLCollections & NodeLists

Most of us believed, at least for some time, that in our DOM Scripting, we always dealt with arrays in our JavaScript:
var my_links = document.getElementsByTagName('a'); // we have three links
alert(my_links.length) // outputs "3"

We later found out that the things we thought were arrays, were instead array-like objects. But how exactly are they like arrays? Those "array-like" objects/elements/things, most of the time, are either HTMLCollections or NodeLists, not native JavaScript array objects. Take a look at what the specification says of them, the keyword is live:

"An HTMLCollection is a list of nodes. Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed."
- DOM Level 1

"The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live."
- DOM Level 3

But what does that mean? It means that live collections, if modified, are updated as the program runs. For example, this is an infinte loop:

var i, j,
    my_links = document.getElementsByTagName('a'); // we have three links

for (i = 0, j = my_links.length; i < j; i += 1 ) {

We're getting our collection (of three links) and then for each link that we have, we're going to append another link to the body. So why is this infinite? Because the collection is live, which means that not only will i increment, j also will, so naturally the loop will keep going.

So why are they called array-like objects? If it looks like an array and acts like an array, then it must be an array, right? Wrong, DOM collections look like arrays because:
  • They have an associated index to each value in the container. But that's something an object can have too:
    var my_obj = {
        0: 'zero',
        1: 'one',
        2: 'two',
        3: 'three'
    alert( my_obj[0] ); // 'zero'
    alert( my_obj[3] ); // 'three'
    The alert statements might look like they want the elements with index 0 and 3 but you're really getting the value from the property named 0 and 3.
  • They have a length property. This is deceptive because arrays have this same property, but so do HTMLCollections and NodeLists. But, because these are not true arrays they do not have push, concat, splice or any of the other array methods.

Be prepared, these are some of the DOM methods (that I know of) that return an HTMLCollection or NodeList:

// DOM Level 1/HTML 4.0
// ---------------------------
// Return an HTMLCollection



// Not part of any standard

// DOM Level 2
// ------------------
// Return a NodeList



// WHATWG Web Applications 1.0
// ---------------------------
// Return a NodeList

Throughout this post I've been talking about NodeLists as such and not as live NodeLists because they are inherintely live. There's an exception to this, there are static NodeLists that act as snapshots and do not update when the document is modified:

// Selectors API Level 1
// ---------------------
// Return a static NodeList

In conclusion, I think it's important to know the differences between a live DOM collection a true JavaScript array, it's also an important thing to be aware of because you'll eventually interact with these.

I know so far I've been talking mostly about the DOM (sorry, this wasn't the exception) but you cannot say that this was a boring topic, or was it?

Thanks for reading and let me know your comments.

Why is getElementsByTagName() faster than querySelectAll()?
Speed Up Your JavaScript (video)
HTMLCollection - MDN Doc Center, NodeList - MDN Doc Center
DOM Level 1 Specification, DOM Level 2 Specification, DOM Level 3 Specification

March 3, 2011

Using innerHTML

innerHTML is a read/write property of a DOM element that gets/sets the HTML contained in the element.

It's fast
This might vary between browsers but, it's almost a fact that creating and inserting elements using innerHTML instead of DOM methods is faster, not only at execution time, it'll also make the script size lighter because less code is needed.

It's clean & readable
Although the name, innerHTML, might seem confusing at first, it comes as the better choice in terms of code readability because DOM methods are very verbose and can consume a lot of lines of code.

It's supported
It was first introduced by Microsoft as proprietary to IE and there's no spec that defines the behavior of innerHTML but it has been adopted by all major browsers because of its usefulness and it pretty much works the same in all of them.

Creating and inserting using DOM methods:
var newDiv = document.createElement('div');
newDiv.setAttribute('id', 'new-div');
newDiv.setAttribute('class', 'big-div');
var text = document.createTextNode('Some text here');

document.body.appendChild(newDiv); // div is inserted in the tree

Creating and inserting using innerHTML:
var newDiv = '<div id=\'new-div\' class=\'big-div\'>Some text here</div>';
document.body.innerHTML = newDiv; // div is inserted in the tree

Reasons not to use it

  • Not standard. Although it's fast and it works, the bottom line is that it is not part of any W3C or DOM standard. However, there are plans of adding it to the HTML5 specification.
  • XSS unsafe. You have to know when to use it, otherwise you are exposing your application to XSS attacks, choose DOM methods until you're familiar with the subject.
  • Not implemented everywhere. There are some table related elements, in IE, that can't be modified with it. The implementation and behavior might vary from browser to browser.
  • Destroys the children. Setting a value to innerHTML will destroy every descendant to that element, if any of those descendants had event handlers, that could potentially create a memory leak in some browsers.
Thanks for reading and let me know your comments.

innerHTML (Mozilla Developer Network)
innerHTML (Microsoft Developer Network)

February 28, 2011

Manipulating DOM elements and styles

Manipulating elements
Once you have access to an element, you can manipulate it using assignment of object properties or DOM methods. Let's take a look at the examples:

<img src="small-dog.png" id="img-dog">
var myImage = document.getElementById('img-dog');

// Object property
myImage.src = 'big-dog.png';

// DOM method
myImage.setAttribute('src', 'big-dog.png');

In both examples we're changing the src of our image element. It's recommended to use the first example, it's easier, shorter, faster and works across browsers. If, for some reason, you can't use it, use the second one. Here's a link to quirksmode.org with more information.

You can also change an element's style dynamically . You can do so by changing the className property or applying a style directly into the style object.

<span id="my-span">Some text here</span>
var mySpan = document.getElementById('my-span');

mySpan.className = 'big'; // the CSS class 'big' makes the text big
mySpan.style.textAlign = 'center'; // centers the text

Both, className and style, are read/write. But, the style object will only reflect styles that are directly applied to the element (i.e. in the markup), not the ones from the cascade. To get those you need go a little bit further:

<span id="my-span">Some text here</span>
#my-span { font-weight: bold; }
var mySpan = document.getElementById('my-span');

mySpan.style.fontWeight; // returns an empty string
mySpan.currentStyle['fontWeight']; // returns 'bold', works only in IE
        getComputedStyle(mySpan, null).
        getPropertyValue('font-weight'); // returns 'bold', doesn't work in IE
As you can see:

  • The CSS property on the style object didn't have anything and returned an empty string.
  • IE's proprietary method is very nice and readable (you could also use the dot notation, e.g. mySpan.currentStyle.fontWeight).
  • The standard way is very verbose and complicated but works on all standards compliant browsers.
If you need to get styles individually I suggest creating a utility function to deal with the cross browser issues (an example from quirksmode.org).
But in general, I recommend using CSS classes for dynamic styling. It is way easier and faster to add/modify/delete CSS classes. It's a style agnostic practice, in case you don't have control over the styles, and also encourages layer separation.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the Dom" (2 of 3)

February 7, 2011

The script tag and the DOM

Today I'm going to talk about the DOM. Things you might not know, tricks, nuances and some best practices (I think). So, let's get to it.

The <script> tag
It first appeared in Netscape Navigator 2 as a way to put programs in HTML documents and it then became part of the HTML standard in version 4.
<script type="text/javascript">...</script>

<!-- // -->
The <!-- // --> hack was a workaround to prevent HTML documents from displaying code on the page by older browsers like Mosaic. You can still see this pattern in pages but it's no longer necessary as today's browsers understand both the script tag and JavaScript.
<script type="text/javascript">
  code here
// -->

The language attribute
Microsoft came up with it as a way to select what kind of language (e.g. VBScript) you wanted to use for your program. The W3C deprecated this in favor of the type attribute. Avoid the language attribute.
<script language="javascript" type="text/javascript">...</script>

The src attribute
It allows you to load a script from an external file. Great, because you don't want to put JavaScript in your HTML, for a large number of reasons: it makes the HTML file heavier, it becomes less maintainable, it becomes less scalable, it's not cachable, it becomes hard to minify or inspect, etc. It is highly recommended that you do not write JavaScript in your HTML and instead use the src attribute.
<script type="text/javascript" scr="js/script.js"></script>

The type attribute
The W3C added the type attribute to replace the language one. It takes a MIME type instead of the name of the language. The official MIME type for JavaScript is application/javascript or application/ecmascript and the most up to date browsers understand this, but not IE. So, if you want cross-browser support (and you should) you have to use type="text/javascript", at least for now. This is a required attribute for HTML validation, but in practice you can just leave this out, the default language on all major browsers is JavaScript and besides if you're using src, it ignores it.
<script type="text/javascript">...</script>
<script type="text/javascript" src="js/script.js">...</script>
<script src="js/script.js">...</script>

Loading time
Because of the way the browser works, loading of a page's assets is incremental and single-threaded, it is recommended that the script tags be placed as low in the body as possible. It is also recommended to place your CSS i.e. link, as high in the head as possible, this will greatly improve the user experience.
You should also minify, gzip and join your script files into one. These will reduce file size and the number of HTTP requests and thus, the time it takes for the browser to load the page.
    <link rel="stylesheet" type="text/css" href="css/styles.css">
    <!-- head contents here -->
    <!-- body contents here -->
    <script type="text/javascript" src="js/script.js"></script>

If you call this before the onload event triggers it will insert stuff into your document, but if you do it after it, it destroys your document and replace it with new stuff. You should avoid using document.write, there are better alternatives now.

  • document.anchors
  • document.applets
  • document.embeds
  • document.forms
  • document.frames
  • document.images
  • document.plugins
  • document.scripts
  • document.stylesheets
Netscape provided these as a way to get and modify elements easier. These are still available but obsolete and you should avoid using them as there are better alternatives now.

The name and id attributes
If an element didn't have an id but it had a name with the same value, you could still get access to it via DOM methods. They used to be interchangeable but they are not anymore.

<input type="text" name="firstname" value="my value">
The JavaScript:
var input = document.getElementById('firstname');
input.value = 'another value'; // sets a value to "firstname" field

Microsoft came up with this as a type of super collection that contained any tag that had a name or id. Since this is propriety thing and not cross-browser, it is best to not use it.

Some of the topics that I did not cover in this post were browser history, how a browser works and document tree structure. If you're interested, click the link below to watch the video.

Thanks for reading and let me know your comments.

Source: Douglas Crockford: "Theory of the DOM" (1 of 3)