Version 3.18.1

APIs

  • Begin typing in the search box above to see results.
Show:

File: event-custom/js/event-do.js

 /**
 * Custom event engine, DOM event listener abstraction layer, synthetic DOM
 * events.
 * @module event-custom
 * @submodule event-custom-base
 */
 
 /**
 * Allows for the insertion of methods that are executed before or after
 * a specified method
 * @class Do
 * @static
 */
 
 var DO_BEFORE = 0,
 DO_AFTER = 1,
 
 DO = {
 
 /**
 * Cache of objects touched by the utility
 * @property objs
 * @static
 * @deprecated Since 3.6.0. The `_yuiaop` property on the AOP'd object
 * replaces the role of this property, but is considered to be private, and
 * is only mentioned to provide a migration path.
 *
 * If you have a use case which warrants migration to the _yuiaop property,
 * please file a ticket to let us know what it's used for and we can see if
 * we need to expose hooks for that functionality more formally.
 */
 objs: null,
 
 /**
 * <p>Execute the supplied method before the specified function. Wrapping
 * function may optionally return an instance of the following classes to
 * further alter runtime behavior:</p>
 * <dl>
 * <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
 * <dd>Immediatly stop execution and return
 * <code>returnValue</code>. No other wrapping functions will be
 * executed.</dd>
 * <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt>
 * <dd>Replace the arguments that the original function will be
 * called with.</dd>
 * <dt></code>Y.Do.Prevent(message)</code></dt>
 * <dd>Don't execute the wrapped function. Other before phase
 * wrappers will be executed.</dd>
 * </dl>
 *
 * @method before
 * @param fn {Function} the function to execute
 * @param obj the object hosting the method to displace
 * @param sFn {string} the name of the method to displace
 * @param c The execution context for fn
 * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
 * when the event fires.
 * @return {EventHandle} handle for the subscription
 * @static
 */
 before: function(fn, obj, sFn, c) {
 // Y.log('Do before: ' + sFn, 'info', 'event');
 var f = fn, a;
 if (c) {
 a = [fn, c].concat(Y.Array(arguments, 4, true));
 f = Y.rbind.apply(Y, a);
 }
 
 return this._inject(DO_BEFORE, f, obj, sFn);
 },
 
 /**
 * <p>Execute the supplied method after the specified function. Wrapping
 * function may optionally return an instance of the following classes to
 * further alter runtime behavior:</p>
 * <dl>
 * <dt></code>Y.Do.Halt(message, returnValue)</code></dt>
 * <dd>Immediatly stop execution and return
 * <code>returnValue</code>. No other wrapping functions will be
 * executed.</dd>
 * <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt>
 * <dd>Return <code>returnValue</code> instead of the wrapped
 * method's original return value. This can be further altered by
 * other after phase wrappers.</dd>
 * </dl>
 *
 * <p>The static properties <code>Y.Do.originalRetVal</code> and
 * <code>Y.Do.currentRetVal</code> will be populated for reference.</p>
 *
 * @method after
 * @param fn {Function} the function to execute
 * @param obj the object hosting the method to displace
 * @param sFn {string} the name of the method to displace
 * @param c The execution context for fn
 * @param arg* {mixed} 0..n additional arguments to supply to the subscriber
 * @return {EventHandle} handle for the subscription
 * @static
 */
 after: function(fn, obj, sFn, c) {
 var f = fn, a;
 if (c) {
 a = [fn, c].concat(Y.Array(arguments, 4, true));
 f = Y.rbind.apply(Y, a);
 }
 
 return this._inject(DO_AFTER, f, obj, sFn);
 },
 
 /**
 * Execute the supplied method before or after the specified function.
 * Used by <code>before</code> and <code>after</code>.
 *
 * @method _inject
 * @param when {string} before or after
 * @param fn {Function} the function to execute
 * @param obj the object hosting the method to displace
 * @param sFn {string} the name of the method to displace
 * @param c The execution context for fn
 * @return {EventHandle} handle for the subscription
 * @private
 * @static
 */
 _inject: function(when, fn, obj, sFn) {
 // object id
 var id = Y.stamp(obj), o, sid;
 
 if (!obj._yuiaop) {
 // create a map entry for the obj if it doesn't exist, to hold overridden methods
 obj._yuiaop = {};
 }
 
 o = obj._yuiaop;
 
 if (!o[sFn]) {
 // create a map entry for the method if it doesn't exist
 o[sFn] = new Y.Do.Method(obj, sFn);
 
 // re-route the method to our wrapper
 obj[sFn] = function() {
 return o[sFn].exec.apply(o[sFn], arguments);
 };
 }
 
 // subscriber id
 sid = id + Y.stamp(fn) + sFn;
 
 // register the callback
 o[sFn].register(sid, fn, when);
 
 return new Y.EventHandle(o[sFn], sid);
 },
 
 /**
 * Detach a before or after subscription.
 *
 * @method detach
 * @param handle {EventHandle} the subscription handle
 * @static
 */
 detach: function(handle) {
 if (handle.detach) {
 handle.detach();
 }
 }
 };
 
 Y.Do = DO;
 
 //////////////////////////////////////////////////////////////////////////
 
 /**
 * Contains the return value from the wrapped method, accessible
 * by 'after' event listeners.
 *
 * @property originalRetVal
 * @static
 * @since 3.2.0
 */
 
 /**
 * Contains the current state of the return value, consumable by
 * 'after' event listeners, and updated if an after subscriber
 * changes the return value generated by the wrapped function.
 *
 * @property currentRetVal
 * @static
 * @since 3.2.0
 */
 
 //////////////////////////////////////////////////////////////////////////
 
 /**
 * Wrapper for a displaced method with aop enabled
 * @class Do.Method
 * @constructor
 * @param obj The object to operate on
 * @param sFn The name of the method to displace
 */
 DO.Method = function(obj, sFn) {
 this.obj = obj;
 this.methodName = sFn;
 this.method = obj[sFn];
 this.before = {};
 this.after = {};
 };
 
 /**
 * Register a aop subscriber
 * @method register
 * @param sid {string} the subscriber id
 * @param fn {Function} the function to execute
 * @param when {string} when to execute the function
 */
 DO.Method.prototype.register = function (sid, fn, when) {
 if (when) {
 this.after[sid] = fn;
 } else {
 this.before[sid] = fn;
 }
 };
 
 /**
 * Unregister a aop subscriber
 * @method delete
 * @param sid {string} the subscriber id
 * @param fn {Function} the function to execute
 * @param when {string} when to execute the function
 */
 DO.Method.prototype._delete = function (sid) {
 // Y.log('Y.Do._delete: ' + sid, 'info', 'Event');
 delete this.before[sid];
 delete this.after[sid];
 };
 
 /**
 * <p>Execute the wrapped method. All arguments are passed into the wrapping
 * functions. If any of the before wrappers return an instance of
 * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped
 * function nor any after phase subscribers will be executed.</p>
 *
 * <p>The return value will be the return value of the wrapped function or one
 * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or
 * <code>Y.Do.AlterReturn</code>.
 *
 * @method exec
 * @param arg* {any} Arguments are passed to the wrapping and wrapped functions
 * @return {any} Return value of wrapped function unless overwritten (see above)
 */
 DO.Method.prototype.exec = function () {
 
 var args = Y.Array(arguments, 0, true),
 i, ret, newRet,
 bf = this.before,
 af = this.after,
 prevented = false;
 
 // execute before
 for (i in bf) {
 if (bf.hasOwnProperty(i)) {
 ret = bf[i].apply(this.obj, args);
 if (ret) {
 switch (ret.constructor) {
 case DO.Halt:
 return ret.retVal;
 case DO.AlterArgs:
 args = ret.newArgs;
 break;
 case DO.Prevent:
 prevented = true;
 break;
 default:
 }
 }
 }
 }
 
 // execute method
 if (!prevented) {
 ret = this.method.apply(this.obj, args);
 }
 
 DO.originalRetVal = ret;
 DO.currentRetVal = ret;
 
 // execute after methods.
 for (i in af) {
 if (af.hasOwnProperty(i)) {
 newRet = af[i].apply(this.obj, args);
 // Stop processing if a Halt object is returned
 if (newRet && newRet.constructor === DO.Halt) {
 return newRet.retVal;
 // Check for a new return value
 } else if (newRet && newRet.constructor === DO.AlterReturn) {
 ret = newRet.newRetVal;
 // Update the static retval state
 DO.currentRetVal = ret;
 }
 }
 }
 
 return ret;
 };
 
 //////////////////////////////////////////////////////////////////////////
 
 /**
 * Return an AlterArgs object when you want to change the arguments that
 * were passed into the function. Useful for Do.before subscribers. An
 * example would be a service that scrubs out illegal characters prior to
 * executing the core business logic.
 * @class Do.AlterArgs
 * @constructor
 * @param msg {String} (optional) Explanation of the altered return value
 * @param newArgs {Array} Call parameters to be used for the original method
 * instead of the arguments originally passed in.
 */
 DO.AlterArgs = function(msg, newArgs) {
 this.msg = msg;
 this.newArgs = newArgs;
 };
 
 /**
 * Return an AlterReturn object when you want to change the result returned
 * from the core method to the caller. Useful for Do.after subscribers.
 * @class Do.AlterReturn
 * @constructor
 * @param msg {String} (optional) Explanation of the altered return value
 * @param newRetVal {any} Return value passed to code that invoked the wrapped
 * function.
 */
 DO.AlterReturn = function(msg, newRetVal) {
 this.msg = msg;
 this.newRetVal = newRetVal;
 };
 
 /**
 * Return a Halt object when you want to terminate the execution
 * of all subsequent subscribers as well as the wrapped method
 * if it has not exectued yet. Useful for Do.before subscribers.
 * @class Do.Halt
 * @constructor
 * @param msg {String} (optional) Explanation of why the termination was done
 * @param retVal {any} Return value passed to code that invoked the wrapped
 * function.
 */
 DO.Halt = function(msg, retVal) {
 this.msg = msg;
 this.retVal = retVal;
 };
 
 /**
 * Return a Prevent object when you want to prevent the wrapped function
 * from executing, but want the remaining listeners to execute. Useful
 * for Do.before subscribers.
 * @class Do.Prevent
 * @constructor
 * @param msg {String} (optional) Explanation of why the termination was done
 */
 DO.Prevent = function(msg) {
 this.msg = msg;
 };
 
 /**
 * Return an Error object when you want to terminate the execution
 * of all subsequent method calls.
 * @class Do.Error
 * @constructor
 * @param msg {String} (optional) Explanation of the altered return value
 * @param retVal {any} Return value passed to code that invoked the wrapped
 * function.
 * @deprecated use Y.Do.Halt or Y.Do.Prevent
 */
 DO.Error = DO.Halt;
 
 
 //////////////////////////////////////////////////////////////////////////
 
 

AltStyle によって変換されたページ (->オリジナル) /