Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2
dojo._hasResource["dijit._Container"] = true;
3
dojo.provide("dijit._Container");
4
 
5
dojo.declare("dijit._Contained",
6
	null,
7
	{
8
		// summary
9
		//		Mixin for widgets that are children of a container widget
10
 
11
		getParent: function(){
12
			// summary:
13
			//		returns the parent widget of this widget, assuming the parent
14
			//		implements dijit._Container
15
			for(var p=this.domNode.parentNode; p; p=p.parentNode){
16
				var id = p.getAttribute && p.getAttribute("widgetId");
17
				if(id){
18
					var parent = dijit.byId(id);
19
					return parent.isContainer ? parent : null;
20
				}
21
			}
22
			return null;
23
		},
24
 
25
		_getSibling: function(which){
26
			var node = this.domNode;
27
			do{
28
				node = node[which+"Sibling"];
29
			}while(node && node.nodeType != 1);
30
			if(!node){ return null; } // null
31
			var id = node.getAttribute("widgetId");
32
			return dijit.byId(id);
33
		},
34
 
35
		getPreviousSibling: function(){
36
			// summary:
37
			//		returns null if this is the first child of the parent,
38
			//		otherwise returns the next element sibling to the "left".
39
 
40
			return this._getSibling("previous");
41
		},
42
 
43
		getNextSibling: function(){
44
			// summary:
45
			//		returns null if this is the last child of the parent,
46
			//		otherwise returns the next element sibling to the "right".
47
 
48
			return this._getSibling("next");
49
		}
50
	}
51
);
52
 
53
dojo.declare("dijit._Container",
54
	null,
55
	{
56
		// summary
57
		//		Mixin for widgets that contain a list of children like SplitContainer
58
 
59
		isContainer: true,
60
 
61
		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
62
			// summary:
63
			//		Process the given child widget, inserting it's dom node as
64
			//		a child of our dom node
65
 
66
			if(insertIndex === undefined){
67
				insertIndex = "last";
68
			}
69
			var refNode = this.containerNode || this.domNode;
70
			if(insertIndex && typeof insertIndex == "number"){
71
				var children = dojo.query("> [widgetid]", refNode);
72
				if(children && children.length >= insertIndex){
73
					refNode = children[insertIndex-1]; insertIndex = "after";
74
				}
75
			}
76
			dojo.place(widget.domNode, refNode, insertIndex);
77
 
78
			// If I've been started but the child widget hasn't been started,
79
			// start it now.  Make sure to do this after widget has been
80
			// inserted into the DOM tree, so it can see that it's being controlled by me,
81
			// so it doesn't try to size itself.
82
			if(this._started && !widget._started){
83
				widget.startup();
84
			}
85
		},
86
 
87
		removeChild: function(/*Widget*/ widget){
88
			// summary:
89
			//		removes the passed widget instance from this widget but does
90
			//		not destroy it
91
			var node = widget.domNode;
92
			node.parentNode.removeChild(node);	// detach but don't destroy
93
		},
94
 
95
		_nextElement: function(node){
96
			do{
97
				node = node.nextSibling;
98
			}while(node && node.nodeType != 1);
99
			return node;
100
		},
101
 
102
		_firstElement: function(node){
103
			node = node.firstChild;
104
			if(node && node.nodeType != 1){
105
				node = this._nextElement(node);
106
			}
107
			return node;
108
		},
109
 
110
		getChildren: function(){
111
			// summary:
112
			//		Returns array of children widgets
113
			return dojo.query("> [widgetId]", this.containerNode || this.domNode).map(dijit.byNode); // Array
114
		},
115
 
116
		hasChildren: function(){
117
			// summary:
118
			//		Returns true if widget has children
119
			var cn = this.containerNode || this.domNode;
120
			return !!this._firstElement(cn); // Boolean
121
		},
122
 
123
		_getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){
124
			// summary:
125
			//		get the next or previous widget sibling of child
126
			// dir:
127
			//		if 1, get the next sibling
128
			//		if -1, get the previous sibling
129
			var node = child.domNode;
130
			var which = (dir>0 ? "nextSibling" : "previousSibling");
131
			do{
132
				node = node[which];
133
			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
134
			return node ? dijit.byNode(node) : null;
135
		}
136
	}
137
);
138
 
139
dojo.declare("dijit._KeyNavContainer",
140
	[dijit._Container],
141
	{
142
 
143
		// summary:
144
		//		A _Container with keyboard navigation of its children.
145
		//		To use this mixin, call connectKeyNavHandlers() in
146
		//		postCreate() and call startupKeyNavChildren() in startup().
147
 
148
/*=====
149
		// focusedChild: Widget
150
		//		The currently focused child widget, or null if there isn't one
151
		focusedChild: null,
152
=====*/
153
 
154
		_keyNavCodes: {},
155
 
156
		connectKeyNavHandlers: function(/*Array*/ prevKeyCodes, /*Array*/ nextKeyCodes){
157
			// summary:
158
			//		Call in postCreate() to attach the keyboard handlers
159
			//		to the container.
160
			// preKeyCodes: Array
161
			//		Key codes for navigating to the previous child.
162
			// nextKeyCodes: Array
163
			//		Key codes for navigating to the next child.
164
 
165
			var keyCodes = this._keyNavCodes = {};
166
			var prev = dojo.hitch(this, this.focusPrev);
167
			var next = dojo.hitch(this, this.focusNext);
168
			dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev });
169
			dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next });
