Follow me: @D_mitar

Most read posts recently



Jul 6th 2011 × MooTools pattern fun: Class Implements + Extends at the same time

Update: Thanks to @CarstenSchwede, who pointed out that the MooTools Class Constructor expects the Extends mutator __before__ the Implements one, meaning you don’t need to worry about any of the stuff I had to come up with (described in this post). Upon further investigation with Arian, it turns out that MooTools 2.0 will NOT be dependent on order of Extends and Implements declarations in classes, thanks to this change by Kamicane.

The neverending debacle of Extends vs Implements, which one to use and how to use them together – has been a source of discomfort for me in MooTools for a while so I thought I’d write up parts of my experiences with it in the hope it may help somebody else.

I came to have a need to write a class that serves as my new mixin and brings a new method ‘kill‘ – (say, Class ninja) to another class (Class badass) that extends Class human. Pretty crazy, right?

The problem is, the pattern of:

var ninja = new Class({
    kill: function() {
        alert("kill!");
    }
});

var human = new Class({
    initialize: function(){
        alert("i r human!");
    }
});

var badass = new Class({
    Implements: [ninja],
    Extends: human,
    initialize: function() {
        alert("i r badass and.. ");
        this.parent();
        this.kill();
    }
});

new badass(); // i r badass, i r human, this.kill is not a function exception.

… simply does not work. The Extend here means the human prototype is the base and it lacks the kill method. Wut?

The main practical difference in subclassing approaches is that the `Implements` (mixin) does not instantiate the subclass whereas `Extends` does, so there can be only one class that is extended whereas implemented ones just copy the methods from the prototypes. How to get around being able to extend a single class only? You need class human to implement ninja instead and class badass to simply extend human. Aside from the side-effect of humans getting a new kill method (which they may or may not know about), it will mean that badass will be able to use .kill as well as call upon his direct parent human.

The whole point is, you may not always be at liberty to rewrite / refactor classes the way you want them without creating complications with other parts of your web app. You could also be be extending a Mootools native class like Request.JSONP and then decide to mixin a new storage class into your extended one (true story!)…

An interesting pattern (or rather, the only pattern I have found to work… ) to overcome this goes something like this:

var ninja = new Class({
    kill: function() {
        alert("kill!");
    }
})

var human = new Class({
    initialize: function(){
        alert("i r human!");
    }
});

human.implement(new ninja);

var badass = new Class({
    Extends: human,
    initialize: function() {
        alert("i r badass and.. ");
        this.parent();
        this.kill();
    }
});

new badass(); // this.kill works.

You could even write this as:

Extends: human.implement(new ninja),

Obviously, you can simply modiy the prototype of the parent class and do:

human.implement({
    kill: function() {
        alert("kills!");
    }
});

But this means the code you already have in ninja needs to be duplicated and this will go for all methods or properties you want to gain access to.

A practical example with Request.JSONP and an example caching class, created to allow use of localStorage. Why would you want to do that? Well, having a class that can allow you to cache replies from Request or Request.JSONP or anything at all is handy. And doing things that fetch non-volatile data through a rate-limited API is expensive, you are encouraged to cache. In other words, if you read a particular user’s Twitter profile / timeline, you should not have to request it again on a reload within the session. Same applies if you are expanding tiny URLs like bit.ly – the URL won’t change for any given hash so there’s no point in continuously fetching it.

In the following example, we cache the response for a user profile JSONP request via the Twitter API:

View the full fiddle here: http://jsfiddle.net/dimitar/AjP5A/.

For a real detailed explanation of Extends vs Implements in MooTools, grab a copy of Pro Javascript with MooTools by keeto.


May 13th 2011 × mootools flickr api class via Request.JSONP

updated for mootools 1.3.2

I needed to bring some images into a thumbnail/gallery and decided to use flickr’s API for easy access. The result is a mini-api which allows you to control your options and parse the images that flickr sends back.

// the class
Request.flickr = new Class({
    Extends: Request.JSONP,
    options: {
        callbackKey: "jsoncallback",
        url: "http://www.flickr.com/services/rest/?",
        log: true
    },
    initialize: function(params, options) {
        this.parent(options);
        this.options.url = this.options.url + Object.toQueryString(params);
    },
    success: function(data, script) {
        this.parent(data, script);
    },
    imageURL: function(obj) {
        return "http://farm{farm}.static.flickr.com/{server}/{id}_{secret}.jpg".substitute(obj);
    }
});

// how to use
new Request.flickr({
    format: 'json',
    api_key: "e7df6c74d2545f55414423463bf99723", // your api here
    per_page: 4,
    tags: "mountains",
    method: "flickr.photos.search"
}, {
    onSuccess: function(data) {
        target = $("action");
        var self = this;
        data.photos.photo.each(function(el) {
            new Asset.image(self.imageURL(el), {
                onload: function() {
                    this.inject(target);
                }
           });
        });
    }
}).send();

Want to see it in action? Here’s an embedded jsfiddle:



May 12th 2011 × CKeditor blues: when it fails to pass on the data via AJAX

CKeditor is a good WYSIWYG content editor and is very popular in various CMS and on-page editing tools. It _tends_ to work and is helpful to those who cannot use HTML natively.

However, from a developer standpoint – it can cause some headaches and it lacks proper API (or otherwise documentation). All you get is a brief reference and you can explore the prototypes and guess.

The problems start when you have a form that you handle through AJAX (XHR) that contains CKEDITOR instances for textareas. Intermittently, the submitted data would fail to update the database without any apparent reason.

After some digging, I came to write a fix (through MooTools 1.3) that is incorporated at the form handler prior to the AJAX call. The idea is simple: find any CKEDITOR instances, retrieve them, get the formatted HTML data out and set it as the value of the original textarea element so that the form will save correctly.

document.id("myform").addEvent("submit", function(e) {
    e.stop();
    // find instances, loop through them
    Object.each(CKEDITOR.instances, function(instance, key) {
        // find a form element that has the same id or name attribute
        var el = document.id(key) || document.getElement("name=[" + key + "]");
        if (el) {
            // set matching original element's value to data
            el.set("value", instance.getData());
        }
    });

    // continue with form processing now.
});

I hope it helps somebody as it has been a nuisance for me for a while.


