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