Follow me: @D_mitar

Most read posts recently



Sep 18th 2012 × Extend Slick pseudo selector to find data-attributes

This is a relatively simple idea. Select elements with data-attributes that match a pattern, for example, div[data-media-*]. The problem is, CSS selectors don;t allow you to wildcard attributes themselves so we need to be creative.

We will extend the Slick selector engine with a data pseudo selector, which will look at the outerHTML of the element and find a match for the attrbute, starting with data-value*:

Slick.definePseudo('data', function(value){
    // wildcard data-startswith search
    var outer = this.outerHTML || new XMLSerializer().serializeToString(this);
    return outer.test('data-' + value);
});

console.log($$("div:data(media-)")); // return all divs with data-media-* attribute

This is it at a first reading. Now, given how performance is important, especially if used on a large DOM without a qualified selector, let’s see if we can optimise it by using a closure where the setup takes place. We will cache the strings we reuse so no new strings need to be made for each element passed to Slick, as well as a single instance of the XMLSerializer, used by the fallback when outerHTML is not available. We also go to Array.join instead of string concatenate for small gains in IE6/7/8

(function(){
    // cache reusable strings
    var data = 'data',
        hyphen = '-',
        // set the fallback via XMLSerializer, if no outerHTML (eg. FF 2 - 10)
        XS = this.XMLSerializer && new XMLSerializer();

    Slick.definePseudo(data, function(value){
        return (this.outerHTML || XS.serializeToString(this)).test([data, value].join(hyphen));
    });
}());

Happy coding.


Aug 21st 2012 × Spying unobtrusively on Class instance events in MooTools

Ever needed to debug how your Class instances fire Events? It can be frustrating and messy, especially if you do not have access to the original Class prototype source. But, you can hack your way around this and create a transparent spy on all fireEvent methods on any Class instance. Here is how:

(function() {
    var spyId = 'spyEvent';

    Class.extend({
        addEventSpy: function (instance) {
            /*
            accepts one argument - Class instance.
            works by adding a local fireEvent method on the instance
            instead of going TO proto chain to Class.Event::fireEvent
            */

            // check if there's a local fireEvent method or already installed spy
            if (instance.hasOwnProperty('fireEvent') && instance.fireEvent.name == spyId) {
                console.log('ERROR: Already have a local fireEvent method');
                return;
            }
            // Events need to be mixed in.
            if (!instance.fireEvent) {
                console.log('ERROR: Can only spy on class instances with an Events mixin');
                return;
            }
            // store original
            var orig = instance.fireEvent;
            instance.fireEvent = function spyEvent() {
                // log to console or do your own observer logic
                console.log('EVENT SPY', this, 'fired', arguments);
                // allow chaining.
                return orig.apply(this, arguments);
            };

        },
        removeEventSpy: function(instance) {
            // clean up that restores orignal if possible.

            // not needed? already using proto one.
            if (!instance.hasOwnProperty('fireEvent')) return;

            // it has a local fireEvent but it needs to be our spy, else it's unsafe.
            if (!instance.fireEvent.name || instance.fireEvent.name != spyId) {
                console.log('ERROR: Somebody else has done this fireEvent');
                return;
            }
            // remove it.
            delete instance.fireEvent;
        }
    });

}());

This is the setup code. Now, you can use it on a Class and test it:

// define a class that uses events
var a = new Class({

    Implements: Events,

    initialize: function() {
        this.events = 0;
    },

    doEvent: function() {
        this.events++;
        console.log('do event', this.events);
        return this.fireEvent('awesome');
    }
});

// make the instance
var b = new a();

// subscribe to all events
Class.addEventSpy(b)

// try firing 2 quick events
b.doEvent().doEvent();    

// clean up spy.
Class.removeEventSpy(b);

// test spy is gone.
b.doEvent();

I hope it is of some use to you. See it in action in this fiddle


Jul 13th 2012 × Epitome does todo

Just a quick update, my MooTools MVP library Epitome now has its own Epitome-todo repository as a submodule, an implementation of the popular TodoMVC demo.

You can see it live here.

If you checkout Epitome from git, you can use:

git submodule init
git submodule update

… and point your browser to your local `example/todo/epitome/` folder.


Jul 6th 2012 × Epitome goes CI via buster.js and Travis CI

Just a quick note – the MooTools MV* framework I wrote for QMetric called ‘Epitome‘ is now covered by Travis CI automated testing.

