summaryrefslogtreecommitdiff
path: root/lib/dijit/_base/focus.js
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dijit/_base/focus.js')
-rw-r--r--lib/dijit/_base/focus.js803
1 files changed, 517 insertions, 286 deletions
diff --git a/lib/dijit/_base/focus.js b/lib/dijit/_base/focus.js
index 32be06aa7..55c5b682d 100644
--- a/lib/dijit/_base/focus.js
+++ b/lib/dijit/_base/focus.js
@@ -1,299 +1,530 @@
/*
- Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
+ Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
Available via Academic Free License >= 2.1 OR the modified BSD license.
see: http://dojotoolkit.org/license for details
*/
-if(!dojo._hasResource["dijit._base.focus"]){
-dojo._hasResource["dijit._base.focus"]=true;
+if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
+dojo._hasResource["dijit._base.focus"] = true;
dojo.provide("dijit._base.focus");
dojo.require("dojo.window");
dojo.require("dijit._base.manager");
-dojo.mixin(dijit,{_curFocus:null,_prevFocus:null,isCollapsed:function(){
-return dijit.getBookmark().isCollapsed;
-},getBookmark:function(){
-var bm,rg,tg,_1=dojo.doc.selection,cf=dijit._curFocus;
-if(dojo.global.getSelection){
-_1=dojo.global.getSelection();
-if(_1){
-if(_1.isCollapsed){
-tg=cf?cf.tagName:"";
-if(tg){
-tg=tg.toLowerCase();
-if(tg=="textarea"||(tg=="input"&&(!cf.type||cf.type.toLowerCase()=="text"))){
-_1={start:cf.selectionStart,end:cf.selectionEnd,node:cf,pRange:true};
-return {isCollapsed:(_1.end<=_1.start),mark:_1};
-}
-}
-bm={isCollapsed:true};
-}else{
-rg=_1.getRangeAt(0);
-bm={isCollapsed:false,mark:rg.cloneRange()};
-}
-}
-}else{
-if(_1){
-tg=cf?cf.tagName:"";
-tg=tg.toLowerCase();
-if(cf&&tg&&(tg=="button"||tg=="textarea"||tg=="input")){
-if(_1.type&&_1.type.toLowerCase()=="none"){
-return {isCollapsed:true,mark:null};
-}else{
-rg=_1.createRange();
-return {isCollapsed:rg.text&&rg.text.length?false:true,mark:{range:rg,pRange:true}};
-}
-}
-bm={};
-try{
-rg=_1.createRange();
-bm.isCollapsed=!(_1.type=="Text"?rg.htmlText.length:rg.length);
-}
-catch(e){
-bm.isCollapsed=true;
-return bm;
-}
-if(_1.type.toUpperCase()=="CONTROL"){
-if(rg.length){
-bm.mark=[];
-var i=0,_2=rg.length;
-while(i<_2){
-bm.mark.push(rg.item(i++));
-}
-}else{
-bm.isCollapsed=true;
-bm.mark=null;
-}
-}else{
-bm.mark=rg.getBookmark();
-}
-}else{
-console.warn("No idea how to store the current selection for this browser!");
-}
-}
-return bm;
-},moveToBookmark:function(_3){
-var _4=dojo.doc,_5=_3.mark;
-if(_5){
-if(dojo.global.getSelection){
-var _6=dojo.global.getSelection();
-if(_6&&_6.removeAllRanges){
-if(_5.pRange){
-var r=_5;
-var n=r.node;
-n.selectionStart=r.start;
-n.selectionEnd=r.end;
-}else{
-_6.removeAllRanges();
-_6.addRange(_5);
-}
-}else{
-console.warn("No idea how to restore selection for this browser!");
-}
-}else{
-if(_4.selection&&_5){
-var rg;
-if(_5.pRange){
-rg=_5.range;
-}else{
-if(dojo.isArray(_5)){
-rg=_4.body.createControlRange();
-dojo.forEach(_5,function(n){
-rg.addElement(n);
+
+
+// summary:
+// These functions are used to query or set the focus and selection.
+//
+// Also, they trace when widgets become activated/deactivated,
+// so that the widget can fire _onFocus/_onBlur events.
+// "Active" here means something similar to "focused", but
+// "focus" isn't quite the right word because we keep track of
+// a whole stack of "active" widgets. Example: ComboButton --> Menu -->
+// MenuItem. The onBlur event for ComboButton doesn't fire due to focusing
+// on the Menu or a MenuItem, since they are considered part of the
+// ComboButton widget. It only happens when focus is shifted
+// somewhere completely different.
+
+dojo.mixin(dijit, {
+ // _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 bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
+
+ if(dojo.global.getSelection){
+ //W3C Range API for selections.
+ sel = dojo.global.getSelection();
+ if(sel){
+ if(sel.isCollapsed){
+ tg = cf? cf.tagName : "";
+ if(tg){
+ //Create a fake rangelike item to restore selections.
+ tg = tg.toLowerCase();
+ if(tg == "textarea" ||
+ (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
+ sel = {
+ start: cf.selectionStart,
+ end: cf.selectionEnd,
+ node: cf,
+ pRange: true
+ };
+ return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
+ }
+ }
+ bm = {isCollapsed:true};
+ if(sel.rangeCount){
+ bm.mark = sel.getRangeAt(0).cloneRange();
+ }
+ }else{
+ rg = sel.getRangeAt(0);
+ bm = {isCollapsed: false, mark: rg.cloneRange()};
+ }
+ }
+ }else if(sel){
+ // If the current focus was a input of some sort and no selection, don't bother saving
+ // a native bookmark. This is because it causes issues with dialog/page selection restore.
+ // So, we need to create psuedo bookmarks to work with.
+ tg = cf ? cf.tagName : "";
+ tg = tg.toLowerCase();
+ if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
+ if(sel.type && sel.type.toLowerCase() == "none"){
+ return {
+ isCollapsed: true,
+ mark: null
+ }
+ }else{
+ rg = sel.createRange();
+ return {
+ isCollapsed: rg.text && rg.text.length?false:true,
+ mark: {
+ range: rg,
+ pRange: true
+ }
+ };
+ }
+ }
+ bm = {};
+
+ //'IE' way for selections.
+ try{
+ // createRange() throws exception when dojo in iframe
+ //and nothing selected, see #9632
+ rg = sel.createRange();
+ bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
+ }catch(e){
+ bm.isCollapsed = true;
+ return bm;
+ }
+ if(sel.type.toUpperCase() == 'CONTROL'){
+ if(rg.length){
+ bm.mark=[];
+ var i=0,len=rg.length;
+ while(i<len){
+ bm.mark.push(rg.item(i++));
+ }
+ }else{
+ bm.isCollapsed = true;
+ bm.mark = null;
+ }
+ }else{
+ bm.mark = rg.getBookmark();
+ }
+ }else{
+ console.warn("No idea how to store the current selection for this browser!");
+ }
+ return bm; // Object
+ },
+
+ moveToBookmark: function(/*Object*/bookmark){
+ // summary:
+ // Moves current selection to a bookmark
+ // bookmark:
+ // This should be a returned object from dijit.getBookmark()
+
+ var _doc = dojo.doc,
+ mark = bookmark.mark;
+ if(mark){
+ if(dojo.global.getSelection){
+ //W3C Rangi API (FF, WebKit, Opera, etc)
+ var sel = dojo.global.getSelection();
+ if(sel && sel.removeAllRanges){
+ if(mark.pRange){
+ var r = mark;
+ var n = r.node;
+ n.selectionStart = r.start;
+ n.selectionEnd = r.end;
+ }else{
+ sel.removeAllRanges();
+ sel.addRange(mark);
+ }
+ }else{
+ console.warn("No idea how to restore selection for this browser!");
+ }
+ }else if(_doc.selection && mark){
+ //'IE' way.
+ var rg;
+ if(mark.pRange){
+ rg = mark.range;
+ }else if(dojo.isArray(mark)){
+ rg = _doc.body.createControlRange();
+ //rg.addElement does not have call/apply method, so can not call it directly
+ //rg is not available in "range.addElement(item)", so can't use that either
+ dojo.forEach(mark, function(n){
+ rg.addElement(n);
+ });
+ }else{
+ rg = _doc.body.createTextRange();
+ rg.moveToBookmark(mark);
+ }
+ rg.select();
+ }
+ }
+ },
+
+ 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._Widget or {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 = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
+ return {
+ node: node,
+ bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
+ openedForWindow: openedForWindow
+ }; // Object
+ },
+
+ 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*/}
+ }
+ dijit._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 && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
+ if(openedForWindow){
+ openedForWindow.focus();
+ }
+ try{
+ dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
+ }catch(e2){
+ /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
+ }
+ }
+ },
+
+ // _activeStack: dijit._Widget[]
+ // 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 dijit.registerWin(iframe.contentWindow, 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()
+
+ dijit.unregisterWin(handle);
+ },
+
+ 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()
+
+ // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
+
+ var mousedownListener = function(evt){
+ dijit._justMouseDowned = true;
+ setTimeout(function(){ dijit._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(dojo.isIE && evt && evt.srcElement && evt.srcElement.parentNode == null){
+ return;
+ }
+
+ dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
+ };
+ //dojo.connect(targetWindow, "onscroll", ???);
+
+ // 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 = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
+ if(doc){
+ if(dojo.isIE){
+ 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,
+ // Should consider those more like a mouse-click than a focus....
+ if(evt.srcElement.tagName.toLowerCase() != "#document" &&
+ dijit.isTabNavigable(evt.srcElement)){
+ dijit._onFocusNode(effectiveNode || evt.srcElement);
+ }else{
+ dijit._onTouchNode(effectiveNode || evt.srcElement);
+ }
+ };
+ doc.attachEvent('onactivate', activateListener);
+ var deactivateListener = function(evt){
+ dijit._onBlurNode(effectiveNode || evt.srcElement);
+ };
+ doc.attachEvent('ondeactivate', deactivateListener);
+
+ return 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);
+ var focusListener = function(evt){
+ dijit._onFocusNode(effectiveNode || evt.target);
+ };
+ doc.addEventListener('focus', focusListener, true);
+ var blurListener = function(evt){
+ dijit._onBlurNode(effectiveNode || evt.target);
+ };
+ doc.addEventListener('blur', blurListener, true);
+
+ return function(){
+ doc.body.removeEventListener('mousedown', mousedownListener, true);
+ doc.removeEventListener('focus', focusListener, true);
+ doc.removeEventListener('blur', blurListener, true);
+ doc = null; // prevent memory leak (apparent circular reference via closure)
+ };
+ }
+ }
+ },
+
+ 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.
+
+ // Currently our handle is actually a function
+ handle && handle();
+ },
+
+ _onBlurNode: function(/*DomNode*/ node){
+ // summary:
+ // Called when focus leaves a node.
+ // Usually ignored, _unless_ it *isn't* follwed by touching another node,
+ // which indicates that we tabbed off the last field on the page,
+ // in which case every widget is marked inactive
+ dijit._prevFocus = dijit._curFocus;
+ dijit._curFocus = null;
+
+ if(dijit._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(dijit._clearActiveWidgetsTimer){
+ clearTimeout(dijit._clearActiveWidgetsTimer);
+ }
+ dijit._clearActiveWidgetsTimer = setTimeout(function(){
+ delete dijit._clearActiveWidgetsTimer;
+ dijit._setStack([]);
+ dijit._prevFocus = 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(dijit._clearActiveWidgetsTimer){
+ clearTimeout(dijit._clearActiveWidgetsTimer);
+ delete dijit._clearActiveWidgetsTimer;
+ }
+
+ // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
+ var newStack=[];
+ try{
+ while(node){
+ var popupParent = dojo.attr(node, "dijitPopupParent");
+ if(popupParent){
+ node=dijit.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 === dojo.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=dojo.window.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 && dijit.byId(id);
+ if(widget && !(by == "mouse" && widget.get("disabled"))){
+ newStack.unshift(id);
+ }
+ node=node.parentNode;
+ }
+ }
+ }catch(e){ /* squelch */ }
+
+ dijit._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;
+ }
+
+ dijit._onTouchNode(node);
+
+ if(node == dijit._curFocus){ return; }
+ if(dijit._curFocus){
+ dijit._prevFocus = dijit._curFocus;
+ }
+ dijit._curFocus = node;
+ dojo.publish("focusNode", [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 = dijit._activeStack;
+ dijit._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, send blur event
+ for(var i=oldStack.length-1; i>=nCommon; i--){
+ widget = dijit.byId(oldStack[i]);
+ if(widget){
+ widget._focused = false;
+ widget.set("focused", false);
+ widget._hasBeenBlurred = true;
+ if(widget._onBlur){
+ widget._onBlur(by);
+ }
+ dojo.publish("widgetBlur", [widget, by]);
+ }
+ }
+
+ // for all element that have come into focus, send focus event
+ for(i=nCommon; i<newStack.length; i++){
+ widget = dijit.byId(newStack[i]);
+ if(widget){
+ widget._focused = true;
+ widget.set("focused", true);
+ if(widget._onFocus){
+ widget._onFocus(by);
+ }
+ dojo.publish("widgetFocus", [widget, by]);
+ }
+ }
+ }
});
-}else{
-rg=_4.body.createTextRange();
-rg.moveToBookmark(_5);
-}
-}
-rg.select();
-}
-}
-}
-},getFocus:function(_7,_8){
-var _9=!dijit._curFocus||(_7&&dojo.isDescendant(dijit._curFocus,_7.domNode))?dijit._prevFocus:dijit._curFocus;
-return {node:_9,bookmark:(_9==dijit._curFocus)&&dojo.withGlobal(_8||dojo.global,dijit.getBookmark),openedForWindow:_8};
-},focus:function(_a){
-if(!_a){
-return;
-}
-var _b="node" in _a?_a.node:_a,_c=_a.bookmark,_d=_a.openedForWindow,_e=_c?_c.isCollapsed:false;
-if(_b){
-var _f=(_b.tagName.toLowerCase()=="iframe")?_b.contentWindow:_b;
-if(_f&&_f.focus){
-try{
-_f.focus();
-}
-catch(e){
-}
-}
-dijit._onFocusNode(_b);
-}
-if(_c&&dojo.withGlobal(_d||dojo.global,dijit.isCollapsed)&&!_e){
-if(_d){
-_d.focus();
-}
-try{
-dojo.withGlobal(_d||dojo.global,dijit.moveToBookmark,null,[_c]);
-}
-catch(e2){
-}
-}
-},_activeStack:[],registerIframe:function(_10){
-return dijit.registerWin(_10.contentWindow,_10);
-},unregisterIframe:function(_11){
-dijit.unregisterWin(_11);
-},registerWin:function(_12,_13){
-var _14=function(evt){
-dijit._justMouseDowned=true;
-setTimeout(function(){
-dijit._justMouseDowned=false;
-},0);
-if(dojo.isIE&&evt&&evt.srcElement&&evt.srcElement.parentNode==null){
-return;
-}
-dijit._onTouchNode(_13||evt.target||evt.srcElement,"mouse");
-};
-var doc=dojo.isIE?_12.document.documentElement:_12.document;
-if(doc){
-if(dojo.isIE){
-doc.attachEvent("onmousedown",_14);
-var _15=function(evt){
-if(evt.srcElement.tagName.toLowerCase()!="#document"&&dijit.isTabNavigable(evt.srcElement)){
-dijit._onFocusNode(_13||evt.srcElement);
-}else{
-dijit._onTouchNode(_13||evt.srcElement);
-}
-};
-doc.attachEvent("onactivate",_15);
-var _16=function(evt){
-dijit._onBlurNode(_13||evt.srcElement);
-};
-doc.attachEvent("ondeactivate",_16);
-return function(){
-doc.detachEvent("onmousedown",_14);
-doc.detachEvent("onactivate",_15);
-doc.detachEvent("ondeactivate",_16);
-doc=null;
-};
-}else{
-doc.addEventListener("mousedown",_14,true);
-var _17=function(evt){
-dijit._onFocusNode(_13||evt.target);
-};
-doc.addEventListener("focus",_17,true);
-var _18=function(evt){
-dijit._onBlurNode(_13||evt.target);
-};
-doc.addEventListener("blur",_18,true);
-return function(){
-doc.removeEventListener("mousedown",_14,true);
-doc.removeEventListener("focus",_17,true);
-doc.removeEventListener("blur",_18,true);
-doc=null;
-};
-}
-}
-},unregisterWin:function(_19){
-_19&&_19();
-},_onBlurNode:function(_1a){
-dijit._prevFocus=dijit._curFocus;
-dijit._curFocus=null;
-if(dijit._justMouseDowned){
-return;
-}
-if(dijit._clearActiveWidgetsTimer){
-clearTimeout(dijit._clearActiveWidgetsTimer);
-}
-dijit._clearActiveWidgetsTimer=setTimeout(function(){
-delete dijit._clearActiveWidgetsTimer;
-dijit._setStack([]);
-dijit._prevFocus=null;
-},100);
-},_onTouchNode:function(_1b,by){
-if(dijit._clearActiveWidgetsTimer){
-clearTimeout(dijit._clearActiveWidgetsTimer);
-delete dijit._clearActiveWidgetsTimer;
-}
-var _1c=[];
-try{
-while(_1b){
-var _1d=dojo.attr(_1b,"dijitPopupParent");
-if(_1d){
-_1b=dijit.byId(_1d).domNode;
-}else{
-if(_1b.tagName&&_1b.tagName.toLowerCase()=="body"){
-if(_1b===dojo.body()){
-break;
-}
-_1b=dojo.window.get(_1b.ownerDocument).frameElement;
-}else{
-var id=_1b.getAttribute&&_1b.getAttribute("widgetId"),_1e=id&&dijit.byId(id);
-if(_1e&&!(by=="mouse"&&_1e.get("disabled"))){
-_1c.unshift(id);
-}
-_1b=_1b.parentNode;
-}
-}
-}
-}
-catch(e){
-}
-dijit._setStack(_1c,by);
-},_onFocusNode:function(_1f){
-if(!_1f){
-return;
-}
-if(_1f.nodeType==9){
-return;
-}
-dijit._onTouchNode(_1f);
-if(_1f==dijit._curFocus){
-return;
-}
-if(dijit._curFocus){
-dijit._prevFocus=dijit._curFocus;
-}
-dijit._curFocus=_1f;
-dojo.publish("focusNode",[_1f]);
-},_setStack:function(_20,by){
-var _21=dijit._activeStack;
-dijit._activeStack=_20;
-for(var _22=0;_22<Math.min(_21.length,_20.length);_22++){
-if(_21[_22]!=_20[_22]){
-break;
-}
-}
-var _23;
-for(var i=_21.length-1;i>=_22;i--){
-_23=dijit.byId(_21[i]);
-if(_23){
-_23._focused=false;
-_23._hasBeenBlurred=true;
-if(_23._onBlur){
-_23._onBlur(by);
-}
-dojo.publish("widgetBlur",[_23,by]);
-}
-}
-for(i=_22;i<_20.length;i++){
-_23=dijit.byId(_20[i]);
-if(_23){
-_23._focused=true;
-if(_23._onFocus){
-_23._onFocus(by);
-}
-dojo.publish("widgetFocus",[_23,by]);
-}
-}
-}});
+
+// register top window and all the iframes it contains
dojo.addOnLoad(function(){
-var _24=dijit.registerWin(window);
-if(dojo.isIE){
-dojo.addOnWindowUnload(function(){
-dijit.unregisterWin(_24);
-_24=null;
-});
-}
+ var handle = dijit.registerWin(window);
+ if(dojo.isIE){
+ dojo.addOnWindowUnload(function(){
+ dijit.unregisterWin(handle);
+ handle = null;
+ })
+ }
});
+
}