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