Read more about how to implement this in your javascript projects in this blog post on the QMetric Tech Blog.


Jun 13th 2012 × So you want delayed events in your mootools class?

I recently found that in the context of Class, .fireEvent() accepts a 3-rd argument, delay. Firing deferred events can be useful but you need to understand the full difference between the patterns available at your disposal.

Pattern one. It relies on delay creating a function and passing arguments to that function at the time of invocation. Does not actually fire until time is due, but the arguments will be saved during invocation (unless they are objects, therefore by reference).

var a = new Class({

    Implements: [Events],

    initialize: function() {
        this.foo = 1;
        this.fireEvent.delay(1000, this, ['event', [this.foo, 'moar']]);
        // won't actually fire until time is due.
        this.addEvent('event', function() {
            console.log(arguments, this);
        });

        this.foo = 2;
    }

});

new a();

In pattern #2, we use the delayed event provided by MooTools. The key thing here is that the event actually `fires` at the time of invocation but does not arrive until the due time. The problem is, ‘just-in-time’ adding of the event after won’t work as there is no event handler prior to calling .fireEvent. In this example, nothing will log – but you can add your event before firing. Arguments will be the same as at the of invocation.

var b = new Class({

    Implements: [Events],

    initialize: function() {
        this.foo = 1;
        this.fireEvent('event', [this.foo, 'moar'], 1000);
        // has already fired, so adding the event handler now is pointless
        this.addEvent('event', function() {
            console.log(arguments, this);
        });

        this.foo = 2;
    }

});

new b();

In pattern 3, we wrap things into an anonymous function that is deferred for later via setTimeout (well, Function.delay() which is the same thing). The bonus to this pattern is that it will dispatch the value at the time of firing, not at the time of deferral.

var c = new Class({

    Implements: [Events],

    initialize: function() {
        this.foo = 1;
        (function() {
            this.fireEvent('event', [this.foo, 'moar']);
        }).delay(1000, this);

        // only pattern that uses fresh enough data
        this.addEvent('event', function() {
            console.log(arguments, this);
        });

        this.foo = 2;
    }

});

new c();

Hope this gives you something to take away in your app development. Look at the jsfiddle and your console here: http://jsfiddle.net/dimitar/mTkvE/


Jun 11th 2012 × Epitome: an example MooTools model / MVC tutorial

I have been a little busy at work but we recently built a small Model class to support our question set and I turned it into a tutorial on how to build your own MV* framework on top of MooTools. It is called ‘Epitome‘ and is available on GitHub here: https://github.com/DimitarChristoff/Epitome. Keep in mind that it may turn out to be MVP/MVVM and not semantic MVC…

You can read the 2 blog posts I wrote on creating the Model and adding the Sync. More coming when I get time…


May 28th 2012 × new mootools github repos for handy little tools

Right then. If you don’t follow me on github, this will be news to you.

Storage. https://github.com/DimitarChristoff/Storage – it’s a class that allows you to API localStorage or sessionStorage, when available – with a fallback to using window.name in older browsers like IE6/7. It can be used as standalone or as a mixin (implemented) class within any other class. It also namespaces each instance within the storage so it can occlude nicely.

And…

Do you remember Router? I had liked it some months back. Turned out, it benefited from a rewrite / refactor and is now a lot more mootoolish. Though Rado accepted my pull request so I can probably delete my fork, leaving it there for now in case I think of anything else.


Apr 27th 2012 × StrongPass: A password strength helper class

Good news, everyone (I miss Futurama).

Three years ago I wrote a mootools plugin for password strength checking, based upon a stack overflow jquery post. I just had cause to revisit this for work at QMetric and refactored it (read, rewrote from scratch) for MooTools 1.4+

The Class is on the forge, it’s fairly flexible and can either be styled to use the default strength indicator or to output whatever you like based upon pass/fail events and scores.

You can check it out here: http://mootools.net/forge/p/strongpass or if you prefer, head to the GitHub repo directly here instead: https://github.com/DimitarChristoff/StrongPass

Links to demos are in the README.md as well as a basic buster.js test suite. Use responsibly!


Feb 13th 2012 × MooTools plugins round-up

Time for a round-up of interesting / quality plugins on the MooTools forge or github. Again.

First off, my favourite find over the last month has to be the MooTools Router. What it does is handle application paths for hashes in the style of the Backbone.js router but it’s really a normal MooTools class. It can tackle dynamic parameters rather well and raises some warnings / events you can work with. For example:

