Version 3.17.2

APIs

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

File: event/js/focusblur.js

/**
 * Adds bubbling and delegation support to DOM events focus and blur.
 *
 * @module event
 * @submodule event-focus
 */
var Event = Y.Event,
 YLang = Y.Lang,
 isString = YLang.isString,
 arrayIndex = Y.Array.indexOf,
 useActivate = (function() {
 // Changing the structure of this test, so that it doesn't use inline JS in HTML,
 // which throws an exception in Win8 packaged apps, due to additional security restrictions:
 // http://msdn.microsoft.com/en-us/library/windows/apps/hh465380.aspx#differences
 var supported = false,
 doc = Y.config.doc,
 p;
 if (doc) {
 p = doc.createElement("p");
 p.setAttribute("onbeforeactivate", ";");
 // onbeforeactivate is a function in IE8+.
 // onbeforeactivate is a string in IE6,7 (unfortunate, otherwise we could have just checked for function below).
 // onbeforeactivate is a function in IE10, in a Win8 App environment (no exception running the test).
 // onbeforeactivate is undefined in Webkit/Gecko.
 // onbeforeactivate is a function in Webkit/Gecko if it's a supported event (e.g. onclick).
 supported = (p.onbeforeactivate !== undefined);
 }
 return supported;
 }());
