]>
git.wh0rd.org - tt-rss.git/blob - lib/dijit/_base/focus.js.uncompressed.js
1 define("dijit/_base/focus", [
2 "dojo/_base/array", // array.forEach
3 "dojo/dom", // dom.isDescendant
4 "dojo/_base/lang", // lang.isArray
5 "dojo/topic", // publish
6 "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
8 "../main" // for exporting symbols to dijit
9 ], function(array
, dom
, lang
, topic
, win
, focus
, dijit
){
16 // Deprecated module to monitor currently focused node and stack of currently focused widgets.
17 // New code should access dijit/focus directly.
20 // Currently focused item on screen
23 // _prevFocus: DomNode
24 // Previously focused item on screen
27 isCollapsed: function(){
29 // Returns true if there is no text selected
30 return dijit
.getBookmark().isCollapsed
;
33 getBookmark: function(){
35 // Retrieves a bookmark that can be used with moveToBookmark to return to the same range
36 var bm
, rg
, tg
, sel
= win
.doc
.selection
, cf
= focus
.curNode
;
38 if(win
.global
.getSelection
){
39 //W3C Range API for selections.
40 sel
= win
.global
.getSelection();
43 tg
= cf
? cf
.tagName
: "";
45 //Create a fake rangelike item to restore selections.
46 tg
= tg
.toLowerCase();
47 if(tg
== "textarea" ||
48 (tg
== "input" && (!cf
.type
|| cf
.type
.toLowerCase() == "text"))){
50 start
: cf
.selectionStart
,
55 return {isCollapsed
: (sel
.end
<= sel
.start
), mark
: sel
}; //Object.
58 bm
= {isCollapsed
:true};
60 bm
.mark
= sel
.getRangeAt(0).cloneRange();
63 rg
= sel
.getRangeAt(0);
64 bm
= {isCollapsed
: false, mark
: rg
.cloneRange()};
68 // If the current focus was a input of some sort and no selection, don't bother saving
69 // a native bookmark. This is because it causes issues with dialog/page selection restore.
70 // So, we need to create psuedo bookmarks to work with.
71 tg
= cf
? cf
.tagName
: "";
72 tg
= tg
.toLowerCase();
73 if(cf
&& tg
&& (tg
== "button" || tg
== "textarea" || tg
== "input")){
74 if(sel
.type
&& sel
.type
.toLowerCase() == "none"){
80 rg
= sel
.createRange();
82 isCollapsed
: rg
.text
&& rg
.text
.length
?false:true,
92 //'IE' way for selections.
94 // createRange() throws exception when dojo in iframe
95 //and nothing selected, see #9632
96 rg
= sel
.createRange();
97 bm
.isCollapsed
= !(sel
.type
== 'Text' ? rg
.htmlText
.length
: rg
.length
);
99 bm
.isCollapsed
= true;
102 if(sel
.type
.toUpperCase() == 'CONTROL'){
105 var i
=0,len
=rg
.length
;
107 bm
.mark
.push(rg
.item(i
++));
110 bm
.isCollapsed
= true;
114 bm
.mark
= rg
.getBookmark();
117 console
.warn("No idea how to store the current selection for this browser!");
122 moveToBookmark: function(/*Object*/ bookmark
){
124 // Moves current selection to a bookmark
126 // This should be a returned object from dijit.getBookmark()
129 mark
= bookmark
.mark
;
131 if(win
.global
.getSelection
){
132 //W3C Rangi API (FF, WebKit, Opera, etc)
133 var sel
= win
.global
.getSelection();
134 if(sel
&& sel
.removeAllRanges
){
137 n
.selectionStart
= mark
.start
;
138 n
.selectionEnd
= mark
.end
;
140 sel
.removeAllRanges();
144 console
.warn("No idea how to restore selection for this browser!");
146 }else if(_doc
.selection
&& mark
){
151 }else if(lang
.isArray(mark
)){
152 rg
= _doc
.body
.createControlRange();
153 //rg.addElement does not have call/apply method, so can not call it directly
154 //rg is not available in "range.addElement(item)", so can't use that either
155 array
.forEach(mark
, function(n
){
159 rg
= _doc
.body
.createTextRange();
160 rg
.moveToBookmark(mark
);
167 getFocus: function(/*Widget?*/ menu
, /*Window?*/ openedForWindow
){
169 // Called as getFocus(), this returns an Object showing the current focus
170 // and selected text.
172 // Called as getFocus(widget), where widget is a (widget representing) a button
173 // that was just pressed, it returns where focus was before that button
174 // was pressed. (Pressing the button may have either shifted focus to the button,
175 // or removed focus altogether.) In this case the selected text is not returned,
176 // since it can't be accurately determined.
178 // menu: dijit/_WidgetBase|{domNode: DomNode} structure
179 // The button that was just pressed. If focus has disappeared or moved
180 // to this button, returns the previous focus. In this case the bookmark
181 // information is already lost, and null is returned.
184 // iframe in which menu was opened
187 // A handle to restore focus/selection, to be passed to `dijit.focus`
188 var node
= !focus
.curNode
|| (menu
&& dom
.isDescendant(focus
.curNode
, menu
.domNode
)) ? dijit
._prevFocus
: focus
.curNode
;
191 bookmark
: node
&& (node
== focus
.curNode
) && win
.withGlobal(openedForWindow
|| win
.global
, dijit
.getBookmark
),
192 openedForWindow
: openedForWindow
196 // _activeStack: dijit/_WidgetBase[]
197 // List of currently active widgets (focused widget and it's ancestors)
200 registerIframe: function(/*DomNode*/ iframe
){
202 // Registers listeners on the specified iframe so that any click
203 // or focus event on that iframe (or anything in it) is reported
204 // as a focus/click event on the `<iframe>` itself.
206 // Currently only used by editor.
208 // Handle to pass to unregisterIframe()
209 return focus
.registerIframe(iframe
);
212 unregisterIframe: function(/*Object*/ handle
){
214 // Unregisters listeners on the specified iframe created by registerIframe.
215 // After calling be sure to delete or null out the handle itself.
217 // Handle returned by registerIframe()
219 handle
&& handle
.remove();
222 registerWin: function(/*Window?*/targetWindow
, /*DomNode?*/ effectiveNode
){
224 // Registers listeners on the specified window (either the main
225 // window or an iframe's window) to detect when the user has clicked somewhere
226 // or focused somewhere.
228 // Users should call registerIframe() instead of this method.
230 // If specified this is the window associated with the iframe,
231 // i.e. iframe.contentWindow.
233 // If specified, report any focus events inside targetWindow as
234 // an event on effectiveNode, rather than on evt.target.
236 // Handle to pass to unregisterWin()
238 return focus
.registerWin(targetWindow
, effectiveNode
);
241 unregisterWin: function(/*Handle*/ handle
){
243 // Unregisters listeners on the specified window (either the main
244 // window or an iframe's window) according to handle returned from registerWin().
245 // After calling be sure to delete or null out the handle itself.
247 handle
&& handle
.remove();
251 // Override focus singleton's focus function so that dijit.focus()
252 // has backwards compatible behavior of restoring selection (although
253 // probably no one is using that).
254 focus
.focus = function(/*Object|DomNode */ handle
){
256 // Sets the focused node and the selection according to argument.
257 // To set focus to an iframe's content, pass in the iframe itself.
259 // object returned by get(), or a DomNode
261 if(!handle
){ return; }
263 var node
= "node" in handle
? handle
.node
: handle
, // because handle is either DomNode or a composite object
264 bookmark
= handle
.bookmark
,
265 openedForWindow
= handle
.openedForWindow
,
266 collapsed
= bookmark
? bookmark
.isCollapsed
: false;
269 // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
270 // but we need to set focus to iframe.contentWindow
272 var focusNode
= (node
.tagName
.toLowerCase() == "iframe") ? node
.contentWindow
: node
;
273 if(focusNode
&& focusNode
.focus
){
275 // Gecko throws sometimes if setting focus is impossible,
276 // node not displayed or something like that
280 focus
._onFocusNode(node
);
284 // do not need to restore if current selection is not empty
285 // (use keyboard to select a menu item) or if previous selection was collapsed
286 // as it may cause focus shift (Esp in IE).
287 if(bookmark
&& win
.withGlobal(openedForWindow
|| win
.global
, dijit
.isCollapsed
) && !collapsed
){
289 openedForWindow
.focus();
292 win
.withGlobal(openedForWindow
|| win
.global
, dijit
.moveToBookmark
, null, [bookmark
]);
294 /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
299 // For back compatibility, monitor changes to focused node and active widget stack,
300 // publishing events and copying changes from focus manager variables into dijit (top level) variables
301 focus.watch("curNode", function(name, oldVal, newVal){
302 dijit._curFocus = newVal;
303 dijit._prevFocus = oldVal;
305 topic.publish("focusNode", newVal); // publish
308 focus.watch("activeStack", function(name, oldVal, newVal){
309 dijit._activeStack = newVal;
312 focus.on("widget-blur", function(widget, by){
313 topic.publish("widgetBlur", widget, by); // publish
315 focus.on("widget-focus", function(widget, by){
316 topic.publish("widgetFocus", widget, by); // publish
319 lang.mixin(dijit, exports);
321 /*===== return exports; =====*/
322 return dijit
; // for back compat :-(