May 3rd 2011 × A powerful and simple mootools modal window class called “baseBox”

This was completely overhauled.

Basically, I just released a new mootools modalBox Class called ‘baseBox’. You can see it on jsfiddle and play with it some. Full details, documentation are available on the project github page.

mootools modal box class

Features:

  • Full CSS support – whatever you do, it assigns to the box.
  • Complete control – plenty of options, events and instance references for any scripting scenario
  • Window nesting / grouping
  • Auto toggle when called on the same parent element
  • Smart closing through delegation
  • CSS3 shadows, gradients out of the box.
  • degradation to solid colours and image urls as fallback via CSS
  • CSS2D transform support – scale for FireFox, WebKit, IE9, Opera(untested?) via standard Fx.morph!
  • degradation via a simple fade when not supported

__VERY_ flexible – should be used as a base to extend. For example, to make a class that Extends baseBox that deals with lightBox-like image only display, here’s all you need to do: baseBox.lightBox.js demo. The lightBox demo is also included in the package and is on GitHub.

Similarly, you can make your own sub-classes, for example, baseBox.Request can work asynchronously to get HTML fragments and show them to the user.

Requirements:
MooTools-core 1.3+
MooTools-more 1.3+ - you need Element.delegate and Drag.move

Apr 22nd 2011 × Tutorial: write a small content slider Class in MooTools and extend it

Difficulty: moderate
Framework: MooTools 1.3 (no previous ver compatibility)
Dependencies: MooTools-more 1.3.1 (no compat mode, just Element.Delegation required to build it)
DocType: HTML5 – optional

Before I begin, if you have not made a MooTools Class before, I suggest you first read this tutorial I made last month on creating a Sliding Tips plugin, which is a good entry level.

I imagine you’d want to see what the end result will will look like before you waste your time reading so:
http://jsfiddle.net/dimitar/Ea4Gp/show/ – the Base Class, cross-fading
http://jsfiddle.net/dimitar/Ea4Gp/5/show/ – the Extended Class with alternative transition effect
http://jsfiddle.net/dimitar/Ea4Gp/5/ – the editable fiddle to play with.
preview

Anyway. I just had cause to write a small class that allows me to swap between various content divs/panes that are part of the DOM and allow for any markup/child elements within. I thought I’d share the code as I could not readily find one that did things how I wanted them to be.

First, let us examine the requirements from a HTML point of view: a parent node (element) contains all the divs that will rotate. The Class needs to pick them up and enhance them. Should javascript be available, the user gets to see multiple content divs, otherwise–just the first one (progressive enhancement). Google has to be able to read text and follow any links within the content divs.

The resulting HTML markup looks like this:

<section class="rotator" id="rotator">
    <div class="pane" style="background-image:url(http://fragged.org/img/home/hunting-home.jpg)">
        <div class="info">
            <h2>Hunting CS style</h2>
            Built for your `camping` pleasure.
        </div>
    </div>
    <div class="pane hide" style="background-image:url(http://fragged.org/img/home/fishing-home.jpg)">
        <div class="info">
            <h2>Fishing? Really? </h2>
            Fishing is for mongs. <a href="#">Click here</a>
        </div>
    </div>
    <div class="pane hide" style="background-image:url(http://fragged.org/img/home/tourism-home.jpg)">
       <div class="info rambling">
           <h2>Rambling and walking</h2>
           Wish you were here? Can't blame you, it's lame.
        </div>
    </div>
</section>

The accompanying CSS that goes along with the markup above:

section.rotator {
    border-bottom: 4px solid #000;
    width: 700px !important;
    height: 280px !important;
    overflow: hidden;
    position: relative;
}

section.rotator div.pane {
    position: absolute;
    width: 700px;
    height: 280px;
    background-repeat: no-repeat;
    background-position: left top;
}

Come the MooTools magic. The Class is _very_ simple:

this.contentSwapper = new Class({

    // mootools options and events mixins as standard
    Implements: [Options, Events],

    // some defaults...
    options: {
        delay: 3000,
        selector: "div",
        controlLeft: "http://fragged.org/img/home/moveLeft.png",
        controlRight: "http://fragged.org/img/home/moveRight.png"
    },

    initialize: function(element, options) {
        // base constructor.

        // check to see if it's called with an element...
        this.element = document.id(element);
        if (!this.element)
            return;

        this.setOptions(options);

        // grab the child divs
        this.elements = this.element.getChildren(this.options.selector);
        this.index = 0;

        // call some methods we are about to define.
        this.attachControls();
        this.startRotation();
        this.attachEvents();
        this.fireEvent("ready");
    },

Once again, I like to break up all the things the Class does into small methods – ideally, as small as possible without getting into ridiculous territory where you write a method that returns a property you can access directly (eg, this.getSize = function() { return this.size; }).

attachControls is a cool method, as it makes use of some of MooTools 1.3′s new features: Slick and zen-like element construction.

attachControls: function() {
    this.controls = $$(
        new Element("img#moveLeft.contentControl[title=Previous][src={controlLeft}]".substitute(this.options)).inject(this.element, "top"),
        new Element("img#moveRight.contentControl[title=Next][src={controlRight}]".substitute(this.options)).inject(this.element, "top")
    );
},

Notice the $$() around the controls. This will create a MooTools HTML collection that is iteration-able (.each or any methods). The collection is basically like an array with added Element prototypes working. Other than that, nothing too complicated takes place – makes a new image with id #moveLeft, class .contentControl, sets the title and the src property.

To attach events: we want the rotation to stop when the user mouses over the main element (section.rotator) so they can read in peace and possibly click any call to action it may have.

attachEvents: function() {
    this.element.addEvents({
        mouseenter: this.stopRotation.bind(this),
        mouseleave: this.startRotation.bind(this),
        "click:relay(img.contentControl)": this.move.bind(this)
    });
},

Hence, mousenter calls our stop method and mouseleave starts again. The “click:relay(img.contentControl)” is MooTools’ way to doing Event Delegation. Saves us you having to bind 2 events and callbacks to both controls by just binding to the parent element.

The movement methods. Very minimal logic, they literally just set variables.

move: function(e, el) {
    // based upon image id, it will match a method name.
    this[el.get("id")](); // call it dynamically
},

moveLeft: function() {
    // set the next frame coming to previous one or last
    var next = (this.index == 0) ? this.elements.length-1 : this.index-1;
    this.swapFrames(next);
    this.fireEvent("left");
},

moveRight: function() {
    // set the next frame coming to next one or first
    var next = (this.index < this.elements.length-1) ? this.index+1 : 0;
    this.swapFrames(next);
    this.fireEvent("right");
},

Now we get to the more interesting parts. The actual swapping of the content is the core of the Class and is what we will modify later when we extend it to make it work differently.

The base class version does a VERY simple transition based around tweening the opacity of the 2 relevant content panes. One fades in while the other fades out.

swapFrames: function(next) {
    // element currently visible is in this.index (as key of this.elements array)
    var curEl = this.elements[this.index];

    // clean up from before, just in case
    curEl.get("tween").removeEvents();

    // reset element and set tween options.
    curEl.set({
        "tween": {
            link: "cancel",
            onComplete: function() {
                // add a css class that sets display to none, for example
                this.element.addClass("hide");
            }
        },
        styles: {
            opacity: 1 // initial opacity reset in case quick clicks
        }
    }).fade(0);

    // now set our new visible frame from this.moveLeft/Right argument
    this.index = next;

    var newEl = this.elements[this.index];
    //clean up, reset, show and fade in.
    newEl.get("tween").removeEvents();
    newEl.setStyle("opacity", 0).removeClass("hide").fade(1);
}

The end result: panes will cross-fade between each other, giving a morphing impression. Less is more, as they say.

Finally, we have 2 small methods that start and stop the automatic rotation. To keep the user interested in your site content, you really need to take no more than 2.5 second from their initial impression of the site or they may _subconciously_ lose interest and just bounce based upon the failure to connect with content shown from the start.

startRotation: function() {
    clearInterval(this.timer);
    this.controls.fade(.5);
    this.timer = this.moveRight.periodical(this.options.delay, this);
    this.fireEvent("start");
},
stopRotation: function() {
    clearInterval(this.timer);
    this.controls.fade(1);
    this.fireEvent("stop");
}

// and end class...
});

