Subversion Repositories Applications.papyrus

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2150 mathias 1
/*
2
	Copyright (c) 2004-2007, The Dojo Foundation
3
	All Rights Reserved.
4
 
5
	Licensed under the Academic Free License version 2.1 or above OR the
6
	modified BSD license. For more information on Dojo licensing, see:
7
 
8
		http://dojotoolkit.org/book/dojo-book-0-9/introduction/licensing
9
*/
10
 
11
/*
12
	This is a compiled version of Dojo, built for deployment and not for
13
	development. To get an editable version, please visit:
14
 
15
		http://dojotoolkit.org
16
 
17
	for documentation and information on getting the source.
18
*/
19
 
20
if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
21
dojo._hasResource["dijit._base.focus"] = true;
22
dojo.provide("dijit._base.focus");
23
 
24
// summary:
25
//		These functions are used to query or set the focus and selection.
26
//
27
//		Also, they trace when widgets become actived/deactivated,
28
//		so that the widget can fire _onFocus/_onBlur events.
29
//		"Active" here means something similar to "focused", but
30
//		"focus" isn't quite the right word because we keep track of
31
//		a whole stack of "active" widgets.  Example:  Combobutton --> Menu -->
32
//		MenuItem.   The onBlur event for Combobutton doesn't fire due to focusing
33
//		on the Menu or a MenuItem, since they are considered part of the
34
//		Combobutton widget.  It only happens when focus is shifted
35
//		somewhere completely different.
36
 
37
dojo.mixin(dijit,
38
{
39
	// _curFocus: DomNode
40
	//		Currently focused item on screen
41
	_curFocus: null,
42
 
43
	// _prevFocus: DomNode
44
	//		Previously focused item on screen
45
	_prevFocus: null,
46
 
47
	isCollapsed: function(){
48
		// summary: tests whether the current selection is empty
49
		var _window = dojo.global;
50
		var _document = dojo.doc;
51
		if(_document.selection){ // IE
52
			return !_document.selection.createRange().text; // Boolean
53
		}else if(_window.getSelection){
54
			var selection = _window.getSelection();
55
			if(dojo.isString(selection)){ // Safari
56
				return !selection; // Boolean
57
			}else{ // Mozilla/W3
58
				return selection.isCollapsed || !selection.toString(); // Boolean
59
			}
60
		}
61
	},
62
 
63
	getBookmark: function(){
64
		// summary: Retrieves a bookmark that can be used with moveToBookmark to return to the same range
65
		var bookmark, selection = dojo.doc.selection;
66
		if(selection){ // IE
67
			var range = selection.createRange();
68
			if(selection.type.toUpperCase()=='CONTROL'){
69
				bookmark = range.length ? dojo._toArray(range) : null;
70
			}else{
71
				bookmark = range.getBookmark();
72
			}
73
		}else{
74
			if(dojo.global.getSelection){
75
				selection = dojo.global.getSelection();
76
				if(selection){
77
					var range = selection.getRangeAt(0);
78
					bookmark = range.cloneRange();
79
				}
80
			}else{
81
				console.debug("No idea how to store the current selection for this browser!");
82
			}
83
		}
84
		return bookmark; // Array
85
	},
86
 
87
	moveToBookmark: function(/*Object*/bookmark){
88
		// summary: Moves current selection to a bookmark
89
		// bookmark: this should be a returned object from dojo.html.selection.getBookmark()
90
		var _document = dojo.doc;
91
		if(_document.selection){ // IE
92
			var range;
93
			if(dojo.isArray(bookmark)){
94
				range = _document.body.createControlRange();
95
				dojo.forEach(bookmark, range.addElement);
96
			}else{
97
				range = _document.selection.createRange();
98
				range.moveToBookmark(bookmark);
99
			}
100
			range.select();
101
		}else{ //Moz/W3C
102
			var selection = dojo.global.getSelection && dojo.global.getSelection();
103
			if(selection && selection.removeAllRanges){
104
				selection.removeAllRanges();
105
				selection.addRange(bookmark);
106
			}else{
107
				console.debug("No idea how to restore selection for this browser!");
108
			}
109
		}
110
	},
111
 
112
	getFocus: function(/*Widget*/menu, /*Window*/ openedForWindow){
113
		// summary:
114
		//	Returns the current focus and selection.
115
		//	Called when a popup appears (either a top level menu or a dialog),
116
		//	or when a toolbar/menubar receives focus
117
		//
118
		// menu:
119
		//	the menu that's being opened
120
		//
121
		// openedForWindow:
122
		//	iframe in which menu was opened
123
		//
124
		// returns:
125
		//	a handle to restore focus/selection
126
 
127
		return {
128
			// Node to return focus to
129
			node: menu && dojo.isDescendant(dijit._curFocus, menu.domNode) ? dijit._prevFocus : dijit._curFocus,
130
 
131
			// Previously selected text
132
			bookmark:
133
				!dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed) ?
134
				dojo.withGlobal(openedForWindow||dojo.global, dijit.getBookmark) :
135
				null,
136
 
137
			openedForWindow: openedForWindow
138
		}; // Object
139
	},
140
 
141
	focus: function(/*Object || DomNode */ handle){
142
		// summary:
143
		//		Sets the focused node and the selection according to argument.
144
		//		To set focus to an iframe's content, pass in the iframe itself.
145
		// handle:
146
		//		object returned by get(), or a DomNode
147
 
148
		if(!handle){ return; }
149
 
150
		var node = "node" in handle ? handle.node : handle,		// because handle is either DomNode or a composite object
151
			bookmark = handle.bookmark,
152
			openedForWindow = handle.openedForWindow;
153
 
154
		// Set the focus
155
		// Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
156
		// but we need to set focus to iframe.contentWindow
157
		if(node){
158
			var focusNode = (node.tagName.toLowerCase()=="iframe") ? node.contentWindow : node;
159
			if(focusNode && focusNode.focus){
160
				try{
161
					// Gecko throws sometimes if setting focus is impossible,
162
					// node not displayed or something like that
163
					focusNode.focus();
164
				}catch(e){/*quiet*/}
165
			}
166
			dijit._onFocusNode(node);
167
		}
168
 
169
		// set the selection
170
		// do not need to restore if current selection is not empty
171
		// (use keyboard to select a menu item)
172
		if(bookmark && dojo.withGlobal(openedForWindow||dojo.global, dijit.isCollapsed)){
173
			if(openedForWindow){
174
				openedForWindow.focus();
175
			}
176
			try{
177
				dojo.withGlobal(openedForWindow||dojo.global, moveToBookmark, null, [bookmark]);
178
			}catch(e){
179
				/*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
180
			}
181
		}
182
	},
183
 
184
	// List of currently active widgets (focused widget and it's ancestors)
185
	_activeStack: [],
186
 
187
	registerWin: function(/*Window?*/targetWindow){
188
		// summary:
189
		//		Registers listeners on the specified window (either the main
190
		//		window or an iframe) to detect when the user has clicked somewhere.
191
		//		Anyone that creates an iframe should call this function.
192
 
193
		if(!targetWindow){
194
			targetWindow = window;
195
		}
196
 
197
		dojo.connect(targetWindow.document, "onmousedown", null, function(evt){
198
			dijit._justMouseDowned = true;
199
			setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
200
			dijit._onTouchNode(evt.target||evt.srcElement);
201
		});
202
		//dojo.connect(targetWindow, "onscroll", ???);
203
 
204
		// Listen for blur and focus events on targetWindow's body
205
		var body = targetWindow.document.body || targetWindow.document.getElementsByTagName("body")[0];
206
		if(body){
207
			if(dojo.isIE){
208
				body.attachEvent('onactivate', function(evt){
209
					if(evt.srcElement.tagName.toLowerCase() != "body"){
210
						dijit._onFocusNode(evt.srcElement);
211
					}
212
				});
213
				body.attachEvent('ondeactivate', function(evt){ dijit._onBlurNode(evt.srcElement); });
214
			}else{
215
				body.addEventListener('focus', function(evt){ dijit._onFocusNode(evt.target); }, true);
216
				body.addEventListener('blur', function(evt){ dijit._onBlurNode(evt.target); }, true);
217
			}
218
		}
219
		body = null;	// prevent memory leak (apparent circular reference via closure)
220
	},
221
 
222
	_onBlurNode: function(/*DomNode*/ node){
223
		// summary:
224
		// 		Called when focus leaves a node.
225
		//		Usually ignored, _unless_ it *isn't* follwed by touching another node,
226
		//		which indicates that we tabbed off the last field on the page,
227
		//		in which case every widget is marked inactive
228
		dijit._prevFocus = dijit._curFocus;
229
		dijit._curFocus = null;
230
 
231
		var w = dijit.getEnclosingWidget(node);
232
		if (w && w._setStateClass){
233
			w._focused = false;
234
			w._setStateClass();
235
		}
236
		if(dijit._justMouseDowned){
237
			// the mouse down caused a new widget to be marked as active; this blur event
238
			// is coming late, so ignore it.
239
			return;
240
		}
241
 
242
		// if the blur event isn't followed by a focus event then mark all widgets as inactive.
243
		if(dijit._clearActiveWidgetsTimer){
244
			clearTimeout(dijit._clearActiveWidgetsTimer);
245
		}
246
		dijit._clearActiveWidgetsTimer = setTimeout(function(){
247
			delete dijit._clearActiveWidgetsTimer; dijit._setStack([]); }, 100);
248
	},
249
 
250
	_onTouchNode: function(/*DomNode*/ node){
251
		// summary
252
		//		Callback when node is focused or mouse-downed
253
 
254
		// ignore the recent blurNode event
255
		if(dijit._clearActiveWidgetsTimer){
256
			clearTimeout(dijit._clearActiveWidgetsTimer);
257
			delete dijit._clearActiveWidgetsTimer;
258
		}
259
 
260
		// compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
261
		var newStack=[];
262
		try{
263
			while(node){
264
				if(node.dijitPopupParent){
265
					node=dijit.byId(node.dijitPopupParent).domNode;
266
				}else if(node.tagName && node.tagName.toLowerCase()=="body"){
267
					// is this the root of the document or just the root of an iframe?
268
					if(node===dojo.body()){
269
						// node is the root of the main document
270
						break;
271
					}
272
					// otherwise, find the iframe this node refers to (can't access it via parentNode,
273
					// need to do this trick instead) and continue tracing up the document
274
					node=dojo.query("iframe").filter(function(iframe){ return iframe.contentDocument.body===node; })[0];
275
				}else{
276
					var id = node.getAttribute && node.getAttribute("widgetId");
277
					if(id){
278
						newStack.unshift(id);
279
					}
280
					node=node.parentNode;
281
				}
282
			}
283
		}catch(e){ /* squelch */ }
284
 
285
		dijit._setStack(newStack);
286
	},
287
 
288
	_onFocusNode: function(/*DomNode*/ node){
289
		// summary
290
		//		Callback when node is focused
291
		if(node && node.tagName && node.tagName.toLowerCase() == "body"){
292
			return;
293
		}
294
		dijit._onTouchNode(node);
295
		if(node==dijit._curFocus){ return; }
296
		dijit._prevFocus = dijit._curFocus;
297
		dijit._curFocus = node;
298
		dojo.publish("focusNode", [node]);
299
 
300
		// handle focus/blur styling
301
		var w = dijit.getEnclosingWidget(node);
302
		if (w && w._setStateClass){
303
			w._focused = true;
304
			w._setStateClass();
305
		}
306
	},
307
 
308
	_setStack: function(newStack){
309
		// summary
310
		//	The stack of active widgets has changed.  Send out appropriate events and record new stack
311
 
312
		var oldStack = dijit._activeStack;
313
		dijit._activeStack = newStack;
314
 
315
		// compare old stack to new stack to see how many elements they have in common
316
		for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
317
			if(oldStack[nCommon] != newStack[nCommon]){
318
				break;
319
			}
320
		}
321
 
322
		// for all elements that have gone out of focus, send blur event
323
		for(var i=oldStack.length-1; i>=nCommon; i--){
324
			var widget = dijit.byId(oldStack[i]);
325
			if(widget){
326
				dojo.publish("widgetBlur", [widget]);
327
				if(widget._onBlur){
328
					widget._onBlur();
329
				}
330
			}
331
		}
332
 
333
		// for all element that have come into focus, send focus event
334
		for(var i=nCommon; i<newStack.length; i++){
335
			var widget = dijit.byId(newStack[i]);
336
			if(widget){
337
				dojo.publish("widgetFocus", [widget]);
338
				if(widget._onFocus){
339
					widget._onFocus();
340
				}
341
			}
342
		}
343
	}
344
});
345
 
346
// register top window and all the iframes it contains
347
dojo.addOnLoad(dijit.registerWin);
348
 
349
}
350
 
351
if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
352
dojo._hasResource["dijit._base.manager"] = true;
353
dojo.provide("dijit._base.manager");
354
 
355
dojo.declare("dijit.WidgetSet", null, {
356
	constructor: function(){
357
		// summary:
358
		//	A set of widgets indexed by id
359
		this._hash={};
360
	},
361
 
362
	add: function(/*Widget*/ widget){
363
		if(this._hash[widget.id]){
364
			throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
365
		}
366
		this._hash[widget.id]=widget;
367
	},
368
 
369
	remove: function(/*String*/ id){
370
		delete this._hash[id];
371
	},
372
 
373
	forEach: function(/*Function*/ func){
374
		for(var id in this._hash){
375
			func(this._hash[id]);
376
		}
377
	},
378
 
379
	filter: function(/*Function*/ filter){
380
		var res = new dijit.WidgetSet();
381
		this.forEach(function(widget){
382
			if(filter(widget)){ res.add(widget); }
383
		});
384
		return res;		// dijit.WidgetSet
385
	},
386
 
387
	byId: function(/*String*/ id){
388
		return this._hash[id];
389
	},
390
 
391
	byClass: function(/*String*/ cls){
392
		return this.filter(function(widget){ return widget.declaredClass==cls; });	// dijit.WidgetSet
393
	}
394
	});
395
 
396
// registry: list of all widgets on page
397
dijit.registry = new dijit.WidgetSet();
398
 
399
dijit._widgetTypeCtr = {};
400
 
401
dijit.getUniqueId = function(/*String*/widgetType){
402
	// summary
403
	//	Generates a unique id for a given widgetType
404
 
405
	var id;
406
	do{
407
		id = widgetType + "_" +
408
			(dijit._widgetTypeCtr[widgetType] !== undefined ?
409
				++dijit._widgetTypeCtr[widgetType] : dijit._widgetTypeCtr[widgetType] = 0);
410
	}while(dijit.byId(id));
411
	return id; // String
412
};
413
 
414
 
415
if(dojo.isIE){
416
	// Only run this for IE because we think it's only necessary in that case,
417
	// and because it causes problems on FF.  See bug #3531 for details.
418
	dojo.addOnUnload(function(){
419
		dijit.registry.forEach(function(widget){ widget.destroy(); });
420
	});
421
}
422
 
423
dijit.byId = function(/*String|Widget*/id){
424
	// summary:
425
	//		Returns a widget by its id, or if passed a widget, no-op (like dojo.byId())
426
	return (dojo.isString(id)) ? dijit.registry.byId(id) : id; // Widget
427
};
428
 
