Tuesday, January 31, 2012

Creating a lightweight JavaScript DOM wrapper for HTML5 applications

I am writing an HTML5 application that I want to run smoothly on both PC's and tablets. Tablets have less memory and processor power than regular PC's and I have been searching for web application design tips that take this fact into account. For instance, I love using the jQuery library but I doubt that it is the best JavaScript solution for mobile devices. It is quite large and targets many different browsers, including the ones that are not fully W3C standards compliant like Internet Explorer 7. A good example is the way that jQuery implements the .ready() method. That method provides Internet Explorer specific fallbacks in case document.addEventListener is not available. I do not need this level of abstraction since I already know that I want my application to run only in browsers that are fully HTML 5 compatible. Examples of those browsers are Chrome, FireFox, and Safari. The Safari brower is also the default browser on one of the major tablet PC's: the iPad.

After taking the above considerations into account and having read some excellent tips ("Don’t rely on frameworks"), I decided to write my own minimalist JavaScript DOM wrapper. Its primary focus is on mobile devices: I try to keep its (compressed) file size as small as possible, and include only those features that I use most. You can find the source code below. If you have any suggestions for improvement, please leave a comment!

(function (window) {
    var document = window.document;

    function WrapIt(selector) {
        this.selector = selector;
        this.element = (typeof selector === "string") ?
            document.getElementById(selector) : selector;
    }

    WrapIt.prototype = {
        get: function () {
            return this.element;
        },

        ready: function (handler) {
            function domReady() {
                document.removeEventListener("DOMContentLoaded", domReady, false);
                handler();
            }
            document.addEventListener("DOMContentLoaded", domReady, false);
            return this;
        },

        next: function () {
            if (this.element && this.element.nodeType) {
                var elm = this.element.nextSibling;
                while (elm && elm.nodeType != 1) {
                    elm = elm.nextSibling;
                }
                return new WrapIt(elm);
            }
            return null;
        },

        previous: function () {
            if (this.element && this.element.nodeType) {
                var elm = this.element.previousSibling;
                while (elm && elm.nodeType != 1) {
                    elm = elm.previousSibling;
                }
                return new WrapIt(elm);
            }
            return null;
        }
    }
    window.$ = function (selector) {
        return new WrapIt(selector);
    }
})(window);

Like jQuery, the wrapper uses a handy $ shortcut to refer to DOM elements. Because each function in the WrapIt class returns an instance of the same class, you can use a fluent syntax and chain function calls as follows:
$("MyDivElementId").next().get().id
This will return the ID of the sibling element that is next to the 'MyDivElementId' element.
I also use the following in most of my HTML pages:
$(document).ready(function () {
    // Do something when the page DOM content has been fully loaded (but
    // before the loading of related files like images).
});

No comments:

Post a Comment