diff options
Diffstat (limited to 'lib/dijit/focus.js.uncompressed.js')
-rw-r--r-- | lib/dijit/focus.js.uncompressed.js | 389 |
1 files changed, 0 insertions, 389 deletions
diff --git a/lib/dijit/focus.js.uncompressed.js b/lib/dijit/focus.js.uncompressed.js deleted file mode 100644 index 749a5bb8c..000000000 --- a/lib/dijit/focus.js.uncompressed.js +++ /dev/null @@ -1,389 +0,0 @@ -define("dijit/focus", [ - "dojo/aspect", - "dojo/_base/declare", // declare - "dojo/dom", // domAttr.get dom.isDescendant - "dojo/dom-attr", // domAttr.get dom.isDescendant - "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy - "dojo/Evented", - "dojo/_base/lang", // lang.hitch - "dojo/on", - "dojo/ready", - "dojo/_base/sniff", // has("ie") - "dojo/Stateful", - "dojo/_base/unload", // unload.addOnWindowUnload - "dojo/_base/window", // win.body - "dojo/window", // winUtils.get - "./a11y", // a11y.isTabNavigable - "./registry", // registry.byId - "." // to set dijit.focus -], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, ready, has, Stateful, unload, win, winUtils, - a11y, registry, dijit){ - - // module: - // dijit/focus - // summary: - // Returns a singleton that tracks the currently focused node, and which widgets are currently "active". - -/*===== - dijit.focus = { - // summary: - // Tracks the currently focused node, and which widgets are currently "active". - // Access via require(["dijit/focus"], function(focus){ ... }). - // - // A widget is considered active if it or a descendant widget has focus, - // or if a non-focusable node of this widget or a descendant was recently clicked. - // - // Call focus.watch("curNode", callback) to track the current focused DOMNode, - // or focus.watch("activeStack", callback) to track the currently focused stack of widgets. - // - // Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when - // when widgets become active/inactive - // - // Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist. - - // curNode: DomNode - // Currently focused item on screen - curNode: null, - - // activeStack: dijit._Widget[] - // List of currently active widgets (focused widget and it's ancestors) - activeStack: [], - - registerIframe: function(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 with remove() method to deregister. - }, - - registerWin: function(targetWindow, 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: Window? - // If specified this is the window associated with the iframe, - // i.e. iframe.contentWindow. - // effectiveNode: DOMNode? - // If specified, report any focus events inside targetWindow as - // an event on effectiveNode, rather than on evt.target. - // returns: - // Handle with remove() method to deregister. - } - }; -=====*/ - - var FocusManager = declare([Stateful, Evented], { - // curNode: DomNode - // Currently focused item on screen - curNode: null, - - // activeStack: dijit._Widget[] - // List of currently active widgets (focused widget and it's ancestors) - activeStack: [], - - constructor: function(){ - // Don't leave curNode/prevNode pointing to bogus elements - var check = lang.hitch(this, function(node){ - if(dom.isDescendant(this.curNode, node)){ - this.set("curNode", null); - } - if(dom.isDescendant(this.prevNode, node)){ - this.set("prevNode", null); - } - }); - aspect.before(domConstruct, "empty", check); - aspect.before(domConstruct, "destroy", check); - }, - - 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 with remove() method to deregister. - return this.registerWin(iframe.contentWindow, iframe); - }, - - 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 with remove() method to deregister. - - // TODO: make this function private in 2.0; Editor/users should call registerIframe(), - - var _this = this; - var mousedownListener = function(evt){ - _this._justMouseDowned = true; - setTimeout(function(){ _this._justMouseDowned = false; }, 0); - - // workaround weird IE bug where the click is on an orphaned node - // (first time clicking a Select/DropDownButton inside a TooltipDialog) - if(has("ie") && evt && evt.srcElement && evt.srcElement.parentNode == null){ - return; - } - - _this._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse"); - }; - - // Listen for blur and focus events on targetWindow's document. - // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble - // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers - // fire. - // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because - // (at least for FF) the focus event doesn't fire on <html> or <body>. - var doc = has("ie") ? targetWindow.document.documentElement : targetWindow.document; - if(doc){ - if(has("ie")){ - targetWindow.document.body.attachEvent('onmousedown', mousedownListener); - var activateListener = function(evt){ - // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1, - // ignore those events - var tag = evt.srcElement.tagName.toLowerCase(); - if(tag == "#document" || tag == "body"){ return; } - - // Previous code called _onTouchNode() for any activate event on a non-focusable node. Can - // probably just ignore such an event as it will be handled by onmousedown handler above, but - // leaving the code for now. - if(a11y.isTabNavigable(evt.srcElement)){ - _this._onFocusNode(effectiveNode || evt.srcElement); - }else{ - _this._onTouchNode(effectiveNode || evt.srcElement); - } - }; - doc.attachEvent('onactivate', activateListener); - var deactivateListener = function(evt){ - _this._onBlurNode(effectiveNode || evt.srcElement); - }; - doc.attachEvent('ondeactivate', deactivateListener); - - return { - remove: function(){ - targetWindow.document.detachEvent('onmousedown', mousedownListener); - doc.detachEvent('onactivate', activateListener); - doc.detachEvent('ondeactivate', deactivateListener); - doc = null; // prevent memory leak (apparent circular reference via closure) - } - }; - }else{ - doc.body.addEventListener('mousedown', mousedownListener, true); - doc.body.addEventListener('touchstart', mousedownListener, true); - var focusListener = function(evt){ - _this._onFocusNode(effectiveNode || evt.target); - }; - doc.addEventListener('focus', focusListener, true); - var blurListener = function(evt){ - _this._onBlurNode(effectiveNode || evt.target); - }; - doc.addEventListener('blur', blurListener, true); - - return { - remove: function(){ - doc.body.removeEventListener('mousedown', mousedownListener, true); - doc.body.removeEventListener('touchstart', mousedownListener, true); - doc.removeEventListener('focus', focusListener, true); - doc.removeEventListener('blur', blurListener, true); - doc = null; // prevent memory leak (apparent circular reference via closure) - } - }; - } - } - }, - - _onBlurNode: function(/*DomNode*/ /*===== node =====*/){ - // summary: - // Called when focus leaves a node. - // Usually ignored, _unless_ it *isn't* followed by touching another node, - // which indicates that we tabbed off the last field on the page, - // in which case every widget is marked inactive - this.set("prevNode", this.curNode); - this.set("curNode", null); - - if(this._justMouseDowned){ - // the mouse down caused a new widget to be marked as active; this blur event - // is coming late, so ignore it. - return; - } - - // if the blur event isn't followed by a focus event then mark all widgets as inactive. - if(this._clearActiveWidgetsTimer){ - clearTimeout(this._clearActiveWidgetsTimer); - } - this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){ - delete this._clearActiveWidgetsTimer; - this._setStack([]); - this.prevNode = null; - }), 100); - }, - - _onTouchNode: function(/*DomNode*/ node, /*String*/ by){ - // summary: - // Callback when node is focused or mouse-downed - // node: - // The node that was touched. - // by: - // "mouse" if the focus/touch was caused by a mouse down event - - // ignore the recent blurNode event - if(this._clearActiveWidgetsTimer){ - clearTimeout(this._clearActiveWidgetsTimer); - delete this._clearActiveWidgetsTimer; - } - - // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem) - var newStack=[]; - try{ - while(node){ - var popupParent = domAttr.get(node, "dijitPopupParent"); - if(popupParent){ - node=registry.byId(popupParent).domNode; - }else if(node.tagName && node.tagName.toLowerCase() == "body"){ - // is this the root of the document or just the root of an iframe? - if(node === win.body()){ - // node is the root of the main document - break; - } - // otherwise, find the iframe this node refers to (can't access it via parentNode, - // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit - node=winUtils.get(node.ownerDocument).frameElement; - }else{ - // if this node is the root node of a widget, then add widget id to stack, - // except ignore clicks on disabled widgets (actually focusing a disabled widget still works, - // to support MenuItem) - var id = node.getAttribute && node.getAttribute("widgetId"), - widget = id && registry.byId(id); - if(widget && !(by == "mouse" && widget.get("disabled"))){ - newStack.unshift(id); - } - node=node.parentNode; - } - } - }catch(e){ /* squelch */ } - - this._setStack(newStack, by); - }, - - _onFocusNode: function(/*DomNode*/ node){ - // summary: - // Callback when node is focused - - if(!node){ - return; - } - - if(node.nodeType == 9){ - // Ignore focus events on the document itself. This is here so that - // (for example) clicking the up/down arrows of a spinner - // (which don't get focus) won't cause that widget to blur. (FF issue) - return; - } - - this._onTouchNode(node); - - if(node == this.curNode){ return; } - this.set("curNode", node); - }, - - _setStack: function(/*String[]*/ newStack, /*String*/ by){ - // summary: - // The stack of active widgets has changed. Send out appropriate events and records new stack. - // newStack: - // array of widget id's, starting from the top (outermost) widget - // by: - // "mouse" if the focus/touch was caused by a mouse down event - - var oldStack = this.activeStack; - this.set("activeStack", newStack); - - // compare old stack to new stack to see how many elements they have in common - for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){ - if(oldStack[nCommon] != newStack[nCommon]){ - break; - } - } - - var widget; - // for all elements that have gone out of focus, set focused=false - for(var i=oldStack.length-1; i>=nCommon; i--){ - widget = registry.byId(oldStack[i]); - if(widget){ - widget._hasBeenBlurred = true; // TODO: used by form widgets, should be moved there - widget.set("focused", false); - if(widget._focusManager == this){ - widget._onBlur(by); - } - this.emit("widget-blur", widget, by); - } - } - - // for all element that have come into focus, set focused=true - for(i=nCommon; i<newStack.length; i++){ - widget = registry.byId(newStack[i]); - if(widget){ - widget.set("focused", true); - if(widget._focusManager == this){ - widget._onFocus(by); - } - this.emit("widget-focus", widget, by); - } - } - }, - - focus: function(node){ - // summary: - // Focus the specified node, suppressing errors if they occur - if(node){ - try{ node.focus(); }catch(e){/*quiet*/} - } - } - }); - - var singleton = new FocusManager(); - - // register top window and all the iframes it contains - ready(function(){ - var handle = singleton.registerWin(win.doc.parentWindow || win.doc.defaultView); - if(has("ie")){ - unload.addOnWindowUnload(function(){ - handle.remove(); - handle = null; - }) - } - }); - - // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility) - // as a function to set focus. - dijit.focus = function(node){ - singleton.focus(node); // indirection here allows dijit/_base/focus.js to override behavior - }; - for(var attr in singleton){ - if(!/^_/.test(attr)){ - dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr]; - } - } - singleton.watch(function(attr, oldVal, newVal){ - dijit.focus[attr] = newVal; - }); - - return singleton; -}); |