429
dijit.byNode = function(/* DOMNode */ node){
430
	// summary:
431
	//		Returns the widget as referenced by node
432
	return dijit.registry.byId(node.getAttribute("widgetId")); // Widget
433
};
434
 
435
dijit.getEnclosingWidget = function(/* DOMNode */ node){
436
	// summary:
437
	//		Returns the widget whose dom tree contains node or null if
438
	//		the node is not contained within the dom tree of any widget
439
	while(node){
440
		if(node.getAttribute && node.getAttribute("widgetId")){
441
			return dijit.registry.byId(node.getAttribute("widgetId"));
442
		}
443
		node = node.parentNode;
444
	}
445
	return null;
446
};
447
 
448
}
449
 
450
if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
451
dojo._hasResource["dijit._base.place"] = true;
452
dojo.provide("dijit._base.place");
453
 
454
// ported from dojo.html.util
455
 
456
dijit.getViewport = function(){
457
	//	summary
458
	//	Returns the dimensions and scroll position of the viewable area of a browser window
459
 
460
	var _window = dojo.global;
461
	var _document = dojo.doc;
462
 
463
	// get viewport size
464
	var w = 0, h = 0;
465
	if(dojo.isMozilla){
466
		// mozilla
467
		// _window.innerHeight includes the height taken by the scroll bar
468
		// clientHeight is ideal but has DTD issues:
469
		// #4539: FF reverses the roles of body.clientHeight/Width and documentElement.clientHeight/Width based on the DTD!
470
		// check DTD to see whether body or documentElement returns the viewport dimensions using this algorithm:
471
		var minw, minh, maxw, maxh;
472
		if(_document.body.clientWidth>_document.documentElement.clientWidth){
473
			minw = _document.documentElement.clientWidth;
474
			maxw = _document.body.clientWidth;
475
		}else{
476
			maxw = _document.documentElement.clientWidth;
477
			minw = _document.body.clientWidth;
478
		}
479
		if(_document.body.clientHeight>_document.documentElement.clientHeight){
480
			minh = _document.documentElement.clientHeight;
481
			maxh = _document.body.clientHeight;
482
		}else{
483
			maxh = _document.documentElement.clientHeight;
484
			minh = _document.body.clientHeight;
485
		}
486
		w = (maxw > _window.innerWidth) ? minw : maxw;
487
		h = (maxh > _window.innerHeight) ? minh : maxh;
488
	}else if(!dojo.isOpera && _window.innerWidth){
489
		//in opera9, dojo.body().clientWidth should be used, instead
490
		//of window.innerWidth/document.documentElement.clientWidth
491
		//so we have to check whether it is opera
492
		w = _window.innerWidth;
493
		h = _window.innerHeight;
494
	}else if(dojo.isIE && _document.documentElement && _document.documentElement.clientHeight){
495
		w = _document.documentElement.clientWidth;
496
		h = _document.documentElement.clientHeight;
497
	}else if(dojo.body().clientWidth){
498
		// IE5, Opera
499
		w = dojo.body().clientWidth;
500
		h = dojo.body().clientHeight;
501
	}
502
 
503
	// get scroll position
504
	var scroll = dojo._docScroll();
505
 
506
	return { w: w, h: h, l: scroll.x, t: scroll.y };	//	object
507
};
508
 
509
dijit.placeOnScreen = function(
510
	/* DomNode */	node,
511
	/* Object */		pos,
512
	/* Object */		corners,
513
	/* boolean? */		tryOnly){
514
	//	summary:
515
	//		Keeps 'node' in the visible area of the screen while trying to
516
	//		place closest to pos.x, pos.y. The input coordinates are
517
	//		expected to be the desired document position.
518
	//
519
	//		Set which corner(s) you want to bind to, such as
520
	//
521
	//			placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
522
	//
523
	//		The desired x/y will be treated as the topleft(TL)/topright(TR) or
524
	//		BottomLeft(BL)/BottomRight(BR) corner of the node. Each corner is tested
525
	//		and if a perfect match is found, it will be used. Otherwise, it goes through
526
	//		all of the specified corners, and choose the most appropriate one.
527
	//
528
	//		NOTE: node is assumed to be absolutely or relatively positioned.
529
 
530
	var choices = dojo.map(corners, function(corner){ return { corner: corner, pos: pos }; });
531
 
532
	return dijit._place(node, choices);
533
}
534
 
535
dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
536
	// summary:
537
	//		Given a list of spots to put node, put it at the first spot where it fits,
538
	//		of if it doesn't fit anywhere then the place with the least overflow
539
	// choices: Array
540
	//		Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
541
	//		Above example says to put the top-left corner of the node at (10,20)
542
	//	layoutNode: Function(node, orient)
543
	//		for things like tooltip, they are displayed differently (and have different dimensions)
544
	//		based on their orientation relative to the parent.   This adjusts the popup based on orientation.
545
 
546
	// get {x: 10, y: 10, w: 100, h:100} type obj representing position of
547
	// viewport over document
548
	var view = dijit.getViewport();
549
 
550
	// This won't work if the node is inside a <div style="position: relative">,
551
	// so reattach it to document.body.   (Otherwise, the positioning will be wrong
552
	// and also it might get cutoff)
553
	if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
554
		dojo.body().appendChild(node);
555
	}
556
 
557
	var best=null;
558
	for(var i=0; i<choices.length; i++){
559
		var corner = choices[i].corner;
560
		var pos = choices[i].pos;
561
 
562
		// configure node to be displayed in given position relative to button
563
		// (need to do this in order to get an accurate size for the node, because
564
		// a tooltips size changes based on position, due to triangle)
565
		if(layoutNode){
566
			layoutNode(corner);
567
		}
568
 
569
		// get node's size
570
		var oldDisplay = node.style.display;
571
		var oldVis = node.style.visibility;
572
		node.style.visibility = "hidden";
573
		node.style.display = "";
574
		var mb = dojo.marginBox(node);
575
		node.style.display = oldDisplay;
576
		node.style.visibility = oldVis;
577
 
578
		// coordinates and size of node with specified corner placed at pos,
579
		// and clipped by viewport
580
		var startX = (corner.charAt(1)=='L' ? pos.x : Math.max(view.l, pos.x - mb.w)),
581
			startY = (corner.charAt(0)=='T' ? pos.y : Math.max(view.t, pos.y -  mb.h)),
582
			endX = (corner.charAt(1)=='L' ? Math.min(view.l+view.w, startX+mb.w) : pos.x),
583
			endY = (corner.charAt(0)=='T' ? Math.min(view.t+view.h, startY+mb.h) : pos.y),
584
			width = endX-startX,
585
			height = endY-startY,
586
			overflow = (mb.w-width) + (mb.h-height);
587
 
588
		if(best==null || overflow<best.overflow){
589
			best = {
590
				corner: corner,
591
				aroundCorner: choices[i].aroundCorner,
592
				x: startX,
593
				y: startY,
594
				w: width,
595
				h: height,
596
				overflow: overflow
597
			};
598
		}
599
		if(overflow==0){
600
			break;
601
		}
602
	}
603
 
604
	node.style.left = best.x + "px";
605
	node.style.top = best.y + "px";
606
	return best;
607
}
608
 
609
dijit.placeOnScreenAroundElement = function(
610
	/* DomNode */		node,
611
	/* DomNode */		aroundNode,
612
	/* Object */		aroundCorners,
613
	/* Function */		layoutNode){
614
 
615
	//	summary
616
	//	Like placeOnScreen, except it accepts aroundNode instead of x,y
617
	//	and attempts to place node around it.  Uses margin box dimensions.
618
	//
619
	//	aroundCorners
620
	//		specify Which corner of aroundNode should be
621
	//		used to place the node => which corner(s) of node to use (see the
622
	//		corners parameter in dijit.placeOnScreen)
623
	//		e.g. {'TL': 'BL', 'BL': 'TL'}
624
	//
625
	//	layoutNode: Function(node, orient)
626
	//		for things like tooltip, they are displayed differently (and have different dimensions)
627
	//		based on their orientation relative to the parent.   This adjusts the popup based on orientation.
628
 
629
 
630
	// get coordinates of aroundNode
631
	aroundNode = dojo.byId(aroundNode);
632
	var oldDisplay = aroundNode.style.display;
633
	aroundNode.style.display="";
634
	// #3172: use the slightly tighter border box instead of marginBox
635
	var aroundNodeW = aroundNode.offsetWidth; //mb.w;
636
	var aroundNodeH = aroundNode.offsetHeight; //mb.h;
637
	var aroundNodePos = dojo.coords(aroundNode, true);
638
	aroundNode.style.display=oldDisplay;
639
 
640
	// Generate list of possible positions for node
641
	var choices = [];
642
	for(var nodeCorner in aroundCorners){
643
		choices.push( {
644
			aroundCorner: nodeCorner,
645
			corner: aroundCorners[nodeCorner],
646
			pos: {
647
				x: aroundNodePos.x + (nodeCorner.charAt(1)=='L' ? 0 : aroundNodeW),
648
				y: aroundNodePos.y + (nodeCorner.charAt(0)=='T' ? 0 : aroundNodeH)
649
			}
650
		});
651
	}
652
 
653
	return dijit._place(node, choices, layoutNode);
654
}
655
 
656
}
657
 
658
if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
659
dojo._hasResource["dijit._base.window"] = true;
660
dojo.provide("dijit._base.window");
661
 
662
dijit.getDocumentWindow = function(doc){
663
	//	summary
664
	// 	Get window object associated with document doc
665
 
666
	// With Safari, there is not way to retrieve the window from the document, so we must fix it.
667
	if(dojo.isSafari && !doc._parentWindow){
668
		/*
669
			This is a Safari specific function that fix the reference to the parent
670
			window from the document object.
671
		*/
672
		var fix=function(win){
673
			win.document._parentWindow=win;
674
			for(var i=0; i<win.frames.length; i++){
675
				fix(win.frames[i]);
676
			}
677
		}
678
		fix(window.top);
679
	}
680
 
681
	//In some IE versions (at least 6.0), document.parentWindow does not return a
682
	//reference to the real window object (maybe a copy), so we must fix it as well
683
	//We use IE specific execScript to attach the real window reference to
684
	//document._parentWindow for later use
685
	if(dojo.isIE && window !== document.parentWindow && !doc._parentWindow){
686
		/*
687
		In IE 6, only the variable "window" can be used to connect events (others
688
		may be only copies).
689
		*/
690
		doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
691
		//to prevent memory leak, unset it after use
692
		//another possibility is to add an onUnload handler which seems overkill to me (liucougar)
693
		var win = doc._parentWindow;
694
		doc._parentWindow = null;
695
		return win;	//	Window
696
	}
697
 
698
	return doc._parentWindow || doc.parentWindow || doc.defaultView;	//	Window
699
}
700
 
701
}
702
 
703
if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
704
dojo._hasResource["dijit._base.popup"] = true;
705
dojo.provide("dijit._base.popup");
706
 
707
 
708
 
709
 
710
 
711
dijit.popup = new function(){
712
	// summary:
713
	//		This class is used to show/hide widgets as popups.
714
	//
715
 
716
	var stack = [],
717
		beginZIndex=1000,
718
		idGen = 1;
719
 
720
	this.open = function(/*Object*/ args){
721
		// summary:
722
		//		Popup the widget at the specified position
723
		//
724
		// args: Object
725
		//		popup: Widget
726
		//			widget to display,
727
		//		parent: Widget
728
		//			the button etc. that is displaying this popup
729
		//		around: DomNode
730
		//			DOM node (typically a button); place popup relative to this node
731
		//		orient: Object
732
		//			structure specifying possible positions of popup relative to "around" node
733
		//		onCancel: Function
734
		//			callback when user has canceled the popup by
735
		//				1. hitting ESC or
736
		//				2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
737
		//				   ie: whenever popupWidget.onCancel() is called, args.onCancel is called
738
		//		onClose: Function
739
		//			callback whenever this popup is closed
740
		//		onExecute: Function
741
		//			callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
742
		//
743
		// examples:
744
		//		1. opening at the mouse position
745
		//			dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
746
		//		2. opening the widget as a dropdown
747
		//			dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}  });
748
		//
749
		//	Note that whatever widget called dijit.popup.open() should also listen to it's own _onBlur callback
750
		//	(fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
751
 
752
		var widget = args.popup,
753
			orient = args.orient || {'BL':'TL', 'TL':'BL'},
754
			around = args.around,
755
			id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+idGen++);
756
 
757
		// make wrapper div to hold widget and possibly hold iframe behind it.
758
		// we can't attach the iframe as a child of the widget.domNode because
759
		// widget.domNode might be a <table>, <ul>, etc.
760
		var wrapper = dojo.doc.createElement("div");
761
		wrapper.id = id;
762
		wrapper.className="dijitPopup";
763
		wrapper.style.zIndex = beginZIndex + stack.length;
764
		wrapper.style.visibility = "hidden";
765
		if(args.parent){
766
			wrapper.dijitPopupParent=args.parent.id;
767
		}
768
		dojo.body().appendChild(wrapper);
769
 
770
		widget.domNode.style.display="";
771
		wrapper.appendChild(widget.domNode);
772
 
773
		var iframe = new dijit.BackgroundIframe(wrapper);
774
 
775
		// position the wrapper node
776
		var best = around ?
777
			dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
778
			dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR']);
779
 
780
		wrapper.style.visibility = "visible";
781
		// TODO: use effects to fade in wrapper
782
 
783
		var handlers = [];
784
 
785
		// Compute the closest ancestor popup that's *not* a child of another popup.
786
		// Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
787
		function getTopPopup(){
788
			for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--);
789
			return stack[pi];
790
		}
791
 
792
		// provide default escape and tab key handling
793
		// (this will work for any widget, not just menu)
794
		handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
795
			if(evt.keyCode == dojo.keys.ESCAPE && args.onCancel){
796
				args.onCancel();
797
			}else if(evt.keyCode == dojo.keys.TAB){
798
				dojo.stopEvent(evt);
799
				var topPopup = getTopPopup();
800
				if(topPopup && topPopup.onCancel){
801
					topPopup.onCancel();
802
				}
803
			}
804
		}));
805
 
806
		// watch for cancel/execute events on the popup and notify the caller
807
		// (for a menu, "execute" means clicking an item)
808
		if(widget.onCancel){
809
			handlers.push(dojo.connect(widget, "onCancel", null, args.onCancel));
810
		}
811
 
812
		handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", null, function(){
813
			var topPopup = getTopPopup();
814
			if(topPopup && topPopup.onExecute){
815
				topPopup.onExecute();
816
			}
817
		}));
818
 
819
		stack.push({
820
			wrapper: wrapper,
821
			iframe: iframe,
822
			widget: widget,
823
			parent: args.parent,
824
			onExecute: args.onExecute,
825
			onCancel: args.onCancel,
826
 			onClose: args.onClose,
827
			handlers: handlers
828
		});
829
 
830
		if(widget.onOpen){
831
			widget.onOpen(best);
832
		}
833
 
834
		return best;
835
	};
836
 
