yui3的node定时器

jquery有一个插件叫Timer,很有意思,咱来实现一个简版的yui3的node timer。但还是应当首先交代下yui3的node扩展的一些事情,yui3 beta在实现上和pre版相比有很大不同,其中就包括yui原生元素的扩展方式的实现,之前在yui3还是pre的时候写过一篇yui3的链式调用的文章,阐述如何给原生的Node增加自定义方法,也就是实现了一个类似Y.Node.get(‘#id’).fuck()。在pre版需要使用 Node.addDOMMethod方法添加声明,而在yui3beta版这个方法就被去掉了,干脆直接通过在Y.Node.prototype上挂载新方法来实现扩展,这样确实方便了许多,自然,yui对Node的保护也变的较为脆弱,岂不是只通过Y.Node.prototype就可以重载原生的接口?但yui3内在的元素比如node和dom之间的继承的实现仍然采用了pre的思路,只是将那个addDomMethod改成了语义更通用的 Y.Node.importMethod(需要扩展的不只有Dom节点)。

再来看node定时器的实现,这里我要实现两个div宽度增长这样一个功能,而且两个div之间的行为不应当相互影响,就类似两个线程同时执行不相互影响。直接裸写代码就应当这样。这里有一个需要注意的地方,就是短时间连续的dom操作可能会造成浏览器假死,就是说实际dom操作已经完成,但在页面上看不到效果,原因在这里。

grow函数的实现:

var grow = function(id){
    setTimeout(function(){
        var _width = Number(Y.Node.get(‘#’+id).getStyle(‘width’).replace(‘px’,”));
        if(_width >= 500)return;
        Y.Node.get(‘#’+id).setStyle(‘width’,(_width+1).toString()+’px’).
        set(‘innerHTML’,(_width+1).toString());
        setTimeout(arguments.callee,0);
    },0);
};

这样就可以看到效果了,例子在这里

http://www.uedmagazine.com/test/execthreads.html

然而这里还是需要手动对相邻的dom操作做settimeout的hack,这里实现了一个everyTime的扩展,可以通过

Y.Node.get('#id').everyTime(10,function(node){
    //your code here
},false);

这样就将settimeout的方法的hack封装进node中,不用写那些晦涩难懂的settimeout和callee了。

实现的代码是这样的:

YUI.add(‘node-timer’,function(Y){
    Y.Node.prototype.everyTime = function() {
        var node = this;
        node._ttime = arguments[0];
        if(typeof arguments[1] == ‘function’){
            node._timer_f = arguments[1];
        }else {
            throw new TypeError(“function must be required”);
            return false;
        }
        var _run_now = (arguments[2] == false)?false:true;
        if(_run_now){
            node.startTimer();
        }
    };
    Y.Node.prototype.stopTimer = function(){
        var node = this;
        setTimeout(function(){
            if(!node._timer)return false;
            clearTimeout(node._timer);
        },0);
    };
    Y.Node.prototype.startTimer = function(){
        var node = this;
        node._timer = setTimeout(function(){
            if(node._timer_f(node) == false){
                clearTimeout(node._timer);
                return false;
            }
            node._timer = setTimeout(arguments.callee,node._ttime);
        },node._ttime);
    };
},”,{requires:['node']});

例子在这里:

http://www.uedmagazine.com/test/yui3NodeTimer.html

用法:

  • node.every(time,foo,flag)
  • time:相邻操作的间隔时间
  • foo:foo(node),每次操作的回调函数,回调参数是node本身,当函数返回false的时候停止循环
  • flag:true,立即执行,false,不立即执行,默认为true

node.stopTimer()

停止执行最后的一次timer,这里多次执行startTimer的时候会对node的timer进行叠加,并不去重,这个以后在说

node.startTimer()

开始执行,这里多次开始会叠加执行

to be continue…

posted at