The controls collection we did earlier fades up and down based upon interaction: when it's stopped, the user is 'over' the element so we make the left and right more visible and we fade them out afterwards so they are less distracting.

This is it. To call the Class with your default options, all you need is:

new contentSwapper(document.id("rotator"));

You can, of course, attach event callbacks that respond to the ones the class has fired:

new contentSwapper.Fancy(document.id("rotator"), {
    onReady: function() {
        console.log("we are up!");
    },
    onStart: function() {
        console.log("and we are moving");
    },
    onStop: function() {
        console.log("Oh! they are reading with mouse on top!");
    }
});

... and so forth and so forth.

Simple. Now, imagine you are happy with your base Class but would like to extend it somewhat, by modifying it slightly to better suit your needs. In this case, we no longer desire to have a standard opacity cross-fade transition between panes so we will try to override that.

MooTools allows you to use the Extends: mutator(?) as part of your class declaration.

contentSwapper.Fancy = new Class({

    Extends: contentSwapper,

    initialize: function(element, options) {
        this.parent(element, options);
    },

We have now extended the base class and have everything it does inherited. But we want to actually override one of the methods to make things snazzy. We will try to make a vertical transition of the new pane over the old one as an experiment.

swapFrames: function(next) {
    var curEl = this.elements[this.index];
    // using morph for multiple CSS properties we will adjust
    // on the same timer, eg, opacity and margintop:
    curEl.get("morph").removeEvents();
    curEl.set({
        styles: {
            zIndex: 1000,
            opacity: 1
        },
        "morph": {
            link: "cancel",
            duration: 1000,
            onComplete: function() {
                this.element.addClass("hide");
            }
        }
    }).morph({
        // we really just want opacity as it looked better but experiment
        opacity: 0
    });

    this.index = next;

    // bring the new element in from the top, 280px.
    var newEl = this.elements[this.index];
    newEl.get("morph").removeEvents();
    newEl.removeClass("hide").setStyles({
        zIndex: 1001,
        marginTop: -280,
        opacity: 0
    }).morph({
        marginTop: 0,
        opacity: 1
    });
}

}); // end extended class

That's it. Now, you can improve that further by setting the marginTop offset into the Fancy options or read the height of this.element instead, your call.

To use the alternative and fancier way of transitioning, you do:

new contentSwapper.Fancy(document.id("rotator"));

Supplemental CSS required:

img.contentControl {
    position: absolute;
    margin-top: 90px;
    z-index: 10000;
    cursor: pointer;
    _cursor: hand;
}
#moveLeft {
    margin-left: 0;
}

#moveRight {
    margin-left: 662px;
}

Dead simple, isn't it? Have fun with MooTools. Any comments, questions or feedback, @D_mitar on Twitter or coda- on #mootools (irc.freenode.net).


Mar 12th 2011 × Tutorial: write a small but flexible MooTools Tips class

The other day somebody came in on the IRC channel and asked if there’s a MooTools script available to replicate the effect of this jQuery plugin.

The main objective was to be also easily able to keep the tip on whilst the mouse skips from the trigger element into it. Since I did not know off the top of my head of an adequate MooTools class to perform the task, I simply took 30 mins to write one. This is to document that and explain the decisions behind it.

To get an idea what our class will do when done, view http://jsfiddle.net/dimitar/WUfNR/show/ or look at the source code on git.

As a disclaimer: this is NOT a port of the jQuery plugin mentioned. I have not looked at the source code and simply am replicating the effect and using their graphics for convenience’ sake.

Also, this mini-tutorial or (even code-review) is aimed at people who already have rudimentary knowledge of Javascript, MooTools, CSS, DOM and understand the concept of classic OOP. Recommended read on how MooTools deals with OOP and the Class constructor in general is Keeto’s Up The Moo Herd III article.

First: decisions, decisions. Planning ahead is important so… The easiest way to achieve the effect we are after without firing onmouseout when moving the mouse into the ‘tip’ is to have the tip become a child element of the trigger element. To understand that better, consider it as a simple HTML/CSS markup solution where a child div has absolute positioning and some negative marginTop. Although this is very easy, it is a somewhat limiting decision as it means the tip element can only be injected into the DOM with a parentNode that can have children. input, img, textarea are not good for us to attach to directly. It’s not that much of a drama as you can wrap them into spans or divs, which will work fine.

