]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/javascript/yui3/build/event/event-focus.js
Release 6.5.0
[Github/sugarcrm.git] / jssource / src_files / include / javascript / yui3 / build / event / event-focus.js
1 /*
2 Copyright (c) 2010, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.com/yui/license.html
5 version: 3.3.0
6 build: 3167
7 */
8 YUI.add('event-focus', function(Y) {
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     YLang    = Y.Lang,
18     isString = YLang.isString,
19     useActivate = YLang.isFunction(
20         Y.DOM.create('<p onbeforeactivate=";"/>').onbeforeactivate);
21
22 function define(type, proxy, directEvent) {
23     var nodeDataKey = '_' + type + 'Notifiers';
24
25     Y.Event.define(type, {
26
27         _attach: function (el, notifier, delegate) {
28             if (Y.DOM.isWindow(el)) {
29                 return Event._attach([type, function (e) {
30                     notifier.fire(e);
31                 }, el]);
32             } else {
33                 return Event._attach(
34                     [proxy, this._proxy, el, this, notifier, delegate],
35                     { capture: true });
36             }
37         },
38
39         _proxy: function (e, notifier, delegate) {
40             var node       = e.target,
41                 notifiers  = node.getData(nodeDataKey),
42                 yuid       = Y.stamp(e.currentTarget._node),
43                 defer      = (useActivate || e.target !== e.currentTarget),
44                 sub        = notifier.handle.sub,
45                 filterArgs = [node, e].concat(sub.args || []),
46                 directSub;
47                 
48             notifier.currentTarget = (delegate) ? node : e.currentTarget;
49             notifier.container     = (delegate) ? e.currentTarget : null;
50
51             if (!sub.filter || sub.filter.apply(node, filterArgs)) {
52                 // Maintain a list to handle subscriptions from nested
53                 // containers div#a>div#b>input #a.on(focus..) #b.on(focus..),
54                 // use one focus or blur subscription that fires notifiers from
55                 // #b then #a to emulate bubble sequence.
56                 if (!notifiers) {
57                     notifiers = {};
58                     node.setData(nodeDataKey, notifiers);
59
60                     // only subscribe to the element's focus if the target is
61                     // not the current target (
62                     if (defer) {
63                         directSub = Event._attach(
64                             [directEvent, this._notify, node._node]).sub;
65                         directSub.once = true;
66                     }
67                 }
68
69                 if (!notifiers[yuid]) {
70                     notifiers[yuid] = [];
71                 }
72
73                 notifiers[yuid].push(notifier);
74
75                 if (!defer) {
76                     this._notify(e);
77                 }
78             }
79         },
80
81         _notify: function (e, container) {
82             var node        = e.currentTarget,
83                 notifiers   = node.getData(nodeDataKey),
84                               // document.get('ownerDocument') returns null
85                 doc         = node.get('ownerDocument') || node,
86                 target      = node,
87                 nots        = [],
88                 notifier, i, len;
89
90             if (notifiers) {
91                 // Walk up the parent axis until the origin node, 
92                 while (target && target !== doc) {
93                     nots.push.apply(nots, notifiers[Y.stamp(target)] || []);
94                     target = target.get('parentNode');
95                 }
96                 nots.push.apply(nots, notifiers[Y.stamp(doc)] || []);
97
98                 for (i = 0, len = nots.length; i < len; ++i) {
99                     notifier = nots[i];
100                     e.currentTarget = nots[i].currentTarget;
101
102                     if (notifier.container) {
103                         e.container = notifier.container;
104                     } else {
105                         delete e.container;
106                     }
107
108                     notifier.fire(e);
109                 }
110
111                 // clear the notifications list (mainly for delegation)
112                 node.clearData(nodeDataKey);
113             }
114         },
115
116         on: function (node, sub, notifier) {
117             sub.onHandle = this._attach(node._node, notifier);
118         },
119
120         detach: function (node, sub) {
121             sub.onHandle.detach();
122         },
123
124         delegate: function (node, sub, notifier, filter) {
125             if (isString(filter)) {
126                 sub.filter = Y.delegate.compileFilter(filter);
127             }
128
129             sub.delegateHandle = this._attach(node._node, notifier, true);
130         },
131
132         detachDelegate: function (node, sub) {
133             sub.delegateHandle.detach();
134         }
135     }, true);
136 }
137
138 // For IE, we need to defer to focusin rather than focus because
139 // `el.focus(); doSomething();` executes el.onbeforeactivate, el.onactivate,
140 // el.onfocusin, doSomething, then el.onfocus.  All others support capture
141 // phase focus, which executes before doSomething.  To guarantee consistent
142 // behavior for this use case, IE's direct subscriptions are made against
143 // focusin so subscribers will be notified before js following el.focus() is
144 // executed.
145 if (useActivate) {
146     //     name     capture phase       direct subscription
147     define("focus", "beforeactivate",   "focusin");
148     define("blur",  "beforedeactivate", "focusout");
149 } else {
150     define("focus", "focus", "focus");
151     define("blur",  "blur",  "blur");
152 }
153
154
155 }, '3.3.0' ,{requires:['event-synthetic']});