837
	this.close = function(/*Widget*/ popup){
838
		// summary:
839
		//		Close specified popup and any popups that it parented
840
		while(dojo.some(stack, function(elem){return elem.widget == popup;})){
841
			var top = stack.pop(),
842
				wrapper = top.wrapper,
843
				iframe = top.iframe,
844
				widget = top.widget,
845
				onClose = top.onClose;
846
 
847
			if(widget.onClose){
848
				widget.onClose();
849
			}
850
			dojo.forEach(top.handlers, dojo.disconnect);
851
 
852
			// #2685: check if the widget still has a domNode so ContentPane can change its URL without getting an error
853
			if(!widget||!widget.domNode){ return; }
854
			dojo.style(widget.domNode, "display", "none");
855
			dojo.body().appendChild(widget.domNode);
856
			iframe.destroy();
857
			dojo._destroyElement(wrapper);
858
 
859
			if(onClose){
860
				onClose();
861
			}
862
		}
863
	};
864
}();
865
 
866
dijit._frames = new function(){
867
	// summary: cache of iframes
868
	var queue = [];
869
 
870
	this.pop = function(){
871
		var iframe;
872
		if(queue.length){
873
			iframe = queue.pop();
874
			iframe.style.display="";
875
		}else{
876
			if(dojo.isIE){
877
				var html="<iframe src='javascript:\"\"'"
878
					+ " style='position: absolute; left: 0px; top: 0px;"
879
					+ "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
880
				iframe = dojo.doc.createElement(html);
881
			}else{
882
			 	var iframe = dojo.doc.createElement("iframe");
883
				iframe.src = 'javascript:""';
884
				iframe.className = "dijitBackgroundIframe";
885
			}
886
			iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
887
			dojo.body().appendChild(iframe);
888
		}
889
		return iframe;
890
	};
891
 
892
	this.push = function(iframe){
893
		iframe.style.display="";
894
		if(dojo.isIE){
895
			iframe.style.removeExpression("width");
896
			iframe.style.removeExpression("height");
897
		}
898
		queue.push(iframe);
899
	}
900
}();
901
 
902
// fill the queue
903
if(dojo.isIE && dojo.isIE < 7){
904
	dojo.addOnLoad(function(){
905
		var f = dijit._frames;
906
		dojo.forEach([f.pop()], f.push);
907
	});
908
}
909
 
910
 
911
dijit.BackgroundIframe = function(/* DomNode */node){
912
	//	summary:
913
	//		For IE z-index schenanigans. id attribute is required.
914
	//
915
	//	description:
916
	//		new dijit.BackgroundIframe(node)
917
	//			Makes a background iframe as a child of node, that fills
918
	//			area (and position) of node
919
 
920
	if(!node.id){ throw new Error("no id"); }
921
	if((dojo.isIE && dojo.isIE < 7) || (dojo.isFF && dojo.isFF < 3 && dojo.hasClass(dojo.body(), "dijit_a11y"))){
922
		var iframe = dijit._frames.pop();
923
		node.appendChild(iframe);
924
		if(dojo.isIE){
925
			iframe.style.setExpression("width", "document.getElementById('" + node.id + "').offsetWidth");
926
			iframe.style.setExpression("height", "document.getElementById('" + node.id + "').offsetHeight");
927
		}
928
		this.iframe = iframe;
929
	}
930
};
931
 
932
dojo.extend(dijit.BackgroundIframe, {
933
	destroy: function(){
934
		//	summary: destroy the iframe
935
		if(this.iframe){
936
			dijit._frames.push(this.iframe);
937
			delete this.iframe;
938
		}
939
	}
940
});
941
 
942
}
943
 
944
if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
945
dojo._hasResource["dijit._base.scroll"] = true;
946
dojo.provide("dijit._base.scroll");
947
 
948
dijit.scrollIntoView = function(/* DomNode */node){
949
	//	summary
950
	//	Scroll the passed node into view, if it is not.
951
 
952
	// don't rely on that node.scrollIntoView works just because the function is there
953
	// it doesnt work in Konqueror or Opera even though the function is there and probably
954
	// not safari either
955
	// dont like browser sniffs implementations but sometimes you have to use it
956
	if(dojo.isIE){
957
		//only call scrollIntoView if there is a scrollbar for this menu,
958
		//otherwise, scrollIntoView will scroll the window scrollbar
959
		if(dojo.marginBox(node.parentNode).h <= node.parentNode.scrollHeight){ //PORT was getBorderBox
960
			node.scrollIntoView(false);
961
		}
962
	}else if(dojo.isMozilla){
963
		node.scrollIntoView(false);
964
	}else{
965
		var parent = node.parentNode;
966
		var parentBottom = parent.scrollTop + dojo.marginBox(parent).h; //PORT was getBorderBox
967
		var nodeBottom = node.offsetTop + dojo.marginBox(node).h;
968
		if(parentBottom < nodeBottom){
969
			parent.scrollTop += (nodeBottom - parentBottom);
970
		}else if(parent.scrollTop > node.offsetTop){
971
			parent.scrollTop -= (parent.scrollTop - node.offsetTop);
972
		}
973
	}
974
};
975
 
976
}
977
 
978
if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
979
dojo._hasResource["dijit._base.sniff"] = true;
980
dojo.provide("dijit._base.sniff");
981
 
982
// ported from dojo.html.applyBrowserClass (style.js)
983
 
984
//	summary:
985
//		Applies pre-set class names based on browser & version to the
986
//		top-level HTML node.  Simply doing a require on this module will
987
//		establish this CSS.  Modified version of Morris' CSS hack.
988
(function(){
989
	var d = dojo;
990
	var ie = d.isIE;
991
	var opera = d.isOpera;
992
	var maj = Math.floor;
993
	var classes = {
994
		dj_ie: ie,
995
//		dj_ie55: ie == 5.5,
996
		dj_ie6: maj(ie) == 6,
997
		dj_ie7: maj(ie) == 7,
998
		dj_iequirks: ie && d.isQuirks,
999
// NOTE: Opera not supported by dijit
1000
		dj_opera: opera,
1001
		dj_opera8: maj(opera) == 8,
1002
		dj_opera9: maj(opera) == 9,
1003
		dj_khtml: d.isKhtml,
1004
		dj_safari: d.isSafari,
1005
		dj_gecko: d.isMozilla
1006
	}; // no dojo unsupported browsers
1007
 
1008
	for(var p in classes){
1009
		if(classes[p]){
1010
			var html = dojo.doc.documentElement; //TODO browser-specific DOM magic needed?
1011
			if(html.className){
1012
				html.className += " " + p;
1013
			}else{
1014
				html.className = p;
1015
			}
1016
		}
1017
	}
1018
})();
1019
 
1020
}
1021
 
1022
if(!dojo._hasResource["dijit._base.bidi"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1023
dojo._hasResource["dijit._base.bidi"] = true;
1024
dojo.provide("dijit._base.bidi");
1025
 
1026
// summary: applies a class to the top of the document for right-to-left stylesheet rules
1027
 
1028
dojo.addOnLoad(function(){
1029
	if(!dojo._isBodyLtr()){
1030
		dojo.addClass(dojo.body(), "dijitRtl");
1031
	}
1032
});
1033
 
1034
}
1035
 
1036
if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1037
dojo._hasResource["dijit._base.typematic"] = true;
1038
dojo.provide("dijit._base.typematic");
1039
 
1040
dijit.typematic = {
1041
	// summary:
1042
	//	These functions are used to repetitively call a user specified callback
1043
	//	method when a specific key or mouse click over a specific DOM node is
1044
	//	held down for a specific amount of time.
1045
	//	Only 1 such event is allowed to occur on the browser page at 1 time.
1046
 
1047
	_fireEventAndReload: function(){
1048
		this._timer = null;
1049
		this._callback(++this._count, this._node, this._evt);
1050
		this._currentTimeout = (this._currentTimeout < 0) ? this._initialDelay : ((this._subsequentDelay > 1) ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay));
1051
		this._timer = setTimeout(dojo.hitch(this, "_fireEventAndReload"), this._currentTimeout);
1052
	},
1053
 
1054
	trigger: function(/*Event*/ evt, /* Object */ _this, /*DOMNode*/ node, /* Function */ callback, /* Object */ obj, /* Number */ subsequentDelay, /* Number */ initialDelay){
1055
		// summary:
1056
		//      Start a timed, repeating callback sequence.
1057
		//      If already started, the function call is ignored.
1058
		//      This method is not normally called by the user but can be
1059
		//      when the normal listener code is insufficient.
1060
		//	Parameters:
1061
		//	evt: key or mouse event object to pass to the user callback
1062
		//	_this: pointer to the user's widget space.
1063
		//	node: the DOM node object to pass the the callback function
1064
		//	callback: function to call until the sequence is stopped called with 3 parameters:
1065
		//		count: integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
1066
		//		node: the DOM node object passed in
1067
		//		evt: key or mouse event object
1068
		//	obj: user space object used to uniquely identify each typematic sequence
1069
		//	subsequentDelay: if > 1, the number of milliseconds until the 3->n events occur
1070
		//		or else the fractional time multiplier for the next event's delay, default=0.9
1071
		//	initialDelay: the number of milliseconds until the 2nd event occurs, default=500ms
1072
		if(obj != this._obj){
1073
			this.stop();
1074
			this._initialDelay = initialDelay || 500;
1075
			this._subsequentDelay = subsequentDelay || 0.90;
1076
			this._obj = obj;
1077
			this._evt = evt;
1078
			this._node = node;
1079
			this._currentTimeout = -1;
1080
			this._count = -1;
1081
			this._callback = dojo.hitch(_this, callback);
1082
			this._fireEventAndReload();
1083
		}
1084
	},
1085
 
1086
	stop: function(){
1087
		// summary:
1088
		//	  Stop an ongoing timed, repeating callback sequence.
1089
		if(this._timer){
1090
			clearTimeout(this._timer);
1091
			this._timer = null;
1092
		}
1093
		if(this._obj){
1094
			this._callback(-1, this._node, this._evt);
1095
			this._obj = null;
1096
		}
1097
	},
1098
 
1099
	addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
1100
		// summary: Start listening for a specific typematic key.
1101
		//	keyObject: an object defining the key to listen for.
1102
		//		key: (mandatory) the keyCode (number) or character (string) to listen for.
1103
		//		ctrlKey: desired ctrl key state to initiate the calback sequence:
1104
		//			pressed (true)
1105
		//			released (false)
1106
		//			either (unspecified)
1107
		//		altKey: same as ctrlKey but for the alt key
1108
		//		shiftKey: same as ctrlKey but for the shift key
1109
		//	See the trigger method for other parameters.
1110
		//	Returns an array of dojo.connect handles
1111
		return [
1112
			dojo.connect(node, "onkeypress", this, function(evt){
1113
				if(evt.keyCode == keyObject.keyCode && (!keyObject.charCode || keyObject.charCode == evt.charCode) &&
1114
				(keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
1115
				(keyObject.altKey === undefined || keyObject.altKey == evt.ctrlKey) &&
1116
				(keyObject.shiftKey === undefined || keyObject.shiftKey == evt.ctrlKey)){
1117
					dojo.stopEvent(evt);
1118
					dijit.typematic.trigger(keyObject, _this, node, callback, keyObject, subsequentDelay, initialDelay);
1119
				}else if(dijit.typematic._obj == keyObject){
1120
					dijit.typematic.stop();
1121
				}
1122
			}),
1123
			dojo.connect(node, "onkeyup", this, function(evt){
1124
				if(dijit.typematic._obj == keyObject){
1125
					dijit.typematic.stop();
1126
				}
1127
			})
1128
		];
1129
	},
1130
 
1131
	addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
1132
		// summary: Start listening for a typematic mouse click.
1133
		//	See the trigger method for other parameters.
1134
		//	Returns an array of dojo.connect handles
1135
		var dc = dojo.connect;
1136
		return [
1137
			dc(node, "mousedown", this, function(evt){
1138
				dojo.stopEvent(evt);
1139
				dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
1140
			}),
1141
			dc(node, "mouseup", this, function(evt){
1142
				dojo.stopEvent(evt);
1143
				dijit.typematic.stop();
1144
			}),
1145
			dc(node, "mouseout", this, function(evt){
1146
				dojo.stopEvent(evt);
1147
				dijit.typematic.stop();
1148
			}),
1149
			dc(node, "mousemove", this, function(evt){
1150
				dojo.stopEvent(evt);
1151
			}),
1152
			dc(node, "dblclick", this, function(evt){
1153
				dojo.stopEvent(evt);
1154
				if(dojo.isIE){
1155
					dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay);
1156
					setTimeout(dijit.typematic.stop, 50);
1157
				}
1158
			})
1159
		];
1160
	},
1161
 
1162
	addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay){
1163
		// summary: Start listening for a specific typematic key and mouseclick.
1164
		//	This is a thin wrapper to addKeyListener and addMouseListener.
1165
		//	mouseNode: the DOM node object to listen on for mouse events.
1166
		//	keyNode: the DOM node object to listen on for key events.
1167
		//	See the addMouseListener and addKeyListener methods for other parameters.
1168
		//	Returns an array of dojo.connect handles
1169
		return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay).concat(
1170
			this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay));
1171
	}
1172
};
1173
 
1174
}
1175
 
1176
if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1177
dojo._hasResource["dijit._base.wai"] = true;
1178
dojo.provide("dijit._base.wai");
1179
 