The start: creating the MooTools class skeleton

this.tippable = new Class({

    Implements: [Options, Events],

    options: {
        tipClass: ".tippable",
    },

    initialize: function(element, options) {
        // public instantiation

        this.setOptions(options);
        this.element = document.id(element);
        if (!this.element)
            return;
    }

});

What is happening here? Basically we are defining a new MooTools Class called ‘tippable’. Within that class we use the MooTools Options and Events classes as mixins. The Options class is useful for merging options from the instance that override the default class options property by doing an `Object.merge(options, this.options);`. This functionality is available through the `this.setOptions(options)` call and is a great practice that allows you to setup defaults that can be changed by the instance. The Events mixin is another very handy Class that brings Events (surprise) into your classes and can be used in conjunction with options object you pass on. The premise is simple: whenever something ‘awesome’ happens in your class that the instance should know about, you can do `this.fireEvent(“awesome”, [params])` and if on your options object on your class instance you have a property `onAwesome: function() { … }`, it will get passed with the scope of the class itself. More on this later.

Maintaining your MooTools Classes requires you to adhere to some unwritten rules that make it easier for developers to follow what’s going on. From that point of view, it’s an accepted convention that if your class deals with a particular element, it should be referenced as `this.element`. An array of elements would be… `this.elements` and so forth (hint: read the linked article above).

We are also making sure that an element has been passed and it’s a DOM node, something that the `document.id()` call ensures. It’s unsafe for the Class to continue if it can’t find the element so it exits quietly. You may want to trigger an exception here or degrade gracefully – depends on your requirements.

Building your Class

It’s now time to add our first ‘real’ method. I like to break the Class down into multiple small methods that are self explanatory and do as little as possible. This is a great practice for many reasons: it means your code is self explanatory and reduces the need for leaving comments. It also allows you to create patterns that you can call again and again. We are going to create a new method we are going to call `attachTip`

attachTip: function() {
    // call creation and events addition
    this.createTip();
    this.attachEvents();
},

As you can see, it will call two more methods we will add: one that creates the tip into the DOM and one that deals with the trigger events.

I am going to post the finished version of the method and it will reveal references to options and methods we have not mentioned yet. Basically – as a practice, I tend to add to my default options object as I see fit whilst I am writing the code and come to a decision about using a static value or a variable that may be useful for the user to override.

createTip: function() {
    // add tip to dom and set initials

    // first event will be onShow
    this.event = "show";
    this.tip = new Element(this.options.tipClass, {
        styles: {
            opacity: 0
        }
    }).set("morph", Object.merge(this.options.fx, {
        onComplete: function() {
            this.fireEvent(this.event);
        }.bind(this)
    }));

    // store title
    this.title = new Element("div.title").inject(this.tip);

    // tip body
    this.body = new Element("div.body").inject(this.tip);

    // append to DOM
    this.tip.inject(this.element, "top");

    // store instance into the tip element for event use!
    this.element.store("tippable", this);

    // set initial title and body values
    this.setTitle(this.options.title);
    this.setHTML(this.options.text);

    // now to position element
    if (this.options.leftOffset === false) {
        var tipWidth = this.tip.getSize().x, elWidth = this.element.getSize().x;
        this.tip.setStyle("marginLeft", (elWidth - tipWidth) / 2);
    }
    else {
        this.tip.setStyle("marginLeft", this.options.leftOffset);
    }

}, // end createTip

As I just pasted this, it occurred to me it would be useful to allow users to define their own CSS ClassNames for the tip title and tip body, even if they can be targeted in CSS as `value-of-this.options.tipClass div.title {..}`. Anyway, that’s a change you can quickly do. Similarly, we are going to be using certain variables passed through options or defaults. The default options for the Class now look like this:

options: {
    // NB: these are zen classes for Slick
    tipClass: "div.tippable",
    text: "",
    textClass: "div.body",
    title: "",
    titleClass: "div.title",
    topOffset: 110, // where it stops above the element
    topOffsetStart: 160, // where the animation starts from.
    leftOffset: false, // if false, center over element, else, integer
    // Fx class options
    fx: {
        duration: 400,
        link: "cancel"
    }
},

To reiterate: if you do not pass an options object to the Class instantiation, it will still work with the default values. If you want to override a single option, you do that and the rest are defaults. The key / interesting options we use are these:

  • tipClass, textClass: a ‘zen-coding like’ element hook to create and style the tip container (by ID or CSS reference). In MooTools 1.3, Slick can work with Element in reverse, you can even declare things like `new Element(“div#someid.foo[html=hi]“);`
  • fx: an object that provides the ability to pass on options to the Fx.Morph instance on the tip element such as duration, Fx.transition and so forth.
  • topOffset and topOffsetStart: can control the ‘animation’ path – where to start from and how far above (or below) the element to stop. By using negative values here, you can do a tip that flies from bottom to top instead…
  • leftOffset: that value I added later when I realised I may not always want to try and center the tip above the trigger element but may want to output it to the left at nn pixels. if False, centered, else, marginLeft becomes leftOffset instead.
  • text / title: Last but not least, the default text body and title for the tip.

Back to the function. In a nutshell, when attaching the tip to the DOM, it makes a new div, say div.tippable (styled through CSS alone) and makes it invisible by default. It also defines the Fx morphing options and helps out a little with the events it will fire onShow and onHide. I will go in more details over why events are important and how you can use them in the instance.

The tip is injected – as stated before – as a child node of the trigger element – so it needs to be styled via CSS to have position: absolute.

An interesting thing that I do here is I also store the tip instance into the trigger element storage (via this.element.store(“tippable”, this);). This allows me to programatically control the tip instance from external javascript by simply having access to the element where I can get the instance by `var instance = doing elObj.retrieve(“tippable”);`. It’s great so that I don’t have to store each instance into a separate variable into my scope in case I want to remove it, modify it or show a tip without mouse events.

Another interesting thing is I have added public methods which allow for the changing of the tip title and body via setTitle and setHTML. This means you can control the content and change it dynamically or even bring in tip content through events and ajax, which I will show later on. Back to the Class, we are adding these two simple methods:

