[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/yuilib/3.17.2/event-base/ -> event-base-debug.js (source)

   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-base', function (Y, NAME) {
   9  
  10  /*
  11   * DOM event listener abstraction layer
  12   * @module event
  13   * @submodule event-base
  14   */
  15  
  16  /**
  17   * The domready event fires at the moment the browser's DOM is
  18   * usable. In most cases, this is before images are fully
  19   * downloaded, allowing you to provide a more responsive user
  20   * interface.
  21   *
  22   * In YUI 3, domready subscribers will be notified immediately if
  23   * that moment has already passed when the subscription is created.
  24   *
  25   * One exception is if the yui.js file is dynamically injected into
  26   * the page.  If this is done, you must tell the YUI instance that
  27   * you did this in order for DOMReady (and window load events) to
  28   * fire normally.  That configuration option is 'injected' -- set
  29   * it to true if the yui.js script is not included inline.
  30   *
  31   * This method is part of the 'event-ready' module, which is a
  32   * submodule of 'event'.
  33   *
  34   * @event domready
  35   * @for YUI
  36   */
  37  Y.publish('domready', {
  38      fireOnce: true,
  39      async: true
  40  });
  41  
  42  if (YUI.Env.DOMReady) {
  43      Y.fire('domready');
  44  } else {
  45      Y.Do.before(function() { Y.fire('domready'); }, YUI.Env, '_ready');
  46  }
  47  
  48  /**
  49   * Custom event engine, DOM event listener abstraction layer, synthetic DOM
  50   * events.
  51   * @module event
  52   * @submodule event-base
  53   */
  54  
  55  /**
  56   * Wraps a DOM event, properties requiring browser abstraction are
  57   * fixed here.  Provids a security layer when required.
  58   * @class DOMEventFacade
  59   * @param ev {Event} the DOM event
  60   * @param currentTarget {HTMLElement} the element the listener was attached to
  61   * @param wrapper {CustomEvent} the custom event wrapper for this DOM event
  62   */
  63  
  64      var ua = Y.UA,
  65  
  66      EMPTY = {},
  67  
  68      /**
  69       * webkit key remapping required for Safari < 3.1
  70       * @property webkitKeymap
  71       * @private
  72       */
  73      webkitKeymap = {
  74          63232: 38, // up
  75          63233: 40, // down
  76          63234: 37, // left
  77          63235: 39, // right
  78          63276: 33, // page up
  79          63277: 34, // page down
  80          25:     9, // SHIFT-TAB (Safari provides a different key code in
  81                     // this case, even though the shiftKey modifier is set)
  82          63272: 46, // delete
  83          63273: 36, // home
  84          63275: 35  // end
  85      },
  86  
  87      /**
  88       * Returns a wrapped node.  Intended to be used on event targets,
  89       * so it will return the node's parent if the target is a text
  90       * node.
  91       *
  92       * If accessing a property of the node throws an error, this is
  93       * probably the anonymous div wrapper Gecko adds inside text
  94       * nodes.  This likely will only occur when attempting to access
  95       * the relatedTarget.  In this case, we now return null because
  96       * the anonymous div is completely useless and we do not know
  97       * what the related target was because we can't even get to
  98       * the element's parent node.
  99       *
 100       * @method resolve
 101       * @private
 102       */
 103      resolve = function(n) {
 104          if (!n) {
 105              return n;
 106          }
 107          try {
 108              if (n && 3 == n.nodeType) {
 109                  n = n.parentNode;
 110              }
 111          } catch(e) {
 112              return null;
 113          }
 114  
 115          return Y.one(n);
 116      },
 117  
 118      DOMEventFacade = function(ev, currentTarget, wrapper) {
 119          this._event = ev;
 120          this._currentTarget = currentTarget;
 121          this._wrapper = wrapper || EMPTY;
 122  
 123          // if not lazy init
 124          this.init();
 125      };
 126  
 127  Y.extend(DOMEventFacade, Object, {
 128  
 129      init: function() {
 130  
 131          var e = this._event,
 132              overrides = this._wrapper.overrides,
 133              x = e.pageX,
 134              y = e.pageY,
 135              c,
 136              currentTarget = this._currentTarget;
 137  
 138          this.altKey   = e.altKey;
 139          this.ctrlKey  = e.ctrlKey;
 140          this.metaKey  = e.metaKey;
 141          this.shiftKey = e.shiftKey;
 142          this.type     = (overrides && overrides.type) || e.type;
 143          this.clientX  = e.clientX;
 144          this.clientY  = e.clientY;
 145  
 146          this.pageX = x;
 147          this.pageY = y;
 148  
 149          // charCode is unknown in keyup, keydown. keyCode is unknown in keypress.
 150          // FF 3.6 - 8+? pass 0 for keyCode in keypress events.
 151          // Webkit, FF 3.6-8+?, and IE9+? pass 0 for charCode in keydown, keyup.
 152          // Webkit and IE9+? duplicate charCode in keyCode.
 153          // Opera never sets charCode, always keyCode (though with the charCode).
 154          // IE6-8 don't set charCode or which.
 155          // All browsers other than IE6-8 set which=keyCode in keydown, keyup, and
 156          // which=charCode in keypress.
 157          //
 158          // Moral of the story: (e.which || e.keyCode) will always return the
 159          // known code for that key event phase. e.keyCode is often different in
 160          // keypress from keydown and keyup.
 161          c = e.keyCode || e.charCode;
 162  
 163          if (ua.webkit && (c in webkitKeymap)) {
 164              c = webkitKeymap[c];
 165          }
 166  
 167          this.keyCode = c;
 168          this.charCode = c;
 169          // Fill in e.which for IE - implementers should always use this over
 170          // e.keyCode or e.charCode.
 171          this.which = e.which || e.charCode || c;
 172          // this.button = e.button;
 173          this.button = this.which;
 174  
 175          this.target = resolve(e.target);
 176          this.currentTarget = resolve(currentTarget);
 177          this.relatedTarget = resolve(e.relatedTarget);
 178  
 179          if (e.type == "mousewheel" || e.type == "DOMMouseScroll") {
 180              this.wheelDelta = (e.detail) ? (e.detail * -1) : Math.round(e.wheelDelta / 80) || ((e.wheelDelta < 0) ? -1 : 1);
 181          }
 182  
 183          if (this._touch) {
 184              this._touch(e, currentTarget, this._wrapper);
 185          }
 186      },
 187  
 188      stopPropagation: function() {
 189          this._event.stopPropagation();
 190          this._wrapper.stopped = 1;
 191          this.stopped = 1;
 192      },
 193  
 194      stopImmediatePropagation: function() {
 195          var e = this._event;
 196          if (e.stopImmediatePropagation) {
 197              e.stopImmediatePropagation();
 198          } else {
 199              this.stopPropagation();
 200          }
 201          this._wrapper.stopped = 2;
 202          this.stopped = 2;
 203      },
 204  
 205      preventDefault: function(returnValue) {
 206          var e = this._event;
 207          e.preventDefault();
 208          if (returnValue) {
 209              e.returnValue = returnValue;
 210          }
 211          this._wrapper.prevented = 1;
 212          this.prevented = 1;
 213      },
 214  
 215      halt: function(immediate) {
 216          if (immediate) {
 217              this.stopImmediatePropagation();
 218          } else {
 219              this.stopPropagation();
 220          }
 221  
 222          this.preventDefault();
 223      }
 224  
 225  });
 226  
 227  DOMEventFacade.resolve = resolve;
 228  Y.DOM2EventFacade = DOMEventFacade;
 229  Y.DOMEventFacade = DOMEventFacade;
 230  
 231      /**
 232       * The native event
 233       * @property _event
 234       * @type {DOMEvent}
 235       * @private
 236       */
 237  
 238      /**
 239      The name of the event (e.g. "click")
 240  
 241      @property type
 242      @type {String}
 243      **/
 244  
 245      /**
 246      `true` if the "alt" or "option" key is pressed.
 247  
 248      @property altKey
 249      @type {Boolean}
 250      **/
 251  
 252      /**
 253      `true` if the shift key is pressed.
 254  
 255      @property shiftKey
 256      @type {Boolean}
 257      **/
 258  
 259      /**
 260      `true` if the "Windows" key on a Windows keyboard, "command" key on an
 261      Apple keyboard, or "meta" key on other keyboards is pressed.
 262  
 263      @property metaKey
 264      @type {Boolean}
 265      **/
 266  
 267      /**
 268      `true` if the "Ctrl" or "control" key is pressed.
 269  
 270      @property ctrlKey
 271      @type {Boolean}
 272      **/
 273  
 274      /**
 275       * The X location of the event on the page (including scroll)
 276       * @property pageX
 277       * @type {Number}
 278       */
 279  
 280      /**
 281       * The Y location of the event on the page (including scroll)
 282       * @property pageY
 283       * @type {Number}
 284       */
 285  
 286      /**
 287       * The X location of the event in the viewport
 288       * @property clientX
 289       * @type {Number}
 290       */
 291  
 292      /**
 293       * The Y location of the event in the viewport
 294       * @property clientY
 295       * @type {Number}
 296       */
 297  
 298      /**
 299       * The keyCode for key events.  Uses charCode if keyCode is not available
 300       * @property keyCode
 301       * @type {Number}
 302       */
 303  
 304      /**
 305       * The charCode for key events.  Same as keyCode
 306       * @property charCode
 307       * @type {Number}
 308       */
 309  
 310      /**
 311       * The button that was pushed. 1 for left click, 2 for middle click, 3 for
 312       * right click.  This is only reliably populated on `mouseup` events.
 313       * @property button
 314       * @type {Number}
 315       */
 316  
 317      /**
 318       * The button that was pushed.  Same as button.
 319       * @property which
 320       * @type {Number}
 321       */
 322  
 323      /**
 324       * Node reference for the targeted element
 325       * @property target
 326       * @type {Node}
 327       */
 328  
 329      /**
 330       * Node reference for the element that the listener was attached to.
 331       * @property currentTarget
 332       * @type {Node}
 333       */
 334  
 335      /**
 336       * Node reference to the relatedTarget
 337       * @property relatedTarget
 338       * @type {Node}
 339       */
 340  
 341      /**
 342       * Number representing the direction and velocity of the movement of the mousewheel.
 343       * Negative is down, the higher the number, the faster.  Applies to the mousewheel event.
 344       * @property wheelDelta
 345       * @type {Number}
 346       */
 347  
 348      /**
 349       * Stops the propagation to the next bubble target
 350       * @method stopPropagation
 351       */
 352  
 353      /**
 354       * Stops the propagation to the next bubble target and
 355       * prevents any additional listeners from being exectued
 356       * on the current target.
 357       * @method stopImmediatePropagation
 358       */
 359  
 360      /**
 361       * Prevents the event's default behavior
 362       * @method preventDefault
 363       * @param returnValue {string} sets the returnValue of the event to this value
 364       * (rather than the default false value).  This can be used to add a customized
 365       * confirmation query to the beforeunload event).
 366       */
 367  
 368      /**
 369       * Stops the event propagation and prevents the default
 370       * event behavior.
 371       * @method halt
 372       * @param immediate {boolean} if true additional listeners
 373       * on the current target will not be executed
 374       */
 375  (function() {
 376  
 377  /**
 378   * The event utility provides functions to add and remove event listeners,
 379   * event cleansing.  It also tries to automatically remove listeners it
 380   * registers during the unload event.
 381   * @module event
 382   * @main event
 383   * @submodule event-base
 384   */
 385  
 386  /**
 387   * The event utility provides functions to add and remove event listeners,
 388   * event cleansing.  It also tries to automatically remove listeners it
 389   * registers during the unload event.
 390   *
 391   * @class Event
 392   * @static
 393   */
 394  
 395  Y.Env.evt.dom_wrappers = {};
 396  Y.Env.evt.dom_map = {};
 397  
 398  var _eventenv = Y.Env.evt,
 399      config = Y.config,
 400      win = config.win,
 401      add = YUI.Env.add,
 402      remove = YUI.Env.remove,
 403  
 404      onLoad = function() {
 405          YUI.Env.windowLoaded = true;
 406          Y.Event._load();
 407          remove(win, "load", onLoad);
 408      },
 409  
 410      onUnload = function() {
 411          Y.Event._unload();
 412      },
 413  
 414      EVENT_READY = 'domready',
 415  
 416      COMPAT_ARG = '~yui|2|compat~',
 417  
 418      shouldIterate = function(o) {
 419          try {
 420              // TODO: See if there's a more performant way to return true early on this, for the common case
 421              return (o && typeof o !== "string" && Y.Lang.isNumber(o.length) && !o.tagName && !Y.DOM.isWindow(o));
 422          } catch(ex) {
 423              Y.log("collection check failure", "warn", "event");
 424              return false;
 425          }
 426      },
 427  
 428      // aliases to support DOM event subscription clean up when the last
 429      // subscriber is detached. deleteAndClean overrides the DOM event's wrapper
 430      // CustomEvent _delete method.
 431      _ceProtoDelete = Y.CustomEvent.prototype._delete,
 432      _deleteAndClean = function(s) {
 433          var ret = _ceProtoDelete.apply(this, arguments);
 434  
 435          if (!this.hasSubs()) {
 436              Y.Event._clean(this);
 437          }
 438  
 439          return ret;
 440      },
 441  
 442  Event = function() {
 443  
 444      /**
 445       * True after the onload event has fired
 446       * @property _loadComplete
 447       * @type boolean
 448       * @static
 449       * @private
 450       */
 451      var _loadComplete =  false,
 452  
 453      /**
 454       * The number of times to poll after window.onload.  This number is
 455       * increased if additional late-bound handlers are requested after
 456       * the page load.
 457       * @property _retryCount
 458       * @static
 459       * @private
 460       */
 461      _retryCount = 0,
 462  
 463      /**
 464       * onAvailable listeners
 465       * @property _avail
 466       * @static
 467       * @private
 468       */
 469      _avail = [],
 470  
 471      /**
 472       * Custom event wrappers for DOM events.  Key is
 473       * 'event:' + Element uid stamp + event type
 474       * @property _wrappers
 475       * @type CustomEvent
 476       * @static
 477       * @private
 478       */
 479      _wrappers = _eventenv.dom_wrappers,
 480  
 481      _windowLoadKey = null,
 482  
 483      /**
 484       * Custom event wrapper map DOM events.  Key is
 485       * Element uid stamp.  Each item is a hash of custom event
 486       * wrappers as provided in the _wrappers collection.  This
 487       * provides the infrastructure for getListeners.
 488       * @property _el_events
 489       * @static
 490       * @private
 491       */
 492      _el_events = _eventenv.dom_map;
 493  
 494      return {
 495  
 496          /**
 497           * The number of times we should look for elements that are not
 498           * in the DOM at the time the event is requested after the document
 499           * has been loaded.  The default is 1000@amp;40 ms, so it will poll
 500           * for 40 seconds or until all outstanding handlers are bound
 501           * (whichever comes first).
 502           * @property POLL_RETRYS
 503           * @type int
 504           * @static
 505           * @final
 506           */
 507          POLL_RETRYS: 1000,
 508  
 509          /**
 510           * The poll interval in milliseconds
 511           * @property POLL_INTERVAL
 512           * @type int
 513           * @static
 514           * @final
 515           */
 516          POLL_INTERVAL: 40,
 517  
 518          /**
 519           * addListener/removeListener can throw errors in unexpected scenarios.
 520           * These errors are suppressed, the method returns false, and this property
 521           * is set
 522           * @property lastError
 523           * @static
 524           * @type Error
 525           */
 526          lastError: null,
 527  
 528  
 529          /**
 530           * poll handle
 531           * @property _interval
 532           * @static
 533           * @private
 534           */
 535          _interval: null,
 536  
 537          /**
 538           * document readystate poll handle
 539           * @property _dri
 540           * @static
 541           * @private
 542           */
 543           _dri: null,
 544  
 545          /**
 546           * True when the document is initially usable
 547           * @property DOMReady
 548           * @type boolean
 549           * @static
 550           */
 551          DOMReady: false,
 552  
 553          /**
 554           * @method startInterval
 555           * @static
 556           * @private
 557           */
 558          startInterval: function() {
 559              if (!Event._interval) {
 560  Event._interval = setInterval(Event._poll, Event.POLL_INTERVAL);
 561              }
 562          },
 563  
 564          /**
 565           * Executes the supplied callback when the item with the supplied
 566           * id is found.  This is meant to be used to execute behavior as
 567           * soon as possible as the page loads.  If you use this after the
 568           * initial page load it will poll for a fixed time for the element.
 569           * The number of times it will poll and the frequency are
 570           * configurable.  By default it will poll for 10 seconds.
 571           *
 572           * <p>The callback is executed with a single parameter:
 573           * the custom object parameter, if provided.</p>
 574           *
 575           * @method onAvailable
 576           *
 577           * @param {string||string[]}   id the id of the element, or an array
 578           * of ids to look for.
 579           * @param {function} fn what to execute when the element is found.
 580           * @param {object}   p_obj an optional object to be passed back as
 581           *                   a parameter to fn.
 582           * @param {boolean|object}  p_override If set to true, fn will execute
 583           *                   in the context of p_obj, if set to an object it
 584           *                   will execute in the context of that object
 585           * @param checkContent {boolean} check child node readiness (onContentReady)
 586           * @static
 587           * @deprecated Use Y.on("available")
 588           */
 589          // @TODO fix arguments
 590          onAvailable: function(id, fn, p_obj, p_override, checkContent, compat) {
 591  
 592              var a = Y.Array(id), i, availHandle;
 593  
 594              for (i=0; i<a.length; i=i+1) {
 595                  _avail.push({
 596                      id:         a[i],
 597                      fn:         fn,
 598                      obj:        p_obj,
 599                      override:   p_override,
 600                      checkReady: checkContent,
 601                      compat:     compat
 602                  });
 603              }
 604              _retryCount = this.POLL_RETRYS;
 605  
 606              // We want the first test to be immediate, but async
 607              setTimeout(Event._poll, 0);
 608  
 609              availHandle = new Y.EventHandle({
 610  
 611                  _delete: function() {
 612                      // set by the event system for lazy DOM listeners
 613                      if (availHandle.handle) {
 614                          availHandle.handle.detach();
 615                          return;
 616                      }
 617  
 618                      var i, j;
 619  
 620                      // otherwise try to remove the onAvailable listener(s)
 621                      for (i = 0; i < a.length; i++) {
 622                          for (j = 0; j < _avail.length; j++) {
 623                              if (a[i] === _avail[j].id) {
 624                                  _avail.splice(j, 1);
 625                              }
 626                          }
 627                      }
 628                  }
 629  
 630              });
 631  
 632              return availHandle;
 633          },
 634  
 635          /**
 636           * Works the same way as onAvailable, but additionally checks the
 637           * state of sibling elements to determine if the content of the
 638           * available element is safe to modify.
 639           *
 640           * <p>The callback is executed with a single parameter:
 641           * the custom object parameter, if provided.</p>
 642           *
 643           * @method onContentReady
 644           *
 645           * @param {string}   id the id of the element to look for.
 646           * @param {function} fn what to execute when the element is ready.
 647           * @param {object}   obj an optional object to be passed back as
 648           *                   a parameter to fn.
 649           * @param {boolean|object}  override If set to true, fn will execute
 650           *                   in the context of p_obj.  If an object, fn will
 651           *                   exectute in the context of that object
 652           *
 653           * @static
 654           * @deprecated Use Y.on("contentready")
 655           */
 656          // @TODO fix arguments
 657          onContentReady: function(id, fn, obj, override, compat) {
 658              return Event.onAvailable(id, fn, obj, override, true, compat);
 659          },
 660  
 661          /**
 662           * Adds an event listener
 663           *
 664           * @method attach
 665           *
 666           * @param {String}   type     The type of event to append
 667           * @param {Function} fn        The method the event invokes
 668           * @param {String|HTMLElement|Array|NodeList} el An id, an element
 669           *  reference, or a collection of ids and/or elements to assign the
 670           *  listener to.
 671           * @param {Object}   context optional context object
 672           * @param {Boolean|object}  args 0..n arguments to pass to the callback
 673           * @return {EventHandle} an object to that can be used to detach the listener
 674           *
 675           * @static
 676           */
 677  
 678          attach: function(type, fn, el, context) {
 679              return Event._attach(Y.Array(arguments, 0, true));
 680          },
 681  
 682          _createWrapper: function (el, type, capture, compat, facade) {
 683  
 684              var cewrapper,
 685                  ek  = Y.stamp(el),
 686                  key = 'event:' + ek + type;
 687  
 688              if (false === facade) {
 689                  key += 'native';
 690              }
 691              if (capture) {
 692                  key += 'capture';
 693              }
 694  
 695  
 696              cewrapper = _wrappers[key];
 697  
 698  
 699              if (!cewrapper) {
 700                  // create CE wrapper
 701                  cewrapper = Y.publish(key, {
 702                      silent: true,
 703                      bubbles: false,
 704                      emitFacade:false,
 705                      contextFn: function() {
 706                          if (compat) {
 707                              return cewrapper.el;
 708                          } else {
 709                              cewrapper.nodeRef = cewrapper.nodeRef || Y.one(cewrapper.el);
 710                              return cewrapper.nodeRef;
 711                          }
 712                      }
 713                  });
 714  
 715                  cewrapper.overrides = {};
 716  
 717                  // for later removeListener calls
 718                  cewrapper.el = el;
 719                  cewrapper.key = key;
 720                  cewrapper.domkey = ek;
 721                  cewrapper.type = type;
 722                  cewrapper.fn = function(e) {
 723                      cewrapper.fire(Event.getEvent(e, el, (compat || (false === facade))));
 724                  };
 725                  cewrapper.capture = capture;
 726  
 727                  if (el == win && type == "load") {
 728                      // window load happens once
 729                      cewrapper.fireOnce = true;
 730                      _windowLoadKey = key;
 731                  }
 732                  cewrapper._delete = _deleteAndClean;
 733  
 734                  _wrappers[key] = cewrapper;
 735                  _el_events[ek] = _el_events[ek] || {};
 736                  _el_events[ek][key] = cewrapper;
 737  
 738                  add(el, type, cewrapper.fn, capture);
 739              }
 740  
 741              return cewrapper;
 742  
 743          },
 744  
 745          _attach: function(args, conf) {
 746  
 747              var compat,
 748                  handles, oEl, cewrapper, context,
 749                  fireNow = false, ret,
 750                  type = args[0],
 751                  fn = args[1],
 752                  el = args[2] || win,
 753                  facade = conf && conf.facade,
 754                  capture = conf && conf.capture,
 755                  overrides = conf && conf.overrides;
 756  
 757              if (args[args.length-1] === COMPAT_ARG) {
 758                  compat = true;
 759              }
 760  
 761              if (!fn || !fn.call) {
 762                  Y.log(type + " attach call failed, invalid callback", "error", "event");
 763                  return false;
 764              }
 765  
 766              // The el argument can be an array of elements or element ids.
 767              if (shouldIterate(el)) {
 768  
 769                  handles=[];
 770  
 771                  Y.each(el, function(v, k) {
 772                      args[2] = v;
 773                      handles.push(Event._attach(args.slice(), conf));
 774                  });
 775  
 776                  // return (handles.length === 1) ? handles[0] : handles;
 777                  return new Y.EventHandle(handles);
 778  
 779              // If the el argument is a string, we assume it is
 780              // actually the id of the element.  If the page is loaded
 781              // we convert el to the actual element, otherwise we
 782              // defer attaching the event until the element is
 783              // ready
 784              } else if (Y.Lang.isString(el)) {
 785  
 786                  // oEl = (compat) ? Y.DOM.byId(el) : Y.Selector.query(el);
 787  
 788                  if (compat) {
 789                      oEl = Y.DOM.byId(el);
 790                  } else {
 791  
 792                      oEl = Y.Selector.query(el);
 793  
 794                      switch (oEl.length) {
 795                          case 0:
 796                              oEl = null;
 797                              break;
 798                          case 1:
 799                              oEl = oEl[0];
 800                              break;
 801                          default:
 802                              args[2] = oEl;
 803                              return Event._attach(args, conf);
 804                      }
 805                  }
 806  
 807                  if (oEl) {
 808  
 809                      el = oEl;
 810  
 811                  // Not found = defer adding the event until the element is available
 812                  } else {
 813  
 814                      ret = Event.onAvailable(el, function() {
 815  
 816                          ret.handle = Event._attach(args, conf);
 817  
 818                      }, Event, true, false, compat);
 819  
 820                      return ret;
 821  
 822                  }
 823              }
 824  
 825              // Element should be an html element or node
 826              if (!el) {
 827                  Y.log("unable to attach event " + type, "warn", "event");
 828                  return false;
 829              }
 830  
 831              if (Y.Node && Y.instanceOf(el, Y.Node)) {
 832                  el = Y.Node.getDOMNode(el);
 833              }
 834  
 835              cewrapper = Event._createWrapper(el, type, capture, compat, facade);
 836              if (overrides) {
 837                  Y.mix(cewrapper.overrides, overrides);
 838              }
 839  
 840              if (el == win && type == "load") {
 841  
 842                  // if the load is complete, fire immediately.
 843                  // all subscribers, including the current one
 844                  // will be notified.
 845                  if (YUI.Env.windowLoaded) {
 846                      fireNow = true;
 847                  }
 848              }
 849  
 850              if (compat) {
 851                  args.pop();
 852              }
 853  
 854              context = args[3];
 855  
 856              // set context to the Node if not specified
 857              // ret = cewrapper.on.apply(cewrapper, trimmedArgs);
 858              ret = cewrapper._on(fn, context, (args.length > 4) ? args.slice(4) : null);
 859  
 860              if (fireNow) {
 861                  cewrapper.fire();
 862              }
 863  
 864              return ret;
 865  
 866          },
 867  
 868          /**
 869           * Removes an event listener.  Supports the signature the event was bound
 870           * with, but the preferred way to remove listeners is using the handle
 871           * that is returned when using Y.on
 872           *
 873           * @method detach
 874           *
 875           * @param {String} type the type of event to remove.
 876           * @param {Function} fn the method the event invokes.  If fn is
 877           * undefined, then all event handlers for the type of event are
 878           * removed.
 879           * @param {String|HTMLElement|Array|NodeList|EventHandle} el An
 880           * event handle, an id, an element reference, or a collection
 881           * of ids and/or elements to remove the listener from.
 882           * @return {boolean} true if the unbind was successful, false otherwise.
 883           * @static
 884           */
 885          detach: function(type, fn, el, obj) {
 886  
 887              var args=Y.Array(arguments, 0, true), compat, l, ok, i,
 888                  id, ce;
 889  
 890              if (args[args.length-1] === COMPAT_ARG) {
 891                  compat = true;
 892                  // args.pop();
 893              }
 894  
 895              if (type && type.detach) {
 896                  return type.detach();
 897              }
 898  
 899              // The el argument can be a string
 900              if (typeof el == "string") {
 901  
 902                  // el = (compat) ? Y.DOM.byId(el) : Y.all(el);
 903                  if (compat) {
 904                      el = Y.DOM.byId(el);
 905                  } else {
 906                      el = Y.Selector.query(el);
 907                      l = el.length;
 908                      if (l < 1) {
 909                          el = null;
 910                      } else if (l == 1) {
 911                          el = el[0];
 912                      }
 913                  }
 914                  // return Event.detach.apply(Event, args);
 915              }
 916  
 917              if (!el) {
 918                  return false;
 919              }
 920  
 921              if (el.detach) {
 922                  args.splice(2, 1);
 923                  return el.detach.apply(el, args);
 924              // The el argument can be an array of elements or element ids.
 925              } else if (shouldIterate(el)) {
 926                  ok = true;
 927                  for (i=0, l=el.length; i<l; ++i) {
 928                      args[2] = el[i];
 929                      ok = ( Y.Event.detach.apply(Y.Event, args) && ok );
 930                  }
 931  
 932                  return ok;
 933              }
 934  
 935              if (!type || !fn || !fn.call) {
 936                  return Event.purgeElement(el, false, type);
 937              }
 938  
 939              id = 'event:' + Y.stamp(el) + type;
 940              ce = _wrappers[id];
 941  
 942              if (ce) {
 943                  return ce.detach(fn);
 944              } else {
 945                  return false;
 946              }
 947  
 948          },
 949  
 950          /**
 951           * Finds the event in the window object, the caller's arguments, or
 952           * in the arguments of another method in the callstack.  This is
 953           * executed automatically for events registered through the event
 954           * manager, so the implementer should not normally need to execute
 955           * this function at all.
 956           * @method getEvent
 957           * @param {Event} e the event parameter from the handler
 958           * @param {HTMLElement} el the element the listener was attached to
 959           * @return {Event} the event
 960           * @static
 961           */
 962          getEvent: function(e, el, noFacade) {
 963              var ev = e || win.event;
 964  
 965              return (noFacade) ? ev :
 966                  new Y.DOMEventFacade(ev, el, _wrappers['event:' + Y.stamp(el) + e.type]);
 967          },
 968  
 969          /**
 970           * Generates an unique ID for the element if it does not already
 971           * have one.
 972           * @method generateId
 973           * @param el the element to create the id for
 974           * @return {string} the resulting id of the element
 975           * @static
 976           */
 977          generateId: function(el) {
 978              return Y.DOM.generateID(el);
 979          },
 980  
 981          /**
 982           * We want to be able to use getElementsByTagName as a collection
 983           * to attach a group of events to.  Unfortunately, different
 984           * browsers return different types of collections.  This function
 985           * tests to determine if the object is array-like.  It will also
 986           * fail if the object is an array, but is empty.
 987           * @method _isValidCollection
 988           * @param o the object to test
 989           * @return {boolean} true if the object is array-like and populated
 990           * @deprecated was not meant to be used directly
 991           * @static
 992           * @private
 993           */
 994          _isValidCollection: shouldIterate,
 995  
 996          /**
 997           * hook up any deferred listeners
 998           * @method _load
 999           * @static
1000           * @private
1001           */
1002          _load: function(e) {
1003              if (!_loadComplete) {
1004                  _loadComplete = true;
1005  
1006                  // Just in case DOMReady did not go off for some reason
1007                  // E._ready();
1008                  if (Y.fire) {
1009                      Y.fire(EVENT_READY);
1010                  }
1011  
1012                  // Available elements may not have been detected before the
1013                  // window load event fires. Try to find them now so that the
1014                  // the user is more likely to get the onAvailable notifications
1015                  // before the window load notification
1016                  Event._poll();
1017              }
1018          },
1019  
1020          /**
1021           * Polling function that runs before the onload event fires,
1022           * attempting to attach to DOM Nodes as soon as they are
1023           * available
1024           * @method _poll
1025           * @static
1026           * @private
1027           */
1028          _poll: function() {
1029              if (Event.locked) {
1030                  return;
1031              }
1032  
1033              if (Y.UA.ie && !YUI.Env.DOMReady) {
1034                  // Hold off if DOMReady has not fired and check current
1035                  // readyState to protect against the IE operation aborted
1036                  // issue.
1037                  Event.startInterval();
1038                  return;
1039              }
1040  
1041              Event.locked = true;
1042  
1043              // keep trying until after the page is loaded.  We need to
1044              // check the page load state prior to trying to bind the
1045              // elements so that we can be certain all elements have been
1046              // tested appropriately
1047              var i, len, item, el, notAvail, executeItem,
1048                  tryAgain = !_loadComplete;
1049  
1050              if (!tryAgain) {
1051                  tryAgain = (_retryCount > 0);
1052              }
1053  
1054              // onAvailable
1055              notAvail = [];
1056  
1057              executeItem = function (el, item) {
1058                  var context, ov = item.override;
1059                  try {
1060                      if (item.compat) {
1061                          if (item.override) {
1062                              if (ov === true) {
1063                                  context = item.obj;
1064                              } else {
1065                                  context = ov;
1066                              }
1067                          } else {
1068                              context = el;
1069                          }
1070                          item.fn.call(context, item.obj);
1071                      } else {
1072                          context = item.obj || Y.one(el);
1073                          item.fn.apply(context, (Y.Lang.isArray(ov)) ? ov : []);
1074                      }
1075                  } catch (e) {
1076                      Y.log("Error in available or contentReady callback", 'error', 'event');
1077                  }
1078              };
1079  
1080              // onAvailable
1081              for (i=0,len=_avail.length; i<len; ++i) {
1082                  item = _avail[i];
1083                  if (item && !item.checkReady) {
1084  
1085                      // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
1086                      el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
1087  
1088                      if (el) {
1089                          executeItem(el, item);
1090                          _avail[i] = null;
1091                      } else {
1092                          notAvail.push(item);
1093                      }
1094                  }
1095              }
1096  
1097              // onContentReady
1098              for (i=0,len=_avail.length; i<len; ++i) {
1099                  item = _avail[i];
1100                  if (item && item.checkReady) {
1101  
1102                      // el = (item.compat) ? Y.DOM.byId(item.id) : Y.one(item.id);
1103                      el = (item.compat) ? Y.DOM.byId(item.id) : Y.Selector.query(item.id, null, true);
1104  
1105                      if (el) {
1106                          // The element is available, but not necessarily ready
1107                          // @todo should we test parentNode.nextSibling?
1108                          if (_loadComplete || (el.get && el.get('nextSibling')) || el.nextSibling) {
1109                              executeItem(el, item);
1110                              _avail[i] = null;
1111                          }
1112                      } else {
1113                          notAvail.push(item);
1114                      }
1115                  }
1116              }
1117  
1118              _retryCount = (notAvail.length === 0) ? 0 : _retryCount - 1;
1119  
1120              if (tryAgain) {
1121                  // we may need to strip the nulled out items here
1122                  Event.startInterval();
1123              } else {
1124                  clearInterval(Event._interval);
1125                  Event._interval = null;
1126              }
1127  
1128              Event.locked = false;
1129  
1130              return;
1131  
1132          },
1133  
1134          /**
1135           * Removes all listeners attached to the given element via addListener.
1136           * Optionally, the node's children can also be purged.
1137           * Optionally, you can specify a specific type of event to remove.
1138           * @method purgeElement
1139           * @param {HTMLElement} el the element to purge
1140           * @param {boolean} recurse recursively purge this element's children
1141           * as well.  Use with caution.
1142           * @param {string} type optional type of listener to purge. If
1143           * left out, all listeners will be removed
1144           * @static
1145           */
1146          purgeElement: function(el, recurse, type) {
1147              // var oEl = (Y.Lang.isString(el)) ? Y.one(el) : el,
1148              var oEl = (Y.Lang.isString(el)) ?  Y.Selector.query(el, null, true) : el,
1149                  lis = Event.getListeners(oEl, type), i, len, children, child;
1150  
1151              if (recurse && oEl) {
1152                  lis = lis || [];
1153                  children = Y.Selector.query('*', oEl);
1154                  len = children.length;
1155                  for (i = 0; i < len; ++i) {
1156                      child = Event.getListeners(children[i], type);
1157                      if (child) {
1158                          lis = lis.concat(child);
1159                      }
1160                  }
1161              }
1162  
1163              if (lis) {
1164                  for (i = 0, len = lis.length; i < len; ++i) {
1165                      lis[i].detachAll();
1166                  }
1167              }
1168  
1169          },
1170  
1171          /**
1172           * Removes all object references and the DOM proxy subscription for
1173           * a given event for a DOM node.
1174           *
1175           * @method _clean
1176           * @param wrapper {CustomEvent} Custom event proxy for the DOM
1177           *                  subscription
1178           * @private
1179           * @static
1180           * @since 3.4.0
1181           */
1182          _clean: function (wrapper) {
1183              var key    = wrapper.key,
1184                  domkey = wrapper.domkey;
1185  
1186              remove(wrapper.el, wrapper.type, wrapper.fn, wrapper.capture);
1187              delete _wrappers[key];
1188              delete Y._yuievt.events[key];
1189              if (_el_events[domkey]) {
1190                  delete _el_events[domkey][key];
1191                  if (!Y.Object.size(_el_events[domkey])) {
1192                      delete _el_events[domkey];
1193                  }
1194              }
1195          },
1196  
1197          /**
1198           * Returns all listeners attached to the given element via addListener.
1199           * Optionally, you can specify a specific type of event to return.
1200           * @method getListeners
1201           * @param el {HTMLElement|string} the element or element id to inspect
1202           * @param type {string} optional type of listener to return. If
1203           * left out, all listeners will be returned
1204           * @return {CustomEvent} the custom event wrapper for the DOM event(s)
1205           * @static
1206           */
1207          getListeners: function(el, type) {
1208              var ek = Y.stamp(el, true), evts = _el_events[ek],
1209                  results=[] , key = (type) ? 'event:' + ek + type : null,
1210                  adapters = _eventenv.plugins;
1211  
1212              if (!evts) {
1213                  return null;
1214              }
1215  
1216              if (key) {
1217                  // look for synthetic events
1218                  if (adapters[type] && adapters[type].eventDef) {
1219                      key += '_synth';
1220                  }
1221  
1222                  if (evts[key]) {
1223                      results.push(evts[key]);
1224                  }
1225  
1226                  // get native events as well
1227                  key += 'native';
1228                  if (evts[key]) {
1229                      results.push(evts[key]);
1230                  }
1231  
1232              } else {
1233                  Y.each(evts, function(v, k) {
1234                      results.push(v);
1235                  });
1236              }
1237  
1238              return (results.length) ? results : null;
1239          },
1240  
1241          /**
1242           * Removes all listeners registered by pe.event.  Called
1243           * automatically during the unload event.
1244           * @method _unload
1245           * @static
1246           * @private
1247           */
1248          _unload: function(e) {
1249              Y.each(_wrappers, function(v, k) {
1250                  if (v.type == 'unload') {
1251                      v.fire(e);
1252                  }
1253                  v.detachAll();
1254              });
1255              remove(win, "unload", onUnload);
1256          },
1257  
1258          /**
1259           * Adds a DOM event directly without the caching, cleanup, context adj, etc
1260           *
1261           * @method nativeAdd
1262           * @param {HTMLElement} el      the element to bind the handler to
1263           * @param {string}      type   the type of event handler
1264           * @param {function}    fn      the callback to invoke
1265           * @param {Boolean}      capture capture or bubble phase
1266           * @static
1267           * @private
1268           */
1269          nativeAdd: add,
1270  
1271          /**
1272           * Basic remove listener
1273           *
1274           * @method nativeRemove
1275           * @param {HTMLElement} el      the element to bind the handler to
1276           * @param {string}      type   the type of event handler
1277           * @param {function}    fn      the callback to invoke
1278           * @param {Boolean}      capture capture or bubble phase
1279           * @static
1280           * @private
1281           */
1282          nativeRemove: remove
1283      };
1284  
1285  }();
1286  
1287  Y.Event = Event;
1288  
1289  if (config.injected || YUI.Env.windowLoaded) {
1290      onLoad();
1291  } else {
1292      add(win, "load", onLoad);
1293  }
1294  
1295  // Process onAvailable/onContentReady items when when the DOM is ready in IE
1296  if (Y.UA.ie) {
1297      Y.on(EVENT_READY, Event._poll);
1298  
1299      // In IE6 and below, detach event handlers when the page is unloaded in
1300      // order to try and prevent cross-page memory leaks. This isn't done in
1301      // other browsers because a) it's not necessary, and b) it breaks the
1302      // back/forward cache.
1303      if (Y.UA.ie < 7) {
1304          try {
1305              add(win, "unload", onUnload);
1306          } catch(e) {
1307              Y.log("Registering unload listener failed.", "warn", "event-base");
1308          }
1309      }
1310  }
1311  
1312  Event.Custom = Y.CustomEvent;
1313  Event.Subscriber = Y.Subscriber;
1314  Event.Target = Y.EventTarget;
1315  Event.Handle = Y.EventHandle;
1316  Event.Facade = Y.EventFacade;
1317  
1318  Event._poll();
1319  
1320  }());
1321  
1322  /**
1323   * DOM event listener abstraction layer
1324   * @module event
1325   * @submodule event-base
1326   */
1327  
1328  /**
1329   * Executes the callback as soon as the specified element
1330   * is detected in the DOM.  This function expects a selector
1331   * string for the element(s) to detect.  If you already have
1332   * an element reference, you don't need this event.
1333   * @event available
1334   * @param type {string} 'available'
1335   * @param fn {function} the callback function to execute.
1336   * @param el {string} an selector for the element(s) to attach
1337   * @param context optional argument that specifies what 'this' refers to.
1338   * @param args* 0..n additional arguments to pass on to the callback function.
1339   * These arguments will be added after the event object.
1340   * @return {EventHandle} the detach handle
1341   * @for YUI
1342   */
1343  Y.Env.evt.plugins.available = {
1344      on: function(type, fn, id, o) {
1345          var a = arguments.length > 4 ?  Y.Array(arguments, 4, true) : null;
1346          return Y.Event.onAvailable.call(Y.Event, id, fn, o, a);
1347      }
1348  };
1349  
1350  /**
1351   * Executes the callback as soon as the specified element
1352   * is detected in the DOM with a nextSibling property
1353   * (indicating that the element's children are available).
1354   * This function expects a selector
1355   * string for the element(s) to detect.  If you already have
1356   * an element reference, you don't need this event.
1357   * @event contentready
1358   * @param type {string} 'contentready'
1359   * @param fn {function} the callback function to execute.
1360   * @param el {string} an selector for the element(s) to attach.
1361   * @param context optional argument that specifies what 'this' refers to.
1362   * @param args* 0..n additional arguments to pass on to the callback function.
1363   * These arguments will be added after the event object.
1364   * @return {EventHandle} the detach handle
1365   * @for YUI
1366   */
1367  Y.Env.evt.plugins.contentready = {
1368      on: function(type, fn, id, o) {
1369          var a = arguments.length > 4 ? Y.Array(arguments, 4, true) : null;
1370          return Y.Event.onContentReady.call(Y.Event, id, fn, o, a);
1371      }
1372  };
1373  
1374  
1375  }, '3.17.2', {"requires": ["event-custom-base"]});


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1