1180
dijit.wai = {
1181
	onload: function(){
1182
		// summary:
1183
		//		Function that detects if we are in high-contrast mode or not,
1184
		//		and sets up a timer to periodically confirm the value.
1185
		//		figure out the background-image style property
1186
		//		and apply that to the image.src property.
1187
		// description:
1188
		//		This must be a named function and not an anonymous
1189
		//		function, so that the widget parsing code can make sure it
1190
		//		registers its onload function after this function.
1191
		//		DO NOT USE "this" within this function.
1192
 
1193
		// create div for testing if high contrast mode is on or images are turned off
1194
		var div = document.createElement("div");
1195
		div.id = "a11yTestNode";
1196
		div.style.cssText = 'border: 1px solid;'
1197
			+ 'border-color:red green;'
1198
			+ 'position: absolute;'
1199
			+ 'height: 5px;'
1200
			+ 'top: -999px;'
1201
			+ 'background-image: url("' + dojo.moduleUrl("dijit", "form/templates/blank.gif") + '");';
1202
		dojo.body().appendChild(div);
1203
 
1204
		// test it
1205
		function check(){
1206
			var cs = dojo.getComputedStyle(div);
1207
			if(cs){
1208
				var bkImg = cs.backgroundImage;
1209
				var needsA11y = (cs.borderTopColor==cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
1210
				dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
1211
			}
1212
		}
1213
		check();
1214
		if(dojo.isIE){
1215
			setInterval(check, 4000);
1216
		}
1217
	}
1218
};
1219
 
1220
// Test if computer is in high contrast mode.
1221
// Make sure the a11y test runs first, before widgets are instantiated.
1222
if(dojo.isIE || dojo.isMoz){	// NOTE: checking in Safari messes things up
1223
	dojo._loaders.unshift(dijit.wai.onload);
1224
}
1225
 
1226
dojo.mixin(dijit,
1227
{
1228
	hasWaiRole: function(/*Element*/ elem){
1229
		// Summary: Return true if elem has a role attribute and false if not.
1230
		if(elem.hasAttribute){
1231
			return elem.hasAttribute("role");
1232
		}else{
1233
			return elem.getAttribute("role") ? true : false;
1234
		}
1235
	},
1236
 
1237
	getWaiRole: function(/*Element*/ elem){
1238
		// Summary: Return the role of elem or an empty string if
1239
		//		elem does not have a role.
1240
		var value = elem.getAttribute("role");
1241
		if(value){
1242
			var prefixEnd = value.indexOf(":");
1243
			return prefixEnd == -1 ? value : value.substring(prefixEnd+1);
1244
		}else{
1245
			return "";
1246
		}
1247
	},
1248
 
1249
	setWaiRole: function(/*Element*/ elem, /*String*/ role){
1250
		// Summary: Set the role on elem. On Firefox 2 and below, "wairole:" is
1251
		//		prepended to the provided role value.
1252
		if(dojo.isFF && dojo.isFF < 3){
1253
			elem.setAttribute("role", "wairole:"+role);
1254
		}else{
1255
			elem.setAttribute("role", role);
1256
		}
1257
	},
1258
 
1259
	removeWaiRole: function(/*Element*/ elem){
1260
		// Summary: Removes the role attribute from elem.
1261
		elem.removeAttribute("role");
1262
	},
1263
 
1264
	hasWaiState: function(/*Element*/ elem, /*String*/ state){
1265
		// Summary: Return true if elem has a value for the given state and
1266
		//		false if it does not.
1267
		//		On Firefox 2 and below, we check for an attribute in namespace
1268
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
1269
		//		On all other browsers, we check for an attribute called
1270
		//		"aria-"+state.
1271
		if(dojo.isFF && dojo.isFF < 3){
1272
			return elem.hasAttributeNS("http://www.w3.org/2005/07/aaa", state);
1273
		}else{
1274
			if(elem.hasAttribute){
1275
				return elem.hasAttribute("aria-"+state);
1276
			}else{
1277
				return elem.getAttribute("aria-"+state) ? true : false;
1278
			}
1279
		}
1280
	},
1281
 
1282
	getWaiState: function(/*Element*/ elem, /*String*/ state){
1283
		// Summary: Return the value of the requested state on elem
1284
		//		or an empty string if elem has no value for state.
1285
		//		On Firefox 2 and below, we check for an attribute in namespace
1286
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
1287
		//		On all other browsers, we check for an attribute called
1288
		//		"aria-"+state.
1289
		if(dojo.isFF && dojo.isFF < 3){
1290
			return elem.getAttributeNS("http://www.w3.org/2005/07/aaa", state);
1291
		}else{
1292
			var value =  elem.getAttribute("aria-"+state);
1293
			return value ? value : "";
1294
		}
1295
	},
1296
 
1297
	setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
1298
		// Summary: Set state on elem to value.
1299
		//		On Firefox 2 and below, we set an attribute in namespace
1300
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
1301
		//		On all other browsers, we set an attribute called
1302
		//		"aria-"+state.
1303
		if(dojo.isFF && dojo.isFF < 3){
1304
			elem.setAttributeNS("http://www.w3.org/2005/07/aaa",
1305
				"aaa:"+state, value);
1306
		}else{
1307
			elem.setAttribute("aria-"+state, value);
1308
		}
1309
	},
1310
 
1311
	removeWaiState: function(/*Element*/ elem, /*String*/ state){
1312
		// Summary: Removes the given state from elem.
1313
		//		On Firefox 2 and below, we remove the attribute in namespace
1314
		//		"http://www.w3.org/2005/07/aaa" with a name of the given state.
1315
		//		On all other browsers, we remove the attribute called
1316
		//		"aria-"+state.
1317
		if(dojo.isFF && dojo.isFF < 3){
1318
			elem.removeAttributeNS("http://www.w3.org/2005/07/aaa", state);
1319
		}else{
1320
			elem.removeAttribute("aria-"+state);
1321
		}
1322
	}
1323
});
1324
 
1325
}
1326
 
1327
if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1328
dojo._hasResource["dijit._base"] = true;
1329
dojo.provide("dijit._base");
1330
 
1331
 
1332
 
1333
 
1334
 
1335
 
1336
 
1337
 
1338
 
1339
 
1340
 
1341
 
1342
}
1343
 
1344
if(!dojo._hasResource["dojo.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1345
dojo._hasResource["dojo.date.stamp"] = true;
1346
dojo.provide("dojo.date.stamp");
1347
 
1348
// Methods to convert dates to or from a wire (string) format using well-known conventions
1349
 
1350
dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
1351
	//	summary:
1352
	//		Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
1353
	//
1354
	//	description:
1355
	//		Accepts a string formatted according to a profile of ISO8601 as defined by
1356
	//		RFC3339 (http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
1357
	//		Can also process dates as specified by http://www.w3.org/TR/NOTE-datetime
1358
	//		The following combinations are valid:
1359
	// 			* dates only
1360
	//				yyyy
1361
	//				yyyy-MM
1362
	//				yyyy-MM-dd
1363
	// 			* times only, with an optional time zone appended
1364
	//				THH:mm
1365
	//				THH:mm:ss
1366
	//				THH:mm:ss.SSS
1367
	// 			* and "datetimes" which could be any combination of the above
1368
	//		timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
1369
	//		Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
1370
	//		input may return null.  Arguments which are out of bounds will be handled
1371
	// 		by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
1372
	//
1373
  	//	formattedString:
1374
	//		A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
1375
	//
1376
	//	defaultTime:
1377
	//		Used for defaults for fields omitted in the formattedString.
1378
	//		Uses 1970-01-01T00:00:00.0Z by default.
1379
 
1380
	if(!dojo.date.stamp._isoRegExp){
1381
		dojo.date.stamp._isoRegExp =
1382
//TODO: could be more restrictive and check for 00-59, etc.
1383
			/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
1384
	}
1385
 
1386
	var match = dojo.date.stamp._isoRegExp.exec(formattedString);
1387
	var result = null;
1388
 
1389
	if(match){
1390
		match.shift();
1391
		match[1] && match[1]--; // Javascript Date months are 0-based
1392
		match[6] && (match[6] *= 1000); // Javascript Date expects fractional seconds as milliseconds
1393
 
1394
		if(defaultTime){
1395
			// mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
1396
			defaultTime = new Date(defaultTime);
1397
			dojo.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
1398
				return defaultTime["get" + prop]();
1399
			}).forEach(function(value, index){
1400
				if(match[index] === undefined){
1401
					match[index] = value;
1402
				}
1403
			});
1404
		}
1405
		result = new Date(match[0]||1970, match[1]||0, match[2]||0, match[3]||0, match[4]||0, match[5]||0, match[6]||0);
1406
 
1407
		var offset = 0;
1408
		var zoneSign = match[7] && match[7].charAt(0);
1409
		if(zoneSign != 'Z'){
1410
			offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
1411
			if(zoneSign != '-'){ offset *= -1; }
1412
		}
1413
		if(zoneSign){
1414
			offset -= result.getTimezoneOffset();
1415
		}
1416
		if(offset){
1417
			result.setTime(result.getTime() + offset * 60000);
1418
		}
1419
	}
1420
 
1421
	return result; // Date or null
1422
}
1423
 
1424
dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*Object?*/options){
1425
	//	summary:
1426
	//		Format a Date object as a string according a subset of the ISO-8601 standard
1427
	//
1428
	//	description:
1429
	//		When options.selector is omitted, output follows RFC3339 (http://www.ietf.org/rfc/rfc3339.txt)
1430
	//		The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
1431
	//		Does not check bounds.
1432
	//
1433
	//	dateObject:
1434
	//		A Date object
1435
	//
1436
	//	object {selector: string, zulu: boolean, milliseconds: boolean}
1437
	//		selector- "date" or "time" for partial formatting of the Date object.
1438
	//			Both date and time will be formatted by default.
1439
	//		zulu- if true, UTC/GMT is used for a timezone
1440
	//		milliseconds- if true, output milliseconds
1441
 
1442
	var _ = function(n){ return (n < 10) ? "0" + n : n; }
1443
	options = options || {};
1444
	var formattedDate = [];
1445
	var getter = options.zulu ? "getUTC" : "get";
1446
	var date = "";
1447
	if(options.selector != "time"){
1448
		date = [dateObject[getter+"FullYear"](), _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
1449
	}
1450
	formattedDate.push(date);
1451
	if(options.selector != "date"){
1452
		var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
1453
		var millis = dateObject[getter+"Milliseconds"]();
1454
		if(options.milliseconds){
1455
			time += "."+ (millis < 100 ? "0" : "") + _(millis);
1456
		}
1457
		if(options.zulu){
1458
			time += "Z";
1459
		}else if(options.selector != "time"){
1460
			var timezoneOffset = dateObject.getTimezoneOffset();
1461
			var absOffset = Math.abs(timezoneOffset);
1462
			time += (timezoneOffset > 0 ? "-" : "+") +
1463
				_(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
1464
		}
1465
		formattedDate.push(time);
1466
	}
1467
	return formattedDate.join('T'); // String
1468
}
1469
 
1470
}
1471
 
1472
if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1473
dojo._hasResource["dojo.parser"] = true;
1474
dojo.provide("dojo.parser");
1475
 
1476
 
1477
dojo.parser = new function(){
1478
 
1479
	var d = dojo;
1480
 
1481
	function val2type(/*Object*/ value){
1482
		// summary:
1483
		//		Returns name of type of given value.
1484
 
1485
		if(d.isString(value)){ return "string"; }
1486
		if(typeof value == "number"){ return "number"; }
1487
		if(typeof value == "boolean"){ return "boolean"; }
1488
		if(d.isFunction(value)){ return "function"; }
1489
		if(d.isArray(value)){ return "array"; } // typeof [] == "object"
1490
		if(value instanceof Date) { return "date"; } // assume timestamp
1491
		if(value instanceof d._Url){ return "url"; }
1492
		return "object";
1493
	}
1494
 
1495
	function str2obj(/*String*/ value, /*String*/ type){
1496
		// summary:
1497
		//		Convert given string value to given type
1498
		switch(type){
1499
			case "string":
1500
				return value;
1501
			case "number":
1502
				return value.length ? Number(value) : NaN;
1503
			case "boolean":
1504
				// for checked/disabled value might be "" or "checked".  interpret as true.
1505
				return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
1506
			case "function":
1507
				if(d.isFunction(value)){
1508
					// IE gives us a function, even when we say something like onClick="foo"
1509
					// (in which case it gives us an invalid function "function(){ foo }").
1510
					//  Therefore, convert to string
1511
					value=value.toString();
1512
					value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
1513
				}
1514
				try{
1515
					if(value.search(/[^\w\.]+/i) != -1){
1516
						// TODO: "this" here won't work
1517
						value = d.parser._nameAnonFunc(new Function(value), this);
1518
					}
1519
					return d.getObject(value, false);
1520
				}catch(e){ return new Function(); }
1521
			case "array":
1522
				return value.split(/\s*,\s*/);
1523
			case "date":
1524
				switch(value){
1525
					case "": return new Date("");	// the NaN of dates
1526
					case "now": return new Date();	// current date
1527
					default: return d.date.stamp.fromISOString(value);
1528
				}
1529
			case "url":
1530
				return d.baseUrl + value;
1531
			default:
1532
				return d.fromJson(value);
1533
		}
1534
	}
1535
 
1536
	var instanceClasses = {
1537
		// map from fully qualified name (like "dijit.Button") to structure like
1538
		// { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
1539
	};
1540
 
1541
	function getClassInfo(/*String*/ className){
1542
		// className:
1543
		//		fully qualified name (like "dijit.Button")
1544
		// returns:
1545
		//		structure like
1546
		//			{
1547
		//				cls: dijit.Button,
1548
		//				params: { label: "string", disabled: "boolean"}
1549
		//			}
1550
 
1551
		if(!instanceClasses[className]){
1552
			// get pointer to widget class
1553
			var cls = d.getObject(className);
1554
			if(!d.isFunction(cls)){
1555
				throw new Error("Could not load class '" + className +
1556
					"'. Did you spell the name correctly and use a full path, like 'dijit.form.Button'?");
1557
			}
1558
			var proto = cls.prototype;
1559
 
1560
			// get table of parameter names & types
1561
			var params={};
1562
			for(var name in proto){
1563
				if(name.charAt(0)=="_"){ continue; } 	// skip internal properties
1564
				var defVal = proto[name];
1565
				params[name]=val2type(defVal);
1566
			}
1567
 
1568
			instanceClasses[className] = { cls: cls, params: params };
1569
		}
1570
		return instanceClasses[className];
1571
	}
1572
 
1573
	this._functionFromScript = function(script){
1574
		var preamble = "";
1575
		var suffix = "";
1576
		var argsStr = script.getAttribute("args");
1577
		if(argsStr){
1578
			d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
1579
				preamble += "var "+part+" = arguments["+idx+"]; ";
1580
			});
1581
		}
1582
		var withStr = script.getAttribute("with");
1583
		if(withStr && withStr.length){
1584
			d.forEach(withStr.split(/\s*,\s*/), function(part){
1585
				preamble += "with("+part+"){";
1586
				suffix += "}";
1587
			});
1588
		}
1589
		return new Function(preamble+script.innerHTML+suffix);
1590
	}
1591
 
1592
	this.instantiate = function(/* Array */nodes){
1593
		// summary:
1594
		//		Takes array of nodes, and turns them into class instances and
1595
		//		potentially calls a layout method to allow them to connect with
1596
		//		any children
1597
		var thelist = [];
1598
		d.forEach(nodes, function(node){
1599
			if(!node){ return; }
1600
			var type = node.getAttribute("dojoType");
1601
			if((!type)||(!type.length)){ return; }
1602
			var clsInfo = getClassInfo(type);
1603
			var clazz = clsInfo.cls;
1604
			var ps = clazz._noScript||clazz.prototype._noScript;
1605
 
1606
			// read parameters (ie, attributes).
1607
			// clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
1608
			var params = {};
1609
			var attributes = node.attributes;
1610
			for(var name in clsInfo.params){
1611
				var item = attributes.getNamedItem(name);
1612
				if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
1613
				var value = item.value;
1614
				// Deal with IE quirks for 'class' and 'style'
1615
				switch(name){
1616
				case "class":
1617
					value = node.className;
1618
					break;
1619
				case "style":
1620
					value = node.style && node.style.cssText; // FIXME: Opera?
1621
				}
1622
				var _type = clsInfo.params[name];
1623
				params[name] = str2obj(value, _type);
1624
			}
1625
 
1626
			// Process <script type="dojo/*"> script tags
1627
			// <script type="dojo/method" event="foo"> tags are added to params, and passed to
1628
			// the widget on instantiation.
1629
			// <script type="dojo/method"> tags (with no event) are executed after instantiation
1630
			// <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
1631
			if(!ps){
1632
				var connects = [],	// functions to connect after instantiation
1633
					calls = [];		// functions to call after instantiation
1634
 
1635
				d.query("> script[type^='dojo/']", node).orphan().forEach(function(script){
1636
					var event = script.getAttribute("event"),
1637
						type = script.getAttribute("type"),
1638
						nf = d.parser._functionFromScript(script);
1639
					if(event){
1640
						if(type == "dojo/connect"){
1641
							connects.push({event: event, func: nf});
1642
						}else{
1643
							params[event] = nf;
1644
						}
1645
					}else{
1646
						calls.push(nf);
1647
					}
1648
				});
1649
			}
1650
 
1651
			var markupFactory = clazz["markupFactory"];
1652
			if(!markupFactory && clazz["prototype"]){
1653
				markupFactory = clazz.prototype["markupFactory"];
1654
			}
1655
			// create the instance
1656
			var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
1657
			thelist.push(instance);
1658
 
1659
			// map it to the JS namespace if that makes sense
1660
			var jsname = node.getAttribute("jsId");
1661
			if(jsname){
1662
				d.setObject(jsname, instance);
1663
			}
1664
 
1665
			// process connections and startup functions
1666
			if(!ps){
1667
				dojo.forEach(connects, function(connect){
1668
					dojo.connect(instance, connect.event, null, connect.func);
1669
				});
1670
				dojo.forEach(calls, function(func){
1671
					func.call(instance);
1672
				});
1673
			}
1674
		});
1675
 
1676
		// Call startup on each top level instance if it makes sense (as for
1677
		// widgets).  Parent widgets will recursively call startup on their
1678
		// (non-top level) children
1679
		d.forEach(thelist, function(instance){
1680
			if(	instance  &&
1681
				(instance.startup) &&
1682
				((!instance.getParent) || (!instance.getParent()))
1683
			){
1684
				instance.startup();
1685
			}
1686
		});
1687
		return thelist;
1688
	};