setTitle: function(what) {
    // set the title content public api
    if (what.length) {
        this.title.set("html", what);
    }
    return this;
},

setHTML: function(what) {
    // set body content public api
    this.body.set("html", what);
    return this;
},

Please note the return this; at the end of some of the methods. This is another unwritten rule in the MooTools world: allow for chaining. By having the Class instance as the exit/return point of a method, it allows you to chain more methods to it. In other words, you can do on a single line:

this.setTitle("hello").setHTML("this be the tip text, ahoy!");

When dealing with DOM events pointing back to your class methods, things are slightly trickier at first:

attachEvents: function() {
    // private
    this.boundEvents = {
        mouseenter: this.showTip.bind(this),
        mouseleave: this.hideTip.bind(this)
    };
    this.element.addEvents(this.boundEvents);
    return this;
},

detatchEvents: function() {
    this.element.removeEvents(this.boundEvents);
    return this;
},

What takes place here is: on attachEvents we set mouseenter and mouseleave to point to the special methods we will create to show or hide the tip respectively. Because these two methods need to keep the scope to the class instance, we bind them to ‘this’. Because we need to be able to remove the tooltips from an element and clean up the events, we store a reference to the bound functions into the class instance so that detachEvents can find the callbacks and remove them (in this.boundEvents).

We are happy now, we can create the class and attach events to it. So here are the two functions that deal with showing and hiding the tip:

showTip: function() {
    // triggered on mousenter or called direct

    // fire onBeforeShow
    this.fireEvent("beforeShow");

    // next event will be onShow through morph onComplete
    this.event = "show";

    // animate properties
    this.tip.morph({
        marginTop: [-this.options.topOffsetStart, -this.options.topOffset],
        opacity: [0, 1]
    });
    return this;
}, // end showTip

hideTip: function() {
    // triggered on mouseleave ot called direct

    // fire onBeforeHide
    this.fireEvent("beforeHide");

    // next morph event will be hide
    this.event = "hide";

    // hide animation
    this.tip.morph({
        marginTop: -this.options.topOffsetStart,
        opacity: [1, 0]
    });
    return this;
} // end hideTip

The first thing we do is we fire off the ‘before’ events. This can tell the instance we are about to start animating the tooltip into view or out of view. Why is this useful? You may want to modify your trigger element and make it an ajax spinner, change some content, modal your screen or even request data from ajax to show later.

this.event = “show”; is a little hook that allows us to pass back to the Fx.Morph onComplete event which event to fire next, in this case onShow. To the instance, that event says, ‘animation is complete and tip is in full view’. One thing you can do here is, for example, passing this to the options when instantiating the Class:

onShow: function() {
    this.setTitle("").setHTML("loading...");
    var self = this;
    new Request({
        url: "someurl.php",
        onComplete: function() {
            self.setHTML(this.response.text);
        }
    }).send("view=getTip&id=" + this.element.get("data-id"));
}

… will fetch some data from an ajax view with some params and then set the tip body text to the response.

The hideTip fires the opposite events, onBeforeHide and onHide. An example use case for onHide can be to make it a one-off tip and remove the tippable after it has been seen:

onHide: {
    this.deatchEvents();
}

And done! Subsequent mouseenters on that element will no longer trigger a tooltip.

That’s it, in a nutshell. You have just created your new MooTools Class and can start using it. Look at the jsfiddle for this tutorial, it is somewhat important to look at the CSS that accompanies the Class:
http://jsfiddle.net/dimitar/WUfNR/. You can also see the events at work (look at your console) and try a a double-click on a trigger image to disable the class.

Any questions, you can always find me on #mootools on irc.freenode.net (nick coda- or d_mitar) or… just ask. I am sure somebody will be there to help. Have fun


Mar 10th 2011 × The MooTools Round-up, week 1 (7 – 13th of March)

Going to start a new series in the blog on everything MooTools on a weekly basis. If you notice how “Round-up” plays on the cows element, that’s no accident. Only wish I was called ‘Woody’. Oh well.

So, what’s new in the world of the greatest javascript framework known to man?

My pick of the latest MooTools plug-ins

  1. Fx.CSS by @tbela99 is a nice class that makes the base MooTools Fx Class compatible with CSS3 transitions and effects. Looks like a very comprehensive effort, a must-see for those that try to phase out Flash.
  2. inPlaceEditor, also by @tbela99 makes for easy on-page editing of elements (contenteditable, cough)
  3. Time by Arieh Glazer gives you rails-like syntax for stating times
  4. Powertools::history by @cpojer of mootools-core is my pick of the litter – giving hashchange or popstate history management with graceful degradation to suit your ajax app needs.

IRC quote of the week
This is meant to be a joke so please be warned.

<kentaromiura> a mootoolist and a jqueryist walks into a bar, the jqueryist throws $ at the bartender while the mootoolist order a new Beer with more class.

For more classic moments like these, visit the MooTools IRC channel #mootools on irc.freenode.net and wait for kentaro’s next show.

Whine of the week
Popular tweets by people that have seriously failed to get the MooTools to works and make teh accordions!

@vgrovestine “IE9 not compatible with MooTools. Color me unimpressed.”
**update, new leader for the week**
@sergio_martino “Mootools has no Live event bindings… how crap is this js library… #mootools #usejquery”

Scoop of the week
Whilst discussing private methods in MooTools Classes, which currently works through the undocumented `.protect()` function decorator, Arian said that MooTools 2 will be getting a public API for it looking like so:

var foo = new Class({
    "private bar": function() {
        alert("this be private");
    },
    realBar: function() {
        this.bar();
    }
});
var myFoo = new foo();
myFoo.bar(); // exception
myFoo.realBar(): // ok

I guess that’s one way to go with it. Another speculation had been a mutator like in Class.Binds: Private: ["bar"]. Apparently, you will be able to control this by writing a regexp mutator yourself and get it to behave like python or whatever takes your fancy.

Tutorial or blog post of the week
This week I came across a great post / overview of MooTools by Jonathan Krause, albeit written in German. http://www.jonathan-krause.de/artikel/mootools/ is the URL if you know German, trust Google Translate or just want to look at the code and the pretty pictures instead.

