Posts Tagged ‘Mootools’

A framework-agnostic model

Posted in 'JavaScript' by James on March 11th, 2009
A framework-agnostic model

If there’s one problem with frameworks in general it’s that they create dependency. If you start developing your web application with PrototypeJS you have, without noticing, made a long-term decision in regard to how your app will be developed from that day on. This dependency is not easily avoidable. The very concept of framework-centered development relies on it.

When we’re talking about JavaScript specifically this is even more true because many JS frameworks will totally change the way in which you code! jQuery is not only a helper library; it’s a totally new way of programming in JavaScript, and because of this it becomes a nightmare when you want to port over to PrototypeJS or MooTools.

Dependency isn’t always a bad thing but it really needs to be considered before blindly adopting some random framework!

If you want an easily portable web application without this dependency then most people would probably suggest no framework at all, but in my opinion a more modular approach would be better; one which allows you to use any framework but without the dependency:

The idea behind this is to take all easily abstracted functionality and bundle it into a single object, here’s an example:

var URLGatherer = (function(){
 
    /* Easily abstracted functionality: */
    var setup = {
 
        DOM : {
            querySelectorAll : jQuery.find
        },
 
        arrayUtils : {
            map : jQuery.map,
            /* jQuery doesn't offer a 'unique' method (for regular arrays)
               so you could quite easily use one from another library. */
            unique : anotherLib.unique
        }
 
    };
 
    return {
 
        gather : function() {
            var anchors = setup.DOM.querySelectorAll('a'),
                hrefs = setup.arrayUtils.map(anchors, function(anchor){
                    return anchor.href;
                });
            return setup.arrayUtils.unique(hrefs);
        }
 
    };
 
})();
 
/* Usage: */
URLGatherer.gather(); // Returns array containing all HREFs on page

All “easily abstracted functionality” has been put in the setup object. The benefit of using this model is that no real dependencies are created. Switching from jQuery to Dojo or from Prototype to MooTools is no problem because you’re containing their abstractions in a single object which can be easily changed at any time!

Element data/storage

Posted in 'JavaScript' by James on February 21st, 2009
Element data/storage

One of the more exciting hidden features of jQuery is its ability to bind data to any DOM element. What’s special about this is that it’s almost completely unobtrusive – the data is not actually bound to the DOM element at all. A numerical pointer is added to the element as an "expando" property; this number points to that element’s assigned spot within jQuery’s cache. The cache is just a regular object and each element’s data is added as a nested object.

MooTools also offers its own variation of element storage. It uses the same method of creating a numerical pointer to a global hashtable. According to this blog post the Prototype library will also be implementing it soon.

// jQuery:
    // Set data:
    $(elem).data('customProperty', 12345);
    // Get data:
    $(elem).data('customProperty');
 
// MooTools:
    // Set data:
    elem.store('customProperty', 12345);
    // Get data:
    elem.retrieve('customProperty');

The point?

Before all this fancy element storage stuff was used the widely accepted method of adding data to elements was to literally add each piece of data as a separate expando property. Not only was this obtrusive but adding a lot of data could massively slow down DOM manipulation (or so I’ve heard). The new method makes much more sense and is much faster apparently.

Creating your own

Implementing your own element storage mechanism is very simple. Like I said, it’s just a case of creating a cache, adding to it and retrieving from it. Here’s a basic attempt:

// WITH ENCAPSULATION:
(function(){
 
    var cache = [0],
        expando = 'data' + +new Date();
 
    function data(elem) {
 
        var cacheIndex = elem[expando],
            nextCacheIndex = cache.length;
 
        if(!cacheIndex) {
            cacheIndex = elem[expando] = nextCacheIndex;
            cache[cacheIndex] = {};
        }
 
        return {
            get : function(key) {
                return cache[cacheIndex][key];
            },
            set : function(key, val) {
                cache[cacheIndex][key] = val;
                return val;
            }
        }
 
    }
 
    window.data = data;
 
})();

Everything is wrapped inside a closure so that the global namespace is not polluted. The cache is only accessible to functions within the same scope. The data function is exposed at the end of the closure so you have access to it. If you’re wondering why the cache is initiated with one value (0) it’s so that checking the expando property doesn’t ever return 0 (a falsey value) – this would make checking for a non existent property a tad harder.

Usage is quite simple:

var myElem = document.getElementById('id');
 
// Setting data:
data(myElem).set('customProperty', 12345);
 
// Retrieving data:
data(myElem).get('customProperty'); // returns 12345

If you’re not a fan of encapsulation and would prefer more direct access to each element’s dataset then this probably suits you more:

// WITHOUT ENCAPSULATION:
(function(){
 
    var cache = [0],
        expando = 'data' + +new Date();
 
    function data(elem) {
 
        var cacheIndex = elem[expando],
            nextCacheIndex = cache.length;
 
        if(!cacheIndex) {
            cacheIndex = elem[expando] = nextCacheIndex;
            cache[cacheIndex] = {};
        }
 
        return cache[cacheIndex];
 
    }
 
    window.data = data;
 
})();

