diff options
author | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
---|---|---|
committer | Andrew Dolgov <[email protected]> | 2011-11-08 20:40:44 +0400 |
commit | 81bea17aefb26859f825b9293c7c99192874806e (patch) | |
tree | fb244408ca271affa2899adb634788802c9a89d8 /lib/dijit/_base/manager.js | |
parent | 870a70e109ac9e80a88047044530de53d0404ec7 (diff) |
upgrade Dojo to 1.6.1
Diffstat (limited to 'lib/dijit/_base/manager.js')
-rw-r--r-- | lib/dijit/_base/manager.js | 718 |
1 files changed, 483 insertions, 235 deletions
diff --git a/lib/dijit/_base/manager.js b/lib/dijit/_base/manager.js index d8d1cf6d5..e5f745622 100644 --- a/lib/dijit/_base/manager.js +++ b/lib/dijit/_base/manager.js @@ -1,245 +1,493 @@ /* - 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.manager"]){ -dojo._hasResource["dijit._base.manager"]=true; +if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. +dojo._hasResource["dijit._base.manager"] = true; dojo.provide("dijit._base.manager"); -dojo.declare("dijit.WidgetSet",null,{constructor:function(){ -this._hash={}; -this.length=0; -},add:function(_1){ -if(this._hash[_1.id]){ -throw new Error("Tried to register widget with id=="+_1.id+" but that id is already registered"); -} -this._hash[_1.id]=_1; -this.length++; -},remove:function(id){ -if(this._hash[id]){ -delete this._hash[id]; -this.length--; -} -},forEach:function(_2,_3){ -_3=_3||dojo.global; -var i=0,id; -for(id in this._hash){ -_2.call(_3,this._hash[id],i++,this._hash); -} -return this; -},filter:function(_4,_5){ -_5=_5||dojo.global; -var _6=new dijit.WidgetSet(),i=0,id; -for(id in this._hash){ -var w=this._hash[id]; -if(_4.call(_5,w,i++,this._hash)){ -_6.add(w); -} -} -return _6; -},byId:function(id){ -return this._hash[id]; -},byClass:function(_7){ -var _8=new dijit.WidgetSet(),id,_9; -for(id in this._hash){ -_9=this._hash[id]; -if(_9.declaredClass==_7){ -_8.add(_9); -} -} -return _8; -},toArray:function(){ -var ar=[]; -for(var id in this._hash){ -ar.push(this._hash[id]); -} -return ar; -},map:function(_a,_b){ -return dojo.map(this.toArray(),_a,_b); -},every:function(_c,_d){ -_d=_d||dojo.global; -var x=0,i; -for(i in this._hash){ -if(!_c.call(_d,this._hash[i],x++,this._hash)){ -return false; -} -} -return true; -},some:function(_e,_f){ -_f=_f||dojo.global; -var x=0,i; -for(i in this._hash){ -if(_e.call(_f,this._hash[i],x++,this._hash)){ -return true; -} -} -return false; -}}); -(function(){ -dijit.registry=new dijit.WidgetSet(); -var _10=dijit.registry._hash,_11=dojo.attr,_12=dojo.hasAttr,_13=dojo.style; -dijit.byId=function(id){ -return typeof id=="string"?_10[id]:id; -}; -var _14={}; -dijit.getUniqueId=function(_15){ -var id; -do{ -id=_15+"_"+(_15 in _14?++_14[_15]:_14[_15]=0); -}while(_10[id]); -return dijit._scopeName=="dijit"?id:dijit._scopeName+"_"+id; -}; -dijit.findWidgets=function(_16){ -var _17=[]; -function _18(_19){ -for(var _1a=_19.firstChild;_1a;_1a=_1a.nextSibling){ -if(_1a.nodeType==1){ -var _1b=_1a.getAttribute("widgetId"); -if(_1b){ -_17.push(_10[_1b]); -}else{ -_18(_1a); -} -} -} -}; -_18(_16); -return _17; -}; -dijit._destroyAll=function(){ -dijit._curFocus=null; -dijit._prevFocus=null; -dijit._activeStack=[]; -dojo.forEach(dijit.findWidgets(dojo.body()),function(_1c){ -if(!_1c._destroyed){ -if(_1c.destroyRecursive){ -_1c.destroyRecursive(); -}else{ -if(_1c.destroy){ -_1c.destroy(); -} -} -} -}); -}; -if(dojo.isIE){ -dojo.addOnWindowUnload(function(){ -dijit._destroyAll(); -}); -} -dijit.byNode=function(_1d){ -return _10[_1d.getAttribute("widgetId")]; -}; -dijit.getEnclosingWidget=function(_1e){ -while(_1e){ -var id=_1e.getAttribute&&_1e.getAttribute("widgetId"); -if(id){ -return _10[id]; -} -_1e=_1e.parentNode; -} -return null; -}; -var _1f=(dijit._isElementShown=function(_20){ -var s=_13(_20); -return (s.visibility!="hidden")&&(s.visibility!="collapsed")&&(s.display!="none")&&(_11(_20,"type")!="hidden"); -}); -dijit.hasDefaultTabStop=function(_21){ -switch(_21.nodeName.toLowerCase()){ -case "a": -return _12(_21,"href"); -case "area": -case "button": -case "input": -case "object": -case "select": -case "textarea": -return true; -case "iframe": -if(dojo.isMoz){ -try{ -return _21.contentDocument.designMode=="on"; -} -catch(err){ -return false; -} -}else{ -if(dojo.isWebKit){ -var doc=_21.contentDocument,_22=doc&&doc.body; -return _22&&_22.contentEditable=="true"; -}else{ -try{ -doc=_21.contentWindow.document; -_22=doc&&doc.body; -return _22&&_22.firstChild&&_22.firstChild.contentEditable=="true"; -} -catch(e){ -return false; -} -} -} -default: -return _21.contentEditable=="true"; -} -}; -var _23=(dijit.isTabNavigable=function(_24){ -if(_11(_24,"disabled")){ -return false; -}else{ -if(_12(_24,"tabIndex")){ -return _11(_24,"tabIndex")>=0; -}else{ -return dijit.hasDefaultTabStop(_24); -} -} -}); -dijit._getTabNavigable=function(_25){ -var _26,_27,_28,_29,_2a,_2b; -var _2c=function(_2d){ -dojo.query("> *",_2d).forEach(function(_2e){ -if((dojo.isIE&&_2e.scopeName!=="HTML")||!_1f(_2e)){ -return; -} -if(_23(_2e)){ -var _2f=_11(_2e,"tabIndex"); -if(!_12(_2e,"tabIndex")||_2f==0){ -if(!_26){ -_26=_2e; -} -_27=_2e; -}else{ -if(_2f>0){ -if(!_28||_2f<_29){ -_29=_2f; -_28=_2e; -} -if(!_2a||_2f>=_2b){ -_2b=_2f; -_2a=_2e; -} -} -} -} -if(_2e.nodeName.toUpperCase()!="SELECT"){ -_2c(_2e); -} + + +dojo.declare("dijit.WidgetSet", null, { + // summary: + // A set of widgets indexed by id. A default instance of this class is + // available as `dijit.registry` + // + // example: + // Create a small list of widgets: + // | var ws = new dijit.WidgetSet(); + // | ws.add(dijit.byId("one")); + // | ws.add(dijit.byId("two")); + // | // destroy both: + // | ws.forEach(function(w){ w.destroy(); }); + // + // example: + // Using dijit.registry: + // | dijit.registry.forEach(function(w){ /* do something */ }); + + constructor: function(){ + this._hash = {}; + this.length = 0; + }, + + add: function(/*dijit._Widget*/ widget){ + // summary: + // Add a widget to this list. If a duplicate ID is detected, a error is thrown. + // + // widget: dijit._Widget + // Any dijit._Widget subclass. + if(this._hash[widget.id]){ + throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); + } + this._hash[widget.id] = widget; + this.length++; + }, + + remove: function(/*String*/ id){ + // summary: + // Remove a widget from this WidgetSet. Does not destroy the widget; simply + // removes the reference. + if(this._hash[id]){ + delete this._hash[id]; + this.length--; + } + }, + + forEach: function(/*Function*/ func, /* Object? */thisObj){ + // summary: + // Call specified function for each widget in this set. + // + // func: + // A callback function to run for each item. Is passed the widget, the index + // in the iteration, and the full hash, similar to `dojo.forEach`. + // + // thisObj: + // An optional scope parameter + // + // example: + // Using the default `dijit.registry` instance: + // | dijit.registry.forEach(function(widget){ + // | console.log(widget.declaredClass); + // | }); + // + // returns: + // Returns self, in order to allow for further chaining. + + thisObj = thisObj || dojo.global; + var i = 0, id; + for(id in this._hash){ + func.call(thisObj, this._hash[id], i++, this._hash); + } + return this; // dijit.WidgetSet + }, + + filter: function(/*Function*/ filter, /* Object? */thisObj){ + // summary: + // Filter down this WidgetSet to a smaller new WidgetSet + // Works the same as `dojo.filter` and `dojo.NodeList.filter` + // + // filter: + // Callback function to test truthiness. Is passed the widget + // reference and the pseudo-index in the object. + // + // thisObj: Object? + // Option scope to use for the filter function. + // + // example: + // Arbitrary: select the odd widgets in this list + // | dijit.registry.filter(function(w, i){ + // | return i % 2 == 0; + // | }).forEach(function(w){ /* odd ones */ }); + + thisObj = thisObj || dojo.global; + var res = new dijit.WidgetSet(), i = 0, id; + for(id in this._hash){ + var w = this._hash[id]; + if(filter.call(thisObj, w, i++, this._hash)){ + res.add(w); + } + } + return res; // dijit.WidgetSet + }, + + byId: function(/*String*/ id){ + // summary: + // Find a widget in this list by it's id. + // example: + // Test if an id is in a particular WidgetSet + // | var ws = new dijit.WidgetSet(); + // | ws.add(dijit.byId("bar")); + // | var t = ws.byId("bar") // returns a widget + // | var x = ws.byId("foo"); // returns undefined + + return this._hash[id]; // dijit._Widget + }, + + byClass: function(/*String*/ cls){ + // summary: + // Reduce this widgetset to a new WidgetSet of a particular `declaredClass` + // + // cls: String + // The Class to scan for. Full dot-notated string. + // + // example: + // Find all `dijit.TitlePane`s in a page: + // | dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); }); + + var res = new dijit.WidgetSet(), id, widget; + for(id in this._hash){ + widget = this._hash[id]; + if(widget.declaredClass == cls){ + res.add(widget); + } + } + return res; // dijit.WidgetSet +}, + + toArray: function(){ + // summary: + // Convert this WidgetSet into a true Array + // + // example: + // Work with the widget .domNodes in a real Array + // | dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; }); + + var ar = []; + for(var id in this._hash){ + ar.push(this._hash[id]); + } + return ar; // dijit._Widget[] +}, + + map: function(/* Function */func, /* Object? */thisObj){ + // summary: + // Create a new Array from this WidgetSet, following the same rules as `dojo.map` + // example: + // | var nodes = dijit.registry.map(function(w){ return w.domNode; }); + // + // returns: + // A new array of the returned values. + return dojo.map(this.toArray(), func, thisObj); // Array + }, + + every: function(func, thisObj){ + // summary: + // A synthetic clone of `dojo.every` acting explicitly on this WidgetSet + // + // func: Function + // A callback function run for every widget in this list. Exits loop + // when the first false return is encountered. + // + // thisObj: Object? + // Optional scope parameter to use for the callback + + thisObj = thisObj || dojo.global; + var x = 0, i; + for(i in this._hash){ + if(!func.call(thisObj, this._hash[i], x++, this._hash)){ + return false; // Boolean + } + } + return true; // Boolean + }, + + some: function(func, thisObj){ + // summary: + // A synthetic clone of `dojo.some` acting explictly on this WidgetSet + // + // func: Function + // A callback function run for every widget in this list. Exits loop + // when the first true return is encountered. + // + // thisObj: Object? + // Optional scope parameter to use for the callback + + thisObj = thisObj || dojo.global; + var x = 0, i; + for(i in this._hash){ + if(func.call(thisObj, this._hash[i], x++, this._hash)){ + return true; // Boolean + } + } + return false; // Boolean + } + }); -}; -if(_1f(_25)){ -_2c(_25); -} -return {first:_26,last:_27,lowest:_28,highest:_2a}; -}; -dijit.getFirstInTabbingOrder=function(_30){ -var _31=dijit._getTabNavigable(dojo.byId(_30)); -return _31.lowest?_31.lowest:_31.first; -}; -dijit.getLastInTabbingOrder=function(_32){ -var _33=dijit._getTabNavigable(dojo.byId(_32)); -return _33.last?_33.last:_33.highest; -}; -dijit.defaultDuration=dojo.config["defaultDuration"]||200; + +(function(){ + + /*===== + dijit.registry = { + // summary: + // A list of widgets on a page. + // description: + // Is an instance of `dijit.WidgetSet` + }; + =====*/ + dijit.registry = new dijit.WidgetSet(); + + var hash = dijit.registry._hash, + attr = dojo.attr, + hasAttr = dojo.hasAttr, + style = dojo.style; + + dijit.byId = function(/*String|dijit._Widget*/ id){ + // summary: + // Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId()) + return typeof id == "string" ? hash[id] : id; // dijit._Widget + }; + + var _widgetTypeCtr = {}; + dijit.getUniqueId = function(/*String*/widgetType){ + // summary: + // Generates a unique id for a given widgetType + + var id; + do{ + id = widgetType + "_" + + (widgetType in _widgetTypeCtr ? + ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0); + }while(hash[id]); + return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String + }; + + dijit.findWidgets = function(/*DomNode*/ root){ + // summary: + // Search subtree under root returning widgets found. + // Doesn't search for nested widgets (ie, widgets inside other widgets). + + var outAry = []; + + function getChildrenHelper(root){ + for(var node = root.firstChild; node; node = node.nextSibling){ + if(node.nodeType == 1){ + var widgetId = node.getAttribute("widgetId"); + if(widgetId){ + var widget = hash[widgetId]; + if(widget){ // may be null on page w/multiple dojo's loaded + outAry.push(widget); + } + }else{ + getChildrenHelper(node); + } + } + } + } + + getChildrenHelper(root); + return outAry; + }; + + dijit._destroyAll = function(){ + // summary: + // Code to destroy all widgets and do other cleanup on page unload + + // Clean up focus manager lingering references to widgets and nodes + dijit._curFocus = null; + dijit._prevFocus = null; + dijit._activeStack = []; + + // Destroy all the widgets, top down + dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){ + // Avoid double destroy of widgets like Menu that are attached to <body> + // even though they are logically children of other widgets. + if(!widget._destroyed){ + if(widget.destroyRecursive){ + widget.destroyRecursive(); + }else if(widget.destroy){ + widget.destroy(); + } + } + }); + }; + + if(dojo.isIE){ + // Only run _destroyAll() for IE because we think it's only necessary in that case, + // and because it causes problems on FF. See bug #3531 for details. + dojo.addOnWindowUnload(function(){ + dijit._destroyAll(); + }); + } + + dijit.byNode = function(/*DOMNode*/ node){ + // summary: + // Returns the widget corresponding to the given DOMNode + return hash[node.getAttribute("widgetId")]; // dijit._Widget + }; + + dijit.getEnclosingWidget = function(/*DOMNode*/ node){ + // summary: + // Returns the widget whose DOM tree contains the specified DOMNode, or null if + // the node is not contained within the DOM tree of any widget + while(node){ + var id = node.getAttribute && node.getAttribute("widgetId"); + if(id){ + return hash[id]; + } + node = node.parentNode; + } + return null; + }; + + var shown = (dijit._isElementShown = function(/*Element*/ elem){ + var s = style(elem); + return (s.visibility != "hidden") + && (s.visibility != "collapsed") + && (s.display != "none") + && (attr(elem, "type") != "hidden"); + }); + + dijit.hasDefaultTabStop = function(/*Element*/ elem){ + // summary: + // Tests if element is tab-navigable even without an explicit tabIndex setting + + // No explicit tabIndex setting, need to investigate node type + switch(elem.nodeName.toLowerCase()){ + case "a": + // An <a> w/out a tabindex is only navigable if it has an href + return hasAttr(elem, "href"); + case "area": + case "button": + case "input": + case "object": + case "select": + case "textarea": + // These are navigable by default + return true; + case "iframe": + // If it's an editor <iframe> then it's tab navigable. + var body; + try{ + // non-IE + var contentDocument = elem.contentDocument; + if("designMode" in contentDocument && contentDocument.designMode == "on"){ + return true; + } + body = contentDocument.body; + }catch(e1){ + // contentWindow.document isn't accessible within IE7/8 + // if the iframe.src points to a foreign url and this + // page contains an element, that could get focus + try{ + body = elem.contentWindow.document.body; + }catch(e2){ + return false; + } + } + return body.contentEditable == 'true' || (body.firstChild && body.firstChild.contentEditable == 'true'); + default: + return elem.contentEditable == 'true'; + } + }; + + var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){ + // summary: + // Tests if an element is tab-navigable + + // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable() + if(attr(elem, "disabled")){ + return false; + }else if(hasAttr(elem, "tabIndex")){ + // Explicit tab index setting + return attr(elem, "tabIndex") >= 0; // boolean + }else{ + // No explicit tabIndex setting, so depends on node type + return dijit.hasDefaultTabStop(elem); + } + }); + + dijit._getTabNavigable = function(/*DOMNode*/ root){ + // summary: + // Finds descendants of the specified root node. + // + // description: + // Finds the following descendants of the specified root node: + // * the first tab-navigable element in document order + // without a tabIndex or with tabIndex="0" + // * the last tab-navigable element in document order + // without a tabIndex or with tabIndex="0" + // * the first element in document order with the lowest + // positive tabIndex value + // * the last element in document order with the highest + // positive tabIndex value + var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {}; + function radioName(node) { + // If this element is part of a radio button group, return the name for that group. + return node && node.tagName.toLowerCase() == "input" && + node.type && node.type.toLowerCase() == "radio" && + node.name && node.name.toLowerCase(); + } + var walkTree = function(/*DOMNode*/parent){ + dojo.query("> *", parent).forEach(function(child){ + // Skip hidden elements, and also non-HTML elements (those in custom namespaces) in IE, + // since show() invokes getAttribute("type"), which crash on VML nodes in IE. + if((dojo.isIE && child.scopeName!=="HTML") || !shown(child)){ + return; + } + + if(isTabNavigable(child)){ + var tabindex = attr(child, "tabIndex"); + if(!hasAttr(child, "tabIndex") || tabindex == 0){ + if(!first){ first = child; } + last = child; + }else if(tabindex > 0){ + if(!lowest || tabindex < lowestTabindex){ + lowestTabindex = tabindex; + lowest = child; + } + if(!highest || tabindex >= highestTabindex){ + highestTabindex = tabindex; + highest = child; + } + } + var rn = radioName(child); + if(dojo.attr(child, "checked") && rn) { + radioSelected[rn] = child; + } + } + if(child.nodeName.toUpperCase() != 'SELECT'){ + walkTree(child); + } + }); + }; + if(shown(root)){ walkTree(root) } + function rs(node) { + // substitute checked radio button for unchecked one, if there is a checked one with the same name. + return radioSelected[radioName(node)] || node; + } + return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) }; + } + dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){ + // summary: + // Finds the descendant of the specified root node + // that is first in the tabbing order + var elems = dijit._getTabNavigable(dojo.byId(root)); + return elems.lowest ? elems.lowest : elems.first; // DomNode + }; + + dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){ + // summary: + // Finds the descendant of the specified root node + // that is last in the tabbing order + var elems = dijit._getTabNavigable(dojo.byId(root)); + return elems.last ? elems.last : elems.highest; // DomNode + }; + + /*===== + dojo.mixin(dijit, { + // defaultDuration: Integer + // The default animation speed (in ms) to use for all Dijit + // transitional animations, unless otherwise specified + // on a per-instance basis. Defaults to 200, overrided by + // `djConfig.defaultDuration` + defaultDuration: 200 + }); + =====*/ + + dijit.defaultDuration = dojo.config["defaultDuration"] || 200; + })(); + } |