1689
 
1690
	this.parse = function(/*DomNode?*/ rootNode){
1691
		// summary:
1692
		//		Search specified node (or root node) recursively for class instances,
1693
		//		and instantiate them Searches for
1694
		//		dojoType="qualified.class.name"
1695
		var list = d.query('[dojoType]', rootNode);
1696
		// go build the object instances
1697
		var instances = this.instantiate(list);
1698
		return instances;
1699
	};
1700
}();
1701
 
1702
//Register the parser callback. It should be the first callback
1703
//after the a11y test.
1704
 
1705
(function(){
1706
	var parseRunner = function(){
1707
		if(djConfig["parseOnLoad"] == true){
1708
			dojo.parser.parse();
1709
		}
1710
	};
1711
 
1712
	// FIXME: need to clobber cross-dependency!!
1713
	if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){
1714
		dojo._loaders.splice(1, 0, parseRunner);
1715
	}else{
1716
		dojo._loaders.unshift(parseRunner);
1717
	}
1718
})();
1719
 
1720
//TODO: ported from 0.4.x Dojo.  Can we reduce this?
1721
dojo.parser._anonCtr = 0;
1722
dojo.parser._anon = {}; // why is this property required?
1723
dojo.parser._nameAnonFunc = function(/*Function*/anonFuncPtr, /*Object*/thisObj){
1724
	// summary:
1725
	//		Creates a reference to anonFuncPtr in thisObj with a completely
1726
	//		unique name. The new name is returned as a String.
1727
	var jpn = "$joinpoint";
1728
	var nso = (thisObj|| dojo.parser._anon);
1729
	if(dojo.isIE){
1730
		var cn = anonFuncPtr["__dojoNameCache"];
1731
		if(cn && nso[cn] === anonFuncPtr){
1732
			return anonFuncPtr["__dojoNameCache"];
1733
		}
1734
	}
1735
	var ret = "__"+dojo.parser._anonCtr++;
1736
	while(typeof nso[ret] != "undefined"){
1737
		ret = "__"+dojo.parser._anonCtr++;
1738
	}
1739
	nso[ret] = anonFuncPtr;
1740
	return ret; // String
1741
}
1742
 
1743
}
1744
 
1745
if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
1746
dojo._hasResource["dijit._Widget"] = true;
1747
dojo.provide("dijit._Widget");
1748
 
1749
 
1750
 
1751
dojo.declare("dijit._Widget", null, {
1752
	// summary:
1753
	//		The foundation of dijit widgets.
1754
	//
1755
	// id: String
1756
	//		a unique, opaque ID string that can be assigned by users or by the
1757
	//		system. If the developer passes an ID which is known not to be
1758
	//		unique, the specified ID is ignored and the system-generated ID is
1759
	//		used instead.
1760
	id: "",
1761
 
1762
	// lang: String
1763
	//	Language to display this widget in (like en-us).
1764
	//	Defaults to brower's specified preferred language (typically the language of the OS)
1765
	lang: "",
1766
 
1767
	// dir: String
1768
	//  Bi-directional support, as defined by the HTML DIR attribute. Either left-to-right "ltr" or right-to-left "rtl".
1769
	dir: "",
1770
 
1771
	// class: String
1772
	// HTML class attribute
1773
	"class": "",
1774
 
1775
	// style: String
1776
	// HTML style attribute
1777
	style: "",
1778
 
1779
	// title: String
1780
	// HTML title attribute
1781
	title: "",
1782
 
1783
	// srcNodeRef: DomNode
1784
	//		pointer to original dom node
1785
	srcNodeRef: null,
1786
 
1787
	// domNode: DomNode
1788
	//		this is our visible representation of the widget! Other DOM
1789
	//		Nodes may by assigned to other properties, usually through the
1790
	//		template system's dojoAttachPonit syntax, but the domNode
1791
	//		property is the canonical "top level" node in widget UI.
1792
	domNode: null,
1793
 
1794
	// attributeMap: Object
1795
	//		A map of attributes and attachpoints -- typically standard HTML attributes -- to set
1796
	//		on the widget's dom, at the "domNode" attach point, by default.
1797
	//		Other node references can be specified as properties of 'this'
1798
	attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},  // TODO: add on* handlers?
1799
 
1800
	//////////// INITIALIZATION METHODS ///////////////////////////////////////
1801
 
1802
	postscript: function(params, srcNodeRef){
1803
		this.create(params, srcNodeRef);
1804
	},
1805
 
1806
	create: function(params, srcNodeRef){
1807
		// summary:
1808
		//		To understand the process by which widgets are instantiated, it
1809
		//		is critical to understand what other methods create calls and
1810
		//		which of them you'll want to override. Of course, adventurous
1811
		//		developers could override create entirely, but this should
1812
		//		only be done as a last resort.
1813
		//
1814
		//		Below is a list of the methods that are called, in the order
1815
		//		they are fired, along with notes about what they do and if/when
1816
		//		you should over-ride them in your widget:
1817
		//
1818
		//			postMixInProperties:
1819
		//				a stub function that you can over-ride to modify
1820
		//				variables that may have been naively assigned by
1821
		//				mixInProperties
1822
		//			# widget is added to manager object here
1823
		//			buildRendering
1824
		//				Subclasses use this method to handle all UI initialization
1825
		//				Sets this.domNode.  Templated widgets do this automatically
1826
		//				and otherwise it just uses the source dom node.
1827
		//			postCreate
1828
		//				a stub function that you can over-ride to modify take
1829
		//				actions once the widget has been placed in the UI
1830
 
1831
		// store pointer to original dom tree
1832
		this.srcNodeRef = dojo.byId(srcNodeRef);
1833
 
1834
		// For garbage collection.  An array of handles returned by Widget.connect()
1835
		// Each handle returned from Widget.connect() is an array of handles from dojo.connect()
1836
		this._connects=[];
1837
 
1838
		// _attaches: String[]
1839
		// 		names of all our dojoAttachPoint variables
1840
		this._attaches=[];
1841
 
1842
		//mixin our passed parameters
1843
		if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
1844
		if(params){
1845
			dojo.mixin(this,params);
1846
		}
1847
		this.postMixInProperties();
1848
 
1849
		// generate an id for the widget if one wasn't specified
1850
		// (be sure to do this before buildRendering() because that function might
1851
		// expect the id to be there.
1852
		if(!this.id){
1853
			this.id=dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
1854
		}
1855
		dijit.registry.add(this);
1856
 
1857
		this.buildRendering();
1858
 
1859
		// Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
1860
		// The placement of these attributes is according to the property mapping in attributeMap.
1861
		// Note special handling for 'style' and 'class' attributes which are lists and can
1862
		// have elements from both old and new structures, and some attributes like "type"
1863
		// cannot be processed this way as they are not mutable.
1864
		if(this.domNode){
1865
			for(var attr in this.attributeMap){
1866
				var mapNode = this[this.attributeMap[attr] || "domNode"];
1867
				var value = this[attr];
1868
				if(typeof value != "object" && (value !== "" || (params && params[attr]))){
1869
					switch(attr){
1870
					case "class":
1871
						dojo.addClass(mapNode, value);
1872
						break;
1873
					case "style":
1874
						if(mapNode.style.cssText){
1875
							mapNode.style.cssText += "; " + value;// FIXME: Opera
1876
						}else{
1877
							mapNode.style.cssText = value;
1878
						}
1879
						break;
1880
					default:
1881
						mapNode.setAttribute(attr, value);
1882
					}
1883
				}
1884
			}
1885
		}
1886
 
1887
		if(this.domNode){
1888
			this.domNode.setAttribute("widgetId", this.id);
1889
		}
1890
		this.postCreate();
1891
 
1892
		// If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
1893
		if(this.srcNodeRef && !this.srcNodeRef.parentNode){
1894
			delete this.srcNodeRef;
1895
		}
1896
	},
1897
 
1898
	postMixInProperties: function(){
1899
		// summary
1900
		//	Called after the parameters to the widget have been read-in,
1901
		//	but before the widget template is instantiated.
1902
		//	Especially useful to set properties that are referenced in the widget template.
1903
	},
1904
 
1905
	buildRendering: function(){
1906
		// summary:
1907
		//		Construct the UI for this widget, setting this.domNode.
1908
		//		Most widgets will mixin TemplatedWidget, which overrides this method.
1909
		this.domNode = this.srcNodeRef || dojo.doc.createElement('div');
1910
	},
1911
 
1912
	postCreate: function(){
1913
		// summary:
1914
		//		Called after a widget's dom has been setup
1915
	},
1916
 
1917
	startup: function(){
1918
		// summary:
1919
		//		Called after a widget's children, and other widgets on the page, have been created.
1920
		//		Provides an opportunity to manipulate any children before they are displayed
1921
		//		This is useful for composite widgets that need to control or layout sub-widgets
1922
		//		Many layout widgets can use this as a wiring phase
1923
	},
1924
 
1925
	//////////// DESTROY FUNCTIONS ////////////////////////////////
1926
 
1927
	destroyRecursive: function(/*Boolean*/ finalize){
1928
		// summary:
1929
		// 		Destroy this widget and it's descendants. This is the generic
1930
		// 		"destructor" function that all widget users should call to
1931
		// 		cleanly discard with a widget. Once a widget is destroyed, it's
1932
		// 		removed from the manager object.
1933
		// finalize: Boolean
1934
		//		is this function being called part of global environment
1935
		//		tear-down?
1936
 
1937
		this.destroyDescendants();
1938
		this.destroy();
1939
	},
1940
 
1941
	destroy: function(/*Boolean*/ finalize){
1942
		// summary:
1943
		// 		Destroy this widget, but not its descendants
1944
		// finalize: Boolean
1945
		//		is this function being called part of global environment
1946
		//		tear-down?
1947
		this.uninitialize();
1948
		dojo.forEach(this._connects, function(array){
1949
			dojo.forEach(array, dojo.disconnect);
1950
		});
1951
		this.destroyRendering(finalize);
1952
		dijit.registry.remove(this.id);
1953
	},
1954
 
1955
	destroyRendering: function(/*Boolean*/ finalize){
1956
		// summary:
1957
		//		Destroys the DOM nodes associated with this widget
1958
		// finalize: Boolean
1959
		//		is this function being called part of global environment
1960
		//		tear-down?
1961
 
1962
		if(this.bgIframe){
1963
			this.bgIframe.destroy();
1964
			delete this.bgIframe;
1965
		}
1966
 
1967
		if(this.domNode){
1968
			dojo._destroyElement(this.domNode);
1969
			delete this.domNode;
1970
		}
1971
 
1972
		if(this.srcNodeRef){
1973
			dojo._destroyElement(this.srcNodeRef);
1974
			delete this.srcNodeRef;
1975
		}
1976
	},
1977
 
1978
	destroyDescendants: function(){
1979
		// summary:
1980
		//		Recursively destroy the children of this widget and their
1981
		//		descendants.
1982
 
1983
		// TODO: should I destroy in the reverse order, to go bottom up?
1984
		dojo.forEach(this.getDescendants(), function(widget){ widget.destroy(); });
1985
	},
1986
 
1987
	uninitialize: function(){
1988
		// summary:
1989
		//		stub function. Over-ride to implement custom widget tear-down
1990
		//		behavior.
1991
		return false;
1992
	},
1993
 
1994
	////////////////// MISCELLANEOUS METHODS ///////////////////
1995
 
1996
	toString: function(){
1997
		// summary:
1998
		//		returns a string that represents the widget. When a widget is
1999
		//		cast to a string, this method will be used to generate the
2000
		//		output. Currently, it does not implement any sort of reversable
2001
		//		serialization.
2002
		return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
2003
	},
2004
 
2005
	getDescendants: function(){
2006
		// summary:
2007
		//	return all the descendant widgets
2008
		var list = dojo.query('[widgetId]', this.domNode);
2009
		return list.map(dijit.byNode);		// Array
2010
	},
2011
 
2012
	nodesWithKeyClick : ["input", "button"],
2013
 
2014
	connect: function(
2015
			/*Object|null*/ obj,
2016
			/*String*/ event,
2017
			/*String|Function*/ method){
2018
 
2019
		// summary:
2020
		//		Connects specified obj/event to specified method of this object
2021
		//		and registers for disconnect() on widget destroy.
2022
		//		Special event: "ondijitclick" triggers on a click or enter-down or space-up
2023
		//		Similar to dojo.connect() but takes three arguments rather than four.
2024
		var handles =[];
2025
		if(event == "ondijitclick"){
2026
			var w = this;
2027
			// add key based click activation for unsupported nodes.
2028
			if(!this.nodesWithKeyClick[obj.nodeName]){
2029
				handles.push(dojo.connect(obj, "onkeydown", this,
2030
					function(e){
2031
						if(e.keyCode == dojo.keys.ENTER){
2032
							return (dojo.isString(method))?
2033
								w[method](e) : method.call(w, e);
2034
						}else if(e.keyCode == dojo.keys.SPACE){
2035
							// stop space down as it causes IE to scroll
2036
							// the browser window
2037
							dojo.stopEvent(e);
2038
						}
2039
			 		}));
2040
				handles.push(dojo.connect(obj, "onkeyup", this,
2041
					function(e){
2042
						if(e.keyCode == dojo.keys.SPACE){
2043
							return dojo.isString(method) ?
2044
								w[method](e) : method.call(w, e);
2045
						}
2046
			 		}));
2047
			}
2048
			event = "onclick";
2049
		}
2050
		handles.push(dojo.connect(obj, event, this, method));
2051
 
2052
		// return handles for FormElement and ComboBox
2053
		this._connects.push(handles);
2054
		return handles;
2055
	},
2056
 
2057
	disconnect: function(/*Object*/ handles){
2058
		// summary:
2059
		//		Disconnects handle created by this.connect.
2060
		//		Also removes handle from this widget's list of connects
2061
		for(var i=0; i<this._connects.length; i++){
2062
			if(this._connects[i]==handles){
2063
				dojo.forEach(handles, dojo.disconnect);
2064
				this._connects.splice(i, 1);
2065
				return;
2066
			}
2067
		}
2068
	},
2069
 
2070
	isLeftToRight: function(){
2071
		// summary:
2072
		//		Checks the DOM to for the text direction for bi-directional support
2073
		// description:
2074
		//		This method cannot be used during widget construction because the widget
2075
		//		must first be connected to the DOM tree.  Parent nodes are searched for the
2076
		//		'dir' attribute until one is found, otherwise left to right mode is assumed.
2077
		//		See HTML spec, DIR attribute for more information.
2078
 
2079
		if(typeof this._ltr == "undefined"){
2080
			this._ltr = dojo.getComputedStyle(this.domNode).direction != "rtl";
2081
		}
2082
		return this._ltr; //Boolean
2083
	},
2084
 
2085
	isFocusable: function(){
2086
		// summary:
2087
		//		Return true if this widget can currently be focused
2088
		//		and false if not
2089
		return this.focus && (dojo.style(this.domNode, "display") != "none");
2090
	}
2091
});
2092
 
