[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 /* 2 YUI 3.17.2 (build 9c3c78e) 3 Copyright 2014 Yahoo! Inc. All rights reserved. 4 Licensed under the BSD License. 5 http://yuilibrary.com/license/ 6 */ 7 8 YUI.add('event-custom-base', function (Y, NAME) { 9 10 /** 11 * Custom event engine, DOM event listener abstraction layer, synthetic DOM 12 * events. 13 * @module event-custom 14 */ 15 16 Y.Env.evt = { 17 handles: {}, 18 plugins: {} 19 }; 20 21 /** 22 * Custom event engine, DOM event listener abstraction layer, synthetic DOM 23 * events. 24 * @module event-custom 25 * @submodule event-custom-base 26 */ 27 28 /** 29 * Allows for the insertion of methods that are executed before or after 30 * a specified method 31 * @class Do 32 * @static 33 */ 34 35 var DO_BEFORE = 0, 36 DO_AFTER = 1, 37 38 DO = { 39 40 /** 41 * Cache of objects touched by the utility 42 * @property objs 43 * @static 44 * @deprecated Since 3.6.0. The `_yuiaop` property on the AOP'd object 45 * replaces the role of this property, but is considered to be private, and 46 * is only mentioned to provide a migration path. 47 * 48 * If you have a use case which warrants migration to the _yuiaop property, 49 * please file a ticket to let us know what it's used for and we can see if 50 * we need to expose hooks for that functionality more formally. 51 */ 52 objs: null, 53 54 /** 55 * <p>Execute the supplied method before the specified function. Wrapping 56 * function may optionally return an instance of the following classes to 57 * further alter runtime behavior:</p> 58 * <dl> 59 * <dt></code>Y.Do.Halt(message, returnValue)</code></dt> 60 * <dd>Immediatly stop execution and return 61 * <code>returnValue</code>. No other wrapping functions will be 62 * executed.</dd> 63 * <dt></code>Y.Do.AlterArgs(message, newArgArray)</code></dt> 64 * <dd>Replace the arguments that the original function will be 65 * called with.</dd> 66 * <dt></code>Y.Do.Prevent(message)</code></dt> 67 * <dd>Don't execute the wrapped function. Other before phase 68 * wrappers will be executed.</dd> 69 * </dl> 70 * 71 * @method before 72 * @param fn {Function} the function to execute 73 * @param obj the object hosting the method to displace 74 * @param sFn {string} the name of the method to displace 75 * @param c The execution context for fn 76 * @param arg* {mixed} 0..n additional arguments to supply to the subscriber 77 * when the event fires. 78 * @return {EventHandle} handle for the subscription 79 * @static 80 */ 81 before: function(fn, obj, sFn, c) { 82 // Y.log('Do before: ' + sFn, 'info', 'event'); 83 var f = fn, a; 84 if (c) { 85 a = [fn, c].concat(Y.Array(arguments, 4, true)); 86 f = Y.rbind.apply(Y, a); 87 } 88 89 return this._inject(DO_BEFORE, f, obj, sFn); 90 }, 91 92 /** 93 * <p>Execute the supplied method after the specified function. Wrapping 94 * function may optionally return an instance of the following classes to 95 * further alter runtime behavior:</p> 96 * <dl> 97 * <dt></code>Y.Do.Halt(message, returnValue)</code></dt> 98 * <dd>Immediatly stop execution and return 99 * <code>returnValue</code>. No other wrapping functions will be 100 * executed.</dd> 101 * <dt></code>Y.Do.AlterReturn(message, returnValue)</code></dt> 102 * <dd>Return <code>returnValue</code> instead of the wrapped 103 * method's original return value. This can be further altered by 104 * other after phase wrappers.</dd> 105 * </dl> 106 * 107 * <p>The static properties <code>Y.Do.originalRetVal</code> and 108 * <code>Y.Do.currentRetVal</code> will be populated for reference.</p> 109 * 110 * @method after 111 * @param fn {Function} the function to execute 112 * @param obj the object hosting the method to displace 113 * @param sFn {string} the name of the method to displace 114 * @param c The execution context for fn 115 * @param arg* {mixed} 0..n additional arguments to supply to the subscriber 116 * @return {EventHandle} handle for the subscription 117 * @static 118 */ 119 after: function(fn, obj, sFn, c) { 120 var f = fn, a; 121 if (c) { 122 a = [fn, c].concat(Y.Array(arguments, 4, true)); 123 f = Y.rbind.apply(Y, a); 124 } 125 126 return this._inject(DO_AFTER, f, obj, sFn); 127 }, 128 129 /** 130 * Execute the supplied method before or after the specified function. 131 * Used by <code>before</code> and <code>after</code>. 132 * 133 * @method _inject 134 * @param when {string} before or after 135 * @param fn {Function} the function to execute 136 * @param obj the object hosting the method to displace 137 * @param sFn {string} the name of the method to displace 138 * @param c The execution context for fn 139 * @return {EventHandle} handle for the subscription 140 * @private 141 * @static 142 */ 143 _inject: function(when, fn, obj, sFn) { 144 // object id 145 var id = Y.stamp(obj), o, sid; 146 147 if (!obj._yuiaop) { 148 // create a map entry for the obj if it doesn't exist, to hold overridden methods 149 obj._yuiaop = {}; 150 } 151 152 o = obj._yuiaop; 153 154 if (!o[sFn]) { 155 // create a map entry for the method if it doesn't exist 156 o[sFn] = new Y.Do.Method(obj, sFn); 157 158 // re-route the method to our wrapper 159 obj[sFn] = function() { 160 return o[sFn].exec.apply(o[sFn], arguments); 161 }; 162 } 163 164 // subscriber id 165 sid = id + Y.stamp(fn) + sFn; 166 167 // register the callback 168 o[sFn].register(sid, fn, when); 169 170 return new Y.EventHandle(o[sFn], sid); 171 }, 172 173 /** 174 * Detach a before or after subscription. 175 * 176 * @method detach 177 * @param handle {EventHandle} the subscription handle 178 * @static 179 */ 180 detach: function(handle) { 181 if (handle.detach) { 182 handle.detach(); 183 } 184 } 185 }; 186 187 Y.Do = DO; 188 189 ////////////////////////////////////////////////////////////////////////// 190 191 /** 192 * Contains the return value from the wrapped method, accessible 193 * by 'after' event listeners. 194 * 195 * @property originalRetVal 196 * @static 197 * @since 3.2.0 198 */ 199 200 /** 201 * Contains the current state of the return value, consumable by 202 * 'after' event listeners, and updated if an after subscriber 203 * changes the return value generated by the wrapped function. 204 * 205 * @property currentRetVal 206 * @static 207 * @since 3.2.0 208 */ 209 210 ////////////////////////////////////////////////////////////////////////// 211 212 /** 213 * Wrapper for a displaced method with aop enabled 214 * @class Do.Method 215 * @constructor 216 * @param obj The object to operate on 217 * @param sFn The name of the method to displace 218 */ 219 DO.Method = function(obj, sFn) { 220 this.obj = obj; 221 this.methodName = sFn; 222 this.method = obj[sFn]; 223 this.before = {}; 224 this.after = {}; 225 }; 226 227 /** 228 * Register a aop subscriber 229 * @method register 230 * @param sid {string} the subscriber id 231 * @param fn {Function} the function to execute 232 * @param when {string} when to execute the function 233 */ 234 DO.Method.prototype.register = function (sid, fn, when) { 235 if (when) { 236 this.after[sid] = fn; 237 } else { 238 this.before[sid] = fn; 239 } 240 }; 241 242 /** 243 * Unregister a aop subscriber 244 * @method delete 245 * @param sid {string} the subscriber id 246 * @param fn {Function} the function to execute 247 * @param when {string} when to execute the function 248 */ 249 DO.Method.prototype._delete = function (sid) { 250 // Y.log('Y.Do._delete: ' + sid, 'info', 'Event'); 251 delete this.before[sid]; 252 delete this.after[sid]; 253 }; 254 255 /** 256 * <p>Execute the wrapped method. All arguments are passed into the wrapping 257 * functions. If any of the before wrappers return an instance of 258 * <code>Y.Do.Halt</code> or <code>Y.Do.Prevent</code>, neither the wrapped 259 * function nor any after phase subscribers will be executed.</p> 260 * 261 * <p>The return value will be the return value of the wrapped function or one 262 * provided by a wrapper function via an instance of <code>Y.Do.Halt</code> or 263 * <code>Y.Do.AlterReturn</code>. 264 * 265 * @method exec 266 * @param arg* {any} Arguments are passed to the wrapping and wrapped functions 267 * @return {any} Return value of wrapped function unless overwritten (see above) 268 */ 269 DO.Method.prototype.exec = function () { 270 271 var args = Y.Array(arguments, 0, true), 272 i, ret, newRet, 273 bf = this.before, 274 af = this.after, 275 prevented = false; 276 277 // execute before 278 for (i in bf) { 279 if (bf.hasOwnProperty(i)) { 280 ret = bf[i].apply(this.obj, args); 281 if (ret) { 282 switch (ret.constructor) { 283 case DO.Halt: 284 return ret.retVal; 285 case DO.AlterArgs: 286 args = ret.newArgs; 287 break; 288 case DO.Prevent: 289 prevented = true; 290 break; 291 default: 292 } 293 } 294 } 295 } 296 297 // execute method 298 if (!prevented) { 299 ret = this.method.apply(this.obj, args); 300 } 301 302 DO.originalRetVal = ret; 303 DO.currentRetVal = ret; 304 305 // execute after methods. 306 for (i in af) { 307 if (af.hasOwnProperty(i)) { 308 newRet = af[i].apply(this.obj, args); 309 // Stop processing if a Halt object is returned 310 if (newRet && newRet.constructor === DO.Halt) { 311 return newRet.retVal; 312 // Check for a new return value 313 } else if (newRet && newRet.constructor === DO.AlterReturn) { 314 ret = newRet.newRetVal; 315 // Update the static retval state 316 DO.currentRetVal = ret; 317 } 318 } 319 } 320 321 return ret; 322 }; 323 324 ////////////////////////////////////////////////////////////////////////// 325 326 /** 327 * Return an AlterArgs object when you want to change the arguments that 328 * were passed into the function. Useful for Do.before subscribers. An 329 * example would be a service that scrubs out illegal characters prior to 330 * executing the core business logic. 331 * @class Do.AlterArgs 332 * @constructor 333 * @param msg {String} (optional) Explanation of the altered return value 334 * @param newArgs {Array} Call parameters to be used for the original method 335 * instead of the arguments originally passed in. 336 */ 337 DO.AlterArgs = function(msg, newArgs) { 338 this.msg = msg; 339 this.newArgs = newArgs; 340 }; 341 342 /** 343 * Return an AlterReturn object when you want to change the result returned 344 * from the core method to the caller. Useful for Do.after subscribers. 345 * @class Do.AlterReturn 346 * @constructor 347 * @param msg {String} (optional) Explanation of the altered return value 348 * @param newRetVal {any} Return value passed to code that invoked the wrapped 349 * function. 350 */ 351 DO.AlterReturn = function(msg, newRetVal) { 352 this.msg = msg; 353 this.newRetVal = newRetVal; 354 }; 355 356 /** 357 * Return a Halt object when you want to terminate the execution 358 * of all subsequent subscribers as well as the wrapped method 359 * if it has not exectued yet. Useful for Do.before subscribers. 360 * @class Do.Halt 361 * @constructor 362 * @param msg {String} (optional) Explanation of why the termination was done 363 * @param retVal {any} Return value passed to code that invoked the wrapped 364 * function. 365 */ 366 DO.Halt = function(msg, retVal) { 367 this.msg = msg; 368 this.retVal = retVal; 369 }; 370 371 /** 372 * Return a Prevent object when you want to prevent the wrapped function 373 * from executing, but want the remaining listeners to execute. Useful 374 * for Do.before subscribers. 375 * @class Do.Prevent 376 * @constructor 377 * @param msg {String} (optional) Explanation of why the termination was done 378 */ 379 DO.Prevent = function(msg) { 380 this.msg = msg; 381 }; 382 383 /** 384 * Return an Error object when you want to terminate the execution 385 * of all subsequent method calls. 386 * @class Do.Error 387 * @constructor 388 * @param msg {String} (optional) Explanation of the altered return value 389 * @param retVal {any} Return value passed to code that invoked the wrapped 390 * function. 391 * @deprecated use Y.Do.Halt or Y.Do.Prevent 392 */ 393 DO.Error = DO.Halt; 394 395 396 ////////////////////////////////////////////////////////////////////////// 397 398 /** 399 * Custom event engine, DOM event listener abstraction layer, synthetic DOM 400 * events. 401 * @module event-custom 402 * @submodule event-custom-base 403 */ 404 405 406 // var onsubscribeType = "_event:onsub", 407 var YArray = Y.Array, 408 409 AFTER = 'after', 410 CONFIGS = [ 411 'broadcast', 412 'monitored', 413 'bubbles', 414 'context', 415 'contextFn', 416 'currentTarget', 417 'defaultFn', 418 'defaultTargetOnly', 419 'details', 420 'emitFacade', 421 'fireOnce', 422 'async', 423 'host', 424 'preventable', 425 'preventedFn', 426 'queuable', 427 'silent', 428 'stoppedFn', 429 'target', 430 'type' 431 ], 432 433 CONFIGS_HASH = YArray.hash(CONFIGS), 434 435 nativeSlice = Array.prototype.slice, 436 437 YUI3_SIGNATURE = 9, 438 YUI_LOG = 'yui:log', 439 440 mixConfigs = function(r, s, ov) { 441 var p; 442 443 for (p in s) { 444 if (CONFIGS_HASH[p] && (ov || !(p in r))) { 445 r[p] = s[p]; 446 } 447 } 448 449 return r; 450 }; 451 452 /** 453 * The CustomEvent class lets you define events for your application 454 * that can be subscribed to by one or more independent component. 455 * 456 * @param {String} type The type of event, which is passed to the callback 457 * when the event fires. 458 * @param {object} defaults configuration object. 459 * @class CustomEvent 460 * @constructor 461 */ 462 463 /** 464 * The type of event, returned to subscribers when the event fires 465 * @property type 466 * @type string 467 */ 468 469 /** 470 * By default all custom events are logged in the debug build, set silent 471 * to true to disable debug outpu for this event. 472 * @property silent 473 * @type boolean 474 */ 475 476 Y.CustomEvent = function(type, defaults) { 477 478 this._kds = Y.CustomEvent.keepDeprecatedSubs; 479 480 this.id = Y.guid(); 481 482 this.type = type; 483 this.silent = this.logSystem = (type === YUI_LOG); 484 485 if (this._kds) { 486 /** 487 * The subscribers to this event 488 * @property subscribers 489 * @type Subscriber {} 490 * @deprecated 491 */ 492 493 /** 494 * 'After' subscribers 495 * @property afters 496 * @type Subscriber {} 497 * @deprecated 498 */ 499 this.subscribers = {}; 500 this.afters = {}; 501 } 502 503 if (defaults) { 504 mixConfigs(this, defaults, true); 505 } 506 }; 507 508 /** 509 * Static flag to enable population of the <a href="#property_subscribers">`subscribers`</a> 510 * and <a href="#property_subscribers">`afters`</a> properties held on a `CustomEvent` instance. 511 * 512 * These properties were changed to private properties (`_subscribers` and `_afters`), and 513 * converted from objects to arrays for performance reasons. 514 * 515 * Setting this property to true will populate the deprecated `subscribers` and `afters` 516 * properties for people who may be using them (which is expected to be rare). There will 517 * be a performance hit, compared to the new array based implementation. 518 * 519 * If you are using these deprecated properties for a use case which the public API 520 * does not support, please file an enhancement request, and we can provide an alternate 521 * public implementation which doesn't have the performance cost required to maintiain the 522 * properties as objects. 523 * 524 * @property keepDeprecatedSubs 525 * @static 526 * @for CustomEvent 527 * @type boolean 528 * @default false 529 * @deprecated 530 */ 531 Y.CustomEvent.keepDeprecatedSubs = false; 532 533 Y.CustomEvent.mixConfigs = mixConfigs; 534 535 Y.CustomEvent.prototype = { 536 537 constructor: Y.CustomEvent, 538 539 /** 540 * Monitor when an event is attached or detached. 541 * 542 * @property monitored 543 * @type boolean 544 */ 545 546 /** 547 * If 0, this event does not broadcast. If 1, the YUI instance is notified 548 * every time this event fires. If 2, the YUI instance and the YUI global 549 * (if event is enabled on the global) are notified every time this event 550 * fires. 551 * @property broadcast 552 * @type int 553 */ 554 555 /** 556 * Specifies whether this event should be queued when the host is actively 557 * processing an event. This will effect exectution order of the callbacks 558 * for the various events. 559 * @property queuable 560 * @type boolean 561 * @default false 562 */ 563 564 /** 565 * This event has fired if true 566 * 567 * @property fired 568 * @type boolean 569 * @default false; 570 */ 571 572 /** 573 * An array containing the arguments the custom event 574 * was last fired with. 575 * @property firedWith 576 * @type Array 577 */ 578 579 /** 580 * This event should only fire one time if true, and if 581 * it has fired, any new subscribers should be notified 582 * immediately. 583 * 584 * @property fireOnce 585 * @type boolean 586 * @default false; 587 */ 588 589 /** 590 * fireOnce listeners will fire syncronously unless async 591 * is set to true 592 * @property async 593 * @type boolean 594 * @default false 595 */ 596 597 /** 598 * Flag for stopPropagation that is modified during fire() 599 * 1 means to stop propagation to bubble targets. 2 means 600 * to also stop additional subscribers on this target. 601 * @property stopped 602 * @type int 603 */ 604 605 /** 606 * Flag for preventDefault that is modified during fire(). 607 * if it is not 0, the default behavior for this event 608 * @property prevented 609 * @type int 610 */ 611 612 /** 613 * Specifies the host for this custom event. This is used 614 * to enable event bubbling 615 * @property host 616 * @type EventTarget 617 */ 618 619 /** 620 * The default function to execute after event listeners 621 * have fire, but only if the default action was not 622 * prevented. 623 * @property defaultFn 624 * @type Function 625 */ 626 627 /** 628 * Flag for the default function to execute only if the 629 * firing event is the current target. This happens only 630 * when using custom event delegation and setting the 631 * flag to `true` mimics the behavior of event delegation 632 * in the DOM. 633 * 634 * @property defaultTargetOnly 635 * @type Boolean 636 * @default false 637 */ 638 639 /** 640 * The function to execute if a subscriber calls 641 * stopPropagation or stopImmediatePropagation 642 * @property stoppedFn 643 * @type Function 644 */ 645 646 /** 647 * The function to execute if a subscriber calls 648 * preventDefault 649 * @property preventedFn 650 * @type Function 651 */ 652 653 /** 654 * The subscribers to this event 655 * @property _subscribers 656 * @type Subscriber [] 657 * @private 658 */ 659 660 /** 661 * 'After' subscribers 662 * @property _afters 663 * @type Subscriber [] 664 * @private 665 */ 666 667 /** 668 * If set to true, the custom event will deliver an EventFacade object 669 * that is similar to a DOM event object. 670 * @property emitFacade 671 * @type boolean 672 * @default false 673 */ 674 675 /** 676 * Supports multiple options for listener signatures in order to 677 * port YUI 2 apps. 678 * @property signature 679 * @type int 680 * @default 9 681 */ 682 signature : YUI3_SIGNATURE, 683 684 /** 685 * The context the the event will fire from by default. Defaults to the YUI 686 * instance. 687 * @property context 688 * @type object 689 */ 690 context : Y, 691 692 /** 693 * Specifies whether or not this event's default function 694 * can be cancelled by a subscriber by executing preventDefault() 695 * on the event facade 696 * @property preventable 697 * @type boolean 698 * @default true 699 */ 700 preventable : true, 701 702 /** 703 * Specifies whether or not a subscriber can stop the event propagation 704 * via stopPropagation(), stopImmediatePropagation(), or halt() 705 * 706 * Events can only bubble if emitFacade is true. 707 * 708 * @property bubbles 709 * @type boolean 710 * @default true 711 */ 712 bubbles : true, 713 714 /** 715 * Returns the number of subscribers for this event as the sum of the on() 716 * subscribers and after() subscribers. 717 * 718 * @method hasSubs 719 * @return Number 720 */ 721 hasSubs: function(when) { 722 var s = 0, 723 a = 0, 724 subs = this._subscribers, 725 afters = this._afters, 726 sib = this.sibling; 727 728 if (subs) { 729 s = subs.length; 730 } 731 732 if (afters) { 733 a = afters.length; 734 } 735 736 if (sib) { 737 subs = sib._subscribers; 738 afters = sib._afters; 739 740 if (subs) { 741 s += subs.length; 742 } 743 744 if (afters) { 745 a += afters.length; 746 } 747 } 748 749 if (when) { 750 return (when === 'after') ? a : s; 751 } 752 753 return (s + a); 754 }, 755 756 /** 757 * Monitor the event state for the subscribed event. The first parameter 758 * is what should be monitored, the rest are the normal parameters when 759 * subscribing to an event. 760 * @method monitor 761 * @param what {string} what to monitor ('detach', 'attach', 'publish'). 762 * @return {EventHandle} return value from the monitor event subscription. 763 */ 764 monitor: function(what) { 765 this.monitored = true; 766 var type = this.id + '|' + this.type + '_' + what, 767 args = nativeSlice.call(arguments, 0); 768 args[0] = type; 769 return this.host.on.apply(this.host, args); 770 }, 771 772 /** 773 * Get all of the subscribers to this event and any sibling event 774 * @method getSubs 775 * @return {Array} first item is the on subscribers, second the after. 776 */ 777 getSubs: function() { 778 779 var sibling = this.sibling, 780 subs = this._subscribers, 781 afters = this._afters, 782 siblingSubs, 783 siblingAfters; 784 785 if (sibling) { 786 siblingSubs = sibling._subscribers; 787 siblingAfters = sibling._afters; 788 } 789 790 if (siblingSubs) { 791 if (subs) { 792 subs = subs.concat(siblingSubs); 793 } else { 794 subs = siblingSubs.concat(); 795 } 796 } else { 797 if (subs) { 798 subs = subs.concat(); 799 } else { 800 subs = []; 801 } 802 } 803 804 if (siblingAfters) { 805 if (afters) { 806 afters = afters.concat(siblingAfters); 807 } else { 808 afters = siblingAfters.concat(); 809 } 810 } else { 811 if (afters) { 812 afters = afters.concat(); 813 } else { 814 afters = []; 815 } 816 } 817 818 return [subs, afters]; 819 }, 820 821 /** 822 * Apply configuration properties. Only applies the CONFIG whitelist 823 * @method applyConfig 824 * @param o hash of properties to apply. 825 * @param force {boolean} if true, properties that exist on the event 826 * will be overwritten. 827 */ 828 applyConfig: function(o, force) { 829 mixConfigs(this, o, force); 830 }, 831 832 /** 833 * Create the Subscription for subscribing function, context, and bound 834 * arguments. If this is a fireOnce event, the subscriber is immediately 835 * notified. 836 * 837 * @method _on 838 * @param fn {Function} Subscription callback 839 * @param [context] {Object} Override `this` in the callback 840 * @param [args] {Array} bound arguments that will be passed to the callback after the arguments generated by fire() 841 * @param [when] {String} "after" to slot into after subscribers 842 * @return {EventHandle} 843 * @protected 844 */ 845 _on: function(fn, context, args, when) { 846 847 if (!fn) { this.log('Invalid callback for CE: ' + this.type); } 848 849 var s = new Y.Subscriber(fn, context, args, when), 850 firedWith; 851 852 if (this.fireOnce && this.fired) { 853 854 firedWith = this.firedWith; 855 856 // It's a little ugly for this to know about facades, 857 // but given the current breakup, not much choice without 858 // moving a whole lot of stuff around. 859 if (this.emitFacade && this._addFacadeToArgs) { 860 this._addFacadeToArgs(firedWith); 861 } 862 863 if (this.async) { 864 setTimeout(Y.bind(this._notify, this, s, firedWith), 0); 865 } else { 866 this._notify(s, firedWith); 867 } 868 } 869 870 if (when === AFTER) { 871 if (!this._afters) { 872 this._afters = []; 873 } 874 this._afters.push(s); 875 } else { 876 if (!this._subscribers) { 877 this._subscribers = []; 878 } 879 this._subscribers.push(s); 880 } 881 882 if (this._kds) { 883 if (when === AFTER) { 884 this.afters[s.id] = s; 885 } else { 886 this.subscribers[s.id] = s; 887 } 888 } 889 890 return new Y.EventHandle(this, s); 891 }, 892 893 /** 894 * Listen for this event 895 * @method subscribe 896 * @param {Function} fn The function to execute. 897 * @return {EventHandle} Unsubscribe handle. 898 * @deprecated use on. 899 */ 900 subscribe: function(fn, context) { 901 Y.log('ce.subscribe deprecated, use "on"', 'warn', 'deprecated'); 902 var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null; 903 return this._on(fn, context, a, true); 904 }, 905 906 /** 907 * Listen for this event 908 * @method on 909 * @param {Function} fn The function to execute. 910 * @param {object} context optional execution context. 911 * @param {mixed} arg* 0..n additional arguments to supply to the subscriber 912 * when the event fires. 913 * @return {EventHandle} An object with a detach method to detch the handler(s). 914 */ 915 on: function(fn, context) { 916 var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null; 917 918 if (this.monitored && this.host) { 919 this.host._monitor('attach', this, { 920 args: arguments 921 }); 922 } 923 return this._on(fn, context, a, true); 924 }, 925 926 /** 927 * Listen for this event after the normal subscribers have been notified and 928 * the default behavior has been applied. If a normal subscriber prevents the 929 * default behavior, it also prevents after listeners from firing. 930 * @method after 931 * @param {Function} fn The function to execute. 932 * @param {object} context optional execution context. 933 * @param {mixed} arg* 0..n additional arguments to supply to the subscriber 934 * when the event fires. 935 * @return {EventHandle} handle Unsubscribe handle. 936 */ 937 after: function(fn, context) { 938 var a = (arguments.length > 2) ? nativeSlice.call(arguments, 2) : null; 939 return this._on(fn, context, a, AFTER); 940 }, 941 942 /** 943 * Detach listeners. 944 * @method detach 945 * @param {Function} fn The subscribed function to remove, if not supplied 946 * all will be removed. 947 * @param {Object} context The context object passed to subscribe. 948 * @return {Number} returns the number of subscribers unsubscribed. 949 */ 950 detach: function(fn, context) { 951 // unsubscribe handle 952 if (fn && fn.detach) { 953 return fn.detach(); 954 } 955 956 var i, s, 957 found = 0, 958 subs = this._subscribers, 959 afters = this._afters; 960 961 if (subs) { 962 for (i = subs.length; i >= 0; i--) { 963 s = subs[i]; 964 if (s && (!fn || fn === s.fn)) { 965 this._delete(s, subs, i); 966 found++; 967 } 968 } 969 } 970 971 if (afters) { 972 for (i = afters.length; i >= 0; i--) { 973 s = afters[i]; 974 if (s && (!fn || fn === s.fn)) { 975 this._delete(s, afters, i); 976 found++; 977 } 978 } 979 } 980 981 return found; 982 }, 983 984 /** 985 * Detach listeners. 986 * @method unsubscribe 987 * @param {Function} fn The subscribed function to remove, if not supplied 988 * all will be removed. 989 * @param {Object} context The context object passed to subscribe. 990 * @return {int|undefined} returns the number of subscribers unsubscribed. 991 * @deprecated use detach. 992 */ 993 unsubscribe: function() { 994 return this.detach.apply(this, arguments); 995 }, 996 997 /** 998 * Notify a single subscriber 999 * @method _notify 1000 * @param {Subscriber} s the subscriber. 1001 * @param {Array} args the arguments array to apply to the listener. 1002 * @protected 1003 */ 1004 _notify: function(s, args, ef) { 1005 1006 this.log(this.type + '->' + 'sub: ' + s.id); 1007 1008 var ret; 1009 1010 ret = s.notify(args, this); 1011 1012 if (false === ret || this.stopped > 1) { 1013 this.log(this.type + ' cancelled by subscriber'); 1014 return false; 1015 } 1016 1017 return true; 1018 }, 1019 1020 /** 1021 * Logger abstraction to centralize the application of the silent flag 1022 * @method log 1023 * @param {string} msg message to log. 1024 * @param {string} cat log category. 1025 */ 1026 log: function(msg, cat) { 1027 if (!this.silent) { Y.log(this.id + ': ' + msg, cat || 'info', 'event'); } 1028 }, 1029 1030 /** 1031 * Notifies the subscribers. The callback functions will be executed 1032 * from the context specified when the event was created, and with the 1033 * following parameters: 1034 * <ul> 1035 * <li>The type of event</li> 1036 * <li>All of the arguments fire() was executed with as an array</li> 1037 * <li>The custom object (if any) that was passed into the subscribe() 1038 * method</li> 1039 * </ul> 1040 * @method fire 1041 * @param {Object*} arguments an arbitrary set of parameters to pass to 1042 * the handler. 1043 * @return {boolean} false if one of the subscribers returned false, 1044 * true otherwise. 1045 * 1046 */ 1047 fire: function() { 1048 1049 // push is the fastest way to go from arguments to arrays 1050 // for most browsers currently 1051 // http://jsperf.com/push-vs-concat-vs-slice/2 1052 1053 var args = []; 1054 args.push.apply(args, arguments); 1055 1056 return this._fire(args); 1057 }, 1058 1059 /** 1060 * Private internal implementation for `fire`, which is can be used directly by 1061 * `EventTarget` and other event module classes which have already converted from 1062 * an `arguments` list to an array, to avoid the repeated overhead. 1063 * 1064 * @method _fire 1065 * @private 1066 * @param {Array} args The array of arguments passed to be passed to handlers. 1067 * @return {boolean} false if one of the subscribers returned false, true otherwise. 1068 */ 1069 _fire: function(args) { 1070 1071 if (this.fireOnce && this.fired) { 1072 this.log('fireOnce event: ' + this.type + ' already fired'); 1073 return true; 1074 } else { 1075 1076 // this doesn't happen if the event isn't published 1077 // this.host._monitor('fire', this.type, args); 1078 1079 this.fired = true; 1080 1081 if (this.fireOnce) { 1082 this.firedWith = args; 1083 } 1084 1085 if (this.emitFacade) { 1086 return this.fireComplex(args); 1087 } else { 1088 return this.fireSimple(args); 1089 } 1090 } 1091 }, 1092 1093 /** 1094 * Set up for notifying subscribers of non-emitFacade events. 1095 * 1096 * @method fireSimple 1097 * @param args {Array} Arguments passed to fire() 1098 * @return Boolean false if a subscriber returned false 1099 * @protected 1100 */ 1101 fireSimple: function(args) { 1102 this.stopped = 0; 1103 this.prevented = 0; 1104 if (this.hasSubs()) { 1105 var subs = this.getSubs(); 1106 this._procSubs(subs[0], args); 1107 this._procSubs(subs[1], args); 1108 } 1109 if (this.broadcast) { 1110 this._broadcast(args); 1111 } 1112 return this.stopped ? false : true; 1113 }, 1114 1115 // Requires the event-custom-complex module for full funcitonality. 1116 fireComplex: function(args) { 1117 this.log('Missing event-custom-complex needed to emit a facade for: ' + this.type); 1118 args[0] = args[0] || {}; 1119 return this.fireSimple(args); 1120 }, 1121 1122 /** 1123 * Notifies a list of subscribers. 1124 * 1125 * @method _procSubs 1126 * @param subs {Array} List of subscribers 1127 * @param args {Array} Arguments passed to fire() 1128 * @param ef {} 1129 * @return Boolean false if a subscriber returns false or stops the event 1130 * propagation via e.stopPropagation(), 1131 * e.stopImmediatePropagation(), or e.halt() 1132 * @private 1133 */ 1134 _procSubs: function(subs, args, ef) { 1135 var s, i, l; 1136 1137 for (i = 0, l = subs.length; i < l; i++) { 1138 s = subs[i]; 1139 if (s && s.fn) { 1140 if (false === this._notify(s, args, ef)) { 1141 this.stopped = 2; 1142 } 1143 if (this.stopped === 2) { 1144 return false; 1145 } 1146 } 1147 } 1148 1149 return true; 1150 }, 1151 1152 /** 1153 * Notifies the YUI instance if the event is configured with broadcast = 1, 1154 * and both the YUI instance and Y.Global if configured with broadcast = 2. 1155 * 1156 * @method _broadcast 1157 * @param args {Array} Arguments sent to fire() 1158 * @private 1159 */ 1160 _broadcast: function(args) { 1161 if (!this.stopped && this.broadcast) { 1162 1163 var a = args.concat(); 1164 a.unshift(this.type); 1165 1166 if (this.host !== Y) { 1167 Y.fire.apply(Y, a); 1168 } 1169 1170 if (this.broadcast === 2) { 1171 Y.Global.fire.apply(Y.Global, a); 1172 } 1173 } 1174 }, 1175 1176 /** 1177 * Removes all listeners 1178 * @method unsubscribeAll 1179 * @return {Number} The number of listeners unsubscribed. 1180 * @deprecated use detachAll. 1181 */ 1182 unsubscribeAll: function() { 1183 return this.detachAll.apply(this, arguments); 1184 }, 1185 1186 /** 1187 * Removes all listeners 1188 * @method detachAll 1189 * @return {Number} The number of listeners unsubscribed. 1190 */ 1191 detachAll: function() { 1192 return this.detach(); 1193 }, 1194 1195 /** 1196 * Deletes the subscriber from the internal store of on() and after() 1197 * subscribers. 1198 * 1199 * @method _delete 1200 * @param s subscriber object. 1201 * @param subs (optional) on or after subscriber array 1202 * @param index (optional) The index found. 1203 * @private 1204 */ 1205 _delete: function(s, subs, i) { 1206 var when = s._when; 1207 1208 if (!subs) { 1209 subs = (when === AFTER) ? this._afters : this._subscribers; 1210 } 1211 1212 if (subs) { 1213 i = YArray.indexOf(subs, s, 0); 1214 1215 if (s && subs[i] === s) { 1216 subs.splice(i, 1); 1217 } 1218 } 1219 1220 if (this._kds) { 1221 if (when === AFTER) { 1222 delete this.afters[s.id]; 1223 } else { 1224 delete this.subscribers[s.id]; 1225 } 1226 } 1227 1228 if (this.monitored && this.host) { 1229 this.host._monitor('detach', this, { 1230 ce: this, 1231 sub: s 1232 }); 1233 } 1234 1235 if (s) { 1236 s.deleted = true; 1237 } 1238 } 1239 }; 1240 /** 1241 * Stores the subscriber information to be used when the event fires. 1242 * @param {Function} fn The wrapped function to execute. 1243 * @param {Object} context The value of the keyword 'this' in the listener. 1244 * @param {Array} args* 0..n additional arguments to supply the listener. 1245 * 1246 * @class Subscriber 1247 * @constructor 1248 */ 1249 Y.Subscriber = function(fn, context, args, when) { 1250 1251 /** 1252 * The callback that will be execute when the event fires 1253 * This is wrapped by Y.rbind if obj was supplied. 1254 * @property fn 1255 * @type Function 1256 */ 1257 this.fn = fn; 1258 1259 /** 1260 * Optional 'this' keyword for the listener 1261 * @property context 1262 * @type Object 1263 */ 1264 this.context = context; 1265 1266 /** 1267 * Unique subscriber id 1268 * @property id 1269 * @type String 1270 */ 1271 this.id = Y.guid(); 1272 1273 /** 1274 * Additional arguments to propagate to the subscriber 1275 * @property args 1276 * @type Array 1277 */ 1278 this.args = args; 1279 1280 this._when = when; 1281 1282 /** 1283 * Custom events for a given fire transaction. 1284 * @property events 1285 * @type {EventTarget} 1286 */ 1287 // this.events = null; 1288 1289 /** 1290 * This listener only reacts to the event once 1291 * @property once 1292 */ 1293 // this.once = false; 1294 1295 }; 1296 1297 Y.Subscriber.prototype = { 1298 constructor: Y.Subscriber, 1299 1300 _notify: function(c, args, ce) { 1301 if (this.deleted && !this.postponed) { 1302 if (this.postponed) { 1303 delete this.fn; 1304 delete this.context; 1305 } else { 1306 delete this.postponed; 1307 return null; 1308 } 1309 } 1310 var a = this.args, ret; 1311 switch (ce.signature) { 1312 case 0: 1313 ret = this.fn.call(c, ce.type, args, c); 1314 break; 1315 case 1: 1316 ret = this.fn.call(c, args[0] || null, c); 1317 break; 1318 default: 1319 if (a || args) { 1320 args = args || []; 1321 a = (a) ? args.concat(a) : args; 1322 ret = this.fn.apply(c, a); 1323 } else { 1324 ret = this.fn.call(c); 1325 } 1326 } 1327 1328 if (this.once) { 1329 ce._delete(this); 1330 } 1331 1332 return ret; 1333 }, 1334 1335 /** 1336 * Executes the subscriber. 1337 * @method notify 1338 * @param args {Array} Arguments array for the subscriber. 1339 * @param ce {CustomEvent} The custom event that sent the notification. 1340 */ 1341 notify: function(args, ce) { 1342 var c = this.context, 1343 ret = true; 1344 1345 if (!c) { 1346 c = (ce.contextFn) ? ce.contextFn() : ce.context; 1347 } 1348 1349 // only catch errors if we will not re-throw them. 1350 if (Y.config && Y.config.throwFail) { 1351 ret = this._notify(c, args, ce); 1352 } else { 1353 try { 1354 ret = this._notify(c, args, ce); 1355 } catch (e) { 1356 Y.error(this + ' failed: ' + e.message, e); 1357 } 1358 } 1359 1360 return ret; 1361 }, 1362 1363 /** 1364 * Returns true if the fn and obj match this objects properties. 1365 * Used by the unsubscribe method to match the right subscriber. 1366 * 1367 * @method contains 1368 * @param {Function} fn the function to execute. 1369 * @param {Object} context optional 'this' keyword for the listener. 1370 * @return {boolean} true if the supplied arguments match this 1371 * subscriber's signature. 1372 */ 1373 contains: function(fn, context) { 1374 if (context) { 1375 return ((this.fn === fn) && this.context === context); 1376 } else { 1377 return (this.fn === fn); 1378 } 1379 }, 1380 1381 valueOf : function() { 1382 return this.id; 1383 } 1384 1385 }; 1386 /** 1387 * Return value from all subscribe operations 1388 * @class EventHandle 1389 * @constructor 1390 * @param {CustomEvent} evt the custom event. 1391 * @param {Subscriber} sub the subscriber. 1392 */ 1393 Y.EventHandle = function(evt, sub) { 1394 1395 /** 1396 * The custom event 1397 * 1398 * @property evt 1399 * @type CustomEvent 1400 */ 1401 this.evt = evt; 1402 1403 /** 1404 * The subscriber object 1405 * 1406 * @property sub 1407 * @type Subscriber 1408 */ 1409 this.sub = sub; 1410 }; 1411 1412 Y.EventHandle.prototype = { 1413 batch: function(f, c) { 1414 f.call(c || this, this); 1415 if (Y.Lang.isArray(this.evt)) { 1416 Y.Array.each(this.evt, function(h) { 1417 h.batch.call(c || h, f); 1418 }); 1419 } 1420 }, 1421 1422 /** 1423 * Detaches this subscriber 1424 * @method detach 1425 * @return {Number} the number of detached listeners 1426 */ 1427 detach: function() { 1428 var evt = this.evt, detached = 0, i; 1429 if (evt) { 1430 // Y.log('EventHandle.detach: ' + this.sub, 'info', 'Event'); 1431 if (Y.Lang.isArray(evt)) { 1432 for (i = 0; i < evt.length; i++) { 1433 detached += evt[i].detach(); 1434 } 1435 } else { 1436 evt._delete(this.sub); 1437 detached = 1; 1438 } 1439 1440 } 1441 1442 return detached; 1443 }, 1444 1445 /** 1446 * Monitor the event state for the subscribed event. The first parameter 1447 * is what should be monitored, the rest are the normal parameters when 1448 * subscribing to an event. 1449 * @method monitor 1450 * @param what {string} what to monitor ('attach', 'detach', 'publish'). 1451 * @return {EventHandle} return value from the monitor event subscription. 1452 */ 1453 monitor: function(what) { 1454 return this.evt.monitor.apply(this.evt, arguments); 1455 } 1456 }; 1457 1458 /** 1459 * Custom event engine, DOM event listener abstraction layer, synthetic DOM 1460 * events. 1461 * @module event-custom 1462 * @submodule event-custom-base 1463 */ 1464 1465 /** 1466 * EventTarget provides the implementation for any object to 1467 * publish, subscribe and fire to custom events, and also 1468 * alows other EventTargets to target the object with events 1469 * sourced from the other object. 1470 * EventTarget is designed to be used with Y.augment to wrap 1471 * EventCustom in an interface that allows events to be listened to 1472 * and fired by name. This makes it possible for implementing code to 1473 * subscribe to an event that either has not been created yet, or will 1474 * not be created at all. 1475 * @class EventTarget 1476 * @param opts a configuration object 1477 * @config emitFacade {boolean} if true, all events will emit event 1478 * facade payloads by default (default false) 1479 * @config prefix {String} the prefix to apply to non-prefixed event names 1480 */ 1481 1482 var L = Y.Lang, 1483 PREFIX_DELIMITER = ':', 1484 CATEGORY_DELIMITER = '|', 1485 AFTER_PREFIX = '~AFTER~', 1486 WILD_TYPE_RE = /(.*?)(:)(.*?)/, 1487 1488 _wildType = Y.cached(function(type) { 1489 return type.replace(WILD_TYPE_RE, "*$2$3"); 1490 }), 1491 1492 /** 1493 * If the instance has a prefix attribute and the 1494 * event type is not prefixed, the instance prefix is 1495 * applied to the supplied type. 1496 * @method _getType 1497 * @private 1498 */ 1499 _getType = function(type, pre) { 1500 1501 if (!pre || !type || type.indexOf(PREFIX_DELIMITER) > -1) { 1502 return type; 1503 } 1504 1505 return pre + PREFIX_DELIMITER + type; 1506 }, 1507 1508 /** 1509 * Returns an array with the detach key (if provided), 1510 * and the prefixed event name from _getType 1511 * Y.on('detachcategory| menu:click', fn) 1512 * @method _parseType 1513 * @private 1514 */ 1515 _parseType = Y.cached(function(type, pre) { 1516 1517 var t = type, detachcategory, after, i; 1518 1519 if (!L.isString(t)) { 1520 return t; 1521 } 1522 1523 i = t.indexOf(AFTER_PREFIX); 1524 1525 if (i > -1) { 1526 after = true; 1527 t = t.substr(AFTER_PREFIX.length); 1528 } 1529 1530 i = t.indexOf(CATEGORY_DELIMITER); 1531 1532 if (i > -1) { 1533 detachcategory = t.substr(0, (i)); 1534 t = t.substr(i+1); 1535 if (t === '*') { 1536 t = null; 1537 } 1538 } 1539 1540 // detach category, full type with instance prefix, is this an after listener, short type 1541 return [detachcategory, (pre) ? _getType(t, pre) : t, after, t]; 1542 }), 1543 1544 ET = function(opts) { 1545 1546 var etState = this._yuievt, 1547 etConfig; 1548 1549 if (!etState) { 1550 etState = this._yuievt = { 1551 events: {}, // PERF: Not much point instantiating lazily. We're bound to have events 1552 targets: null, // PERF: Instantiate lazily, if user actually adds target, 1553 config: { 1554 host: this, 1555 context: this 1556 }, 1557 chain: Y.config.chain 1558 }; 1559 } 1560 1561 etConfig = etState.config; 1562 1563 if (opts) { 1564 mixConfigs(etConfig, opts, true); 1565 1566 if (opts.chain !== undefined) { 1567 etState.chain = opts.chain; 1568 } 1569 1570 if (opts.prefix) { 1571 etConfig.prefix = opts.prefix; 1572 } 1573 } 1574 }; 1575 1576 ET.prototype = { 1577 1578 constructor: ET, 1579 1580 /** 1581 * Listen to a custom event hosted by this object one time. 1582 * This is the equivalent to <code>on</code> except the 1583 * listener is immediatelly detached when it is executed. 1584 * @method once 1585 * @param {String} type The name of the event 1586 * @param {Function} fn The callback to execute in response to the event 1587 * @param {Object} [context] Override `this` object in callback 1588 * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 1589 * @return {EventHandle} A subscription handle capable of detaching the 1590 * subscription 1591 */ 1592 once: function() { 1593 var handle = this.on.apply(this, arguments); 1594 handle.batch(function(hand) { 1595 if (hand.sub) { 1596 hand.sub.once = true; 1597 } 1598 }); 1599 return handle; 1600 }, 1601 1602 /** 1603 * Listen to a custom event hosted by this object one time. 1604 * This is the equivalent to <code>after</code> except the 1605 * listener is immediatelly detached when it is executed. 1606 * @method onceAfter 1607 * @param {String} type The name of the event 1608 * @param {Function} fn The callback to execute in response to the event 1609 * @param {Object} [context] Override `this` object in callback 1610 * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 1611 * @return {EventHandle} A subscription handle capable of detaching that 1612 * subscription 1613 */ 1614 onceAfter: function() { 1615 var handle = this.after.apply(this, arguments); 1616 handle.batch(function(hand) { 1617 if (hand.sub) { 1618 hand.sub.once = true; 1619 } 1620 }); 1621 return handle; 1622 }, 1623 1624 /** 1625 * Takes the type parameter passed to 'on' and parses out the 1626 * various pieces that could be included in the type. If the 1627 * event type is passed without a prefix, it will be expanded 1628 * to include the prefix one is supplied or the event target 1629 * is configured with a default prefix. 1630 * @method parseType 1631 * @param {String} type the type 1632 * @param {String} [pre] The prefix. Defaults to this._yuievt.config.prefix 1633 * @since 3.3.0 1634 * @return {Array} an array containing: 1635 * * the detach category, if supplied, 1636 * * the prefixed event type, 1637 * * whether or not this is an after listener, 1638 * * the supplied event type 1639 */ 1640 parseType: function(type, pre) { 1641 return _parseType(type, pre || this._yuievt.config.prefix); 1642 }, 1643 1644 /** 1645 * Subscribe a callback function to a custom event fired by this object or 1646 * from an object that bubbles its events to this object. 1647 * 1648 * Callback functions for events published with `emitFacade = true` will 1649 * receive an `EventFacade` as the first argument (typically named "e"). 1650 * These callbacks can then call `e.preventDefault()` to disable the 1651 * behavior published to that event's `defaultFn`. See the `EventFacade` 1652 * API for all available properties and methods. Subscribers to 1653 * non-`emitFacade` events will receive the arguments passed to `fire()` 1654 * after the event name. 1655 * 1656 * To subscribe to multiple events at once, pass an object as the first 1657 * argument, where the key:value pairs correspond to the eventName:callback, 1658 * or pass an array of event names as the first argument to subscribe to 1659 * all listed events with the same callback. 1660 * 1661 * Returning `false` from a callback is supported as an alternative to 1662 * calling `e.preventDefault(); e.stopPropagation();`. However, it is 1663 * recommended to use the event methods whenever possible. 1664 * 1665 * @method on 1666 * @param {String} type The name of the event 1667 * @param {Function} fn The callback to execute in response to the event 1668 * @param {Object} [context] Override `this` object in callback 1669 * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 1670 * @return {EventHandle} A subscription handle capable of detaching that 1671 * subscription 1672 */ 1673 on: function(type, fn, context) { 1674 1675 var yuievt = this._yuievt, 1676 parts = _parseType(type, yuievt.config.prefix), f, c, args, ret, ce, 1677 detachcategory, handle, store = Y.Env.evt.handles, after, adapt, shorttype, 1678 Node = Y.Node, n, domevent, isArr; 1679 1680 // full name, args, detachcategory, after 1681 this._monitor('attach', parts[1], { 1682 args: arguments, 1683 category: parts[0], 1684 after: parts[2] 1685 }); 1686 1687 if (L.isObject(type)) { 1688 1689 if (L.isFunction(type)) { 1690 return Y.Do.before.apply(Y.Do, arguments); 1691 } 1692 1693 f = fn; 1694 c = context; 1695 args = nativeSlice.call(arguments, 0); 1696 ret = []; 1697 1698 if (L.isArray(type)) { 1699 isArr = true; 1700 } 1701 1702 after = type._after; 1703 delete type._after; 1704 1705 Y.each(type, function(v, k) { 1706 1707 if (L.isObject(v)) { 1708 f = v.fn || ((L.isFunction(v)) ? v : f); 1709 c = v.context || c; 1710 } 1711 1712 var nv = (after) ? AFTER_PREFIX : ''; 1713 1714 args[0] = nv + ((isArr) ? v : k); 1715 args[1] = f; 1716 args[2] = c; 1717 1718 ret.push(this.on.apply(this, args)); 1719 1720 }, this); 1721 1722 return (yuievt.chain) ? this : new Y.EventHandle(ret); 1723 } 1724 1725 detachcategory = parts[0]; 1726 after = parts[2]; 1727 shorttype = parts[3]; 1728 1729 // extra redirection so we catch adaptor events too. take a look at this. 1730 if (Node && Y.instanceOf(this, Node) && (shorttype in Node.DOM_EVENTS)) { 1731 args = nativeSlice.call(arguments, 0); 1732 args.splice(2, 0, Node.getDOMNode(this)); 1733 // Y.log("Node detected, redirecting with these args: " + args); 1734 return Y.on.apply(Y, args); 1735 } 1736 1737 type = parts[1]; 1738 1739 if (Y.instanceOf(this, YUI)) { 1740 1741 adapt = Y.Env.evt.plugins[type]; 1742 args = nativeSlice.call(arguments, 0); 1743 args[0] = shorttype; 1744 1745 if (Node) { 1746 n = args[2]; 1747 1748 if (Y.instanceOf(n, Y.NodeList)) { 1749 n = Y.NodeList.getDOMNodes(n); 1750 } else if (Y.instanceOf(n, Node)) { 1751 n = Node.getDOMNode(n); 1752 } 1753 1754 domevent = (shorttype in Node.DOM_EVENTS); 1755 1756 // Captures both DOM events and event plugins. 1757 if (domevent) { 1758 args[2] = n; 1759 } 1760 } 1761 1762 // check for the existance of an event adaptor 1763 if (adapt) { 1764 Y.log('Using adaptor for ' + shorttype + ', ' + n, 'info', 'event'); 1765 handle = adapt.on.apply(Y, args); 1766 } else if ((!type) || domevent) { 1767 handle = Y.Event._attach(args); 1768 } 1769 1770 } 1771 1772 if (!handle) { 1773 ce = yuievt.events[type] || this.publish(type); 1774 handle = ce._on(fn, context, (arguments.length > 3) ? nativeSlice.call(arguments, 3) : null, (after) ? 'after' : true); 1775 1776 // TODO: More robust regex, accounting for category 1777 if (type.indexOf("*:") !== -1) { 1778 this._hasSiblings = true; 1779 } 1780 } 1781 1782 if (detachcategory) { 1783 store[detachcategory] = store[detachcategory] || {}; 1784 store[detachcategory][type] = store[detachcategory][type] || []; 1785 store[detachcategory][type].push(handle); 1786 } 1787 1788 return (yuievt.chain) ? this : handle; 1789 1790 }, 1791 1792 /** 1793 * subscribe to an event 1794 * @method subscribe 1795 * @deprecated use on 1796 */ 1797 subscribe: function() { 1798 Y.log('EventTarget subscribe() is deprecated, use on()', 'warn', 'deprecated'); 1799 return this.on.apply(this, arguments); 1800 }, 1801 1802 /** 1803 * Detach one or more listeners the from the specified event 1804 * @method detach 1805 * @param type {string|Object} Either the handle to the subscriber or the 1806 * type of event. If the type 1807 * is not specified, it will attempt to remove 1808 * the listener from all hosted events. 1809 * @param fn {Function} The subscribed function to unsubscribe, if not 1810 * supplied, all subscribers will be removed. 1811 * @param context {Object} The custom object passed to subscribe. This is 1812 * optional, but if supplied will be used to 1813 * disambiguate multiple listeners that are the same 1814 * (e.g., you subscribe many object using a function 1815 * that lives on the prototype) 1816 * @return {EventTarget} the host 1817 */ 1818 detach: function(type, fn, context) { 1819 1820 var evts = this._yuievt.events, 1821 i, 1822 Node = Y.Node, 1823 isNode = Node && (Y.instanceOf(this, Node)); 1824 1825 // detachAll disabled on the Y instance. 1826 if (!type && (this !== Y)) { 1827 for (i in evts) { 1828 if (evts.hasOwnProperty(i)) { 1829 evts[i].detach(fn, context); 1830 } 1831 } 1832 if (isNode) { 1833 Y.Event.purgeElement(Node.getDOMNode(this)); 1834 } 1835 1836 return this; 1837 } 1838 1839 var parts = _parseType(type, this._yuievt.config.prefix), 1840 detachcategory = L.isArray(parts) ? parts[0] : null, 1841 shorttype = (parts) ? parts[3] : null, 1842 adapt, store = Y.Env.evt.handles, detachhost, cat, args, 1843 ce, 1844 1845 keyDetacher = function(lcat, ltype, host) { 1846 var handles = lcat[ltype], ce, i; 1847 if (handles) { 1848 for (i = handles.length - 1; i >= 0; --i) { 1849 ce = handles[i].evt; 1850 if (ce.host === host || ce.el === host) { 1851 handles[i].detach(); 1852 } 1853 } 1854 } 1855 }; 1856 1857 if (detachcategory) { 1858 1859 cat = store[detachcategory]; 1860 type = parts[1]; 1861 detachhost = (isNode) ? Y.Node.getDOMNode(this) : this; 1862 1863 if (cat) { 1864 if (type) { 1865 keyDetacher(cat, type, detachhost); 1866 } else { 1867 for (i in cat) { 1868 if (cat.hasOwnProperty(i)) { 1869 keyDetacher(cat, i, detachhost); 1870 } 1871 } 1872 } 1873 1874 return this; 1875 } 1876 1877 // If this is an event handle, use it to detach 1878 } else if (L.isObject(type) && type.detach) { 1879 type.detach(); 1880 return this; 1881 // extra redirection so we catch adaptor events too. take a look at this. 1882 } else if (isNode && ((!shorttype) || (shorttype in Node.DOM_EVENTS))) { 1883 args = nativeSlice.call(arguments, 0); 1884 args[2] = Node.getDOMNode(this); 1885 Y.detach.apply(Y, args); 1886 return this; 1887 } 1888 1889 adapt = Y.Env.evt.plugins[shorttype]; 1890 1891 // The YUI instance handles DOM events and adaptors 1892 if (Y.instanceOf(this, YUI)) { 1893 args = nativeSlice.call(arguments, 0); 1894 // use the adaptor specific detach code if 1895 if (adapt && adapt.detach) { 1896 adapt.detach.apply(Y, args); 1897 return this; 1898 // DOM event fork 1899 } else if (!type || (!adapt && Node && (type in Node.DOM_EVENTS))) { 1900 args[0] = type; 1901 Y.Event.detach.apply(Y.Event, args); 1902 return this; 1903 } 1904 } 1905 1906 // ce = evts[type]; 1907 ce = evts[parts[1]]; 1908 if (ce) { 1909 ce.detach(fn, context); 1910 } 1911 1912 return this; 1913 }, 1914 1915 /** 1916 * detach a listener 1917 * @method unsubscribe 1918 * @deprecated use detach 1919 */ 1920 unsubscribe: function() { 1921 Y.log('EventTarget unsubscribe() is deprecated, use detach()', 'warn', 'deprecated'); 1922 return this.detach.apply(this, arguments); 1923 }, 1924 1925 /** 1926 * Removes all listeners from the specified event. If the event type 1927 * is not specified, all listeners from all hosted custom events will 1928 * be removed. 1929 * @method detachAll 1930 * @param type {String} The type, or name of the event 1931 */ 1932 detachAll: function(type) { 1933 return this.detach(type); 1934 }, 1935 1936 /** 1937 * Removes all listeners from the specified event. If the event type 1938 * is not specified, all listeners from all hosted custom events will 1939 * be removed. 1940 * @method unsubscribeAll 1941 * @param type {String} The type, or name of the event 1942 * @deprecated use detachAll 1943 */ 1944 unsubscribeAll: function() { 1945 Y.log('EventTarget unsubscribeAll() is deprecated, use detachAll()', 'warn', 'deprecated'); 1946 return this.detachAll.apply(this, arguments); 1947 }, 1948 1949 /** 1950 * Creates a new custom event of the specified type. If a custom event 1951 * by that name already exists, it will not be re-created. In either 1952 * case the custom event is returned. 1953 * 1954 * @method publish 1955 * 1956 * @param type {String} the type, or name of the event 1957 * @param opts {object} optional config params. Valid properties are: 1958 * 1959 * <ul> 1960 * <li> 1961 * 'broadcast': whether or not the YUI instance and YUI global are notified when the event is fired (false) 1962 * </li> 1963 * <li> 1964 * 'bubbles': whether or not this event bubbles (true) 1965 * Events can only bubble if emitFacade is true. 1966 * </li> 1967 * <li> 1968 * 'context': the default execution context for the listeners (this) 1969 * </li> 1970 * <li> 1971 * 'defaultFn': the default function to execute when this event fires if preventDefault was not called 1972 * </li> 1973 * <li> 1974 * 'emitFacade': whether or not this event emits a facade (false) 1975 * </li> 1976 * <li> 1977 * 'prefix': the prefix for this targets events, e.g., 'menu' in 'menu:click' 1978 * </li> 1979 * <li> 1980 * 'fireOnce': if an event is configured to fire once, new subscribers after 1981 * the fire will be notified immediately. 1982 * </li> 1983 * <li> 1984 * 'async': fireOnce event listeners will fire synchronously if the event has already 1985 * fired unless async is true. 1986 * </li> 1987 * <li> 1988 * 'preventable': whether or not preventDefault() has an effect (true) 1989 * </li> 1990 * <li> 1991 * 'preventedFn': a function that is executed when preventDefault is called 1992 * </li> 1993 * <li> 1994 * 'queuable': whether or not this event can be queued during bubbling (false) 1995 * </li> 1996 * <li> 1997 * 'silent': if silent is true, debug messages are not provided for this event. 1998 * </li> 1999 * <li> 2000 * 'stoppedFn': a function that is executed when stopPropagation is called 2001 * </li> 2002 * 2003 * <li> 2004 * 'monitored': specifies whether or not this event should send notifications about 2005 * when the event has been attached, detached, or published. 2006 * </li> 2007 * <li> 2008 * 'type': the event type (valid option if not provided as the first parameter to publish) 2009 * </li> 2010 * </ul> 2011 * 2012 * @return {CustomEvent} the custom event 2013 * 2014 */ 2015 publish: function(type, opts) { 2016 2017 var ret, 2018 etState = this._yuievt, 2019 etConfig = etState.config, 2020 pre = etConfig.prefix; 2021 2022 if (typeof type === "string") { 2023 if (pre) { 2024 type = _getType(type, pre); 2025 } 2026 ret = this._publish(type, etConfig, opts); 2027 } else { 2028 ret = {}; 2029 2030 Y.each(type, function(v, k) { 2031 if (pre) { 2032 k = _getType(k, pre); 2033 } 2034 ret[k] = this._publish(k, etConfig, v || opts); 2035 }, this); 2036 2037 } 2038 2039 return ret; 2040 }, 2041 2042 /** 2043 * Returns the fully qualified type, given a short type string. 2044 * That is, returns "foo:bar" when given "bar" if "foo" is the configured prefix. 2045 * 2046 * NOTE: This method, unlike _getType, does no checking of the value passed in, and 2047 * is designed to be used with the low level _publish() method, for critical path 2048 * implementations which need to fast-track publish for performance reasons. 2049 * 2050 * @method _getFullType 2051 * @private 2052 * @param {String} type The short type to prefix 2053 * @return {String} The prefixed type, if a prefix is set, otherwise the type passed in 2054 */ 2055 _getFullType : function(type) { 2056 2057 var pre = this._yuievt.config.prefix; 2058 2059 if (pre) { 2060 return pre + PREFIX_DELIMITER + type; 2061 } else { 2062 return type; 2063 } 2064 }, 2065 2066 /** 2067 * The low level event publish implementation. It expects all the massaging to have been done 2068 * outside of this method. e.g. the `type` to `fullType` conversion. It's designed to be a fast 2069 * path publish, which can be used by critical code paths to improve performance. 2070 * 2071 * @method _publish 2072 * @private 2073 * @param {String} fullType The prefixed type of the event to publish. 2074 * @param {Object} etOpts The EventTarget specific configuration to mix into the published event. 2075 * @param {Object} ceOpts The publish specific configuration to mix into the published event. 2076 * @return {CustomEvent} The published event. If called without `etOpts` or `ceOpts`, this will 2077 * be the default `CustomEvent` instance, and can be configured independently. 2078 */ 2079 _publish : function(fullType, etOpts, ceOpts) { 2080 2081 var ce, 2082 etState = this._yuievt, 2083 etConfig = etState.config, 2084 host = etConfig.host, 2085 context = etConfig.context, 2086 events = etState.events; 2087 2088 ce = events[fullType]; 2089 2090 // PERF: Hate to pull the check out of monitor, but trying to keep critical path tight. 2091 if ((etConfig.monitored && !ce) || (ce && ce.monitored)) { 2092 this._monitor('publish', fullType, { 2093 args: arguments 2094 }); 2095 } 2096 2097 if (!ce) { 2098 // Publish event 2099 ce = events[fullType] = new Y.CustomEvent(fullType, etOpts); 2100 2101 if (!etOpts) { 2102 ce.host = host; 2103 ce.context = context; 2104 } 2105 } 2106 2107 if (ceOpts) { 2108 mixConfigs(ce, ceOpts, true); 2109 } 2110 2111 return ce; 2112 }, 2113 2114 /** 2115 * This is the entry point for the event monitoring system. 2116 * You can monitor 'attach', 'detach', 'fire', and 'publish'. 2117 * When configured, these events generate an event. click -> 2118 * click_attach, click_detach, click_publish -- these can 2119 * be subscribed to like other events to monitor the event 2120 * system. Inividual published events can have monitoring 2121 * turned on or off (publish can't be turned off before it 2122 * it published) by setting the events 'monitor' config. 2123 * 2124 * @method _monitor 2125 * @param what {String} 'attach', 'detach', 'fire', or 'publish' 2126 * @param eventType {String|CustomEvent} The prefixed name of the event being monitored, or the CustomEvent object. 2127 * @param o {Object} Information about the event interaction, such as 2128 * fire() args, subscription category, publish config 2129 * @private 2130 */ 2131 _monitor: function(what, eventType, o) { 2132 var monitorevt, ce, type; 2133 2134 if (eventType) { 2135 if (typeof eventType === "string") { 2136 type = eventType; 2137 ce = this.getEvent(eventType, true); 2138 } else { 2139 ce = eventType; 2140 type = eventType.type; 2141 } 2142 2143 if ((this._yuievt.config.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) { 2144 monitorevt = type + '_' + what; 2145 o.monitored = what; 2146 this.fire.call(this, monitorevt, o); 2147 } 2148 } 2149 }, 2150 2151 /** 2152 * Fire a custom event by name. The callback functions will be executed 2153 * from the context specified when the event was created, and with the 2154 * following parameters. 2155 * 2156 * The first argument is the event type, and any additional arguments are 2157 * passed to the listeners as parameters. If the first of these is an 2158 * object literal, and the event is configured to emit an event facade, 2159 * that object is mixed into the event facade and the facade is provided 2160 * in place of the original object. 2161 * 2162 * If the custom event object hasn't been created, then the event hasn't 2163 * been published and it has no subscribers. For performance sake, we 2164 * immediate exit in this case. This means the event won't bubble, so 2165 * if the intention is that a bubble target be notified, the event must 2166 * be published on this object first. 2167 * 2168 * @method fire 2169 * @param type {String|Object} The type of the event, or an object that contains 2170 * a 'type' property. 2171 * @param arguments {Object*} an arbitrary set of parameters to pass to 2172 * the handler. If the first of these is an object literal and the event is 2173 * configured to emit an event facade, the event facade will replace that 2174 * parameter after the properties the object literal contains are copied to 2175 * the event facade. 2176 * @return {Boolean} True if the whole lifecycle of the event went through, 2177 * false if at any point the event propagation was halted. 2178 */ 2179 fire: function(type) { 2180 2181 var typeIncluded = (typeof type === "string"), 2182 argCount = arguments.length, 2183 t = type, 2184 yuievt = this._yuievt, 2185 etConfig = yuievt.config, 2186 pre = etConfig.prefix, 2187 ret, 2188 ce, 2189 ce2, 2190 args; 2191 2192 if (typeIncluded && argCount <= 3) { 2193 2194 // PERF: Try to avoid slice/iteration for the common signatures 2195 2196 // Most common 2197 if (argCount === 2) { 2198 args = [arguments[1]]; // fire("foo", {}) 2199 } else if (argCount === 3) { 2200 args = [arguments[1], arguments[2]]; // fire("foo", {}, opts) 2201 } else { 2202 args = []; // fire("foo") 2203 } 2204 2205 } else { 2206 args = nativeSlice.call(arguments, ((typeIncluded) ? 1 : 0)); 2207 } 2208 2209 if (!typeIncluded) { 2210 t = (type && type.type); 2211 } 2212 2213 if (pre) { 2214 t = _getType(t, pre); 2215 } 2216 2217 ce = yuievt.events[t]; 2218 2219 if (this._hasSiblings) { 2220 ce2 = this.getSibling(t, ce); 2221 2222 if (ce2 && !ce) { 2223 ce = this.publish(t); 2224 } 2225 } 2226 2227 // PERF: trying to avoid function call, since this is a critical path 2228 if ((etConfig.monitored && (!ce || ce.monitored)) || (ce && ce.monitored)) { 2229 this._monitor('fire', (ce || t), { 2230 args: args 2231 }); 2232 } 2233 2234 // this event has not been published or subscribed to 2235 if (!ce) { 2236 if (yuievt.hasTargets) { 2237 return this.bubble({ type: t }, args, this); 2238 } 2239 2240 // otherwise there is nothing to be done 2241 ret = true; 2242 } else { 2243 2244 if (ce2) { 2245 ce.sibling = ce2; 2246 } 2247 2248 ret = ce._fire(args); 2249 } 2250 2251 return (yuievt.chain) ? this : ret; 2252 }, 2253 2254 getSibling: function(type, ce) { 2255 var ce2; 2256 2257 // delegate to *:type events if there are subscribers 2258 if (type.indexOf(PREFIX_DELIMITER) > -1) { 2259 type = _wildType(type); 2260 ce2 = this.getEvent(type, true); 2261 if (ce2) { 2262 ce2.applyConfig(ce); 2263 ce2.bubbles = false; 2264 ce2.broadcast = 0; 2265 } 2266 } 2267 2268 return ce2; 2269 }, 2270 2271 /** 2272 * Returns the custom event of the provided type has been created, a 2273 * falsy value otherwise 2274 * @method getEvent 2275 * @param type {String} the type, or name of the event 2276 * @param prefixed {String} if true, the type is prefixed already 2277 * @return {CustomEvent} the custom event or null 2278 */ 2279 getEvent: function(type, prefixed) { 2280 var pre, e; 2281 2282 if (!prefixed) { 2283 pre = this._yuievt.config.prefix; 2284 type = (pre) ? _getType(type, pre) : type; 2285 } 2286 e = this._yuievt.events; 2287 return e[type] || null; 2288 }, 2289 2290 /** 2291 * Subscribe to a custom event hosted by this object. The 2292 * supplied callback will execute after any listeners add 2293 * via the subscribe method, and after the default function, 2294 * if configured for the event, has executed. 2295 * 2296 * @method after 2297 * @param {String} type The name of the event 2298 * @param {Function} fn The callback to execute in response to the event 2299 * @param {Object} [context] Override `this` object in callback 2300 * @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 2301 * @return {EventHandle} A subscription handle capable of detaching the 2302 * subscription 2303 */ 2304 after: function(type, fn) { 2305 2306 var a = nativeSlice.call(arguments, 0); 2307 2308 switch (L.type(type)) { 2309 case 'function': 2310 return Y.Do.after.apply(Y.Do, arguments); 2311 case 'array': 2312 // YArray.each(a[0], function(v) { 2313 // v = AFTER_PREFIX + v; 2314 // }); 2315 // break; 2316 case 'object': 2317 a[0]._after = true; 2318 break; 2319 default: 2320 a[0] = AFTER_PREFIX + type; 2321 } 2322 2323 return this.on.apply(this, a); 2324 2325 }, 2326 2327 /** 2328 * Executes the callback before a DOM event, custom event 2329 * or method. If the first argument is a function, it 2330 * is assumed the target is a method. For DOM and custom 2331 * events, this is an alias for Y.on. 2332 * 2333 * For DOM and custom events: 2334 * type, callback, context, 0-n arguments 2335 * 2336 * For methods: 2337 * callback, object (method host), methodName, context, 0-n arguments 2338 * 2339 * @method before 2340 * @return detach handle 2341 */ 2342 before: function() { 2343 return this.on.apply(this, arguments); 2344 } 2345 2346 }; 2347 2348 Y.EventTarget = ET; 2349 2350 // make Y an event target 2351 Y.mix(Y, ET.prototype); 2352 ET.call(Y, { bubbles: false }); 2353 2354 YUI.Env.globalEvents = YUI.Env.globalEvents || new ET(); 2355 2356 /** 2357 * Hosts YUI page level events. This is where events bubble to 2358 * when the broadcast config is set to 2. This property is 2359 * only available if the custom event module is loaded. 2360 * @property Global 2361 * @type EventTarget 2362 * @for YUI 2363 */ 2364 Y.Global = YUI.Env.globalEvents; 2365 2366 // @TODO implement a global namespace function on Y.Global? 2367 2368 /** 2369 `Y.on()` can do many things: 2370 2371 <ul> 2372 <li>Subscribe to custom events `publish`ed and `fire`d from Y</li> 2373 <li>Subscribe to custom events `publish`ed with `broadcast` 1 or 2 and 2374 `fire`d from any object in the YUI instance sandbox</li> 2375 <li>Subscribe to DOM events</li> 2376 <li>Subscribe to the execution of a method on any object, effectively 2377 treating that method as an event</li> 2378 </ul> 2379 2380 For custom event subscriptions, pass the custom event name as the first argument 2381 and callback as the second. The `this` object in the callback will be `Y` unless 2382 an override is passed as the third argument. 2383 2384 Y.on('io:complete', function () { 2385 Y.MyApp.updateStatus('Transaction complete'); 2386 }); 2387 2388 To subscribe to DOM events, pass the name of a DOM event as the first argument 2389 and a CSS selector string as the third argument after the callback function. 2390 Alternately, the third argument can be a `Node`, `NodeList`, `HTMLElement`, 2391 array, or simply omitted (the default is the `window` object). 2392 2393 Y.on('click', function (e) { 2394 e.preventDefault(); 2395 2396 // proceed with ajax form submission 2397 var url = this.get('action'); 2398 ... 2399 }, '#my-form'); 2400 2401 The `this` object in DOM event callbacks will be the `Node` targeted by the CSS 2402 selector or other identifier. 2403 2404 `on()` subscribers for DOM events or custom events `publish`ed with a 2405 `defaultFn` can prevent the default behavior with `e.preventDefault()` from the 2406 event object passed as the first parameter to the subscription callback. 2407 2408 To subscribe to the execution of an object method, pass arguments corresponding to the call signature for 2409 <a href="../classes/Do.html#methods_before">`Y.Do.before(...)`</a>. 2410 2411 NOTE: The formal parameter list below is for events, not for function 2412 injection. See `Y.Do.before` for that signature. 2413 2414 @method on 2415 @param {String} type DOM or custom event name 2416 @param {Function} fn The callback to execute in response to the event 2417 @param {Object} [context] Override `this` object in callback 2418 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 2419 @return {EventHandle} A subscription handle capable of detaching the 2420 subscription 2421 @see Do.before 2422 @for YUI 2423 **/ 2424 2425 /** 2426 Listen for an event one time. Equivalent to `on()`, except that 2427 the listener is immediately detached when executed. 2428 2429 See the <a href="#methods_on">`on()` method</a> for additional subscription 2430 options. 2431 2432 @see on 2433 @method once 2434 @param {String} type DOM or custom event name 2435 @param {Function} fn The callback to execute in response to the event 2436 @param {Object} [context] Override `this` object in callback 2437 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 2438 @return {EventHandle} A subscription handle capable of detaching the 2439 subscription 2440 @for YUI 2441 **/ 2442 2443 /** 2444 Listen for an event one time. Equivalent to `once()`, except, like `after()`, 2445 the subscription callback executes after all `on()` subscribers and the event's 2446 `defaultFn` (if configured) have executed. Like `after()` if any `on()` phase 2447 subscriber calls `e.preventDefault()`, neither the `defaultFn` nor the `after()` 2448 subscribers will execute. 2449 2450 The listener is immediately detached when executed. 2451 2452 See the <a href="#methods_on">`on()` method</a> for additional subscription 2453 options. 2454 2455 @see once 2456 @method onceAfter 2457 @param {String} type The custom event name 2458 @param {Function} fn The callback to execute in response to the event 2459 @param {Object} [context] Override `this` object in callback 2460 @param {Any} [arg*] 0..n additional arguments to supply to the subscriber 2461 @return {EventHandle} A subscription handle capable of detaching the 2462 subscription 2463 @for YUI 2464 **/ 2465 2466 /** 2467 Like `on()`, this method creates a subscription to a custom event or to the 2468 execution of a method on an object. 2469 2470 For events, `after()` subscribers are executed after the event's 2471 `defaultFn` unless `e.preventDefault()` was called from an `on()` subscriber. 2472 2473 See the <a href="#methods_on">`on()` method</a> for additional subscription 2474 options. 2475 2476 NOTE: The subscription signature shown is for events, not for function 2477 injection. See <a href="../classes/Do.html#methods_after">`Y.Do.after`</a> 2478 for that signature. 2479 2480 @see on 2481 @see Do.after 2482 @method after 2483 @param {String} type The custom event name 2484 @param {Function} fn The callback to execute in response to the event 2485 @param {Object} [context] Override `this` object in callback 2486 @param {Any} [args*] 0..n additional arguments to supply to the subscriber 2487 @return {EventHandle} A subscription handle capable of detaching the 2488 subscription 2489 @for YUI 2490 **/ 2491 2492 2493 }, '3.17.2', {"requires": ["oop"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |