MINI Sh3ll
/*
---
name: "Events"
description: ""
license:
- "[GNU Lesser General Public License](http://opensource.org/licenses/lgpl-license.php)"
- "[MIT License](http://opensource.org/licenses/mit-license.php)"
requires:
- Core
- declare
inspiration:
- "[MooTools](http://mootools.net)"
provides: Events
...
*/
/** @class atom.Events */
declare( 'atom.Events', {
/** @constructs */
initialize: function (context) {
this.context = context || this;
this.locked = [];
this.events = {};
this.actions = {};
this.readyList = {};
},
/**
* @param {String} name
* @return Boolean
*/
exists: function (name) {
var array = this.events[this.removeOn( name )];
return !!(array && array.length);
},
/**
* @param {String} name
* @param {Function} callback
* @return Boolean
*/
add: function (name, callback) {
this.run( 'addOne', name, callback );
return this;
},
/**
* @param {String} name
* @param {Function} [callback]
* @return Boolean
*/
remove: function (name, callback) {
if (typeof name == 'string' && !callback) {
this.removeAll( name );
} else {
this.run( 'removeOne', name, callback );
}
return this;
},
/**
* @param {String} name
* @param {Array} args
* @return atom.Events
*/
fire: function (name, args) {
args = args ? slice.call( args ) : [];
name = this.removeOn( name );
this.locked.push(name);
var i = 0, l, events = this.events[name];
if (events) for (l = events.length; i < l; i++) {
events[i].apply( this.context, args );
}
this.unlock( name );
return this;
},
/**
* @param {String} name
* @param {Array} [args=null]
* @return atom.Events
*/
ready: function (name, args) {
name = this.removeOn( name );
this.locked.push(name);
if (name in this.readyList) {
throw new Error( 'Event «'+name+'» is ready' );
}
this.readyList[name] = args;
this.fire(name, args);
this.removeAll(name);
this.unlock( name );
return this;
},
/**
* @param {String} name
* @param {Array} [args=null]
* @return atom.Events
*/
ensureReady: function (name, args) {
if (!(name in this.readyList)) {
this.ready(name, args);
}
return this;
},
// only private are below
/** @private */
context: null,
/** @private */
events: {},
/** @private */
readyList: {},
/** @private */
locked: [],
/** @private */
actions: {},
/** @private */
removeOn: function (name) {
return (name || '').replace(/^on([A-Z])/, function(full, first){
return first.toLowerCase();
});
},
/** @private */
removeAll: function (name) {
var events = this.events[name];
if (events) for (var i = events.length; i--;) {
this.removeOne( name, events[i] );
}
},
/** @private */
unlock: function (name) {
var action,
all = this.actions[name],
index = this.locked.indexOf( name );
this.locked.splice(index, 1);
if (all) for (index = 0; index < all.length; index++) {
action = all[index];
this[action.method]( name, action.callback );
}
},
/** @private */
run: function (method, name, callback) {
var i = 0, l = 0;
if (Array.isArray(name)) {
for (i = 0, l = name.length; i < l; i++) {
this[method](name[i], callback);
}
} else if (typeof name == 'object') {
for (i in name) {
this[method](i, name[i]);
}
} else if (typeof name == 'string') {
this[method](name, callback);
} else {
throw new TypeError( 'Wrong arguments in Events.' + method );
}
},
/** @private */
register: function (name, method, callback) {
var actions = this.actions;
if (!actions[name]) {
actions[name] = [];
}
actions[name].push({ method: method, callback: callback })
},
/** @private */
addOne: function (name, callback) {
var events, ready, context;
name = this.removeOn( name );
if (this.locked.indexOf(name) == -1) {
ready = this.readyList[name];
if (ready) {
context = this.context;
setTimeout(function () {
callback.apply(context, ready);
}, 0);
return this;
} else {
events = this.events;
if (!events[name]) {
events[name] = [callback];
} else {
events[name].push(callback);
}
}
} else {
this.register(name, 'addOne', callback);
}
},
/** @private */
removeOne: function (name, callback) {
name = this.removeOn( name );
if (this.locked.indexOf(name) == -1) {
var events = this.events[name], i = events.length;
while (i--) if (events[i] == callback) {
events.splice(i, 1);
}
} else {
this.register(name, 'removeOne', callback);
}
}
});
// local alias
var Events = atom.Events;
OHA YOOOO