event-custom-base.js revision e806a570fd5dbd8a6ef84c8e580763818b165618
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Custom event engine, DOM event listener abstraction layer, synthetic DOM
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @module event-custom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Custom event engine, DOM event listener abstraction layer, synthetic DOM
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @module event-custom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @submodule event-custom-base
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin(function() {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Allows for the insertion of methods that are executed before or after
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * a specified method
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Cache of objects touched by the utility
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @property objs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Execute the supplied method before the specified function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method before
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param fn {Function} the function to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param obj the object hosting the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sFn {string} the name of the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param c The execution context for fn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * when the event fires.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @return {string} handle for the subscription
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin var f = fn, a;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Execute the supplied method after the specified function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method after
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param fn {Function} the function to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param obj the object hosting the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sFn {string} the name of the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param c The execution context for fn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @return {string} handle for the subscription
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin var f = fn, a;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Execute the supplied method after the specified function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method _inject
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param when {string} before or after
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param fn {Function} the function to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param obj the object hosting the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sFn {string} the name of the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param c The execution context for fn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @return {string} handle for the subscription
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @private
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // object id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // create a map entry for the obj if it doesn't exist
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin if (! o[sFn]) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // create a map entry for the method if it doesn't exist
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // re-route the method to our wrapper
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin function() {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // subscriber id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // register the callback
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Detach a before or after subscription
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method detach
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param handle {string} the subscription handle
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin//////////////////////////////////////////////////////////////////////////
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Wrapper for a displaced method with aop enabled
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.Method
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @constructor
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param obj The object to operate on
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sFn The name of the method to displace
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Register a aop subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method register
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sid {string} the subscriber id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param fn {Function} the function to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param when {string} when to execute the function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chinY.Do.Method.prototype.register = function (sid, fn, when) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Unregister a aop subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method delete
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sid {string} the subscriber id
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param fn {Function} the function to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param when {string} when to execute the function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Execute the wrapped method
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method exec
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // execute before
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i in bf) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // execute method
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // execute after methods.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin for (i in af) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // Stop processing if a Halt object is returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // Check for a new return value
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin } else if (newRet && newRet.constructor == Y.Do.AlterReturn) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin//////////////////////////////////////////////////////////////////////////
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return an AlterArgs object when you want to change the arguments that
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * were passed into the function. An example would be a service that scrubs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * out illegal characters prior to executing the core business logic.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.AlterArgs
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return an AlterReturn object when you want to change the result returned
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * from the core method to the caller
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.AlterReturn
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return a Halt object when you want to terminate the execution
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * of all subsequent subscribers as well as the wrapped method
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * if it has not exectued yet.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.Halt
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return a Prevent object when you want to prevent the wrapped function
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * from executing, but want the remaining listeners to execute
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.Prevent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return an Error object when you want to terminate the execution
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * of all subsequent method calls.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class Do.Error
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @deprecated use Y.Do.Halt or Y.Do.Prevent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin//////////////////////////////////////////////////////////////////////////
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin// Y["Event"] && Y.Event.addListener(window, "unload", Y.Do._unload, Y.Do);
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Custom event engine, DOM event listener abstraction layer, synthetic DOM
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @module event-custom
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @submodule event-custom-base
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Return value from all subscribe operations
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class EventHandle
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @constructor
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param evt {CustomEvent} the custom event
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param sub {Subscriber} the subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin// var onsubscribeType = "_event:onsub",
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'broadcast',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'monitored',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'bubbles',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'context',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'contextFn',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'currentTarget',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'defaultFn',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'defaultTargetOnly',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'details',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'emitFacade',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'fireOnce',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'preventable',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'preventedFn',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'queuable',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin 'stoppedFn',
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The custom event
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type CustomEvent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The subscriber object
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type Subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Detaches this subscriber
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method detach
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin detach: function() {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Monitor the event state for the subscribed event. The first parameter
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * is what should be monitored, the rest are the normal parameters when
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * subscribing to an event.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @method monitor
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param what {string} what to monitor ('attach', 'detach', 'publish')
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @return {EventHandle} return value from the monitor event subscription
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The CustomEvent class lets you define events for your application
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * that can be subscribed to by one or more independent component.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param {String} type The type of event, which is passed to the callback
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * when the event fires
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @param o configuration object
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @class CustomEvent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @constructor
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // if (arguments.length > 2) {
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin// this.log('CustomEvent context and silent are now in the config', 'warn', 'Event');
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin o = o || {};
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The type of event, returned to subscribers when the event fires
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @property type
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type string
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * The context the the event will fire from by default. Defaults to the YUI
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * instance.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @property context
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type object
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * Monitor when an event is attached or detached.
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @property monitored
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type boolean
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // this.monitored = false;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * If 0, this event does not broadcast. If 1, the YUI instance is notified
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * every time this event fires. If 2, the YUI instance and the YUI global
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * (if event is enabled on the global) are notified every time this event
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @property broadcast
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * @type int
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin // this.broadcast = 0;
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * By default all custom events are logged in the debug build, set silent
da2e3ebdc1edfbc5028edf1354e7dd2fa69a7968chin * to true to disable debug outpu for this event.
this.subscribers = {};
this.afters = {};
this.preventable = true;
this.bubbles = true;
this.applyConfig(o, true);
if (sib) {
if (when) {
this.monitored = true;
getSubs: function() {
if (sib) {
if (!fn) {
if (this.async) {
this.afterCount++;
this.subCount++;
return new Y.EventHandle(this, s);
if (this.host) {
for (i in subs) {
s = subs[i];
this._delete(s);
found++;
return found;
unsubscribe: function() {
var ret;
if (!this.silent) {
fire: function() {
this.fired = true;
if (this.emitFacade) {
if (this.hasSubs()) {
return this.stopped ? false : true;
for (i in subs) {
s = subs[i];
if (s && s.fn) {
var a = Y.Array(args);
if (this.host !== Y) {
unsubscribeAll: function() {
detachAll: function() {
return this.detach();
_delete: function(s) {
this.subCount--;
this.afterCount--;
if (this.host) {
ce: this,
sub: s
delete s.fn;
delete s.context;
if (a || args) {
if (this.once) {
return ret;
var c = this.context,
ret = true;
return ret;
if (context) {
var L = Y.Lang,
YArray = Y.Array,
return type;
if (!L.isString(t)) {
after = true;
events: {},
targets: {},
config: o,
bubbling: false,
defaults: {
host: this,
once: function() {
return handle;
f = fn;
c = context;
ret = {};
isArr = true;
if (L.isObject(v)) {
c = v.context || c;
if (this instanceof YUI) {
if (Node) {
if (n instanceof Y.NodeList) {
} else if (n instanceof Node) {
if (domevent) {
if (adapt) {
if (!handle) {
handle = ce._on(fn, context, (arguments.length > 3) ? YArray(arguments, 3, true) : null, (after) ? 'after' : true);
if (detachcategory) {
subscribe: function() {
if (!type && (this !== Y)) {
for (i in evts) {
if (isNode) {
ce,
if (handles) {
if (detachcategory) {
if (cat) {
if (type) {
for (i in cat) {
if (this instanceof YUI) {
if (ce) {
unsubscribe: function() {
unsubscribeAll: function() {
* 'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false)
* 'defaultFn': the default function to execute when this event fires if preventDefault was not called
ret = {};
return ret;
if (ce) {
if (opts) {
if (!ce) {
ret = true;
var ce2;
if (ce2) {
return ce2;
var pre, e;
if (!prefixed) {
return e[type] || null;
before: function() {
bubbles: false