开发者

Chaining AddClass/RemoveClass Events With Mootools

I'm currently putting together a css animation, and part of achieving this involves changing the class name of the body at specific intervals.

Being quite new to mootools (and js in general) the best way I've thought of achieving this has been to simply add/remove classes to the body at delayed intervals, like so:

(function() {$(document.body).addClass('load');}).delay(20);
(function() {$(document.body).addClass('load-two');}).delay(2000);
(function() {$(document.body).addClass('load-three');}).delay(2700);
(function() {$(document.body).addClass('load-four');}).delay(4500);

However the more I read up on the subject, the more I'm convinced that this is an inefficient way of achieving what I want to.

The above c开发者_开发知识库ode works in all the browsers I've tested it in, but would I be better using a chain class to achieve what I want? I have looked over the Mootools docs on setting up a chain, but for whatever reason, I'm struggling to get the demo working.

So the crux of what I'm asking, is if there's a better way of writing the code posted above, and what are the benefits of using a different method?

Thanks.


setting up a chain in mootools is quite simple. however, using the Chain class as a mixin can be a little more involved.

typically, it's geared up towards chaining of Fx-based classes and methods and not ones that are synchronous. say you have a tween effect which has link: chain in play, you can .chain(function() {}) the instance to do something else after.

the callChain example as a standalone is fine and easy enough but it offers little in terms of timing controls.

then there's the linear timeline approach. in your case, your first callback runs after 20 ms, 1980 ms after that the second, third runs 1680 ms after the second and so forth. if you chain things so that each successive step calls the next one, you need to take that into account and actually pass on the time to wait between the 2 actions instead.

the other way to do so is to just defer them as you have done from the start.

I had a go at streamlining the former a little here: http://jsfiddle.net/dimitar/mpzzq/

(function(){
    Chain.implement({
        slowChain: function(duration){
            // console.log(duration);
            this.callChain.delay(duration === null ? 500 : duration, this);
        }
    });

    var db = $(document.body);
    var fixBody = function(cn, delay) {
        console.log(arguments);
        db.addClass(cn);
        console.log(cn, delay);
        if (this.$chain.length) {
            this.slowChain(delay || 0);
        }
    };

    var myChain = new Chain(),
        funcs = [{
            fn: fixBody,
            args: ["load"],
            delay: 1980
        }, {
            fn: fixBody,
            args: ["load-two"],
            delay: 700
        }, {
            fn: fixBody,
            args: ["load-three"],
            delay: 2000
        }, {
            fn: fixBody,
            args: ["load-four"],
            delay: 0
        }];

    myChain.chain(
        funcs.map(function(el) {
            el.args.push(el.delay);
            return el.fn.bind.apply(el.fn, [myChain].concat(el.args));
        })
    );

    document.getElement("button").addEvents({
        click: function() {
            myChain.slowChain(20);
        }
    });
})();

so in my funcs array of objects i define the func callback, the arguments to pass on and the delay. keep in mind that the func itself has the this scope set to the chain instance and self calls next one on the chain but you can easily mod this and work with it.

hope it gives you some ideas.

here it is at take 2 with a decorator function that calls the chain on a delay:

// function decorator.
Function.implement({
    chainDelay: function(delay, bind) {
        // allows you to set a delay for chained funcs and auto call stack (if bind is a chain instance)
        var self = this,                 
            args = (arguments.length > 2) ? Array.slice(arguments, 2) : null;
        return function() {
            setTimeout(function() {
                self.apply(bind, args.concat(Array.from(arguments)));
                if (bind && bind.$chain && bind.$chain.length)
                    bind.callChain.call(bind);
            }, delay);
        }
    },
    justChain: function(bind) {
        // runs a chained func when due and auto calls stack for next (if bind is a chain instance and avail)
        var self = this, args = (arguments.length > 1) ? Array.slice(arguments, 1) : null;
        return function() {
            self.call(bind, args);
            if (bind && bind.$chain && bind.$chain.length)
                bind.callChain.call(bind);
        }
    }
});


var moo = new Chain();

moo.chain(
    // some delayed ones.
    (function(what) {
        console.log(what);
    }).chainDelay(3000, moo, "hi"),
    (function(what, ever) {
        console.log(what, ever);
    }).chainDelay(3000, moo, "there", "coda"),
    (function(what) {
        new Element("div[id=foo][html=" + what +"]").inject(document.body);
    }).chainDelay(1000, moo, "mootools FTW!"),
    // regular ones here for good measure!    
    (function() {
        document.id("foo").setStyle("color", "red")
    }).justChain(moo),
    (function() {
        document.id("foo").setStyle("background-color", "blue")
    })    
);

moo.callChain();

example of that: http://jsfiddle.net/dimitar/Y4KCB/4/

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