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