2093
}
2094
 
2095
if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2096
dojo._hasResource["dojo.string"] = true;
2097
dojo.provide("dojo.string");
2098
 
2099
dojo.string.pad = function(/*String*/text, /*int*/size, /*String?*/ch, /*boolean?*/end){
2100
	// summary:
2101
	//		Pad a string to guarantee that it is at least 'size' length by
2102
	//		filling with the character 'c' at either the start or end of the
2103
	//		string. Pads at the start, by default.
2104
	// text: the string to pad
2105
	// size: length to provide padding
2106
	// ch: character to pad, defaults to '0'
2107
	// end: adds padding at the end if true, otherwise pads at start
2108
 
2109
	var out = String(text);
2110
	if(!ch){
2111
		ch = '0';
2112
	}
2113
	while(out.length < size){
2114
		if(end){
2115
			out += ch;
2116
		}else{
2117
			out = ch + out;
2118
		}
2119
	}
2120
	return out;	// String
2121
};
2122
 
2123
dojo.string.substitute = function(	/*String*/template,
2124
									/*Object or Array*/map,
2125
									/*Function?*/transform,
2126
									/*Object?*/thisObject){
2127
	// summary:
2128
	//		Performs parameterized substitutions on a string. Throws an
2129
	//		exception if any parameter is unmatched.
2130
	// description:
2131
	//		For example,
2132
	//		|	dojo.string.substitute("File '${0}' is not found in directory '${1}'.",["foo.html","/temp"]);
2133
	//		|	dojo.string.substitute("File '${name}' is not found in directory '${info.dir}'.",{name: "foo.html", info: {dir: "/temp"}});
2134
	//		both return
2135
	//			"File 'foo.html' is not found in directory '/temp'."
2136
	// template:
2137
	//		a string with expressions in the form ${key} to be replaced or
2138
	//		${key:format} which specifies a format function.  NOTE syntax has
2139
	//		changed from %{key}
2140
	// map: where to look for substitutions
2141
	// transform:
2142
	//		a function to process all parameters before substitution takes
2143
	//		place, e.g. dojo.string.encodeXML
2144
	// thisObject:
2145
	//		where to look for optional format function; default to the global
2146
	//		namespace
2147
 
2148
	return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g, function(match, key, format){
2149
		var value = dojo.getObject(key,false,map);
2150
		if(format){ value = dojo.getObject(format,false,thisObject)(value);}
2151
		if(transform){ value = transform(value, key); }
2152
		return value.toString();
2153
	}); // string
2154
};
2155
 
2156
dojo.string.trim = function(/*String*/ str){
2157
	// summary: trims whitespaces from both sides of the string
2158
	// description:
2159
	//	This version of trim() was taken from Steven Levithan's blog:
2160
	//	http://blog.stevenlevithan.com/archives/faster-trim-javascript.
2161
	//	The short yet good-performing version of this function is
2162
	//	dojo.trim(), which is part of the base.
2163
	str = str.replace(/^\s+/, '');
2164
	for(var i = str.length - 1; i > 0; i--){
2165
		if(/\S/.test(str.charAt(i))){
2166
			str = str.substring(0, i + 1);
2167
			break;
2168
		}
2169
	}
2170
	return str;	// String
2171
};
2172
 
2173
}
2174
 
2175
if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2176
dojo._hasResource["dijit._Templated"] = true;
2177
dojo.provide("dijit._Templated");
2178
 
2179
 
2180
 
2181
 
2182
 
2183
 
2184
dojo.declare("dijit._Templated",
2185
	null,
2186
	{
2187
		// summary:
2188
		//		mixin for widgets that are instantiated from a template
2189
 
2190
		// templateNode: DomNode
2191
		//		a node that represents the widget template. Pre-empts both templateString and templatePath.
2192
		templateNode: null,
2193
 
2194
		// templateString String:
2195
		//		a string that represents the widget template. Pre-empts the
2196
		//		templatePath. In builds that have their strings "interned", the
2197
		//		templatePath is converted to an inline templateString, thereby
2198
		//		preventing a synchronous network call.
2199
		templateString: null,
2200
 
2201
		// templatePath: String
2202
		//	Path to template (HTML file) for this widget
2203
		templatePath: null,
2204
 
2205
		// widgetsInTemplate Boolean:
2206
		//		should we parse the template to find widgets that might be
2207
		//		declared in markup inside it? false by default.
2208
		widgetsInTemplate: false,
2209
 
2210
		// containerNode DomNode:
2211
		//		holds child elements. "containerNode" is generally set via a
2212
		//		dojoAttachPoint assignment and it designates where children of
2213
		//		the src dom node will be placed
2214
		containerNode: null,
2215
 
2216
		// skipNodeCache Boolean:
2217
		//		if using a cached widget template node poses issues for a
2218
		//		particular widget class, it can set this property to ensure
2219
		//		that its template is always re-built from a string
2220
		_skipNodeCache: false,
2221
 
2222
		// method over-ride
2223
		buildRendering: function(){
2224
			// summary:
2225
			//		Construct the UI for this widget from a template, setting this.domNode.
2226
 
2227
			// Lookup cached version of template, and download to cache if it
2228
			// isn't there already.  Returns either a DomNode or a string, depending on
2229
			// whether or not the template contains ${foo} replacement parameters.
2230
			var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);
2231
 
2232
			var node;
2233
			if(dojo.isString(cached)){
2234
				var className = this.declaredClass, _this = this;
2235
				// Cache contains a string because we need to do property replacement
2236
				// do the property replacement
2237
				var tstr = dojo.string.substitute(cached, this, function(value, key){
2238
					if(key.charAt(0) == '!'){ value = _this[key.substr(1)]; }
2239
					if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
2240
					if(!value){ return ""; }
2241
 
2242
					// Substitution keys beginning with ! will skip the transform step,
2243
					// in case a user wishes to insert unescaped markup, e.g. ${!foo}
2244
					return key.charAt(0) == "!" ? value :
2245
						// Safer substitution, see heading "Attribute values" in
2246
						// http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
2247
						value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
2248
				}, this);
2249
 
2250
				node = dijit._Templated._createNodesFromText(tstr)[0];
2251
			}else{
2252
				// if it's a node, all we have to do is clone it
2253
				node = cached.cloneNode(true);
2254
			}
2255
 
2256
			// recurse through the node, looking for, and attaching to, our
2257
			// attachment points which should be defined on the template node.
2258
			this._attachTemplateNodes(node);
2259
 
2260
			var source = this.srcNodeRef;
2261
			if(source && source.parentNode){
2262
				source.parentNode.replaceChild(node, source);
2263
			}
2264
 
2265
			this.domNode = node;
2266
			if(this.widgetsInTemplate){
2267
				var childWidgets = dojo.parser.parse(node);
2268
				this._attachTemplateNodes(childWidgets, function(n,p){
2269
					return n[p];
2270
				});
2271
			}
2272
 
2273
			this._fillContent(source);
2274
		},
2275
 
2276
		_fillContent: function(/*DomNode*/ source){
2277
			// summary:
2278
			//		relocate source contents to templated container node
2279
			//		this.containerNode must be able to receive children, or exceptions will be thrown
2280
			var dest = this.containerNode;
2281
			if(source && dest){
2282
				while(source.hasChildNodes()){
2283
					dest.appendChild(source.firstChild);
2284
				}
2285
			}
2286
		},
2287
 
2288
		_attachTemplateNodes: function(rootNode, getAttrFunc){
2289
			// summary:
2290
			//		map widget properties and functions to the handlers specified in
2291
			//		the dom node and it's descendants. This function iterates over all
2292
			//		nodes and looks for these properties:
2293
			//			* dojoAttachPoint
2294
			//			* dojoAttachEvent
2295
			//			* waiRole
2296
			//			* waiState
2297
			// rootNode: DomNode|Array[Widgets]
2298
			//		the node to search for properties. All children will be searched.
2299
			// getAttrFunc: function?
2300
			//		a function which will be used to obtain property for a given
2301
			//		DomNode/Widget
2302
 
2303
			getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };
2304
 
2305
			var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
2306
			var x=dojo.isArray(rootNode)?0:-1;
2307
			for(; x<nodes.length; x++){
2308
				var baseNode = (x == -1) ? rootNode : nodes[x];
2309
				if(this.widgetsInTemplate && getAttrFunc(baseNode,'dojoType')){
2310
					continue;
2311
				}
2312
				// Process dojoAttachPoint
2313
				var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint");
2314
				if(attachPoint){
2315
					var point, points = attachPoint.split(/\s*,\s*/);
2316
					while(point=points.shift()){
2317
						if(dojo.isArray(this[point])){
2318
							this[point].push(baseNode);
2319
						}else{
2320
							this[point]=baseNode;
2321
						}
2322
					}
2323
				}
2324
 
2325
				// Process dojoAttachEvent
2326
				var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent");
2327
				if(attachEvent){
2328
					// NOTE: we want to support attributes that have the form
2329
					// "domEvent: nativeEvent; ..."
2330
					var event, events = attachEvent.split(/\s*,\s*/);
2331
					var trim = dojo.trim;
2332
					while(event=events.shift()){
2333
						if(event){
2334
							var thisFunc = null;
2335
							if(event.indexOf(":") != -1){
2336
								// oh, if only JS had tuple assignment
2337
								var funcNameArr = event.split(":");
2338
								event = trim(funcNameArr[0]);
2339
								thisFunc = trim(funcNameArr[1]);
2340
							}else{
2341
								event = trim(event);
2342
							}
2343
							if(!thisFunc){
2344
								thisFunc = event;
2345
							}
2346
							this.connect(baseNode, event, thisFunc);
2347
						}
2348
					}
2349
				}
2350
 
2351
				// waiRole, waiState
2352
				var role = getAttrFunc(baseNode, "waiRole");
2353
				if(role){
2354
					dijit.setWaiRole(baseNode, role);
2355
				}
2356
				var values = getAttrFunc(baseNode, "waiState");
2357
				if(values){
2358
					dojo.forEach(values.split(/\s*,\s*/), function(stateValue){
2359
						if(stateValue.indexOf('-') != -1){
2360
							var pair = stateValue.split('-');
2361
							dijit.setWaiState(baseNode, pair[0], pair[1]);
2362
						}
2363
					});
2364
				}
2365
 
2366
			}
2367
		}
2368
	}
2369
);
2370
 
2371
// key is either templatePath or templateString; object is either string or DOM tree
2372
dijit._Templated._templateCache = {};
2373
 
2374
dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){
2375
	// summary:
2376
	//		static method to get a template based on the templatePath or
2377
	//		templateString key
2378
	// templatePath: String
2379
	//		the URL to get the template from. dojo.uri.Uri is often passed as well.
2380
	// templateString: String?
2381
	//		a string to use in lieu of fetching the template from a URL
2382
	// Returns:
2383
	//	Either string (if there are ${} variables that need to be replaced) or just
2384
	//	a DOM tree (if the node can be cloned directly)
2385
 
2386
	// is it already cached?
2387
	var tmplts = dijit._Templated._templateCache;
2388
	var key = templateString || templatePath;
2389
	var cached = tmplts[key];
2390
	if(cached){
2391
		return cached;
2392
	}
2393
 
2394
	// If necessary, load template string from template path
2395
	if(!templateString){
2396
		templateString = dijit._Templated._sanitizeTemplateString(dojo._getText(templatePath));
2397
	}
2398
 
2399
	templateString = dojo.string.trim(templateString);
2400
 
2401
	if(templateString.match(/\$\{([^\}]+)\}/g) || alwaysUseString){
2402
		// there are variables in the template so all we can do is cache the string
2403
		return (tmplts[key] = templateString); //String
2404
	}else{
2405
		// there are no variables in the template so we can cache the DOM tree
2406
		return (tmplts[key] = dijit._Templated._createNodesFromText(templateString)[0]); //Node
2407
	}
2408
};
2409
 
2410
dijit._Templated._sanitizeTemplateString = function(/*String*/tString){
2411
	// summary:
2412
	//		Strips <?xml ...?> declarations so that external SVG and XML
2413
	// 		documents can be added to a document without worry. Also, if the string
2414
	//		is an HTML document, only the part inside the body tag is returned.
2415
	if(tString){
2416
		tString = tString.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
2417
		var matches = tString.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
2418
		if(matches){
2419
			tString = matches[1];
2420
		}
2421
	}else{
2422
		tString = "";
2423
	}
2424
	return tString; //String
2425
};
2426
 
2427
 
2428
if(dojo.isIE){
2429
	dojo.addOnUnload(function(){
2430
		var cache = dijit._Templated._templateCache;
2431
		for(var key in cache){
2432
			var value = cache[key];
2433
			if(!isNaN(value.nodeType)){ // isNode equivalent
2434
				dojo._destroyElement(value);
2435
			}
2436
			delete cache[key];
2437
		}
2438
	});
2439
}
2440
 