170
			this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
171
			if(dojo.isIE){
172
				this.connect(this.domNode, "onactivate", "_onContainerFocus");
173
				this.connect(this.domNode, "ondeactivate", "_onContainerBlur");
174
			}else{
175
				this.connect(this.domNode, "onfocus", "_onContainerFocus");
176
				this.connect(this.domNode, "onblur", "_onContainerBlur");
177
			}
178
		},
179
 
180
		startupKeyNavChildren: function(){
181
			// summary:
182
			//		Call in startup() to set child tabindexes to -1
183
			dojo.forEach(this.getChildren(), dojo.hitch(this, "_setTabIndexMinusOne"));
184
		},
185
 
186
		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
187
			// summary: Add a child to our _Container
188
			dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
189
			this._setTabIndexMinusOne(widget);
190
		},
191
 
192
		focus: function(){
193
			// summary: Default focus() implementation: focus the first child.
194
			this.focusFirstChild();
195
		},
196
 
197
		focusFirstChild: function(){
198
			// summary: Focus the first focusable child in the container.
199
			this.focusChild(this._getFirstFocusableChild());
200
		},
201
 
202
		focusNext: function(){
203
			// summary: Focus the next widget or focal node (for widgets
204
			//		with multiple focal nodes) within this container.
205
			if(this.focusedChild && this.focusedChild.hasNextFocalNode
206
					&& this.focusedChild.hasNextFocalNode()){
207
				this.focusedChild.focusNext();
208
				return;
209
			}
210
			var child = this._getNextFocusableChild(this.focusedChild, 1);
211
			if(child.getFocalNodes){
212
				this.focusChild(child, child.getFocalNodes()[0]);
213
			}else{
214
				this.focusChild(child);
215
			}
216
		},
217
 
218
		focusPrev: function(){
219
			// summary: Focus the previous widget or focal node (for widgets
220
			//		with multiple focal nodes) within this container.
221
			if(this.focusedChild && this.focusedChild.hasPrevFocalNode
222
					&& this.focusedChild.hasPrevFocalNode()){
223
				this.focusedChild.focusPrev();
224
				return;
225
			}
226
			var child = this._getNextFocusableChild(this.focusedChild, -1);
227
			if(child.getFocalNodes){
228
				var nodes = child.getFocalNodes();
229
				this.focusChild(child, nodes[nodes.length-1]);
230
			}else{
231
				this.focusChild(child);
232
			}
233
		},
234
 
235
		focusChild: function(/*Widget*/ widget, /*Node?*/ node){
236
			// summary: Focus widget. Optionally focus 'node' within widget.
237
			if(widget){
238
				if(this.focusedChild && widget !== this.focusedChild){
239
					this._onChildBlur(this.focusedChild);
240
				}
241
				this.focusedChild = widget;
242
				if(node && widget.focusFocalNode){
243
					widget.focusFocalNode(node);
244
				}else{
245
					widget.focus();
246
				}
247
			}
248
		},
249
 
250
		_setTabIndexMinusOne: function(/*Widget*/ widget){
251
			if(widget.getFocalNodes){
252
				dojo.forEach(widget.getFocalNodes(), function(node){
253
					node.setAttribute("tabIndex", -1);
254
				});
255
			}else{
256
				(widget.focusNode || widget.domNode).setAttribute("tabIndex", -1);
257
			}
258
		},
259
 
260
		_onContainerFocus: function(evt){
261
			this.domNode.setAttribute("tabIndex", -1);
262
			if(evt.target === this.domNode){
263
				this.focusFirstChild();
264
			}else{
265
				var widget = dijit.getEnclosingWidget(evt.target);
266
				if(widget && widget.isFocusable()){
267
					this.focusedChild = widget;
268
				}
269
			}
270
		},
271
 
272
		_onContainerBlur: function(evt){
273
			if(this.tabIndex){
274
				this.domNode.setAttribute("tabIndex", this.tabIndex);
275
			}
276
		},
277
 
278
		_onContainerKeypress: function(evt){
279
			if(evt.ctrlKey || evt.altKey){ return; }
280
			var func = this._keyNavCodes[evt.keyCode];
281
			if(func){
282
				func();
283
				dojo.stopEvent(evt);
284
			}
285
		},
286
 
287
		_onChildBlur: function(/*Widget*/ widget){
288
			// summary:
289
			//		Called when focus leaves a child widget to go
290
			//		to a sibling widget.
291
		},
292
 
293
		_getFirstFocusableChild: function(){
294
			return this._getNextFocusableChild(null, 1);
295
		},
296
 
297
		_getNextFocusableChild: function(child, dir){
298
			if(child){
299
				child = this._getSiblingOfChild(child, dir);
300
			}
301
			var children = this.getChildren();
302
			for(var i=0; i < children.length; i++){
303
				if(!child){
304
					child = children[(dir>0) ? 0 : (children.length-1)];
305
				}
306
				if(child.isFocusable()){
307
					return child;
308
				}
309
				child = this._getSiblingOfChild(child, dir);
310
			}
311
		}
312
	}
313
);
314
 
315
}