1 
  2 /**
  3  * @class EventMixin是一个包含事件相关功能的mixin。可以通过 Class.mix(target, EventMixin) 来为target增加事件功能。
  4  * @mixin
  5  * @static
  6  * @module hilo/event/EventMixin
  7  * @requires hilo/core/Class
  8  */
  9 var EventMixin = {
 10     _listeners: null,
 11 
 12     /**
 13      * 增加一个事件监听。
 14      * @param {String} type 要监听的事件类型。
 15      * @param {Function} listener 事件监听回调函数。
 16      * @param {Boolean} once 是否是一次性监听,即回调函数响应一次后即删除,不再响应。
 17      */
 18     on: function(type, listener, once){
 19         var listeners = (this._listeners = this._listeners || {});
 20         var eventListeners = (listeners[type] = listeners[type] || []);
 21         for(var i = 0, len = eventListeners.length; i < len; i++){
 22             var el = eventListeners[i];
 23             if(el.listener === listener) return;
 24         }
 25         eventListeners.push({listener:listener, once:once});
 26         return this;
 27     },
 28 
 29     /**
 30      * 删除一个事件监听。如果不传入任何参数,则删除所有的事件监听;如果不传入第二个参数,则删除指定类型的所有事件监听。
 31      * @param {String} type 要删除监听的事件类型。
 32      * @param {Function} listener 要删除监听的回调函数。
 33      */
 34     off: function(type, listener){
 35         //remove all event listeners
 36         if(arguments.length == 0){
 37             this._listeners = null;
 38             return this;
 39         }
 40 
 41         var eventListeners = this._listeners && this._listeners[type];
 42         if(eventListeners){
 43             //remove event listeners by specified type
 44             if(arguments.length == 1){
 45                 delete this._listeners[type];
 46                 return this;
 47             }
 48 
 49             for(var i = 0, len = eventListeners.length; i < len; i++){
 50                 var el = eventListeners[i];
 51                 if(el.listener === listener){
 52                     eventListeners.splice(i, 1);
 53                     if(eventListeners.length === 0) delete this._listeners[type];
 54                     break;
 55                 }
 56             }
 57         }
 58         return this;
 59     },
 60 
 61     /**
 62      * 发送事件。当第一个参数类型为Object时,则把它作为一个整体事件对象。
 63      * @param {String} type 要发送的事件类型。
 64      * @param {Object} detail 要发送的事件的具体信息,即事件随带参数。
 65      */
 66     fire: function(type, detail){
 67         var event, eventType;
 68         if(typeof type === 'string'){
 69             eventType = type;
 70         }else{
 71             event = type;
 72             eventType = type.type;
 73         }
 74 
 75         var listeners = this._listeners;
 76         if(!listeners) return false;
 77 
 78         var eventListeners = listeners[eventType];
 79         if(eventListeners){
 80             eventListeners = eventListeners.slice(0);
 81             event = event || new EventObject(eventType, this, detail);
 82             
 83             for(var i = 0; i < eventListeners.length && !event._stopped; i++){
 84                 var el = eventListeners[i];
 85                 el.listener.call(this, event);
 86                 if(el.once) eventListeners.splice(i--, 1);
 87             }
 88 
 89             if(eventListeners.length == 0) delete listeners[eventType];
 90             return true;
 91         }
 92         return false;
 93     }
 94 };
 95 
 96 /**
 97  * 事件对象类。当前仅为内部类,以后有需求的话可能会考虑独立为公开类。
 98  */
 99 var EventObject = Class.create({
100     constructor: function EventObject(type, target, detail){
101         this.type = type;
102         this.target = target;
103         this.detail = detail;
104         this.timeStamp = +new Date();
105     },
106 
107     type: null,
108     target: null,
109     detail: null,
110     timeStamp: 0,
111 
112     stopImmediatePropagation: function(){
113         this._stopped = true;
114     }
115 });
116