[转帖]Mootools源码分析-17 -- Element-4

原帖地址:http://space.flash8.net/space/?18713/viewspace-403269.html

原作者:我佛山人

 

//Element事件的setter,addEvents的快捷方式

Element.Properties.events 
= {set: function(events)    {

    
this.addEvents(events);

}};

//Element、Window 和 Document的事件扩展

Native.implement([Element, Window, Document], {

    
//添加事件监听,有别于addListener,可以使用自定义事件
    addEvent: function(type, fn)    {
        
//取临时对象,注意提供的默认值
        var events = this.retrieve('events', {});
        
//查找指定类型的事件列表
        events[type] = events[type] || {'keys': [], 'values': []};
        
//如果已经添加了该监听
        if (events[type].keys.contains(fn))    return this;
        
//添加到事件订阅列表
        events[type].keys.push(fn);
        
var realType = type, custom = Element.Events.get(type), condition = fn, self = this;
        
//如果是自定义事件
        if (custom)    {
        
//添加自定义事件时的处理
            if (custom.onAdd)    custom.onAdd.call(this, fn);
        
//自定义事件的条件
            if (custom.condition)    {
                condition 
= function(event)    {
                    
if (custom.condition.call(this, event))    return fn.call(this, event);
                    
return false;
                };
            }
            realType 
= custom.base || realType;
        }
        
var defn = function()    {
            
return fn.call(self);
        };
        
//内置事件类型处理    
        var nativeEvent = Element.NativeEvents[realType] || 0;
        
//如果是内置的事件
        if (nativeEvent)    {
            
//如果是交互事件
            if (nativeEvent == 2)    {
                
//闭包
                defn = function(event)    {
                
//这样最后传给监听函数的参数是经包装过Event对象
                    event = new Event(event, self.getWindow());
                    
//这个条件用于扩展内置事件
                    if (condition.call(self, event) === false)    event.stop();
                };
            }
            
//最终还是调用addListener
            this.addListener(realType, defn);
        }
        
//添加到列表
        events[type].values.push(defn);
        
return this;
    },


    
//移除事件监听

    removeEvent: 
function(type, fn)    {

        
//取临时对象,不提供默认值
        var events = this.retrieve('events');
        
//如果临时对象不存在,说明监听不存在,直接返回
        if (!events || !events[type])    return this;
        
//检查是否已添加本监听
        var pos = events[type].keys.indexOf(fn);
        
//没有则返回
        if (pos == -1)    return this;
        
//从队列中移除
        var key = events[type].keys.splice(pos, 1)[0];
        
var value = events[type].values.splice(pos, 1)[0];
        
//自定义事件处理
        var custom = Element.Events.get(type);
        
//如果是自定义事件
        if (custom)    {
            
//自定义事件的移除处理
            if (custom.onRemove)    custom.onRemove.call(this, fn);
            type 
= custom.base || type;
        }
        
//如果是内置事件还需要调用removeListener来处理
        return (Element.NativeEvents[type]) ? this.removeListener(type, value) : this;
    },
    
    
//批量添加事件监听
    addEvents: function(events)    {
        
for (var event in events)    this.addEvent(event, events[event]);
        
return this;
    },

//批量移除事件监听
    removeEvents: function(type)    {
        
//取临时对象,不提供默认值
        var events = this.retrieve('events');
        
//没有事件监听直接返回
        if (!events)    return this;
        
//如果不提供type参数,移除所有类型的事件
        if (!type)    {
            
for (var evType in events) this.removeEvents(evType);
            events 
= null;
        }    
else if (events[type])    {
            
//移除指定类型的事件
            while (events[type].keys[0])    this.removeEvent(type, events[type].keys[0]);
            events[type] 
= null;
        }
        
return this;
    },

    
//事件通知
    fireEvent: function(type, args, delay)    {
        
//取临时对象,不提供默认值
        var events = this.retrieve('events');
        
//没有事件监听
        if (!events || !events[type])    return this;
        events[type].keys.each(
function(fn)    {
            
//注意事件监听的函数中this默认指向当前Element
            fn.create({'bind'this'delay': delay, 'arguments': args})();
        }, 
this);
        
return this;
    },

    
//事件复制
    cloneEvents: function(from, type)    {
        
//事件源
        from = $(from);
        
var fevents = from.retrieve('events');
        
if (!fevents)    return this;
        
//不提供type参数则复制所有事件
        if (!type)    {
            
for (var evType in fevents)    this.cloneEvents(from, evType);
        }    
else if (fevents[type])    {
        
//复制指定类型的事件
            fevents[type].keys.each(function(fn)    {
                
this.addEvent(type, fn);
            }, 
this);
        }
        
return this;
    }
});


//内置事件,分两种类型

Element.NativeEvents 
= {
    click: 
2, dblclick: 2, mouseup: 2, mousedown: 2, contextmenu: 2//mouse buttons
    mousewheel: 2, DOMMouseScroll: 2//mouse wheel
    mouseover: 2, mouseout: 2, mousemove: 2, selectstart: 2, selectend: 2//mouse movement
    keydown: 2, keypress: 2, keyup: 2//keyboard
    focus: 2, blur: 2, change: 2, reset: 2, select: 2, submit: 2//form elements
    load: 1, unload: 1, beforeunload: 1, resize: 1, move: 1, DOMContentLoaded: 1, readystatechange: 1//window
    error: 1, abort: 1, scroll: 1 //misc
};

//就地执行的匿名函数
(function()    {
    
var $check = function(event)    {
        
var related = event.relatedTarget;
        
if (related == undefined)    return true;
        
if (related === false)    return false;
        
return ($type(this!= 'document' && related != this && related.prefix != 'xul' && !this.hasChild(related));
    };

    
//基于原事件扩展出的自定义事件
    Element.Events = new Hash({
        
//鼠标进入事件
        mouseenter: {
            base: 
'mouseover',
            condition: $check
        },
        
//鼠标离开事件
        mouseleave: {
            base: 
'mouseout',
            condition: $check
        },
//鼠标滚轮事件
        mousewheel: {
            base: (Browser.Engine.gecko) 
? 'DOMMouseScroll' : 'mousewheel'
        }
    });
})();

 

posted @ 2009-11-06 10:47  webgis松鼠  阅读(235)  评论(0)    收藏  举报