It works on exactly the same principle, the only difference is that you have direct access to each element’s data object and you can traverse it using normal dot notation (like any object):

var myElem = document.getElementById('id');
 
// Setting data:
data(myElem).customProperty = 12345;
 
// Retrieving data:
data(myElem).customProperty; // returns 12345
 
// The data can be ANYTHING! -
data(myElem).info = {
    a : 123,
    b : [4,5,6]
};

For me, the second version (without encapsulation) is a little nicer, not only because it’s shorter but also because I have direct access. For something like this there’s no sense in having ‘get’ and ’set’ methods – it’s just syntactic sugar.

Experimenting…

I was thinking about possible different methods of achieving this without the need for even one expando property – so the DOM element in question does not change at all.

You could have the cache’s indexes correspond to an element’s position within the DOM but this is unreliable because there is always the possibility that the DOM may change. I then tried to think of some way to store a reference to each element and then look it up when needed but that really didn’t work out. Another way would be to identify certain unique properties of each element and use them as pointers – but it’s likely that these unique properties will also be susceptible to change.

So, it seems there is no way to avoid the use of at least one expando property per element…

Getting the real time in JavaScript

Posted in 'Code Snippets, JavaScript, News, PHP, Uncategorized, Usability' by James on January 29th, 2009

Getting the time in JavaScript is pretty simple. Using the Date constructor will give us the time as set on the user’s computer, but what if we want the accurate time, or the time in a different timezone?

Even with getTimezoneOffset() you’re still relying on the client!

It turns out that the only way of getting a complete and accurate time from any timezone requires a little bit of server interaction. Luckily there are a few APIs out there that offer this service (actually, there’s only one; well I couldn’t find any others)!

Here we’re using the ‘json-time’ API developed by Simon Willson:

JSON-time

function getTime(zone, success) {
    var url = 'http://json-time.appspot.com/time.json?tz=' + zone,
        ud = 'json' + (+new Date());
    window[ud]= function(o){
        success && success(new Date(o.datetime), o);
    };
    document.getElementsByTagName('head')[0].appendChild((function(){
        var s = document.createElement('script');
        s.type = 'text/javascript';
        s.src = url + '&callback=' + ud;
        return s;
    })());
}

Usage

The first parameter of the callback function is the time (having been passed through the Date constructor), so you can use Date methods such as getSeconds() etc. The second parameter is the entire object returned from the JSON request.

// Alert GMT:
getTime('GMT', function(time){
    alert(time);
});
 
// Get London time, and format it:
getTime('Europe/London', function(time){
    var formatted = time.getHours() + ':' 
                  + time.getMinutes() + ':'
                  + time.getSeconds();
    alert( 'The time in London is ' + formatted );
});

For reference, here’s a list of all the available timezones (to use one, remove the backslash).

jQuery version

$.getTime = function(zone, success) {
    var url = 'http://json-time.appspot.com/time.json?tz='
            + zone + '&callback=?';
    $.getJSON(url, function(o){
        success && success(new Date(o.datetime), o);
    });
};
 
// Usage:
$.getTime('GMT', function(time){
    alert(time);
});

MooTools version

You’ll need to download the JsonP class.

function getTime(zone, success) {
    var url = 'http://json-time.appspot.com/time.json';
    new JsonP(url, {
        data: { tz: zone },
        onComplete: function(o){
            success && success(new Date(o.datetime), o);
        }
    }).request();
}
 
// Usage:
getTime('GMT', function(time){
    alert(time);
});

Thank you Simon Willison for making this API; seriously, I searched around the entire internets just for one damn API and I almost lost hope!

JavaScript libraries vs. Usability

Posted in 'JavaScript, Usability' by James on October 18th, 2008
JavaScript libraries vs. Usability

JavaScript libraries like MooTools, jQuery, Dojo and Prototype have proven very popular with developers recently, perhaps too popular!?

Over the last year there’s been a major recognition boost for these libraries, especially those featuring animations/effects and Ajax capabilities. Blinking/fading/sliding text was in fashion back in the nineties but it seems, following the hype of Web 2.0, these effects have made a massive comeback!

To be honest I think it’s great; what better way to expand the imagination of the average developer than to give him/her some brand new toy to play with? Web developers are now thinking of innovative ways to utilise these new-found JavaScript enhancements and designers are pushing boundaries with their designs, integrating these enhancements into their mockups!

This is all wonderful, but unfortunately I fear the overuse of JavaScript libraries such as jQuery has had a detrimental effect on usability. Obviously we had issues before these libraries and we will surely continue to rave about it afterwards but I cannot help but notice what is happening right now; people are turning a blind eye to usability and focusing all their attention on making their websites as smooth and swish as possible!