And another article I came across that’s slightly older but nice none-the-less: 12 Steps to MooTools Mastery by the MooTools team member I am afraid to admit I know least about, Jacob Thornton.

JavaScript fun
In case you missed it, here’s the most unique game of its type: a hashtag URL ascii char chaser game (called URL Hunter, really). Enjoy.


Feb 18th 2011 × How to clone element storage in mootools

Ever needed to clone an element and take your element storage with it? I have and it’s not easy. There’s Element.cloneEvents(), which takes the storage.events callbacks but any other storage you may have used remains unavailable behind the closure that MooTools uses for the storage object.

This bit of code tracks of any data you store (via the lstore method only) in the element’s native storage and then provides a new Element prototype Element.cloneStorage(srcElement).

(function() {
    var eliminateOrig = Element.prototype.eliminate;
    var localStorage = {};

    var get = function(uid){
        return (localStorage[uid] || (localStorage[uid] = [])); // converted to an array to store keys stored
    };

    Element.implement({
        lstore: function(property, value) {
            // use this instead of Element.store
            var storage = get(this.uid);
            // store the key so we can clone it after
            if (!storage[property])
                storage.push(property);
            return this.store.apply(this, arguments);
        },
        eliminate: function(property) {
            var storage = get(this.uid);
            storage.erase(property);
            return eliminateOrig.apply(this, arguments);
        },
        cloneStorage: function(from) {
            // new prototype to clone
            var other = get(from.uid);
            other.each(function(el) {
                this.lstore(el, from.retrieve(el));
            }, this);
            return this;
        }
    });
})();

Here is an example usage test:

document.id("bar").lstore("hello", "there");
document.id("foo").lstore("foo", "bar");
document.id("foo").cloneStorage(document.id("bar"));

// if clone works this should now say 'there':
console.log(document.id("foo").retrieve("hello"));

document.id("foo").store("ugly", "face");
console.log(document.id("foo").retrieve("ugly"));

// testing eliminate.
document.id("bar").lstore("eliminateTest", new Image());
document.id("bar").eliminate("eliminateTest");
document.id("foo").cloneStorage(document.id("bar"));
//should now be null
console.log(document.id("foo").retrieve("eliminateTest"));

To view this on jsfiddle: http://jsfiddle.net/dimitar/225HJ/

And the gist: https://gist.github.com/833584

Thanks to Tim Weink (Timmeh aka FunFactor) for the inspiration and also for pointing out that copying ALL storage is not a good idea due to class instances being stuffed there for things like Fx.Tween / Morph / Request etc, hence making me refactor it to only clone the storage that was passed through the lstore method.


Feb 11th 2011 × Feature detect base64 image support, revisited

Recently I had cause to revisit my old routine that checks if a browser can work with base64-encoded images. This is a test that modernizr does not offer so the only way to do so is to Feature-detect. To the rescue: an empty 1x1px gif image gets encoded and is then set as the src of a new Image element, then tested. If base64 is supported, the resulting image object will have width and height of exactly 1px.

Here’s the code, extending the MooTools Browser.Features object, NEARLY synchronous (best check with a 50ms delay though or loop while Browser.Featrues.base64 === null):

(function() {
    Browser.Features.base64 = null;
    var callback = function() {
        Browser.Features.base64 = this.width == 1 && this.height == 1;
        // alert(Browser.Features.base64); // true || false
    };

    var img = new Image(), img = document.id(img) || new Element("img");
    img.onload = img.onerror = img.onabort = callback;
    // 1x1 px gif to test with
    img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";

})();

And to see it in action:
http://www.jsfiddle.net/dimitar/5JT45/13/show/ or editable jsfiddle

Gist: https://gist.github.com/821370

An encoding tool that can help you convert your images: binary to base64 translator.

In reality, IE7 upwards supports it fine so all this “Feature Detect” can be skipped but it’s somewhat nicer that way.


Jan 28th 2011 × Some “-More” intermoos: a long chat with Aaron Newton

Our next mootools interview is a a bit long. Let it not be said that I did not warn you – but it’s worth the read. So, without further adieu…

One of the biggest “names” you are likely to hear whilst talking about MooTools (or even javascript in general) is that of Aaron Newton. Through his time working for CNET, Aaron adopted the use of MooTools and started contributing a lot of practical plugins that ended up as the base of the official MooTools plugins repository, also known as mootools-more. He has also written a book, given talks and worked very hard at promoting MooTools to the rest of the world. Author of the highly acclaimed and mootorial (hello world guide for mootools) as well as the ever-so-slightly controversial website jqueryvsmootools.com, you cannot hope to meet a nicer and more patient MooTool-er online. We catch up with him and ask him a few questions…

Name: Aaron Newton
Nickname: nutron, sometimes anutron
Country: USA
MooTools role: Lead developer for -more
Age: 35
Company / Occupation: Cloudera / Senior UI Developer
Blog: http://www.clientcide.com
Website(s): http://www.clientcide.com
Twitter: @anutron
GitHub: https://github.com/anutron
Famous for: Client(SC)ide, MooTools-more, MooTools Essentials book,
Programming to patterns talks, jqueryvsmootools.com,
The Mootorial
Hi Aaron, appreciate you taking the time. Can you tell us a little bit about yourself? Things like, your programming / computing background, are you classically trained, what are your favourite foods, drinks or pets, hobbies and what not…
The first thing you need to know about my “computing background” is that I went to college for Jazz Guitar. At roughly the same time the web was being born. I was always into computers; building them and playing games and making art with them. When the web first showed up I started fiddling with HTML and making galleries of my photography (which I also studied in high school and college). I took some graphic design courses and helped design, build, and maintain the web site for my school. In 1997 I got a call from a friend to come to California and work on a startup as an interface designer which pretty much killed my music career.

I started my own company in 1999, a music site called Epitonic. It kinda died when the rest of the web did. I joined CNET as a product manager and built more music oriented sites there but slowly moved into technical product management focused on internal projects. At some point I hacked together some prototypes for the network and was annoyed at the lack of JavaScript infrastructure.

I took it on myself to research all the budding frameworks, pick one, and standardize the whole company around it. I started w/ Prototype and Moo.fx but when MooTools came out I quickly latched onto it. I started blogging all this, originally as an internal blog for CNET developers but later as a public blog where we started releasing all the things I was putting together. If you feel like it, you can read my initial impressions of MooTools in this post and a followup that I posted shortly after that.

