Hilo/docs/api-zh/code/event/EventMixin.js
2016-12-14 14:40:55 +08:00

141 lines
4.5 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Hilo
* Copyright 2015 alibaba.com
* Licensed under the MIT License
*/
/**
* @class EventMixin是一个包含事件相关功能的mixin。可以通过 Class.mix(target, EventMixin) 来为target增加事件功能。
* @static
* @mixin
* @module hilo/event/EventMixin
* @requires hilo/core/Class
*/
var EventMixin = /** @lends EventMixin# */{
_listeners: null,
/**
* 增加一个事件监听。
* @param {String} type 要监听的事件类型。
* @param {Function} listener 事件监听回调函数。
* @param {Boolean} once 是否是一次性监听,即回调函数响应一次后即删除,不再响应。
* @returns {Object} 对象本身。链式调用支持。
*/
on: function(type, listener, once){
var listeners = (this._listeners = this._listeners || {});
var eventListeners = (listeners[type] = listeners[type] || []);
for(var i = 0, len = eventListeners.length; i < len; i++){
var el = eventListeners[i];
if(el.listener === listener) return;
}
eventListeners.push({listener:listener, once:once});
return this;
},
/**
* 删除一个事件监听。如果不传入任何参数,则删除所有的事件监听;如果不传入第二个参数,则删除指定类型的所有事件监听。
* @param {String} type 要删除监听的事件类型。
* @param {Function} listener 要删除监听的回调函数。
* @returns {Object} 对象本身。链式调用支持。
*/
off: function(type, listener){
//remove all event listeners
if(arguments.length == 0){
this._listeners = null;
return this;
}
var eventListeners = this._listeners && this._listeners[type];
if(eventListeners){
//remove event listeners by specified type
if(arguments.length == 1){
delete this._listeners[type];
return this;
}
for(var i = 0, len = eventListeners.length; i < len; i++){
var el = eventListeners[i];
if(el.listener === listener){
eventListeners.splice(i, 1);
if(eventListeners.length === 0) delete this._listeners[type];
break;
}
}
}
return this;
},
/**
* 发送事件。当第一个参数类型为Object时则把它作为一个整体事件对象。
* @param {String} type 要发送的事件类型。
* @param {Object} detail 要发送的事件的具体信息,即事件随带参数。
* @returns {Boolean} 是否成功调度事件。
*/
fire: function(type, detail){
var event, eventType;
if(typeof type === 'string'){
eventType = type;
}else{
event = type;
eventType = type.type;
}
var listeners = this._listeners;
if(!listeners) return false;
var eventListeners = listeners[eventType];
if(eventListeners){
var eventListenersCopy = eventListeners.slice(0);
event = event || new EventObject(eventType, this, detail);
if(event._stopped) return false;
for(var i = 0; i < eventListenersCopy.length; i++){
var el = eventListenersCopy[i];
el.listener.call(this, event);
if(el.once) {
var index = eventListeners.indexOf(el);
if(index > -1){
eventListeners.splice(index, 1);
}
}
}
if(eventListeners.length == 0) delete listeners[eventType];
return true;
}
return false;
}
};
/**
* 事件对象类。当前仅为内部类,以后有需求的话可能会考虑独立为公开类。
*/
var EventObject = Class.create({
constructor: function EventObject(type, target, detail){
this.type = type;
this.target = target;
this.detail = detail;
this.timeStamp = +new Date();
},
type: null,
target: null,
detail: null,
timeStamp: 0,
stopImmediatePropagation: function(){
this._stopped = true;
}
});
//Trick: `stopImmediatePropagation` compatibility
var RawEvent = window.Event;
if(RawEvent){
var proto = RawEvent.prototype,
stop = proto.stopImmediatePropagation;
proto.stopImmediatePropagation = function(){
stop && stop.call(this);
this._stopped = true;
};
}