You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
207 lines
7.2 KiB
207 lines
7.2 KiB
define([ |
|
"dojo/_base/array", // array.forEach |
|
"dojo/dom", // dom.isDescendant |
|
"dojo/_base/lang", // lang.isArray |
|
"dojo/topic", // publish |
|
"dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal |
|
"../focus", |
|
"../selection", |
|
"../main" // for exporting symbols to dijit |
|
], function(array, dom, lang, topic, win, focus, selection, dijit){ |
|
|
|
// module: |
|
// dijit/_base/focus |
|
|
|
var exports = { |
|
// summary: |
|
// Deprecated module to monitor currently focused node and stack of currently focused widgets. |
|
// New code should access dijit/focus directly. |
|
|
|
// _curFocus: DomNode |
|
// Currently focused item on screen |
|
_curFocus: null, |
|
|
|
// _prevFocus: DomNode |
|
// Previously focused item on screen |
|
_prevFocus: null, |
|
|
|
isCollapsed: function(){ |
|
// summary: |
|
// Returns true if there is no text selected |
|
return dijit.getBookmark().isCollapsed; |
|
}, |
|
|
|
getBookmark: function(){ |
|
// summary: |
|
// Retrieves a bookmark that can be used with moveToBookmark to return to the same range |
|
var sel = win.global == window ? selection : new selection.SelectionManager(win.global); |
|
return sel.getBookmark(); |
|
}, |
|
|
|
moveToBookmark: function(/*Object*/ bookmark){ |
|
// summary: |
|
// Moves current selection to a bookmark |
|
// bookmark: |
|
// This should be a returned object from dijit.getBookmark() |
|
|
|
var sel = win.global == window ? selection : new selection.SelectionManager(win.global); |
|
return sel.moveToBookmark(bookmark); |
|
}, |
|
|
|
getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){ |
|
// summary: |
|
// Called as getFocus(), this returns an Object showing the current focus |
|
// and selected text. |
|
// |
|
// Called as getFocus(widget), where widget is a (widget representing) a button |
|
// that was just pressed, it returns where focus was before that button |
|
// was pressed. (Pressing the button may have either shifted focus to the button, |
|
// or removed focus altogether.) In this case the selected text is not returned, |
|
// since it can't be accurately determined. |
|
// |
|
// menu: dijit/_WidgetBase|{domNode: DomNode} structure |
|
// The button that was just pressed. If focus has disappeared or moved |
|
// to this button, returns the previous focus. In this case the bookmark |
|
// information is already lost, and null is returned. |
|
// |
|
// openedForWindow: |
|
// iframe in which menu was opened |
|
// |
|
// returns: |
|
// A handle to restore focus/selection, to be passed to `dijit.focus` |
|
var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode; |
|
return { |
|
node: node, |
|
bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark), |
|
openedForWindow: openedForWindow |
|
}; // Object |
|
}, |
|
|
|
// _activeStack: dijit/_WidgetBase[] |
|
// List of currently active widgets (focused widget and it's ancestors) |
|
_activeStack: [], |
|
|
|
registerIframe: function(/*DomNode*/ iframe){ |
|
// summary: |
|
// Registers listeners on the specified iframe so that any click |
|
// or focus event on that iframe (or anything in it) is reported |
|
// as a focus/click event on the `<iframe>` itself. |
|
// description: |
|
// Currently only used by editor. |
|
// returns: |
|
// Handle to pass to unregisterIframe() |
|
return focus.registerIframe(iframe); |
|
}, |
|
|
|
unregisterIframe: function(/*Object*/ handle){ |
|
// summary: |
|
// Unregisters listeners on the specified iframe created by registerIframe. |
|
// After calling be sure to delete or null out the handle itself. |
|
// handle: |
|
// Handle returned by registerIframe() |
|
|
|
handle && handle.remove(); |
|
}, |
|
|
|
registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){ |
|
// summary: |
|
// Registers listeners on the specified window (either the main |
|
// window or an iframe's window) to detect when the user has clicked somewhere |
|
// or focused somewhere. |
|
// description: |
|
// Users should call registerIframe() instead of this method. |
|
// targetWindow: |
|
// If specified this is the window associated with the iframe, |
|
// i.e. iframe.contentWindow. |
|
// effectiveNode: |
|
// If specified, report any focus events inside targetWindow as |
|
// an event on effectiveNode, rather than on evt.target. |
|
// returns: |
|
// Handle to pass to unregisterWin() |
|
|
|
return focus.registerWin(targetWindow, effectiveNode); |
|
}, |
|
|
|
unregisterWin: function(/*Handle*/ handle){ |
|
// summary: |
|
// Unregisters listeners on the specified window (either the main |
|
// window or an iframe's window) according to handle returned from registerWin(). |
|
// After calling be sure to delete or null out the handle itself. |
|
|
|
handle && handle.remove(); |
|
} |
|
}; |
|
|
|
// Override focus singleton's focus function so that dijit.focus() |
|
// has backwards compatible behavior of restoring selection (although |
|
// probably no one is using that). |
|
focus.focus = function(/*Object|DomNode */ handle){ |
|
// summary: |
|
// Sets the focused node and the selection according to argument. |
|
// To set focus to an iframe's content, pass in the iframe itself. |
|
// handle: |
|
// object returned by get(), or a DomNode |
|
|
|
if(!handle){ return; } |
|
|
|
var node = "node" in handle ? handle.node : handle, // because handle is either DomNode or a composite object |
|
bookmark = handle.bookmark, |
|
openedForWindow = handle.openedForWindow, |
|
collapsed = bookmark ? bookmark.isCollapsed : false; |
|
|
|
// Set the focus |
|
// Note that for iframe's we need to use the <iframe> to follow the parentNode chain, |
|
// but we need to set focus to iframe.contentWindow |
|
if(node){ |
|
var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node; |
|
if(focusNode && focusNode.focus){ |
|
try{ |
|
// Gecko throws sometimes if setting focus is impossible, |
|
// node not displayed or something like that |
|
focusNode.focus(); |
|
}catch(e){/*quiet*/} |
|
} |
|
focus._onFocusNode(node); |
|
} |
|
|
|
// set the selection |
|
// do not need to restore if current selection is not empty |
|
// (use keyboard to select a menu item) or if previous selection was collapsed |
|
// as it may cause focus shift (Esp in IE). |
|
if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){ |
|
if(openedForWindow){ |
|
openedForWindow.focus(); |
|
} |
|
try{ |
|
win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]); |
|
}catch(e2){ |
|
/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */ |
|
} |
|
} |
|
}; |
|
|
|
// For back compatibility, monitor changes to focused node and active widget stack, |
|
// publishing events and copying changes from focus manager variables into dijit (top level) variables |
|
focus.watch("curNode", function(name, oldVal, newVal){ |
|
dijit._curFocus = newVal; |
|
dijit._prevFocus = oldVal; |
|
if(newVal){ |
|
topic.publish("focusNode", newVal); // publish |
|
} |
|
}); |
|
focus.watch("activeStack", function(name, oldVal, newVal){ |
|
dijit._activeStack = newVal; |
|
}); |
|
|
|
focus.on("widget-blur", function(widget, by){ |
|
topic.publish("widgetBlur", widget, by); // publish |
|
}); |
|
focus.on("widget-focus", function(widget, by){ |
|
topic.publish("widgetFocus", widget, by); // publish |
|
}); |
|
|
|
lang.mixin(dijit, exports); |
|
|
|
/*===== return exports; =====*/ |
|
return dijit; // for back compat :-( |
|
});
|
|
|