Since then I’ve been active in the MooTools developer community non-stop. I left CNET and did another startup on my own (www.iminta.com) and then in 2009 I joined Cloudera as employee number 10. Cloudera now has six front-end developers (including Thomas Aylott ed: “SubtleGradient” of mootools-core and Slick teams), all cranking out MooTools code.

It is fair to say that your book “MooTools Essentials” along with the numerous and helpful responses you make daily on the mailing list and the vast resource that is Clientcide were probably the biggest contributing factors in my own decision to adopt MooTools as my framework of choice. How do you find the time, dedication and patience to continue evangelising for MooTools and generally, be so kind and welcoming to new users?
Well, lately, I don’t. I haven’t posted much to Clientcide in roughly two years. I have a lot of code on my github account that I want to release but I don’t have time to write docs and promote it. Some of my latest work is perhaps the most interesting I’ve ever done. The Clientcide libraries still haven’t seen a release against MooTools 1.3, though the work is done in github. MooTools More now has 4 other developers on the team and they are responsible for most of the new features and work you see there. So, in short, though I remain active on the mailing lists and I do author a large amount of JS, my contributions this last year or so have been rather thin as Cloudera continues to require nearly all my attention.

But, that said, in general over the years I’ve made it a priority to make the framework easier to learn, adopt, and use out of self-interest. I genuinely enjoy teaching and helping others, but I do these things for MooTools because I want to see the framework succeed. Where others on the team focus on code quality and features, I’ve focused on stability, documentation, tutorials, message boards, etc. because I want to write MooTools code where I work and if no one is adopting it then there’s no market for it. Already you can see that jQuery, which is a fine library for it’s scope, is the defacto standard in much of the market. This makes it harder for people who see the value of MooTools to find work using the framework. Much of my time is dedicated towards adoption to ensure that the project is healthy and can not only survive, say, Valerio getting hit by a bus, but also allow me and you and others to continue working on MooTools in our day jobs.
Did CNET adopt the framework through your insistence or was it the other way around, you picked up the framework because of your work requirements and what was already in place?
I mentioned some of this already, but my somewhat self-appointed task at CNET was to create a common JS story for the network. I was a product manager there and every time I’d ask for some aspect of my product to be interactive I’d get blank stares from all the Java guys on my development team. I’d often end up writing the JS for my product myself. After a while I could see that the problem was only going to get worse as the web got more sophisticated; if CNET didn’t adapt our customers would find a site that just felt out of date.

Initially I chose Prototype. I researched a bunch of frameworks and I liked Prototype’s model a lot. But the library was really verbose (it was like, 70K in those days) and it didn’t have element enhancements nor effects; for those you needed Scriptaculous – another 70K or so. Moo.fx came out and it was 3K (!). I started building on top of that and then MooTools itself followed. I loved the framework from the start, but it was not even a 1.0 release yet (r87); there weren’t even docs for it. I knew I couldn’t get the CNET engineers to even consider it without those things, so my first contribution was the documentation. I authored these by reading through the entire source and documenting each method. That single week’s worth taught me more about JavaScript than anything before or since.
Most other team members seem to focus on contributing for mootools-core whereas you are within your elements when it comes to mootools-more. Let’s also not forget of the huge UI-centric collection that you maintain at your site Clientcide. Is it fair to say that UI is your passion, the practical application of the framework in web apps? Or do you just contribute parts of what you are required to write for your day job? What would you enjoy working on if time and money were not an issue?
While working at CNET I decided to release everything I could. At the same time, I continued to contribute to MooTools Core. Most of my contributions to Core were added because I needed stuff in my actual work. $merge for example didn’t exist in r82. I wrote the first implementation of it (which Valerio immediately rewrote). This was the pattern for a long time; I’d work on my stuff for my job while Valerio and others worked on Core. When I found
something wanting, I’d push it up into Core when I could. As I released more and more stuff on Clientcide it became harder to maintain that code and still contribute to Core in any meaningful way.

About two years ago the MooTools development community decided, at my urging, to focus on growth. Specifically to work to increase the number of people contributing to the framework. The dev mailing list went from something like 12 to maybe around 70 today. About that time we decided to pull over a lot of the Clientcide plugins and make them an official MooTools release. If you look at the MooTools More library today there are about 65 plugins (if you exclude all the localization files). About 40 of those came from Clientcide. Nearly all of them have been rewritten by the team (and are much better for it); they certainly aren’t my contributions any more. Clientcide still has about 50 plugins in it (the next version deprecates about 20 of them). All that code is already too much to maintain, so any notion that I might have about contributing to Core goes right out the window. My todo list is already too long.

As for what I would do if I could do anything; if I could just take a week of vacation and work… well, I always have a long laundry list of things that I’m trying to accomplish. I want to improve the test coverage in MooTools More (which is already in pretty good shape thanks to the rest of the More team). I want to implement some automated UI testing with Windmill or Dohbot or something. I have several repos on github that I want to release; the Behavior library in particular. I need to update the Mootorial. Blah blah blah. It’s a long list.
How well did you know javascript before picking up MooTools? Has it made you a better programmer?
I would say I was an average developer with an average understanding of JavaScript. I wrote a lot of functions but never used inheritance. My work in JS wasn’t very object oriented. I had a cursory understanding of prototypes but not why they were useful. As I stated earlier, reading through the MooTools source code taught me more in one week than anything I’ve ever done. Valerio is a brilliant developer; his work borders on art if you ask me.