function define(type, proxy, directEvent) {
 var nodeDataKey = '_' + type + 'Notifiers';
 Y.Event.define(type, {
 _useActivate : useActivate,
 _attach: function (el, notifier, delegate) {
 if (Y.DOM.isWindow(el)) {
 return Event._attach([type, function (e) {
 notifier.fire(e);
 }, el]);
 } else {
 return Event._attach(
 [proxy, this._proxy, el, this, notifier, delegate],
 { capture: true });
 }
 },
 _proxy: function (e, notifier, delegate) {
 var target = e.target,
 currentTarget = e.currentTarget,
 notifiers = target.getData(nodeDataKey),
 yuid = Y.stamp(currentTarget._node),
 defer = (useActivate || target !== currentTarget),
 directSub;
 notifier.currentTarget = (delegate) ? target : currentTarget;
 notifier.container = (delegate) ? currentTarget : null;
 // Maintain a list to handle subscriptions from nested
 // containers div#a>div#b>input #a.on(focus..) #b.on(focus..),
 // use one focus or blur subscription that fires notifiers from
 // #b then #a to emulate bubble sequence.
 if (!notifiers) {
 notifiers = {};
 target.setData(nodeDataKey, notifiers);
 // only subscribe to the element's focus if the target is
 // not the current target (
 if (defer) {
 directSub = Event._attach(
 [directEvent, this._notify, target._node]).sub;
 directSub.once = true;
 }
 } else {
 // In old IE, defer is always true. In capture-phase browsers,
 // The delegate subscriptions will be encountered first, which
 // will establish the notifiers data and direct subscription
 // on the node. If there is also a direct subscription to the
 // node's focus/blur, it should not call _notify because the
 // direct subscription from the delegate sub(s) exists, which
 // will call _notify. So this avoids _notify being called
 // twice, unnecessarily.
 defer = true;
 }
 if (!notifiers[yuid]) {
 notifiers[yuid] = [];
 }
 notifiers[yuid].push(notifier);
 if (!defer) {
 this._notify(e);
 }
 },
 _notify: function (e, container) {
 var currentTarget = e.currentTarget,
 notifierData = currentTarget.getData(nodeDataKey),
 axisNodes = currentTarget.ancestors(),
 doc = currentTarget.get('ownerDocument'),
 delegates = [],
 // Used to escape loops when there are no more
 // notifiers to consider
 count = notifierData ?
 Y.Object.keys(notifierData).length :
 0,
 target, notifiers, notifier, yuid, match, tmp, i, len, sub, ret;
 // clear the notifications list (mainly for delegation)
 currentTarget.clearData(nodeDataKey);
 // Order the delegate subs by their placement in the parent axis
 axisNodes.push(currentTarget);
 // document.get('ownerDocument') returns null
 // which we'll use to prevent having duplicate Nodes in the list
 if (doc) {
 axisNodes.unshift(doc);
 }
 // ancestors() returns the Nodes from top to bottom
 axisNodes._nodes.reverse();
 if (count) {
 // Store the count for step 2
 tmp = count;
 axisNodes.some(function (node) {
 var yuid = Y.stamp(node),
 notifiers = notifierData[yuid],
 i, len;
 if (notifiers) {
 count--;
 for (i = 0, len = notifiers.length; i < len; ++i) {
 if (notifiers[i].handle.sub.filter) {
 delegates.push(notifiers[i]);
 }
 }
 }
 return !count;
 });
 count = tmp;
 }
 // Walk up the parent axis, notifying direct subscriptions and
 // testing delegate filters.
 while (count && (target = axisNodes.shift())) {
 yuid = Y.stamp(target);
 notifiers = notifierData[yuid];
 if (notifiers) {
 for (i = 0, len = notifiers.length; i < len; ++i) {
 notifier = notifiers[i];
 sub = notifier.handle.sub;
 match = true;
 e.currentTarget = target;
 if (sub.filter) {
 match = sub.filter.apply(target,
 [target, e].concat(sub.args || []));
 // No longer necessary to test against this
 // delegate subscription for the nodes along
 // the parent axis.
 delegates.splice(
 arrayIndex(delegates, notifier), 1);
 }
 if (match) {
 // undefined for direct subs
 e.container = notifier.container;
 ret = notifier.fire(e);
 }
 if (ret === false || e.stopped === 2) {
 break;
 }
 }
 delete notifiers[yuid];
 count--;
 }
 if (e.stopped !== 2) {
 // delegates come after subs targeting this specific node
 // because they would not normally report until they'd
 // bubbled to the container node.
 for (i = 0, len = delegates.length; i < len; ++i) {
 notifier = delegates[i];
 sub = notifier.handle.sub;
 if (sub.filter.apply(target,
 [target, e].concat(sub.args || []))) {
 e.container = notifier.container;
 e.currentTarget = target;
 ret = notifier.fire(e);
 }
 if (ret === false || e.stopped === 2 ||
 // If e.stopPropagation() is called, notify any
 // delegate subs from the same container, but break
 // once the container changes. This emulates
 // delegate() behavior for events like 'click' which
 // won't notify delegates higher up the parent axis.
 (e.stopped && delegates[i+1] &&
 delegates[i+1].container !== notifier.container)) {
 break;
 }
 }
 }
 if (e.stopped) {
 break;
 }
 }
 },
 on: function (node, sub, notifier) {
 sub.handle = this._attach(node._node, notifier);
 },
 detach: function (node, sub) {
 sub.handle.detach();
 },
 delegate: function (node, sub, notifier, filter) {
 if (isString(filter)) {
 sub.filter = function (target) {
 return Y.Selector.test(target._node, filter,
 node === target ? null : node._node);
 };
 }
 sub.handle = this._attach(node._node, notifier, true);
 },
 detachDelegate: function (node, sub) {
 sub.handle.detach();
 }
 }, true);
}
// For IE, we need to defer to focusin rather than focus because
// `el.focus(); doSomething();` executes el.onbeforeactivate, el.onactivate,
// el.onfocusin, doSomething, then el.onfocus. All others support capture
// phase focus, which executes before doSomething. To guarantee consistent
// behavior for this use case, IE's direct subscriptions are made against
// focusin so subscribers will be notified before js following el.focus() is
// executed.
if (useActivate) {
 // name capture phase direct subscription
 define("focus", "beforeactivate", "focusin");
 define("blur", "beforedeactivate", "focusout");
} else {
 define("focus", "focus", "focus");
 define("blur", "blur", "blur");
}
 

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