| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- Copyright (c) 2010, Yahoo! Inc. All rights reserved.
- Code licensed under the BSD License:
- http://developer.yahoo.com/yui/license.html
- version: 3.4.0
- build: nightly
- */
- YUI.add('event-focus', function(Y) {
-
- /**
- * 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,
- useActivate = YLang.isFunction(
- Y.DOM.create('<p onbeforeactivate=";"/>').onbeforeactivate);
-
- function define(type, proxy, directEvent) {
- var nodeDataKey = '_' + type + 'Notifiers';
-
- Y.Event.define(type, {
-
- _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 node = e.target,
- notifiers = node.getData(nodeDataKey),
- yuid = Y.stamp(e.currentTarget._node),
- defer = (useActivate || e.target !== e.currentTarget),
- sub = notifier.handle.sub,
- filterArgs = [node, e].concat(sub.args || []),
- directSub;
-
- notifier.currentTarget = (delegate) ? node : e.currentTarget;
- notifier.container = (delegate) ? e.currentTarget : null;
-
- if (!sub.filter || sub.filter.apply(node, filterArgs)) {
- // 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 = {};
- node.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, node._node]).sub;
- directSub.once = true;
- }
- }
-
- if (!notifiers[yuid]) {
- notifiers[yuid] = [];
- }
-
- notifiers[yuid].push(notifier);
-
- if (!defer) {
- this._notify(e);
- }
- }
- },
-
- _notify: function (e, container) {
- var node = e.currentTarget,
- notifiers = node.getData(nodeDataKey),
- // document.get('ownerDocument') returns null
- doc = node.get('ownerDocument') || node,
- target = node,
- nots = [],
- notifier, i, len;
-
- if (notifiers) {
- // Walk up the parent axis until the origin node,
- while (target && target !== doc) {
- nots.push.apply(nots, notifiers[Y.stamp(target)] || []);
- target = target.get('parentNode');
- }
- nots.push.apply(nots, notifiers[Y.stamp(doc)] || []);
-
- for (i = 0, len = nots.length; i < len; ++i) {
- notifier = nots[i];
- e.currentTarget = nots[i].currentTarget;
-
- if (notifier.container) {
- e.container = notifier.container;
- }
-
- notifier.fire(e);
- }
-
- // clear the notifications list (mainly for delegation)
- node.clearData(nodeDataKey);
- }
- },
-
- on: function (node, sub, notifier) {
- sub.onHandle = this._attach(node._node, notifier);
- },
-
- detach: function (node, sub) {
- sub.onHandle.detach();
- },
-
- delegate: function (node, sub, notifier, filter) {
- if (isString(filter)) {
- sub.filter = Y.delegate.compileFilter(filter);
- }
-
- sub.delegateHandle = this._attach(node._node, notifier, true);
- },
-
- detachDelegate: function (node, sub) {
- sub.delegateHandle.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");
- }
-
-
-
- }, '3.4.0' ,{requires:['event-synthetic']});
|