What I’ve learned since then is less about being a better coder and more about working with people. I’ve pushed on the MooTools community pretty hard to adopt a lot of the process and principals that I find in my day jobs. Many of the MooTools developers don’t have jobs as full time developers in a community of developers. They are freelancers or are in school. Valerio spends nearly all his time working on MooTools itself. I’ve had a very different experience working in organizations with dozens or even hundreds of developers. There’s a different priority at work there. At Cloudera I’m surrounded by hardcore developers – some of the smartest guys I’ve ever met. We contribute to a lot of other open source projects (mostly Apache projects) and I see the merit in the structure that those projects have. Doug Cutting, creator of Hadoop, Lucene, Nutch and others, works at Cloudera. He’s the chairman of Apache! I’ve picked his brain a lot about what makes Apache projects succeed or fail. I try and bring a lot of that knowledge to the MooTools developer community. I’m not always successful at it, but there are numerous things that we do now that came from my talks with Doug and others.
Your talks on Programming to the pattern have made me–and perhaps many others that were also not classically trained in programming–to rethink how we think of code architecture and structure. Are you a perfectionist when it comes to architecture and producing code that scales well and is easily re-usable? How do you approach a new task to determine your coding structure and do you think MooTools renders itself well to this kind of thinking?
I’m not a perfectionist. Look at my code on github and compare it to Valerio’s. Valerio and the other MooTools developers will often choose beautiful code over just about anything; usually that’s a good thing. Their dedication to releasing the best code they can possibly produce is what makes MooTools so wonderful to work with. I am not the kind of person that could produce a MooTools even if I had the technical talent.

I’m a pragmatist. I make things that work and that are extensible, reusable, etc. I often find myself redoing what I’ve done before or extending something I’ve done before usually because I had a lack of foresight in my initial API design. It’s what makes me look so productive. I produce a lot of things that work but they certainly aren’t perfect. I don’t even strive for perfection; I strive for flexibility and functional completeness. I’m not afraid to rewrite something a few times.

That programming to patterns talk that I give is based entirely on my own revelations as a developer. I spent many years doing things the hard way. The stuff I do now is taking that pattern thinking even further (for example, the Behavior stuff I’ve mentioned already). But I can point to several things I’ve authored here at Cloudera that are on their 3rd rewrite.

As for MooTools, I can’t imagine being able to author JavaScript this way without it or something very similar. If I didn’t have MooTools, I’d probably write it myself (only worse) just to keep from going back to the way I used to author code.
When talk of MooTools ART first came up, your demos of UI prototypes based upon it seemed very promising. Are you still working on that and is any of that work (going to be) sourced on Clientcide? MooTools still needs a supported UI project…
Credit where it’s due: Valerio authored many of those demos. We actually use ART in our product at Cloudera. We may at some point remove it or at least portions of it; at the scale we are using it it’s a little slow (not MooTools fault but rather that of SVG/VML). We’re pushing the edge a little I guess.

As for release, there are two things here; ART, and the widget framework that happens to use it. ART continues to slowly march towards release, but that’s something you’ll have to ask Valerio about. It’s unofficially a MooTools project; as soon as it’s ready for 1.0 you’ll probably see it on MooTools.net, but certainly not Clientcide.

As for the widget framework, that falls directly into the “on my long list of things to do” category. Will I release it? It’s on github now with demos and stuff. The real question is will I find the time. The more code I release, the more stuff I have to maintain. The value of open source software is that if it’s useful you find others to help you maintain and grow it, but even that takes a time investment. I’d like to think that as Cloudera matures a bit we’ll be able to focus a little more on packaging this stuff up and pushing for others to adopt it…
What will MooTools 2.0 bring to mootools-more? I know there was some talk of certain features being swapped over, like Event Delegation and JSONP to -core, Swiff to -more. What can we expect to see?
I have learned not to make predictions about future releases of MooTools the hard way. I wrote a second edition of my book against the 2.0 branch of MooTools. That was about two years ago. Since then we decided to focus on a more iterative approach to releases so much of the 2.0 branch got back-ported to become MooTools 1.3. The work on my book is essentially worthless.

These days I focus on the current release. When Core goes into testing and its API is locked down, that’s when the work on MooTools More gets safe to start. I’ll point out that the rest of the MooTools More team, in particular
Tim Wienk, Arian Stolwijk, and Christoph Pojer, were instrumental in updating More for 1.3. I contributed very little to that effort I’m sad to say. Cloudera has yet to upgrade to 1.3, though I hope to do that soon.
If time and resources were not an issue, what new features or changes would you like to see most come into the framework or the framework website?
Most of the things I want to change aren’t about the features or organization of the code but rather priorities and the social structure of the project. Writing software is a social challenge as much as anything. I’d like to see the number of committers on the project quadruple. It would make it harder to introduce change in some ways, but it would make the project more resilient. MooTools More went from essentially one full-time committer to five and there are some awesome things in there now that I personally would never have had time to author. If there were 100 people with committer status it would require each of us individually to give up influence but it would be for the best.

As for the web site, I’d like to see it more focused on adoption. The new Demo environment is a good start in that direction. I’d like to see more tutorials and more community engagement. The guys working on the site are awesome, but like me they have other responsibilities to their jobs and families. We can only go as fast as we can donate time.
If you had not been involved in MooTools, what do you think you’d be doing instead?
Sooner or later I want to go back to managing products. I am involved with MooTools because I care about building good products. I want the web projects I work on to be interactive and fun to use. In some ways, I don’t care if I write the code itself. I like doing it, but if I were to do another startup of my own, I’d eventually hire someone else to take over that work and I’d focus on the product design.
If you could give one tip to new MooTools developers, what would it be?
Read the source. If it takes you a week or a month, if you can get to a point where you understand how and why MooTools does what it does – every single line and function – your skills will improve. The second thing I’d recommend is getting involved. Write about what you do on your blog. Release some code! Go into Lighthouse and find a bug to fix. Improve the docs. Makes some demos for us!
Your top 5 resources for web developers (can be websites like jsFiddle, IDEs, tutorials, CSS frameworks like boilerplate, etc)
Oh jeez. Instead of top 5, I’m just going to list some stuff I use a lot.

  • jsFiddle obviously; no surprise
  • JSLint – I use TextMate and have this integrated to show me errors and warnings when I save a file. It’s a life-saver.
  • Git and gitub have both changed my life.
  • I love ReCSS (http://david.dojotoolkit.org/recss.html); WTFramework (http://nouincolor.com/wtframework/2.0/) is also pretty cool
  • j for command line work is another huge time saver (https://github.com/rupa/j)
  • I love visor for the mac (http://visor.binaryage.com/) – my command line is never more than a single keystroke a way
  • I regularly visit the Mozilla Developer Center for docs on JS, HTML, CSS (https://developer.mozilla.org/en-US/)

Thanks once again!