2441
(function(){
2442
	var tagMap = {
2443
		cell: {re: /^<t[dh][\s\r\n>]/i, pre: "<table><tbody><tr>", post: "</tr></tbody></table>"},
2444
		row: {re: /^<tr[\s\r\n>]/i, pre: "<table><tbody>", post: "</tbody></table>"},
2445
		section: {re: /^<(thead|tbody|tfoot)[\s\r\n>]/i, pre: "<table>", post: "</table>"}
2446
	};
2447
 
2448
	// dummy container node used temporarily to hold nodes being created
2449
	var tn;
2450
 
2451
	dijit._Templated._createNodesFromText = function(/*String*/text){
2452
		// summary:
2453
		//	Attempts to create a set of nodes based on the structure of the passed text.
2454
 
2455
		if(!tn){
2456
			tn = dojo.doc.createElement("div");
2457
			tn.style.display="none";
2458
			dojo.body().appendChild(tn);
2459
		}
2460
		var tableType = "none";
2461
		var rtext = text.replace(/^\s+/, "");
2462
		for(var type in tagMap){
2463
			var map = tagMap[type];
2464
			if(map.re.test(rtext)){
2465
				tableType = type;
2466
				text = map.pre + text + map.post;
2467
				break;
2468
			}
2469
		}
2470
 
2471
		tn.innerHTML = text;
2472
		if(tn.normalize){
2473
			tn.normalize();
2474
		}
2475
 
2476
		var tag = { cell: "tr", row: "tbody", section: "table" }[tableType];
2477
		var _parent = (typeof tag != "undefined") ?
2478
						tn.getElementsByTagName(tag)[0] :
2479
						tn;
2480
 
2481
		var nodes = [];
2482
		while(_parent.firstChild){
2483
			nodes.push(_parent.removeChild(_parent.firstChild));
2484
		}
2485
		tn.innerHTML="";
2486
		return nodes;	//	Array
2487
	}
2488
})();
2489
 
2490
// These arguments can be specified for widgets which are used in templates.
2491
// Since any widget can be specified as sub widgets in template, mix it
2492
// into the base widget class.  (This is a hack, but it's effective.)
2493
dojo.extend(dijit._Widget,{
2494
	dojoAttachEvent: "",
2495
	dojoAttachPoint: "",
2496
	waiRole: "",
2497
	waiState:""
2498
})
2499
 
2500
}
2501
 
2502
if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2503
dojo._hasResource["dijit._Container"] = true;
2504
dojo.provide("dijit._Container");
2505
 
2506
dojo.declare("dijit._Contained",
2507
	null,
2508
	{
2509
		// summary
2510
		//		Mixin for widgets that are children of a container widget
2511
 
2512
		getParent: function(){
2513
			// summary:
2514
			//		returns the parent widget of this widget, assuming the parent
2515
			//		implements dijit._Container
2516
			for(var p=this.domNode.parentNode; p; p=p.parentNode){
2517
				var id = p.getAttribute && p.getAttribute("widgetId");
2518
				if(id){
2519
					var parent = dijit.byId(id);
2520
					return parent.isContainer ? parent : null;
2521
				}
2522
			}
2523
			return null;
2524
		},
2525
 
2526
		_getSibling: function(which){
2527
			var node = this.domNode;
2528
			do{
2529
				node = node[which+"Sibling"];
2530
			}while(node && node.nodeType != 1);
2531
			if(!node){ return null; } // null
2532
			var id = node.getAttribute("widgetId");
2533
			return dijit.byId(id);
2534
		},
2535
 
2536
		getPreviousSibling: function(){
2537
			// summary:
2538
			//		returns null if this is the first child of the parent,
2539
			//		otherwise returns the next element sibling to the "left".
2540
 
2541
			return this._getSibling("previous");
2542
		},
2543
 
2544
		getNextSibling: function(){
2545
			// summary:
2546
			//		returns null if this is the last child of the parent,
2547
			//		otherwise returns the next element sibling to the "right".
2548
 
2549
			return this._getSibling("next");
2550
		}
2551
	}
2552
);
2553
 
2554
dojo.declare("dijit._Container",
2555
	null,
2556
	{
2557
		// summary
2558
		//		Mixin for widgets that contain a list of children like SplitContainer
2559
 
2560
		isContainer: true,
2561
 
2562
		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
2563
			// summary:
2564
			//		Process the given child widget, inserting it's dom node as
2565
			//		a child of our dom node
2566
 
2567
			if(insertIndex === undefined){
2568
				insertIndex = "last";
2569
			}
2570
			var refNode = this.containerNode || this.domNode;
2571
			if(insertIndex && typeof insertIndex == "number"){
2572
				var children = dojo.query("> [widgetid]", refNode);
2573
				if(children && children.length >= insertIndex){
2574
					refNode = children[insertIndex-1]; insertIndex = "after";
2575
				}
2576
			}
2577
			dojo.place(widget.domNode, refNode, insertIndex);
2578
 
2579
			// If I've been started but the child widget hasn't been started,
2580
			// start it now.  Make sure to do this after widget has been
2581
			// inserted into the DOM tree, so it can see that it's being controlled by me,
2582
			// so it doesn't try to size itself.
2583
			if(this._started && !widget._started){
2584
				widget.startup();
2585
			}
2586
		},
2587
 
2588
		removeChild: function(/*Widget*/ widget){
2589
			// summary:
2590
			//		removes the passed widget instance from this widget but does
2591
			//		not destroy it
2592
			var node = widget.domNode;
2593
			node.parentNode.removeChild(node);	// detach but don't destroy
2594
		},
2595
 
2596
		_nextElement: function(node){
2597
			do{
2598
				node = node.nextSibling;
2599
			}while(node && node.nodeType != 1);
2600
			return node;
2601
		},
2602
 
2603
		_firstElement: function(node){
2604
			node = node.firstChild;
2605
			if(node && node.nodeType != 1){
2606
				node = this._nextElement(node);
2607
			}
2608
			return node;
2609
		},
2610
 
2611
		getChildren: function(){
2612
			// summary:
2613
			//		Returns array of children widgets
2614
			return dojo.query("> [widgetId]", this.containerNode || this.domNode).map(dijit.byNode); // Array
2615
		},
2616
 
2617
		hasChildren: function(){
2618
			// summary:
2619
			//		Returns true if widget has children
2620
			var cn = this.containerNode || this.domNode;
2621
			return !!this._firstElement(cn); // Boolean
2622
		},
2623
 
2624
		_getSiblingOfChild: function(/*Widget*/ child, /*int*/ dir){
2625
			// summary:
2626
			//		get the next or previous widget sibling of child
2627
			// dir:
2628
			//		if 1, get the next sibling
2629
			//		if -1, get the previous sibling
2630
			var node = child.domNode;
2631
			var which = (dir>0 ? "nextSibling" : "previousSibling");
2632
			do{
2633
				node = node[which];
2634
			}while(node && (node.nodeType != 1 || !dijit.byNode(node)));
2635
			return node ? dijit.byNode(node) : null;
2636
		}
2637
	}
2638
);
2639
 
2640
dojo.declare("dijit._KeyNavContainer",
2641
	[dijit._Container],
2642
	{
2643
 
2644
		// summary:
2645
		//		A _Container with keyboard navigation of its children.
2646
		//		To use this mixin, call connectKeyNavHandlers() in
2647
		//		postCreate() and call startupKeyNavChildren() in startup().
2648
 
2649
/*=====
2650
		// focusedChild: Widget
2651
		//		The currently focused child widget, or null if there isn't one
2652
		focusedChild: null,
2653
=====*/
2654
 
2655
		_keyNavCodes: {},
2656
 
2657
		connectKeyNavHandlers: function(/*Array*/ prevKeyCodes, /*Array*/ nextKeyCodes){
2658
			// summary:
2659
			//		Call in postCreate() to attach the keyboard handlers
2660
			//		to the container.
2661
			// preKeyCodes: Array
2662
			//		Key codes for navigating to the previous child.
2663
			// nextKeyCodes: Array
2664
			//		Key codes for navigating to the next child.
2665
 
2666
			var keyCodes = this._keyNavCodes = {};
2667
			var prev = dojo.hitch(this, this.focusPrev);
2668
			var next = dojo.hitch(this, this.focusNext);
2669
			dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev });
2670
			dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next });
2671
			this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
2672
			if(dojo.isIE){
2673
				this.connect(this.domNode, "onactivate", "_onContainerFocus");
2674
				this.connect(this.domNode, "ondeactivate", "_onContainerBlur");
2675
			}else{
2676
				this.connect(this.domNode, "onfocus", "_onContainerFocus");
2677
				this.connect(this.domNode, "onblur", "_onContainerBlur");
2678
			}
2679
		},
2680
 
2681
		startupKeyNavChildren: function(){
2682
			// summary:
2683
			//		Call in startup() to set child tabindexes to -1
2684
			dojo.forEach(this.getChildren(), dojo.hitch(this, "_setTabIndexMinusOne"));
2685
		},
2686
 
2687
		addChild: function(/*Widget*/ widget, /*int?*/ insertIndex){
2688
			// summary: Add a child to our _Container
2689
			dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
2690
			this._setTabIndexMinusOne(widget);
2691
		},
2692
 
2693
		focus: function(){
2694
			// summary: Default focus() implementation: focus the first child.
2695
			this.focusFirstChild();
2696
		},
2697
 
2698
		focusFirstChild: function(){
2699
			// summary: Focus the first focusable child in the container.
2700
			this.focusChild(this._getFirstFocusableChild());
2701
		},
2702
 
2703
		focusNext: function(){
2704
			// summary: Focus the next widget or focal node (for widgets
2705
			//		with multiple focal nodes) within this container.
2706
			if(this.focusedChild && this.focusedChild.hasNextFocalNode
2707
					&& this.focusedChild.hasNextFocalNode()){
2708
				this.focusedChild.focusNext();
2709
				return;
2710
			}
2711
			var child = this._getNextFocusableChild(this.focusedChild, 1);
2712
			if(child.getFocalNodes){
2713
				this.focusChild(child, child.getFocalNodes()[0]);
2714
			}else{
2715
				this.focusChild(child);
2716
			}
2717
		},
2718
 
2719
		focusPrev: function(){
2720
			// summary: Focus the previous widget or focal node (for widgets
2721
			//		with multiple focal nodes) within this container.
2722
			if(this.focusedChild && this.focusedChild.hasPrevFocalNode
2723
					&& this.focusedChild.hasPrevFocalNode()){
2724
				this.focusedChild.focusPrev();
2725
				return;
2726
			}
2727
			var child = this._getNextFocusableChild(this.focusedChild, -1);
2728
			if(child.getFocalNodes){
2729
				var nodes = child.getFocalNodes();
2730
				this.focusChild(child, nodes[nodes.length-1]);
2731
			}else{
2732
				this.focusChild(child);
2733
			}
2734
		},
2735
 
2736
		focusChild: function(/*Widget*/ widget, /*Node?*/ node){
2737
			// summary: Focus widget. Optionally focus 'node' within widget.
2738
			if(widget){
2739
				if(this.focusedChild && widget !== this.focusedChild){
2740
					this._onChildBlur(this.focusedChild);
2741
				}
2742
				this.focusedChild = widget;
2743
				if(node && widget.focusFocalNode){
2744
					widget.focusFocalNode(node);
2745
				}else{
2746
					widget.focus();
2747
				}
2748
			}
2749
		},
2750
 
2751
		_setTabIndexMinusOne: function(/*Widget*/ widget){
2752
			if(widget.getFocalNodes){
2753
				dojo.forEach(widget.getFocalNodes(), function(node){
2754
					node.setAttribute("tabIndex", -1);
2755
				});
2756
			}else{
2757
				(widget.focusNode || widget.domNode).setAttribute("tabIndex", -1);
2758
			}
2759
		},
2760
 
2761
		_onContainerFocus: function(evt){
2762
			this.domNode.setAttribute("tabIndex", -1);
2763
			if(evt.target === this.domNode){
2764
				this.focusFirstChild();
2765
			}else{
2766
				var widget = dijit.getEnclosingWidget(evt.target);
2767
				if(widget && widget.isFocusable()){
2768
					this.focusedChild = widget;
2769
				}
2770
			}
2771
		},
2772
 
2773
		_onContainerBlur: function(evt){
2774
			if(this.tabIndex){
2775
				this.domNode.setAttribute("tabIndex", this.tabIndex);
2776
			}
2777
		},
2778
 
2779
		_onContainerKeypress: function(evt){
2780
			if(evt.ctrlKey || evt.altKey){ return; }
2781
			var func = this._keyNavCodes[evt.keyCode];
2782
			if(func){
2783
				func();
2784
				dojo.stopEvent(evt);
2785
			}
2786
		},
2787
 
2788
		_onChildBlur: function(/*Widget*/ widget){
2789
			// summary:
2790
			//		Called when focus leaves a child widget to go
2791
			//		to a sibling widget.
2792
		},
2793
 
2794
		_getFirstFocusableChild: function(){
2795
			return this._getNextFocusableChild(null, 1);
2796
		},
2797
 
2798
		_getNextFocusableChild: function(child, dir){
2799
			if(child){
2800
				child = this._getSiblingOfChild(child, dir);
2801
			}
2802
			var children = this.getChildren();
2803
			for(var i=0; i < children.length; i++){
2804
				if(!child){
2805
					child = children[(dir>0) ? 0 : (children.length-1)];
2806
				}
2807
				if(child.isFocusable()){
2808
					return child;
2809
				}
2810
				child = this._getSiblingOfChild(child, dir);
2811
			}
2812
		}
2813
	}
2814
);
2815
 
2816
}
2817
 
2818
if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
2819
dojo._hasResource["dijit.layout._LayoutWidget"] = true;
2820
dojo.provide("dijit.layout._LayoutWidget");
2821
 
2822
 
2823
 
2824
 
2825
dojo.declare("dijit.layout._LayoutWidget",
2826
	[dijit._Widget, dijit._Container, dijit._Contained],
2827
	{
2828
		// summary
2829
		//		Mixin for widgets that contain a list of children like SplitContainer.
2830
		//		Widgets which mixin this code must define layout() to lay out the children
2831
 
2832
		isLayoutContainer: true,
2833
 
2834
		postCreate: function(){
2835
			dojo.addClass(this.domNode, "dijitContainer");
2836
		},
2837
 
2838
		startup: function(){
2839
			// summary:
2840
			//		Called after all the widgets have been instantiated and their
2841
			//		dom nodes have been inserted somewhere under document.body.
2842
			//
2843
			//		Widgets should override this method to do any initialization
2844
			//		dependent on other widgets existing, and then call
2845
			//		this superclass method to finish things off.
2846
			//
2847
			//		startup() in subclasses shouldn't do anything
2848
			//		size related because the size of the widget hasn't been set yet.
2849
 
2850
			if(this._started){ return; }
2851
			this._started=true;
2852
 
2853
			if(this.getChildren){
2854
				dojo.forEach(this.getChildren(), function(child){ child.startup(); });
2855
			}
2856
 
2857
			// If I am a top level widget
2858
			if(!this.getParent || !this.getParent()){
2859
				// Do recursive sizing and layout of all my descendants
2860
				// (passing in no argument to resize means that it has to glean the size itself)
2861
				this.resize();
2862
 
2863
				// since my parent isn't a layout container, and my style is width=height=100% (or something similar),
2864
				// then I need to watch when the window resizes, and size myself accordingly
2865
				// (passing in no argument to resize means that it has to glean the size itself)
2866
				this.connect(window, 'onresize', function(){this.resize();});
2867
			}
2868
		},
2869
 
2870
		resize: function(args){
2871
			// summary:
2872
			//		Explicitly set this widget's size (in pixels),
2873
			//		and then call layout() to resize contents (and maybe adjust child widgets)
2874
			//
2875
			// args: Object?
2876
			//		{w: int, h: int, l: int, t: int}
2877
 
2878
			var node = this.domNode;
2879
 
2880
			// set margin box size, unless it wasn't specified, in which case use current size
2881
			if(args){
2882
				dojo.marginBox(node, args);
2883
 
2884
				// set offset of the node
2885
				if(args.t){ node.style.top = args.t + "px"; }
2886
				if(args.l){ node.style.left = args.l + "px"; }
2887
			}
2888
			// If either height or width wasn't specified by the user, then query node for it.
2889
			// But note that setting the margin box and then immediately querying dimensions may return
2890
			// inaccurate results, so try not to depend on it.
2891
			var mb = dojo.mixin(dojo.marginBox(node), args||{});
2892
 
2893
			// Save the size of my content box.
2894
			this._contentBox = dijit.layout.marginBox2contentBox(node, mb);
2895
 
2896
			// Callback for widget to adjust size of it's children
2897
			this.layout();
2898
		},
2899
 
2900
		layout: function(){
2901
			//	summary
2902
			//		Widgets override this method to size & position their contents/children.
2903
			//		When this is called this._contentBox is guaranteed to be set (see resize()).
2904
			//
2905
			//		This is called after startup(), and also when the widget's size has been
2906
			//		changed.
2907
		}
2908
	}
2909
);
2910
 