BO.Router = Router.implement({
    // routes definition
    routes: {
        '#!customer/:id/'           : 'loadCustomer',
        '#!customer/:id/cancel/'    : 'cancelCustomer',
    },

    // router init
    init: function(){
        console.log('init')
    },

    loadCustomer: function() {
        console.log("loading customer with id " + this.param.id);

        BO.user.model.set({
            id: this.param.id
        });

        BO.user.model.on("change", function() {
            BO.user.view.render();
        });

        BO.user.model.fetch({
            success: function() {
                BO.user.model.off("change");
                BO.user.model.trigger("fetch");
            }
        });

    }
});

Second. Twipsy – It’s a port of the Twitter Bootstrap Twipsy tooltip plugin (now renamed in BootStrap 2.0 to bootstrap-tooltip.js). Rather nice and just works. Also, extendible so you can implement the boostrap-popover.js through it.

Third. A plugin by yours truly and Arian from mootools-core – it’s scrollspy. That’s not David Walsh’ scrollspy, it’s a port of the Twitter Bootstrap scrollspy instead. It allows you to react to elements of interest that come into view and do things to them or your nav items that are somehow related.

Fourth. “MooStrap offers the initialization function of large-scale application from middle-scale. Every one initialization processing is performed and it secures that initialization of application is ensured.” – well, perhaps english is not their strong part but if you can get past things like ‘paturn’, it does provide a nice platform to build on.

Last but not least. Composer.js is a nice alternative to Backbone.js in MooTools. It is early days but it’s looking promising for the lyonbros plugin. There are some differences in terms of approaches vs Backbone or Spine but it gets the job done. Only downside is, not mature enough and lack of tests supplied make it difficult to build on it and contribute. Hopefully, easily fixed.


Feb 10th 2012 × MooTools Request.Spy – monitor all requests through the Request class prototype

An interesting question on StackOverflow prompted me to look into creating a universal spy/logger for all Requests that MooTools. The objective is: being able to log / spy on all XHR requests w/o modifying code anywhere.

It is trivial to override the Request Class and change the prototype of the success and failure. The problem is, Request is extended and used by Request.HTML and Request.JSON, who in turn override these methods. So we need something more flexible.

After a LOT of thinking, I eventually came up with this solution, which automates it and gives a nice API:

(function() {
    // what we will extend
    var classes = [Request, Request.HTML, Request.JSON],
        // map to a text name
        mapper = ["Request", "Request.HTML", "Request.JSON"],
        // store reference to original methods
        orig = {
            onSuccess: Request.prototype.onSuccess,
            onFailure: Request.prototype.onFailure
        },
        // changes to protos to implement
        changes = {
            onSuccess: function(){
                Request.Spy && typeof Request.Spy == "function" && Request.Spy.apply(this, arguments);
                orig.onSuccess.apply(this, arguments);
            },
            onFailure: function(){
                Request.Spy && typeof Request.Spy == "function" && Request.Spy.apply(this, arguments);
                orig.onFailure.apply(this, arguments);
            }
        };

    // implement our changes object into the classes
    classes.invoke('implement', changes);

    // allow us to tell which Class prototype has called the ajax, only needs to go on Request,
    // the other subclasses will inherit it automatically.
    Request.implement({
        getClass: function() {
            var ret;
            Array.each(classes, function(klass, index) {
                if (instanceOf(this, klass)) {
                    ret = mapper[index];
                }
            }, this);
            return ret;
        }
    });
})();

// to enable spying, just define Request.Spy as a function:
Request.Spy = function() {
    // you can implement a pub/sub system via trivial events here, making requests available to your app at any time.
    console.log(this.getClass(), arguments);
};

// test it via normal Request
new Request({
    url: "/echo/html/",
    data: {
        html: "normal data"
    }
}).send();

// test via HTML
new Request.HTML({
    url: "/echo/html/",
    data: {
        html: "<p>normal data</p>"
    }
}).send();

// test via JSON
new Request.JSON({
     url: "/echo/json/",
     data: {
        json: JSON.encode({'normal':'data'})
     }
}).send();

You can see it in action in this jsfiddle: http://jsfiddle.net/dimitar/3rnKe/. Hope somebody finds it useful. P.S. strictly speaking, you only need to apply the method to the sub classes if they have their own implementation of onSuccess or onFailure. Else, changing the prototype of Request is enough. To make this universal for any class, you can check via hasOwnProperty and if so, apply, else – skip.