src/cm/media/js/lib/yui/yui3-3.15.0/build/event-focus/event-focus-debug.js
changeset 602 e16a97fb364a
equal deleted inserted replaced
601:d334a616c023 602:e16a97fb364a
       
     1 YUI.add('event-focus', function (Y, NAME) {
       
     2 
       
     3 /**
       
     4  * Adds bubbling and delegation support to DOM events focus and blur.
       
     5  *
       
     6  * @module event
       
     7  * @submodule event-focus
       
     8  */
       
     9 var Event    = Y.Event,
       
    10 
       
    11     YLang    = Y.Lang,
       
    12 
       
    13     isString = YLang.isString,
       
    14 
       
    15     arrayIndex = Y.Array.indexOf,
       
    16 
       
    17     useActivate = (function() {
       
    18 
       
    19         // Changing the structure of this test, so that it doesn't use inline JS in HTML,
       
    20         // which throws an exception in Win8 packaged apps, due to additional security restrictions:
       
    21         // http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx#differences
       
    22 
       
    23         var supported = false,
       
    24             doc = Y.config.doc,
       
    25             p;
       
    26 
       
    27         if (doc) {
       
    28 
       
    29             p = doc.createElement("p");
       
    30             p.setAttribute("onbeforeactivate", ";");
       
    31 
       
    32             // onbeforeactivate is a function in IE8+.
       
    33             // onbeforeactivate is a string in IE6,7 (unfortunate, otherwise we could have just checked for function below).
       
    34             // onbeforeactivate is a function in IE10, in a Win8 App environment (no exception running the test).
       
    35 
       
    36             // onbeforeactivate is undefined in Webkit/Gecko.
       
    37             // onbeforeactivate is a function in Webkit/Gecko if it's a supported event (e.g. onclick).
       
    38 
       
    39             supported = (p.onbeforeactivate !== undefined);
       
    40         }
       
    41 
       
    42         return supported;
       
    43     }());
       
    44 
       
    45 function define(type, proxy, directEvent) {
       
    46     var nodeDataKey = '_' + type + 'Notifiers';
       
    47 
       
    48     Y.Event.define(type, {
       
    49 
       
    50         _useActivate : useActivate,
       
    51 
       
    52         _attach: function (el, notifier, delegate) {
       
    53             if (Y.DOM.isWindow(el)) {
       
    54                 return Event._attach([type, function (e) {
       
    55                     notifier.fire(e);
       
    56                 }, el]);
       
    57             } else {
       
    58                 return Event._attach(
       
    59                     [proxy, this._proxy, el, this, notifier, delegate],
       
    60                     { capture: true });
       
    61             }
       
    62         },
       
    63 
       
    64         _proxy: function (e, notifier, delegate) {
       
    65             var target        = e.target,
       
    66                 currentTarget = e.currentTarget,
       
    67                 notifiers     = target.getData(nodeDataKey),
       
    68                 yuid          = Y.stamp(currentTarget._node),
       
    69                 defer         = (useActivate || target !== currentTarget),
       
    70                 directSub;
       
    71 
       
    72             notifier.currentTarget = (delegate) ? target : currentTarget;
       
    73             notifier.container     = (delegate) ? currentTarget : null;
       
    74 
       
    75             // Maintain a list to handle subscriptions from nested
       
    76             // containers div#a>div#b>input #a.on(focus..) #b.on(focus..),
       
    77             // use one focus or blur subscription that fires notifiers from
       
    78             // #b then #a to emulate bubble sequence.
       
    79             if (!notifiers) {
       
    80                 notifiers = {};
       
    81                 target.setData(nodeDataKey, notifiers);
       
    82 
       
    83                 // only subscribe to the element's focus if the target is
       
    84                 // not the current target (
       
    85                 if (defer) {
       
    86                     directSub = Event._attach(
       
    87                         [directEvent, this._notify, target._node]).sub;
       
    88                     directSub.once = true;
       
    89                 }
       
    90             } else {
       
    91                 // In old IE, defer is always true.  In capture-phase browsers,
       
    92                 // The delegate subscriptions will be encountered first, which
       
    93                 // will establish the notifiers data and direct subscription
       
    94                 // on the node.  If there is also a direct subscription to the
       
    95                 // node's focus/blur, it should not call _notify because the
       
    96                 // direct subscription from the delegate sub(s) exists, which
       
    97                 // will call _notify.  So this avoids _notify being called
       
    98                 // twice, unnecessarily.
       
    99                 defer = true;
       
   100             }
       
   101 
       
   102             if (!notifiers[yuid]) {
       
   103                 notifiers[yuid] = [];
       
   104             }
       
   105 
       
   106             notifiers[yuid].push(notifier);
       
   107 
       
   108             if (!defer) {
       
   109                 this._notify(e);
       
   110             }
       
   111         },
       
   112 
       
   113         _notify: function (e, container) {
       
   114             var currentTarget = e.currentTarget,
       
   115                 notifierData  = currentTarget.getData(nodeDataKey),
       
   116                 axisNodes     = currentTarget.ancestors(),
       
   117                 doc           = currentTarget.get('ownerDocument'),
       
   118                 delegates     = [],
       
   119                                 // Used to escape loops when there are no more
       
   120                                 // notifiers to consider
       
   121                 count         = notifierData ?
       
   122                                     Y.Object.keys(notifierData).length :
       
   123                                     0,
       
   124                 target, notifiers, notifier, yuid, match, tmp, i, len, sub, ret;
       
   125 
       
   126             // clear the notifications list (mainly for delegation)
       
   127             currentTarget.clearData(nodeDataKey);
       
   128 
       
   129             // Order the delegate subs by their placement in the parent axis
       
   130             axisNodes.push(currentTarget);
       
   131             // document.get('ownerDocument') returns null
       
   132             // which we'll use to prevent having duplicate Nodes in the list
       
   133             if (doc) {
       
   134                 axisNodes.unshift(doc);
       
   135             }
       
   136 
       
   137             // ancestors() returns the Nodes from top to bottom
       
   138             axisNodes._nodes.reverse();
       
   139 
       
   140             if (count) {
       
   141                 // Store the count for step 2
       
   142                 tmp = count;
       
   143                 axisNodes.some(function (node) {
       
   144                     var yuid      = Y.stamp(node),
       
   145                         notifiers = notifierData[yuid],
       
   146                         i, len;
       
   147 
       
   148                     if (notifiers) {
       
   149                         count--;
       
   150                         for (i = 0, len = notifiers.length; i < len; ++i) {
       
   151                             if (notifiers[i].handle.sub.filter) {
       
   152                                 delegates.push(notifiers[i]);
       
   153                             }
       
   154                         }
       
   155                     }
       
   156 
       
   157                     return !count;
       
   158                 });
       
   159                 count = tmp;
       
   160             }
       
   161 
       
   162             // Walk up the parent axis, notifying direct subscriptions and
       
   163             // testing delegate filters.
       
   164             while (count && (target = axisNodes.shift())) {
       
   165                 yuid = Y.stamp(target);
       
   166 
       
   167                 notifiers = notifierData[yuid];
       
   168 
       
   169                 if (notifiers) {
       
   170                     for (i = 0, len = notifiers.length; i < len; ++i) {
       
   171                         notifier = notifiers[i];
       
   172                         sub      = notifier.handle.sub;
       
   173                         match    = true;
       
   174 
       
   175                         e.currentTarget = target;
       
   176 
       
   177                         if (sub.filter) {
       
   178                             match = sub.filter.apply(target,
       
   179                                 [target, e].concat(sub.args || []));
       
   180 
       
   181                             // No longer necessary to test against this
       
   182                             // delegate subscription for the nodes along
       
   183                             // the parent axis.
       
   184                             delegates.splice(
       
   185                                 arrayIndex(delegates, notifier), 1);
       
   186                         }
       
   187 
       
   188                         if (match) {
       
   189                             // undefined for direct subs
       
   190                             e.container = notifier.container;
       
   191                             ret = notifier.fire(e);
       
   192                         }
       
   193 
       
   194                         if (ret === false || e.stopped === 2) {
       
   195                             break;
       
   196                         }
       
   197                     }
       
   198 
       
   199                     delete notifiers[yuid];
       
   200                     count--;
       
   201                 }
       
   202 
       
   203                 if (e.stopped !== 2) {
       
   204                     // delegates come after subs targeting this specific node
       
   205                     // because they would not normally report until they'd
       
   206                     // bubbled to the container node.
       
   207                     for (i = 0, len = delegates.length; i < len; ++i) {
       
   208                         notifier = delegates[i];
       
   209                         sub = notifier.handle.sub;
       
   210 
       
   211                         if (sub.filter.apply(target,
       
   212                             [target, e].concat(sub.args || []))) {
       
   213 
       
   214                             e.container = notifier.container;
       
   215                             e.currentTarget = target;
       
   216                             ret = notifier.fire(e);
       
   217                         }
       
   218 
       
   219                         if (ret === false || e.stopped === 2 ||
       
   220                             // If e.stopPropagation() is called, notify any
       
   221                             // delegate subs from the same container, but break
       
   222                             // once the container changes. This emulates
       
   223                             // delegate() behavior for events like 'click' which
       
   224                             // won't notify delegates higher up the parent axis.
       
   225                             (e.stopped && delegates[i+1] &&
       
   226                              delegates[i+1].container !== notifier.container)) {
       
   227                             break;
       
   228                         }
       
   229                     }
       
   230                 }
       
   231 
       
   232                 if (e.stopped) {
       
   233                     break;
       
   234                 }
       
   235             }
       
   236         },
       
   237 
       
   238         on: function (node, sub, notifier) {
       
   239             sub.handle = this._attach(node._node, notifier);
       
   240         },
       
   241 
       
   242         detach: function (node, sub) {
       
   243             sub.handle.detach();
       
   244         },
       
   245 
       
   246         delegate: function (node, sub, notifier, filter) {
       
   247             if (isString(filter)) {
       
   248                 sub.filter = function (target) {
       
   249                     return Y.Selector.test(target._node, filter,
       
   250                         node === target ? null : node._node);
       
   251                 };
       
   252             }
       
   253 
       
   254             sub.handle = this._attach(node._node, notifier, true);
       
   255         },
       
   256 
       
   257         detachDelegate: function (node, sub) {
       
   258             sub.handle.detach();
       
   259         }
       
   260     }, true);
       
   261 }
       
   262 
       
   263 // For IE, we need to defer to focusin rather than focus because
       
   264 // `el.focus(); doSomething();` executes el.onbeforeactivate, el.onactivate,
       
   265 // el.onfocusin, doSomething, then el.onfocus.  All others support capture
       
   266 // phase focus, which executes before doSomething.  To guarantee consistent
       
   267 // behavior for this use case, IE's direct subscriptions are made against
       
   268 // focusin so subscribers will be notified before js following el.focus() is
       
   269 // executed.
       
   270 if (useActivate) {
       
   271     //     name     capture phase       direct subscription
       
   272     define("focus", "beforeactivate",   "focusin");
       
   273     define("blur",  "beforedeactivate", "focusout");
       
   274 } else {
       
   275     define("focus", "focus", "focus");
       
   276     define("blur",  "blur",  "blur");
       
   277 }
       
   278 
       
   279 
       
   280 }, '@VERSION@', {"requires": ["event-synthetic"]});