2911
dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
2912
	// summary:
2913
	//		Given the margin-box size of a node, return it's content box size.
2914
	//		Functions like dojo.contentBox() but is more reliable since it doesn't have
2915
	//		to wait for the browser to compute sizes.
2916
	var cs = dojo.getComputedStyle(node);
2917
	var me=dojo._getMarginExtents(node, cs);
2918
	var pb=dojo._getPadBorderExtents(node, cs);
2919
	return {
2920
		l: dojo._toPixelValue(node, cs.paddingLeft),
2921
		t: dojo._toPixelValue(node, cs.paddingTop),
2922
		w: mb.w - (me.w + pb.w),
2923
		h: mb.h - (me.h + pb.h)
2924
	};
2925
};
2926
 
2927
(function(){
2928
	var capitalize = function(word){
2929
		return word.substring(0,1).toUpperCase() + word.substring(1);
2930
	};
2931
 
2932
	var size = function(widget, dim){
2933
		// size the child
2934
		widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
2935
 
2936
		// record child's size, but favor our own numbers when we have them.
2937
		// the browser lies sometimes
2938
		dojo.mixin(widget, dojo.marginBox(widget.domNode));
2939
		dojo.mixin(widget, dim);
2940
	};
2941
 
2942
	dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
2943
		/**
2944
		 * summary
2945
		 *		Layout a bunch of child dom nodes within a parent dom node
2946
		 * container:
2947
		 *		parent node
2948
		 * dim:
2949
		 *		{l, t, w, h} object specifying dimensions of container into which to place children
2950
		 * children:
2951
		 *		an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
2952
		 */
2953
 
2954
		// copy dim because we are going to modify it
2955
		dim = dojo.mixin({}, dim);
2956
 
2957
		dojo.addClass(container, "dijitLayoutContainer");
2958
 
2959
		// Move "client" elements to the end of the array for layout.  a11y dictates that the author
2960
		// needs to be able to put them in the document in tab-order, but this algorithm requires that
2961
		// client be last.
2962
		children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; })
2963
			.concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; }));
2964
 
2965
		// set positions/sizes
2966
		dojo.forEach(children, function(child){
2967
			var elm = child.domNode,
2968
				pos = child.layoutAlign;
2969
 
2970
			// set elem to upper left corner of unused space; may move it later
2971
			var elmStyle = elm.style;
2972
			elmStyle.left = dim.l+"px";
2973
			elmStyle.top = dim.t+"px";
2974
			elmStyle.bottom = elmStyle.right = "auto";
2975
 
2976
			dojo.addClass(elm, "dijitAlign" + capitalize(pos));
2977
 
2978
			// set size && adjust record of remaining space.
2979
			// note that setting the width of a <div> may affect it's height.
2980
			if(pos=="top" || pos=="bottom"){
2981
				size(child, { w: dim.w });
2982
				dim.h -= child.h;
2983
				if(pos=="top"){
2984
					dim.t += child.h;
2985
				}else{
2986
					elmStyle.top = dim.t + dim.h + "px";
2987
				}
2988
			}else if(pos=="left" || pos=="right"){
2989
				size(child, { h: dim.h });
2990
				dim.w -= child.w;
2991
				if(pos=="left"){
2992
					dim.l += child.w;
2993
				}else{
2994
					elmStyle.left = dim.l + dim.w + "px";
2995
				}
2996
			}else if(pos=="client"){
2997
				size(child, dim);
2998
			}
2999
		});
3000
	};
3001
 
3002
})();
3003
 
3004
}
3005
 
3006
if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
3007
dojo._hasResource["dijit.form._FormWidget"] = true;
3008
dojo.provide("dijit.form._FormWidget");
3009
 
3010
 
3011
 
3012
 
3013
dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated],
3014
{
3015
	/*
3016
	Summary:
3017
		FormElement widgets correspond to native HTML elements such as <input> or <button> or <select>.
3018
		Each FormElement represents a single input value, and has a (possibly hidden) <input> element,
3019
		to which it serializes its input value, so that form submission (either normal submission or via FormBind?)
3020
		works as expected.
3021
 
3022
		All these widgets should have these attributes just like native HTML input elements.
3023
		You can set them during widget construction, but after that they are read only.
3024
 
3025
		They also share some common methods.
3026
	*/
3027
 
3028
	// baseClass: String
3029
	//		Root CSS class of the widget (ex: dijitTextBox), used to add CSS classes of widget
3030
	//		(ex: "dijitTextBox dijitTextBoxInvalid dijitTextBoxFocused dijitTextBoxInvalidFocused")
3031
	//		See _setStateClass().
3032
	baseClass: "",
3033
 
3034
	// value: String
3035
	//		Corresponds to the native HTML <input> element's attribute.
3036
	value: "",
3037
 
3038
	// name: String
3039
	//		Name used when submitting form; same as "name" attribute or plain HTML elements
3040
	name: "",
3041
 
3042
	// id: String
3043
	//		Corresponds to the native HTML <input> element's attribute.
3044
	//		Also becomes the id for the widget.
3045
	id: "",
3046
 
3047
	// alt: String
3048
	//		Corresponds to the native HTML <input> element's attribute.
3049
	alt: "",
3050
 
3051
	// type: String
3052
	//		Corresponds to the native HTML <input> element's attribute.
3053
	type: "text",
3054
 
3055
	// tabIndex: Integer
3056
	//		Order fields are traversed when user hits the tab key
3057
	tabIndex: "0",
3058
 
3059
	// disabled: Boolean
3060
	//		Should this widget respond to user input?
3061
	//		In markup, this is specified as "disabled='disabled'", or just "disabled".
3062
	disabled: false,
3063
 
3064
	// intermediateChanges: Boolean
3065
	//		Fires onChange for each value change or only on demand
3066
	intermediateChanges: false,
3067
 
3068
	// These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
3069
	// Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
3070
	// directly in the template as read by the parser in order to function. IE is known to specifically
3071
	// require the 'name' attribute at element creation time.
3072
	attributeMap: dojo.mixin(dojo.clone(dijit._Widget.prototype.attributeMap),
3073
		{id:"focusNode", tabIndex:"focusNode", alt:"focusNode"}),
3074
 
3075
	setDisabled: function(/*Boolean*/ disabled){
3076
		// summary:
3077
		//		Set disabled state of widget.
3078
 
3079
		this.domNode.disabled = this.disabled = disabled;
3080
		if(this.focusNode){
3081
			this.focusNode.disabled = disabled;
3082
		}
3083
		if(disabled){
3084
			//reset those, because after the domNode is disabled, we can no longer receive
3085
			//mouse related events, see #4200
3086
			this._hovering = false;
3087
			this._active = false;
3088
		}
3089
		dijit.setWaiState(this.focusNode || this.domNode, "disabled", disabled);
3090
		this._setStateClass();
3091
	},
3092
 
3093
 
3094
	_onMouse : function(/*Event*/ event){
3095
		// summary:
3096
		//	Sets _hovering, _active, and stateModifier properties depending on mouse state,
3097
		//	then calls setStateClass() to set appropriate CSS classes for this.domNode.
3098
		//
3099
		//	To get a different CSS class for hover, send onmouseover and onmouseout events to this method.
3100
		//	To get a different CSS class while mouse button is depressed, send onmousedown to this method.
3101
 
3102
		var mouseNode = event.target;
3103
		if(mouseNode && mouseNode.getAttribute){
3104
			this.stateModifier = mouseNode.getAttribute("stateModifier") || "";
3105
		}
3106
 
3107
		if(!this.disabled){
3108
			switch(event.type){
3109
				case "mouseenter" :
3110
				case "mouseover" :
3111
					this._hovering = true;
3112
					break;
3113
 
3114
				case "mouseout" :
3115
				case "mouseleave" :
3116
					this._hovering = false;
3117
					break;
3118
 
3119
				case "mousedown" :
3120
					this._active = true;
3121
					// set a global event to handle mouseup, so it fires properly
3122
					//	even if the cursor leaves the button
3123
					var self = this;
3124
					// #2685: use this.connect and disconnect so destroy works properly
3125
					var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
3126
						self._active = false;
3127
						self._setStateClass();
3128
						self.disconnect(mouseUpConnector);
3129
					});
3130
					break;
3131
			}
3132
			this._setStateClass();
3133
		}
3134
	},
3135
 
3136
	isFocusable: function(){
3137
		return !this.disabled && (dojo.style(this.domNode, "display") != "none");
3138
	},
3139
 
3140
	focus: function(){
3141
		dijit.focus(this.focusNode);
3142
	},
3143
 
3144
	_setStateClass: function(){
3145
		// summary
3146
		//	Update the visual state of the widget by setting the css classes on this.domNode
3147
		//  (or this.stateNode if defined) by combining this.baseClass with
3148
		//	various suffixes that represent the current widget state(s).
3149
		//
3150
		//	In the case where a widget has multiple
3151
		//	states, it sets the class based on all possible
3152
		//  combinations.  For example, an invalid form widget that is being hovered
3153
		//	will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
3154
		//
3155
		//	For complex widgets with multiple regions, there can be various hover/active states,
3156
		//	such as "Hover" or "CloseButtonHover" (for tab buttons).
3157
		//	This is controlled by a stateModifier="CloseButton" attribute on the close button node.
3158
		//
3159
		//	The widget may have one or more of the following states, determined
3160
		//	by this.state, this.checked, this.valid, and this.selected:
3161
		//		Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
3162
		//		Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
3163
		//		Selected - ex: currently selected tab will have this.selected==true
3164
		//
3165
		//	In addition, it may have at most one of the following states,
3166
		//	based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
3167
		//		Disabled	- if the widget is disabled
3168
		//		Active		- if the mouse (or space/enter key?) is being pressed down
3169
		//		Focused		- if the widget has focus
3170
		//		Hover		- if the mouse is over the widget
3171
		//
3172
		//	(even if multiple af the above conditions are true we only pick the first matching one)
3173
 
3174
 
3175
		// Get original (non state related, non baseClass related) class specified in template
3176
		if(!("staticClass" in this)){
3177
			this.staticClass = (this.stateNode||this.domNode).className;
3178
		}
3179
 
3180
		// Compute new set of classes
3181
		var classes = [ this.baseClass ];
3182
 
3183
		function multiply(modifier){
3184
			classes=classes.concat(dojo.map(classes, function(c){ return c+modifier; }));
3185
		}
3186
 
3187
		if(this.checked){
3188
			multiply("Checked");
3189
		}
3190
		if(this.state){
3191
			multiply(this.state);
3192
		}
3193
		if(this.selected){
3194
			multiply("Selected");
3195
		}
3196
 
3197
		// Only one of these four can be applied.
3198
		// Active trumps Focused, Focused trumps Hover, and Disabled trumps all.
3199
		if(this.disabled){
3200
			multiply("Disabled");
3201
		}else if(this._active){
3202
			multiply(this.stateModifier+"Active");
3203
		}else{
3204
			if(this._focused){
3205
				multiply("Focused");
3206
			}
3207
			if((this.stateModifier || !this._focused) && this._hovering){
3208
				multiply(this.stateModifier+"Hover");
3209
			}
3210
		}
3211
		(this.stateNode || this.domNode).className = this.staticClass + " " + classes.join(" ");
3212
	},
3213
 
3214
	onChange: function(newValue){
3215
		// summary: callback when value is changed
3216
	},
3217
 
3218
	postCreate: function(){
3219
		this.setValue(this.value, null); // null reserved for initial value
3220
		this.setDisabled(this.disabled);
3221
		this._setStateClass();
3222
	},
3223
 
3224
	setValue: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
3225
		// summary: set the value of the widget.
3226
		this._lastValue = newValue;
3227
		dijit.setWaiState(this.focusNode || this.domNode, "valuenow", this.forWaiValuenow());
3228
		if(priorityChange === undefined){ priorityChange = true; } // setValue with value only should fire onChange
3229
		if(this._lastValueReported == undefined && priorityChange === null){ // don't report the initial value
3230
			this._lastValueReported = newValue;
3231
		}
3232
		if((this.intermediateChanges || priorityChange) &&
3233
			((newValue && newValue.toString)?newValue.toString():newValue) !== ((this._lastValueReported && this._lastValueReported.toString)?this._lastValueReported.toString():this._lastValueReported)){
3234
			this._lastValueReported = newValue;
3235
			this.onChange(newValue);
3236
		}
3237
	},
3238
 
3239
	getValue: function(){
3240
		// summary: get the value of the widget.
3241
		return this._lastValue;
3242
	},
3243
 
3244
	undo: function(){
3245
		// summary: restore the value to the last value passed to onChange
3246
		this.setValue(this._lastValueReported, false);
3247
	},
3248
 
3249
	_onKeyPress: function(e){
3250
		if(e.keyCode == dojo.keys.ESCAPE && !e.shiftKey && !e.ctrlKey && !e.altKey){
3251
			var v = this.getValue();
3252
			var lv = this._lastValueReported;
3253
			// Equality comparison of objects such as dates are done by reference so
3254
			// two distinct objects are != even if they have the same data. So use
3255
			// toStrings in case the values are objects.
3256
			if((typeof lv != "undefined") && ((v!==null && v.toString)?v.toString():null) !== lv.toString()){
3257
				this.undo();
3258
				dojo.stopEvent(e);
3259
				return false;
3260
			}
3261
		}
3262
		return true;
3263
	},
3264
 
3265
	forWaiValuenow: function(){
3266
		// summary: returns a value, reflecting the current state of the widget,
3267
		//		to be used for the ARIA valuenow.
3268
		// 		This method may be overridden by subclasses that want
3269
		// 		to use something other than this.getValue() for valuenow
3270
		return this.getValue();
3271
	}
3272
});
3273
 
3274
}
3275
 
3276
if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
3277
dojo._hasResource["dijit.dijit"] = true;
3278
dojo.provide("dijit.dijit");
3279
 
3280
// All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
3281
 
3282
 
3283
// And some other stuff that we tend to pull in all the time anyway
3284
 
3285
 
3286
 
3287
 
3288
 
3289
 
3290
 
3291
}
3292