]>
Commit | Line | Data |
---|---|---|
1354d172 AD |
1 | define("dijit/registry", [ |
2 | "dojo/_base/array", // array.forEach array.map | |
3 | "dojo/_base/sniff", // has("ie") | |
4 | "dojo/_base/unload", // unload.addOnWindowUnload | |
5 | "dojo/_base/window", // win.body | |
6 | "." // dijit._scopeName | |
7 | ], function(array, has, unload, win, dijit){ | |
8 | ||
9 | // module: | |
10 | // dijit/registry | |
11 | // summary: | |
12 | // Registry of existing widget on page, plus some utility methods. | |
13 | // Must be accessed through AMD api, ex: | |
14 | // require(["dijit/registry"], function(registry){ registry.byId("foo"); }) | |
15 | ||
16 | var _widgetTypeCtr = {}, hash = {}; | |
17 | ||
18 | var registry = { | |
19 | // summary: | |
20 | // A set of widgets indexed by id | |
21 | ||
22 | length: 0, | |
23 | ||
24 | add: function(/*dijit._Widget*/ widget){ | |
25 | // summary: | |
26 | // Add a widget to the registry. If a duplicate ID is detected, a error is thrown. | |
27 | // | |
28 | // widget: dijit._Widget | |
29 | // Any dijit._Widget subclass. | |
30 | if(hash[widget.id]){ | |
31 | throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered"); | |
32 | } | |
33 | hash[widget.id] = widget; | |
34 | this.length++; | |
35 | }, | |
36 | ||
37 | remove: function(/*String*/ id){ | |
38 | // summary: | |
39 | // Remove a widget from the registry. Does not destroy the widget; simply | |
40 | // removes the reference. | |
41 | if(hash[id]){ | |
42 | delete hash[id]; | |
43 | this.length--; | |
44 | } | |
45 | }, | |
46 | ||
47 | byId: function(/*String|Widget*/ id){ | |
48 | // summary: | |
49 | // Find a widget by it's id. | |
50 | // If passed a widget then just returns the widget. | |
51 | return typeof id == "string" ? hash[id] : id; // dijit._Widget | |
52 | }, | |
53 | ||
54 | byNode: function(/*DOMNode*/ node){ | |
55 | // summary: | |
56 | // Returns the widget corresponding to the given DOMNode | |
57 | return hash[node.getAttribute("widgetId")]; // dijit._Widget | |
58 | }, | |
59 | ||
60 | toArray: function(){ | |
61 | // summary: | |
62 | // Convert registry into a true Array | |
63 | // | |
64 | // example: | |
65 | // Work with the widget .domNodes in a real Array | |
66 | // | array.map(dijit.registry.toArray(), function(w){ return w.domNode; }); | |
67 | ||
68 | var ar = []; | |
69 | for(var id in hash){ | |
70 | ar.push(hash[id]); | |
71 | } | |
72 | return ar; // dijit._Widget[] | |
73 | }, | |
74 | ||
75 | getUniqueId: function(/*String*/widgetType){ | |
76 | // summary: | |
77 | // Generates a unique id for a given widgetType | |
78 | ||
79 | var id; | |
80 | do{ | |
81 | id = widgetType + "_" + | |
82 | (widgetType in _widgetTypeCtr ? | |
83 | ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0); | |
84 | }while(hash[id]); | |
85 | return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String | |
86 | }, | |
87 | ||
88 | findWidgets: function(/*DomNode*/ root){ | |
89 | // summary: | |
90 | // Search subtree under root returning widgets found. | |
91 | // Doesn't search for nested widgets (ie, widgets inside other widgets). | |
92 | ||
93 | var outAry = []; | |
94 | ||
95 | function getChildrenHelper(root){ | |
96 | for(var node = root.firstChild; node; node = node.nextSibling){ | |
97 | if(node.nodeType == 1){ | |
98 | var widgetId = node.getAttribute("widgetId"); | |
99 | if(widgetId){ | |
100 | var widget = hash[widgetId]; | |
101 | if(widget){ // may be null on page w/multiple dojo's loaded | |
102 | outAry.push(widget); | |
103 | } | |
104 | }else{ | |
105 | getChildrenHelper(node); | |
106 | } | |
107 | } | |
108 | } | |
109 | } | |
110 | ||
111 | getChildrenHelper(root); | |
112 | return outAry; | |
113 | }, | |
114 | ||
115 | _destroyAll: function(){ | |
116 | // summary: | |
117 | // Code to destroy all widgets and do other cleanup on page unload | |
118 | ||
119 | // Clean up focus manager lingering references to widgets and nodes | |
120 | dijit._curFocus = null; | |
121 | dijit._prevFocus = null; | |
122 | dijit._activeStack = []; | |
123 | ||
124 | // Destroy all the widgets, top down | |
125 | array.forEach(registry.findWidgets(win.body()), function(widget){ | |
126 | // Avoid double destroy of widgets like Menu that are attached to <body> | |
127 | // even though they are logically children of other widgets. | |
128 | if(!widget._destroyed){ | |
129 | if(widget.destroyRecursive){ | |
130 | widget.destroyRecursive(); | |
131 | }else if(widget.destroy){ | |
132 | widget.destroy(); | |
133 | } | |
134 | } | |
135 | }); | |
136 | }, | |
137 | ||
138 | getEnclosingWidget: function(/*DOMNode*/ node){ | |
139 | // summary: | |
140 | // Returns the widget whose DOM tree contains the specified DOMNode, or null if | |
141 | // the node is not contained within the DOM tree of any widget | |
142 | while(node){ | |
143 | var id = node.getAttribute && node.getAttribute("widgetId"); | |
144 | if(id){ | |
145 | return hash[id]; | |
146 | } | |
147 | node = node.parentNode; | |
148 | } | |
149 | return null; | |
150 | }, | |
151 | ||
152 | // In case someone needs to access hash. | |
153 | // Actually, this is accessed from WidgetSet back-compatibility code | |
154 | _hash: hash | |
155 | }; | |
156 | ||
157 | if(has("ie")){ | |
158 | // Only run _destroyAll() for IE because we think it's only necessary in that case, | |
159 | // and because it causes problems on FF. See bug #3531 for details. | |
160 | unload.addOnWindowUnload(function(){ | |
161 | registry._destroyAll(); | |
162 | }); | |
163 | } | |
164 | ||
165 | /*===== | |
166 | dijit.registry = { | |
167 | // summary: | |
168 | // A list of widgets on a page. | |
169 | }; | |
170 | =====*/ | |
171 | dijit.registry = registry; | |
172 | ||
173 | return registry; | |
174 | }); |