mirror of
https://github.com/hiloteam/Hilo.git
synced 2025-12-08 20:35:59 +00:00
141 lines
4.5 KiB
JavaScript
141 lines
4.5 KiB
JavaScript
/**
|
|
* Hilo
|
|
* Copyright 2015 alibaba.com
|
|
* Licensed under the MIT License
|
|
*/
|
|
|
|
/**
|
|
* @class EventMixin is a mixin on event related functions. Use Class.mix(target, EventMixin) to add event function onto target.
|
|
* @static
|
|
* @mixin
|
|
* @module hilo/event/EventMixin
|
|
* @requires hilo/core/Class
|
|
*/
|
|
var EventMixin = /** @lends EventMixin# */{
|
|
_listeners: null,
|
|
|
|
/**
|
|
* Add an event listenser.
|
|
* @param {String} type Event type to listen.
|
|
* @param {Function} listener Callback function of event listening.
|
|
* @param {Boolean} once Listen on event only once and no more response after the first response?
|
|
* @returns {Object} The Event itself. Functions chain call supported.
|
|
*/
|
|
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;
|
|
},
|
|
|
|
/**
|
|
* Remove one event listener. Remove all event listeners if no parameter provided, and remove all event listeners on one type which is provided as the only parameter.
|
|
* @param {String} type The type of event listener that want to remove.
|
|
* @param {Function} listener Event listener callback function to be removed.
|
|
* @returns {Object} The Event itself. Functions chain call supported.
|
|
*/
|
|
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;
|
|
},
|
|
|
|
/**
|
|
* Send events. If the first parameter is an Object, take it as an Event Object.
|
|
* @param {String} type Event type to send.
|
|
* @param {Object} detail The detail (parameters go with the event) of Event to send.
|
|
* @returns {Boolean} Whether Event call successfully.
|
|
*/
|
|
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;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Event Object class. It's an private class now, but maybe will become a public class if needed.
|
|
*/
|
|
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;
|
|
};
|
|
}
|