summaryrefslogtreecommitdiff
path: root/lib/dijit/focus.js.uncompressed.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dijit/focus.js.uncompressed.js')
-rw-r--r--lib/dijit/focus.js.uncompressed.js364
1 files changed, 0 insertions, 364 deletions
diff --git a/lib/dijit/focus.js.uncompressed.js b/lib/dijit/focus.js.uncompressed.js
deleted file mode 100644
index 3bf92b36a..000000000
--- a/lib/dijit/focus.js.uncompressed.js
+++ /dev/null
@@ -1,364 +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/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
- "./main" // 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
-
- var FocusManager = declare([Stateful, Evented], {
- // 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/_WidgetBase[]
- // 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.
- // Using attachEvent()/addEventListener() rather than on() to try to catch mouseDown events even
- // if other code calls evt.stopPropagation(). But rethink for 2.0 since that doesn't work for attachEvent(),
- // which watches events at the bubbling phase rather than capturing phase, like addEventListener(..., false).
- // 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 focusinListener = 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('onfocusin', focusinListener);
- var focusoutListener = function(evt){
- _this._onBlurNode(effectiveNode || evt.srcElement);
- };
- doc.attachEvent('onfocusout', focusoutListener);
-
- return {
- remove: function(){
- targetWindow.document.detachEvent('onmousedown', mousedownListener);
- doc.detachEvent('onfocusin', focusinListener);
- doc.detachEvent('onfocusout', focusoutListener);
- 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
-
- // If the blur event isn't followed by a focus event, it means the user clicked on something unfocusable,
- // so clear focus.
- if(this._clearFocusTimer){
- clearTimeout(this._clearFocusTimer);
- }
- this._clearFocusTimer = setTimeout(lang.hitch(this, function(){
- this.set("prevNode", this.curNode);
- this.set("curNode", null);
- }), 0);
-
- 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 or touch 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([]);
- }), 0);
- },
-
- _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;
- }
-
- // There was probably a blur event right before this event, but since we have a new focus, don't
- // do anything with the blur
- if(this._clearFocusTimer){
- clearTimeout(this._clearFocusTimer);
- delete this._clearFocusTimer;
- }
-
- this._onTouchNode(node);
-
- if(node == this.curNode){ return; }
- this.set("prevNode", this.curNode);
- 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(winUtils.get(win.doc));
- if(has("ie")){
- unload.addOnWindowUnload(function(){
- if(handle){ // because this gets called twice when doh.robot is running
- handle.remove();
- handle = null;
- }
- });
- }
- });
-
- // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
- // as a function to set focus. Remove for 2.0.
- 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;
-});