]> git.wh0rd.org - tt-rss.git/blobdiff - lib/dojo/tt-rss-layer.js.uncompressed.js
make precache_headlines_idle() start slower
[tt-rss.git] / lib / dojo / tt-rss-layer.js.uncompressed.js
index fa2e12157d1ee24882fbcd79c0908e2959f89ec7..cc43d87269134d48a30345c038cccbae3172f8f1 100644 (file)
-/*
-       Copyright (c) 2004-2010, The Dojo Foundation All Rights Reserved.
-       Available via Academic Free License >= 2.1 OR the modified BSD license.
-       see: http://dojotoolkit.org/license for details
-*/
+require({cache:{
+'dijit/form/TextBox':function(){
+require({cache:{
+'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}});
+define("dijit/form/TextBox", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-construct", // domConstruct.create
+       "dojo/dom-style", // domStyle.getComputedStyle
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.hitch
+       "dojo/_base/sniff", // has("ie") has("mozilla")
+       "dojo/_base/window", // win.doc.selection.createRange
+       "./_FormValueWidget",
+       "./_TextBoxMixin",
+       "dojo/text!./templates/TextBox.html",
+       ".."    // to export dijit._setSelectionRange, remove in 2.0
+], function(declare, domConstruct, domStyle, kernel, lang, has, win,
+                       _FormValueWidget, _TextBoxMixin, template, dijit){
 
-/*
-       This is an optimized version of Dojo, built for deployment and not for
-       development. To get sources and documentation, please visit:
+/*=====
+       var _FormValueWidget = dijit.form._FormValueWidget;
+       var _TextBoxMixin = dijit.form._TextBoxMixin;
+=====*/
 
-               http://dojotoolkit.org
-*/
+       // module:
+       //              dijit/form/TextBox
+       // summary:
+       //              A base class for textbox form inputs
 
-dojo.provide("tt-rss-layer");
-if(!dojo._hasResource["dojo.date.stamp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.date.stamp"] = true;
-dojo.provide("dojo.date.stamp");
+       var TextBox = declare(/*====="dijit.form.TextBox", =====*/ [_FormValueWidget, _TextBoxMixin], {
+               // summary:
+               //              A base class for textbox form inputs
 
-// Methods to convert dates to or from a wire (string) format using well-known conventions
+               templateString: template,
+               _singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" data-dojo-attach-point="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />',
 
-dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
-       //      summary:
-       //              Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
-       //
-       //      description:
-       //              Accepts a string formatted according to a profile of ISO8601 as defined by
-       //              [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
-       //              Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
-       //              The following combinations are valid:
-       //
-       //                      * dates only
-       //                      |       * yyyy
-       //                      |       * yyyy-MM
-       //                      |       * yyyy-MM-dd
-       //                      * times only, with an optional time zone appended
-       //                      |       * THH:mm
-       //                      |       * THH:mm:ss
-       //                      |       * THH:mm:ss.SSS
-       //                      * and "datetimes" which could be any combination of the above
-       //
-       //              timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
-       //              Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
-       //              input may return null.  Arguments which are out of bounds will be handled
-       //              by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
-       //              Only years between 100 and 9999 are supported.
-       //
-       //      formattedString:
-       //              A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
-       //
-       //      defaultTime:
-       //              Used for defaults for fields omitted in the formattedString.
-       //              Uses 1970-01-01T00:00:00.0Z by default.
+               _buttonInputDisabled: has("ie") ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events
 
-       if(!dojo.date.stamp._isoRegExp){
-               dojo.date.stamp._isoRegExp =
-//TODO: could be more restrictive and check for 00-59, etc.
-                       /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
-       }
+               baseClass: "dijitTextBox",
 
-       var match = dojo.date.stamp._isoRegExp.exec(formattedString),
-               result = null;
+               postMixInProperties: function(){
+                       var type = this.type.toLowerCase();
+                       if(this.templateString && this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == this.constructor.prototype.templateString)){
+                               this.templateString = this._singleNodeTemplate;
+                       }
+                       this.inherited(arguments);
+               },
 
-       if(match){
-               match.shift();
-               if(match[1]){match[1]--;} // Javascript Date months are 0-based
-               if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
+               _onInput: function(e){
+                       this.inherited(arguments);
+                       if(this.intermediateChanges){ // _TextBoxMixin uses onInput
+                               var _this = this;
+                               // the setTimeout allows the key to post to the widget input box
+                               setTimeout(function(){ _this._handleOnChange(_this.get('value'), false); }, 0);
+                       }
+               },
 
-               if(defaultTime){
-                       // mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
-                       defaultTime = new Date(defaultTime);
-                       dojo.forEach(dojo.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
-                               return defaultTime["get" + prop]();
-                       }), function(value, index){
-                               match[index] = match[index] || value;
-                       });
-               }
-               result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults
-               if(match[0] < 100){
-                       result.setFullYear(match[0] || 1970);
-               }
+               _setPlaceHolderAttr: function(v){
+                       this._set("placeHolder", v);
+                       if(!this._phspan){
+                               this._attachPoints.push('_phspan');
+                               // dijitInputField class gives placeHolder same padding as the input field
+                               // parent node already has dijitInputField class but it doesn't affect this <span>
+                               // since it's position: absolute.
+                               this._phspan = domConstruct.create('span',{className:'dijitPlaceHolder dijitInputField'},this.textbox,'after');
+                       }
+                       this._phspan.innerHTML="";
+                       this._phspan.appendChild(document.createTextNode(v));
+                       this._updatePlaceHolder();
+               },
 
-               var offset = 0,
-                       zoneSign = match[7] && match[7].charAt(0);
-               if(zoneSign != 'Z'){
-                       offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
-                       if(zoneSign != '-'){ offset *= -1; }
-               }
-               if(zoneSign){
-                       offset -= result.getTimezoneOffset();
-               }
-               if(offset){
-                       result.setTime(result.getTime() + offset * 60000);
-               }
-       }
+               _updatePlaceHolder: function(){
+                       if(this._phspan){
+                               this._phspan.style.display=(this.placeHolder&&!this.focused&&!this.textbox.value)?"":"none";
+                       }
+               },
 
-       return result; // Date or null
-}
+               _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
+                       this.inherited(arguments);
+                       this._updatePlaceHolder();
+               },
 
-/*=====
-       dojo.date.stamp.__Options = function(){
-               //      selector: String
-               //              "date" or "time" for partial formatting of the Date object.
-               //              Both date and time will be formatted by default.
-               //      zulu: Boolean
-               //              if true, UTC/GMT is used for a timezone
-               //      milliseconds: Boolean
-               //              if true, output milliseconds
-               this.selector = selector;
-               this.zulu = zulu;
-               this.milliseconds = milliseconds;
-       }
-=====*/
+               getDisplayedValue: function(){
+                       // summary:
+                       //              Deprecated.  Use get('displayedValue') instead.
+                       // tags:
+                       //              deprecated
+                       kernel.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use set('displayedValue') instead.", "", "2.0");
+                       return this.get('displayedValue');
+               },
 
-dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
-       //      summary:
-       //              Format a Date object as a string according a subset of the ISO-8601 standard
-       //
-       //      description:
-       //              When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
-       //              The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
-       //              Does not check bounds.  Only years between 100 and 9999 are supported.
-       //
-       //      dateObject:
-       //              A Date object
+               setDisplayedValue: function(/*String*/ value){
+                       // summary:
+                       //              Deprecated.  Use set('displayedValue', ...) instead.
+                       // tags:
+                       //              deprecated
+                       kernel.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0");
+                       this.set('displayedValue', value);
+               },
 
-       var _ = function(n){ return (n < 10) ? "0" + n : n; };
-       options = options || {};
-       var formattedDate = [],
-               getter = options.zulu ? "getUTC" : "get",
-               date = "";
-       if(options.selector != "time"){
-               var year = dateObject[getter+"FullYear"]();
-               date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
-       }
-       formattedDate.push(date);
-       if(options.selector != "date"){
-               var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
-               var millis = dateObject[getter+"Milliseconds"]();
-               if(options.milliseconds){
-                       time += "."+ (millis < 100 ? "0" : "") + _(millis);
-               }
-               if(options.zulu){
-                       time += "Z";
-               }else if(options.selector != "time"){
-                       var timezoneOffset = dateObject.getTimezoneOffset();
-                       var absOffset = Math.abs(timezoneOffset);
-                       time += (timezoneOffset > 0 ? "-" : "+") + 
-                               _(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
+               _onBlur: function(e){
+                       if(this.disabled){ return; }
+                       this.inherited(arguments);
+                       this._updatePlaceHolder();
+               },
+
+               _onFocus: function(/*String*/ by){
+                       if(this.disabled || this.readOnly){ return; }
+                       this.inherited(arguments);
+                       this._updatePlaceHolder();
                }
-               formattedDate.push(time);
-       }
-       return formattedDate.join('T'); // String
-}
+       });
 
-}
+       if(has("ie")){
+               TextBox = declare(/*===== "dijit.form.TextBox.IEMixin", =====*/ TextBox, {
+                       declaredClass: "dijit.form.TextBox",    // for user code referencing declaredClass
 
-if(!dojo._hasResource["dojo.parser"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.parser"] = true;
-dojo.provide("dojo.parser");
+                       _isTextSelected: function(){
+                               var range = win.doc.selection.createRange();
+                               var parent = range.parentElement();
+                               return parent == this.textbox && range.text.length == 0;
+                       },
+
+                       postCreate: function(){
+                               this.inherited(arguments);
+                               // IE INPUT tag fontFamily has to be set directly using STYLE
+                               // the setTimeout gives IE a chance to render the TextBox and to deal with font inheritance
+                               setTimeout(lang.hitch(this, function(){
+                                       try{
+                                               var s = domStyle.getComputedStyle(this.domNode); // can throw an exception if widget is immediately destroyed
+                                               if(s){
+                                                       var ff = s.fontFamily;
+                                                       if(ff){
+                                                               var inputs = this.domNode.getElementsByTagName("INPUT");
+                                                               if(inputs){
+                                                                       for(var i=0; i < inputs.length; i++){
+                                                                               inputs[i].style.fontFamily = ff;
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }catch(e){/*when used in a Dialog, and this is called before the dialog is
+                                               shown, s.fontFamily would trigger "Invalid Argument" error.*/}
+                               }), 0);
+                       }
+               });
 
+               // Overrides definition of _setSelectionRange from _TextBoxMixin (TODO: move to _TextBoxMixin.js?)
+               dijit._setSelectionRange = _TextBoxMixin._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
+                       if(element.createTextRange){
+                               var r = element.createTextRange();
+                               r.collapse(true);
+                               r.moveStart("character", -99999); // move to 0
+                               r.moveStart("character", start); // delta from 0 is the correct position
+                               r.moveEnd("character", stop-start);
+                               r.select();
+                       }
+               }
+       }else if(has("mozilla")){
+               TextBox = declare(/*===== "dijit.form.TextBox.MozMixin", =====*/TextBox, {
+                       declaredClass: "dijit.form.TextBox",    // for user code referencing declaredClass
 
-new Date("X"); // workaround for #11279, new Date("") == NaN
+                       _onBlur: function(e){
+                               this.inherited(arguments);
+                               if(this.selectOnClick){
+                                               // clear selection so that the next mouse click doesn't reselect
+                                       this.textbox.selectionStart = this.textbox.selectionEnd = undefined;
+                               }
+                       }
+               });
+       }else{
+               TextBox.prototype.declaredClass = "dijit.form.TextBox";
+       }
+       lang.setObject("dijit.form.TextBox", TextBox);  // don't do direct assignment, it confuses API doc parser
 
-dojo.parser = new function(){
-       // summary: The Dom/Widget parsing package
+       return TextBox;
+});
 
-       var d = dojo;
-       this._attrName = d._scopeName + "Type";
-       this._query = "[" + this._attrName + "]";
+},
+'dijit/_base/scroll':function(){
+define("dijit/_base/scroll", [
+       "dojo/window", // windowUtils.scrollIntoView
+       ".."    // export symbol to dijit
+], function(windowUtils, dijit){
+       // module:
+       //              dijit/_base/scroll
+       // summary:
+       //              Back compatibility module, new code should use windowUtils directly instead of using this module.
 
-       function val2type(/*Object*/ value){
+       dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
                // summary:
-               //              Returns name of type of given value.
+               //              Scroll the passed node into view, if it is not already.
+               //              Deprecated, use `windowUtils.scrollIntoView` instead.
 
-               if(d.isString(value)){ return "string"; }
-               if(typeof value == "number"){ return "number"; }
-               if(typeof value == "boolean"){ return "boolean"; }
-               if(d.isFunction(value)){ return "function"; }
-               if(d.isArray(value)){ return "array"; } // typeof [] == "object"
-               if(value instanceof Date) { return "date"; } // assume timestamp
-               if(value instanceof d._Url){ return "url"; }
-               return "object";
-       }
+               windowUtils.scrollIntoView(node, pos);
+       };
+});
 
-       function str2obj(/*String*/ value, /*String*/ type){
-               // summary:
-               //              Convert given string value to given type
-               switch(type){
-                       case "string":
-                               return value;
-                       case "number":
-                               return value.length ? Number(value) : NaN;
-                       case "boolean":
-                               // for checked/disabled value might be "" or "checked".  interpret as true.
-                               return typeof value == "boolean" ? value : !(value.toLowerCase()=="false");
-                       case "function":
-                               if(d.isFunction(value)){
-                                       // IE gives us a function, even when we say something like onClick="foo"
-                                       // (in which case it gives us an invalid function "function(){ foo }"). 
-                                       //  Therefore, convert to string
-                                       value=value.toString();
-                                       value=d.trim(value.substring(value.indexOf('{')+1, value.length-1));
-                               }
-                               try{
-                                       if(value === "" || value.search(/[^\w\.]+/i) != -1){
-                                               // The user has specified some text for a function like "return x+5"
-                                               return new Function(value);
-                                       }else{
-                                               // The user has specified the name of a function like "myOnClick"
-                                               // or a single word function "return"
-                                               return d.getObject(value, false) || new Function(value);
-                                       }
-                               }catch(e){ return new Function(); }
-                       case "array":
-                               return value ? value.split(/\s*,\s*/) : [];
-                       case "date":
-                               switch(value){
-                                       case "": return new Date("");   // the NaN of dates
-                                       case "now": return new Date();  // current date
-                                       default: return d.date.stamp.fromISOString(value);
-                               }
-                       case "url":
-                               return d.baseUrl + value;
-                       default:
-                               return d.fromJson(value);
-               }
-       }
+},
+'dijit/_TemplatedMixin':function(){
+define("dijit/_TemplatedMixin", [
+       "dojo/_base/lang", // lang.getObject
+       "dojo/touch",
+       "./_WidgetBase",
+       "dojo/string", // string.substitute string.trim
+       "dojo/cache",   // dojo.cache
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-construct", // domConstruct.destroy, domConstruct.toDom
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/unload", // unload.addOnWindowUnload
+       "dojo/_base/window" // win.doc
+], function(lang, touch, _WidgetBase, string, cache, array, declare, domConstruct, has, unload, win) {
 
-       var instanceClasses = {
-               // map from fully qualified name (like "dijit.Button") to structure like
-               // { cls: dijit.Button, params: {label: "string", disabled: "boolean"} }
-       };
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+=====*/
 
-       // Widgets like BorderContainer add properties to _Widget via dojo.extend().
-       // If BorderContainer is loaded after _Widget's parameter list has been cached,
-       // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
-       dojo.connect(dojo, "extend", function(){
-               instanceClasses = {};
-       });
+       // module:
+       //              dijit/_TemplatedMixin
+       // summary:
+       //              Mixin for widgets that are instantiated from a template
 
-       function getClassInfo(/*String*/ className){
-               // className:
-               //              fully qualified name (like "dijit.form.Button")
-               // returns:
-               //              structure like
-               //                      { 
-               //                              cls: dijit.Button, 
-               //                              params: { label: "string", disabled: "boolean"}
-               //                      }
-
-               if(!instanceClasses[className]){
-                       // get pointer to widget class
-                       var cls = d.getObject(className);
-                       if(!cls){ return null; }                // class not defined [yet]
-
-                       var proto = cls.prototype;
-       
-                       // get table of parameter names & types
-                       var params = {}, dummyClass = {};
-                       for(var name in proto){
-                               if(name.charAt(0)=="_"){ continue; }    // skip internal properties
-                               if(name in dummyClass){ continue; }             // skip "constructor" and "toString"
-                               var defVal = proto[name];
-                               params[name]=val2type(defVal);
-                       }
+       var _TemplatedMixin = declare("dijit._TemplatedMixin", null, {
+               // summary:
+               //              Mixin for widgets that are instantiated from a template
 
-                       instanceClasses[className] = { cls: cls, params: params };
-               }
-               return instanceClasses[className];
-       }
+               // templateString: [protected] String
+               //              A string that represents the widget template.
+               //              Use in conjunction with dojo.cache() to load from a file.
+               templateString: null,
 
-       this._functionFromScript = function(script){
-               var preamble = "";
-               var suffix = "";
-               var argsStr = script.getAttribute("args");
-               if(argsStr){
-                       d.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
-                               preamble += "var "+part+" = arguments["+idx+"]; ";
-                       });
-               }
-               var withStr = script.getAttribute("with");
-               if(withStr && withStr.length){
-                       d.forEach(withStr.split(/\s*,\s*/), function(part){
-                               preamble += "with("+part+"){";
-                               suffix += "}";
-                       });
-               }
-               return new Function(preamble+script.innerHTML+suffix);
-       }
+               // templatePath: [protected deprecated] String
+               //              Path to template (HTML file) for this widget relative to dojo.baseUrl.
+               //              Deprecated: use templateString with require([... "dojo/text!..."], ...) instead
+               templatePath: null,
 
-       this.instantiate = function(/* Array */nodes, /* Object? */mixin, /* Object? */args){
-               // summary:
-               //              Takes array of nodes, and turns them into class instances and
-               //              potentially calls a startup method to allow them to connect with
-               //              any children.
-               // nodes: Array
-               //              Array of nodes or objects like
-               //      |               {
-               //      |                       type: "dijit.form.Button",
-               //      |                       node: DOMNode,
-               //      |                       scripts: [ ... ],       // array of <script type="dojo/..."> children of node
-               //      |                       inherited: { ... }      // settings inherited from ancestors like dir, theme, etc.
-               //      |               }
-               // mixin: Object?
-               //              An object that will be mixed in with each node in the array.
-               //              Values in the mixin will override values in the node, if they
-               //              exist.
-               // args: Object?
-               //              An object used to hold kwArgs for instantiation.
-               //              Supports 'noStart' and inherited.
-               var thelist = [], dp = dojo.parser;
-               mixin = mixin||{};
-               args = args||{};
-               
-               d.forEach(nodes, function(obj){
-                       if(!obj){ return; }
+               // skipNodeCache: [protected] Boolean
+               //              If using a cached widget template nodes poses issues for a
+               //              particular widget class, it can set this property to ensure
+               //              that its template is always re-built from a string
+               _skipNodeCache: false,
 
-                       // Get pointers to DOMNode, dojoType string, and clsInfo (metadata about the dojoType), etc.s
-                       var node, type, clsInfo, clazz, scripts;
-                       if(obj.node){
-                               // new format of nodes[] array, object w/lots of properties pre-computed for me
-                               node = obj.node;
-                               type = obj.type;
-                               clsInfo = obj.clsInfo || (type && getClassInfo(type));
-                               clazz = clsInfo && clsInfo.cls;
-                               scripts = obj.scripts;
-                       }else{
-                               // old (backwards compatible) format of nodes[] array, simple array of DOMNodes
-                               node = obj;
-                               type = dp._attrName in mixin ? mixin[dp._attrName] : node.getAttribute(dp._attrName);
-                               clsInfo = type && getClassInfo(type);
-                               clazz = clsInfo && clsInfo.cls;
-                               scripts = (clazz && (clazz._noScript || clazz.prototype._noScript) ? [] : 
-                                                       d.query("> script[type^='dojo/']", node));
-                       }
-                       if(!clsInfo){
-                               throw new Error("Could not load class '" + type);
-                       }
+               // _earlyTemplatedStartup: Boolean
+               //              A fallback to preserve the 1.0 - 1.3 behavior of children in
+               //              templates having their startup called before the parent widget
+               //              fires postCreate. Defaults to 'false', causing child widgets to
+               //              have their .startup() called immediately before a parent widget
+               //              .startup(), but always after the parent .postCreate(). Set to
+               //              'true' to re-enable to previous, arguably broken, behavior.
+               _earlyTemplatedStartup: false,
 
-                       // Setup hash to hold parameter settings for this widget.   Start with the parameter
-                       // settings inherited from ancestors ("dir" and "lang").
-                       // Inherited setting may later be overridden by explicit settings on node itself.
-                       var params = {},
-                               attributes = node.attributes;
-                       if(args.defaults){
-                               // settings for the document itself (or whatever subtree is being parsed)
-                               dojo.mixin(params, args.defaults);
-                       }
-                       if(obj.inherited){
-                               // settings from dir=rtl or lang=... on a node above this node
-                               dojo.mixin(params, obj.inherited);
-                       }
+/*=====
+               // _attachPoints: [private] String[]
+               //              List of widget attribute names associated with data-dojo-attach-point=... in the
+               //              template, ex: ["containerNode", "labelNode"]
+               _attachPoints: [],
+ =====*/
 
-                       // read parameters (ie, attributes) specified on DOMNode
-                       // clsInfo.params lists expected params like {"checked": "boolean", "n": "number"}
-                       for(var name in clsInfo.params){
-                               var item = name in mixin?{value:mixin[name],specified:true}:attributes.getNamedItem(name);
-                               if(!item || (!item.specified && (!dojo.isIE || name.toLowerCase()!="value"))){ continue; }
-                               var value = item.value;
-                               // Deal with IE quirks for 'class' and 'style'
-                               switch(name){
-                               case "class":
-                                       value = "className" in mixin?mixin.className:node.className;
-                                       break;
-                               case "style":
-                                       value = "style" in mixin?mixin.style:(node.style && node.style.cssText); // FIXME: Opera?
-                               }
-                               var _type = clsInfo.params[name];
-                               if(typeof value == "string"){
-                                       params[name] = str2obj(value, _type);
-                               }else{
-                                       params[name] = value;
-                               }
-                       }
+/*=====
+               // _attachEvents: [private] Handle[]
+               //              List of connections associated with data-dojo-attach-event=... in the
+               //              template
+               _attachEvents: [],
+ =====*/
 
-                       // Process <script type="dojo/*"> script tags
-                       // <script type="dojo/method" event="foo"> tags are added to params, and passed to
-                       // the widget on instantiation.
-                       // <script type="dojo/method"> tags (with no event) are executed after instantiation
-                       // <script type="dojo/connect" event="foo"> tags are dojo.connected after instantiation
-                       // note: dojo/* script tags cannot exist in self closing widgets, like <input />
-                       var connects = [],      // functions to connect after instantiation
-                               calls = [];             // functions to call after instantiation
-
-                       d.forEach(scripts, function(script){
-                               node.removeChild(script);
-                               var event = script.getAttribute("event"),
-                                       type = script.getAttribute("type"),
-                                       nf = d.parser._functionFromScript(script);
-                               if(event){
-                                       if(type == "dojo/connect"){
-                                               connects.push({event: event, func: nf});
-                                       }else{
-                                               params[event] = nf;
-                                       }
-                               }else{
-                                       calls.push(nf);
-                               }
-                       });
+               constructor: function(){
+                       this._attachPoints = [];
+                       this._attachEvents = [];
+               },
 
-                       var markupFactory = clazz.markupFactory || clazz.prototype && clazz.prototype.markupFactory;
-                       // create the instance
-                       var instance = markupFactory ? markupFactory(params, node, clazz) : new clazz(params, node);
-                       thelist.push(instance);
+               _stringRepl: function(tmpl){
+                       // summary:
+                       //              Does substitution of ${foo} type properties in template string
+                       // tags:
+                       //              private
+                       var className = this.declaredClass, _this = this;
+                       // Cache contains a string because we need to do property replacement
+                       // do the property replacement
+                       return string.substitute(tmpl, this, function(value, key){
+                               if(key.charAt(0) == '!'){ value = lang.getObject(key.substr(1), false, _this); }
+                               if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
+                               if(value == null){ return ""; }
 
-                       // map it to the JS namespace if that makes sense
-                       var jsname = node.getAttribute("jsId");
-                       if(jsname){
-                               d.setObject(jsname, instance);
+                               // Substitution keys beginning with ! will skip the transform step,
+                               // in case a user wishes to insert unescaped markup, e.g. ${!foo}
+                               return key.charAt(0) == "!" ? value :
+                                       // Safer substitution, see heading "Attribute values" in
+                                       // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+                                       value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
+                       }, this);
+               },
+
+               buildRendering: function(){
+                       // summary:
+                       //              Construct the UI for this widget from a template, setting this.domNode.
+                       // tags:
+                       //              protected
+
+                       if(!this.templateString){
+                               this.templateString = cache(this.templatePath, {sanitize: true});
                        }
 
-                       // process connections and startup functions
-                       d.forEach(connects, function(connect){
-                               d.connect(instance, connect.event, null, connect.func);
-                       });
-                       d.forEach(calls, function(func){
-                               func.call(instance);
-                       });
-               });
+                       // Lookup cached version of template, and download to cache if it
+                       // isn't there already.  Returns either a DomNode or a string, depending on
+                       // whether or not the template contains ${foo} replacement parameters.
+                       var cached = _TemplatedMixin.getCachedTemplate(this.templateString, this._skipNodeCache);
 
-               // Call startup on each top level instance if it makes sense (as for
-               // widgets).  Parent widgets will recursively call startup on their
-               // (non-top level) children
-               if(!mixin._started){
-                       // TODO: for 2.0, when old instantiate() API is desupported, store parent-child
-                       // relationships in the nodes[] array so that no getParent() call is needed.
-                       // Note that will  require a parse() call from ContentPane setting a param that the
-                       // ContentPane is the parent widget (so that the parse doesn't call startup() on the
-                       // ContentPane's children)
-                       d.forEach(thelist, function(instance){
-                               if(     !args.noStart && instance  && 
-                                       instance.startup &&
-                                       !instance._started && 
-                                       (!instance.getParent || !instance.getParent())
-                               ){
-                                       instance.startup();
+                       var node;
+                       if(lang.isString(cached)){
+                               node = domConstruct.toDom(this._stringRepl(cached));
+                               if(node.nodeType != 1){
+                                       // Flag common problems such as templates with multiple top level nodes (nodeType == 11)
+                                       throw new Error("Invalid template: " + cached);
                                }
-                       });
-               }
-               return thelist;
-       };
+                       }else{
+                               // if it's a node, all we have to do is clone it
+                               node = cached.cloneNode(true);
+                       }
 
-       this.parse = function(/*DomNode?*/ rootNode, /* Object? */ args){
-               // summary:
-               //              Scan the DOM for class instances, and instantiate them.
-               //
-               // description:
-               //              Search specified node (or root node) recursively for class instances,
-               //              and instantiate them Searches for
-               //              dojoType="qualified.class.name"
-               //
-               // rootNode: DomNode?
-               //              A default starting root node from which to start the parsing. Can be
-               //              omitted, defaulting to the entire document. If omitted, the `args`
-               //              object can be passed in this place. If the `args` object has a 
-               //              `rootNode` member, that is used.
-               //
-               // args:
-               //              a kwArgs object passed along to instantiate()
-               //              
-               //                      * noStart: Boolean?
-               //                              when set will prevent the parser from calling .startup()
-               //                              when locating the nodes. 
-               //                      * rootNode: DomNode?
-               //                              identical to the function's `rootNode` argument, though
-               //                              allowed to be passed in via this `args object. 
-               //                      * inherited: Object
-               //                              Hash possibly containing dir and lang settings to be applied to
-               //                              parsed widgets, unless there's another setting on a sub-node that overrides
-               //
-               //
-               // example:
-               //              Parse all widgets on a page:
-               //      |               dojo.parser.parse();
-               //
-               // example:
-               //              Parse all classes within the node with id="foo"
-               //      |               dojo.parser.parse(dojo.byId(foo));
-               //
-               // example:
-               //              Parse all classes in a page, but do not call .startup() on any 
-               //              child
-               //      |               dojo.parser.parse({ noStart: true })
-               //
-               // example:
-               //              Parse all classes in a node, but do not call .startup()
-               //      |               dojo.parser.parse(someNode, { noStart:true });
-               //      |               // or
-               //      |               dojo.parser.parse({ noStart:true, rootNode: someNode });
+                       this.domNode = node;
 
-               // determine the root node based on the passed arguments.
-               var root;
-               if(!args && rootNode && rootNode.rootNode){
-                       args = rootNode;
-                       root = args.rootNode;
-               }else{
-                       root = rootNode;
-               }
+                       // Call down to _Widget.buildRendering() to get base classes assigned
+                       // TODO: change the baseClass assignment to _setBaseClassAttr
+                       this.inherited(arguments);
+
+                       // recurse through the node, looking for, and attaching to, our
+                       // attachment points and events, which should be defined on the template node.
+                       this._attachTemplateNodes(node, function(n,p){ return n.getAttribute(p); });
+
+                       this._beforeFillContent();              // hook for _WidgetsInTemplateMixin
 
-               var attrName = this._attrName;
-               function scan(parent, list){
-                       // summary:
-                       //              Parent is an Object representing a DOMNode, with or without a dojoType specified.
-                       //              Scan parent's children looking for nodes with dojoType specified, storing in list[].
-                       //              If parent has a dojoType, also collects <script type=dojo/*> children and stores in parent.scripts[].
-                       // parent: Object
-                       //              Object representing the parent node, like
-                       //      |       {
-                       //      |               node: DomNode,                  // scan children of this node
-                       //      |               inherited: {dir: "rtl"},        // dir/lang setting inherited from above node
-                       //      |
-                       //      |               // attributes only set if node has dojoType specified
-                       //      |               scripts: [],                    // empty array, put <script type=dojo/*> in here
-                       //      |               clsInfo: { cls: dijit.form.Button, ...}
-                       //      |       }
-                       // list: DomNode[]
-                       //              Output array of objects (same format as parent) representing nodes to be turned into widgets
-
-                       // Effective dir and lang settings on parent node, either set directly or inherited from grandparent
-                       var inherited = dojo.clone(parent.inherited);
-                       dojo.forEach(["dir", "lang"], function(name){
-                               var val = parent.node.getAttribute(name);
-                               if(val){
-                                       inherited[name] = val;
+                       this._fillContent(this.srcNodeRef);
+               },
+
+               _beforeFillContent: function(){
+               },
+
+               _fillContent: function(/*DomNode*/ source){
+                       // summary:
+                       //              Relocate source contents to templated container node.
+                       //              this.containerNode must be able to receive children, or exceptions will be thrown.
+                       // tags:
+                       //              protected
+                       var dest = this.containerNode;
+                       if(source && dest){
+                               while(source.hasChildNodes()){
+                                       dest.appendChild(source.firstChild);
                                }
-                       });
+                       }
+               },
 
-                       // if parent is a widget, then search for <script type=dojo/*> tags and put them in scripts[].
-                       var scripts = parent.scripts;
-
-                       // unless parent is a widget with the stopParser flag set, continue search for dojoType, recursively
-                       var recurse = !parent.clsInfo || !parent.clsInfo.cls.prototype.stopParser;
-
-                       // scan parent's children looking for dojoType and <script type=dojo/*>
-                       for(var child = parent.node.firstChild; child; child = child.nextSibling){
-                               if(child.nodeType == 1){
-                                       var type = recurse && child.getAttribute(attrName);
-                                       if(type){
-                                               // if dojoType specified, add to output array of nodes to instantiate
-                                               var params = {
-                                                       "type": type,
-                                                       clsInfo: getClassInfo(type),    // note: won't find classes declared via dojo.Declaration
-                                                       node: child,
-                                                       scripts: [], // <script> nodes that are parent's children
-                                                       inherited: inherited // dir & lang attributes inherited from parent
-                                               };
-                                               list.push(params);
-
-                                               // Recurse, collecting <script type="dojo/..."> children, and also looking for
-                                               // descendant nodes with dojoType specified (unless the widget has the stopParser flag),
-                                               scan(params, list);
-                                       }else if(scripts && child.nodeName.toLowerCase() == "script"){
-                                               // if <script type="dojo/...">, save in scripts[]
-                                               type = child.getAttribute("type");
-                                               if (type && /^dojo\//i.test(type)) {
-                                                       scripts.push(child);
+               _attachTemplateNodes: function(rootNode, getAttrFunc){
+                       // summary:
+                       //              Iterate through the template and attach functions and nodes accordingly.
+                       //              Alternately, if rootNode is an array of widgets, then will process data-dojo-attach-point
+                       //              etc. for those widgets.
+                       // description:
+                       //              Map widget properties and functions to the handlers specified in
+                       //              the dom node and it's descendants. This function iterates over all
+                       //              nodes and looks for these properties:
+                       //                      * dojoAttachPoint/data-dojo-attach-point
+                       //                      * dojoAttachEvent/data-dojo-attach-event
+                       // rootNode: DomNode|Widget[]
+                       //              the node to search for properties. All children will be searched.
+                       // getAttrFunc: Function
+                       //              a function which will be used to obtain property for a given
+                       //              DomNode/Widget
+                       // tags:
+                       //              private
+
+                       var nodes = lang.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
+                       var x = lang.isArray(rootNode) ? 0 : -1;
+                       for(; x<nodes.length; x++){
+                               var baseNode = (x == -1) ? rootNode : nodes[x];
+                               if(this.widgetsInTemplate && (getAttrFunc(baseNode, "dojoType") || getAttrFunc(baseNode, "data-dojo-type"))){
+                                       continue;
+                               }
+                               // Process data-dojo-attach-point
+                               var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint") || getAttrFunc(baseNode, "data-dojo-attach-point");
+                               if(attachPoint){
+                                       var point, points = attachPoint.split(/\s*,\s*/);
+                                       while((point = points.shift())){
+                                               if(lang.isArray(this[point])){
+                                                       this[point].push(baseNode);
+                                               }else{
+                                                       this[point]=baseNode;
                                                }
-                                       }else if(recurse){
-                                               // Recurse, looking for grandchild nodes with dojoType specified
-                                               scan({
-                                                       node: child,
-                                                       inherited: inherited
-                                               }, list);
+                                               this._attachPoints.push(point);
                                        }
                                }
-                       }
-               }
 
-               // Make list of all nodes on page w/dojoType specified
-               var list = [];
-               scan({
-                       node: root ? dojo.byId(root) : dojo.body(),
-                       inherited: (args && args.inherited) || {
-                               dir: dojo._isBodyLtr() ? "ltr" : "rtl"
+                               // Process data-dojo-attach-event
+                               var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent") || getAttrFunc(baseNode, "data-dojo-attach-event");
+                               if(attachEvent){
+                                       // NOTE: we want to support attributes that have the form
+                                       // "domEvent: nativeEvent; ..."
+                                       var event, events = attachEvent.split(/\s*,\s*/);
+                                       var trim = lang.trim;
+                                       while((event = events.shift())){
+                                               if(event){
+                                                       var thisFunc = null;
+                                                       if(event.indexOf(":") != -1){
+                                                               // oh, if only JS had tuple assignment
+                                                               var funcNameArr = event.split(":");
+                                                               event = trim(funcNameArr[0]);
+                                                               thisFunc = trim(funcNameArr[1]);
+                                                       }else{
+                                                               event = trim(event);
+                                                       }
+                                                       if(!thisFunc){
+                                                               thisFunc = event;
+                                                       }
+                                                       // Map "press", "move" and "release" to keys.touch, keys.move, keys.release
+                                                       this._attachEvents.push(this.connect(baseNode, touch[event] || event, thisFunc));
+                                               }
+                                       }
+                               }
                        }
-               }, list);
+               },
 
-               // go build the object instances
-               return this.instantiate(list, null, args); // Array
-       };
-}();
+               destroyRendering: function(){
+                       // Delete all attach points to prevent IE6 memory leaks.
+                       array.forEach(this._attachPoints, function(point){
+                               delete this[point];
+                       }, this);
+                       this._attachPoints = [];
 
-//Register the parser callback. It should be the first callback
-//after the a11y test.
+                       // And same for event handlers
+                       array.forEach(this._attachEvents, this.disconnect, this);
+                       this._attachEvents = [];
 
-(function(){
-       var parseRunner = function(){ 
-               if(dojo.config.parseOnLoad){
-                       dojo.parser.parse(); 
+                       this.inherited(arguments);
                }
-       };
-
-       // FIXME: need to clobber cross-dependency!!
-       if(dojo.exists("dijit.wai.onload") && (dijit.wai.onload === dojo._loaders[0])){
-               dojo._loaders.splice(1, 0, parseRunner);
-       }else{
-               dojo._loaders.unshift(parseRunner);
-       }
-})();
-
-}
-
-if(!dojo._hasResource["dojo.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.window"] = true;
-dojo.provide("dojo.window");
-
-dojo.window.getBox = function(){
-       // summary:
-       //              Returns the dimensions and scroll position of the viewable area of a browser window
-
-       var scrollRoot = (dojo.doc.compatMode == 'BackCompat') ? dojo.body() : dojo.doc.documentElement;
-
-       // get scroll position
-       var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work
-       return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
-};
-
-dojo.window.get = function(doc){
-       // summary:
-       //              Get window object associated with document doc
-
-       // In some IE versions (at least 6.0), document.parentWindow does not return a
-       // reference to the real window object (maybe a copy), so we must fix it as well
-       // We use IE specific execScript to attach the real window reference to
-       // document._parentWindow for later use
-       if(dojo.isIE && window !== document.parentWindow){
-               /*
-               In IE 6, only the variable "window" can be used to connect events (others
-               may be only copies).
-               */
-               doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
-               //to prevent memory leak, unset it after use
-               //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
-               var win = doc._parentWindow;
-               doc._parentWindow = null;
-               return win;     //      Window
-       }
+       });
 
-       return doc.parentWindow || doc.defaultView;     //      Window
-};
+       // key is templateString; object is either string or DOM tree
+       _TemplatedMixin._templateCache = {};
+
+       _TemplatedMixin.getCachedTemplate = function(templateString, alwaysUseString){
+               // summary:
+               //              Static method to get a template based on the templatePath or
+               //              templateString key
+               // templateString: String
+               //              The template
+               // alwaysUseString: Boolean
+               //              Don't cache the DOM tree for this template, even if it doesn't have any variables
+               // returns: Mixed
+               //              Either string (if there are ${} variables that need to be replaced) or just
+               //              a DOM tree (if the node can be cloned directly)
+
+               // is it already cached?
+               var tmplts = _TemplatedMixin._templateCache;
+               var key = templateString;
+               var cached = tmplts[key];
+               if(cached){
+                       try{
+                               // if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
+                               if(!cached.ownerDocument || cached.ownerDocument == win.doc){
+                                       // string or node of the same document
+                                       return cached;
+                               }
+                       }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
+                       domConstruct.destroy(cached);
+               }
 
-dojo.window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
-       // summary:
-       //              Scroll the passed node into view, if it is not already.
-       
-       // don't rely on node.scrollIntoView working just because the function is there
+               templateString = string.trim(templateString);
 
-       try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
-               node = dojo.byId(node);
-               var doc = node.ownerDocument || dojo.doc,
-                       body = doc.body || dojo.body(),
-                       html = doc.documentElement || body.parentNode,
-                       isIE = dojo.isIE, isWK = dojo.isWebKit;
-               // if an untested browser, then use the native method
-               if((!(dojo.isMoz || isIE || isWK || dojo.isOpera) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
-                       node.scrollIntoView(false); // short-circuit to native if possible
-                       return;
+               if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
+                       // there are variables in the template so all we can do is cache the string
+                       return (tmplts[key] = templateString); //String
+               }else{
+                       // there are no variables in the template so we can cache the DOM tree
+                       var node = domConstruct.toDom(templateString);
+                       if(node.nodeType != 1){
+                               throw new Error("Invalid template: " + templateString);
+                       }
+                       return (tmplts[key] = node); //Node
                }
-               var backCompat = doc.compatMode == 'BackCompat',
-                       clientAreaRoot = backCompat? body : html,
-                       scrollRoot = isWK ? body : clientAreaRoot,
-                       rootWidth = clientAreaRoot.clientWidth,
-                       rootHeight = clientAreaRoot.clientHeight,
-                       rtl = !dojo._isBodyLtr(),
-                       nodePos = pos || dojo.position(node),
-                       el = node.parentNode,
-                       isFixed = function(el){
-                               return ((isIE <= 6 || (isIE && backCompat))? false : (dojo.style(el, 'position').toLowerCase() == "fixed"));
-                       };
-               if(isFixed(node)){ return; } // nothing to do
+       };
 
-               while(el){
-                       if(el == body){ el = scrollRoot; }
-                       var elPos = dojo.position(el),
-                               fixedPos = isFixed(el);
-       
-                       if(el == scrollRoot){
-                               elPos.w = rootWidth; elPos.h = rootHeight;
-                               if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
-                               if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0
-                               if(elPos.y < 0 || !isIE){ elPos.y = 0; }
-                       }else{
-                               var pb = dojo._getPadBorderExtents(el);
-                               elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
-                       }
-       
-                       if(el != scrollRoot){ // body, html sizes already have the scrollbar removed
-                               var clientSize = el.clientWidth,
-                                       scrollBarSize = elPos.w - clientSize;
-                               if(clientSize > 0 && scrollBarSize > 0){
-                                       elPos.w = clientSize;
-                                       if(isIE && rtl){ elPos.x += scrollBarSize; }
-                               }
-                               clientSize = el.clientHeight;
-                               scrollBarSize = elPos.h - clientSize;
-                               if(clientSize > 0 && scrollBarSize > 0){
-                                       elPos.h = clientSize;
-                               }
-                       }
-                       if(fixedPos){ // bounded by viewport, not parents
-                               if(elPos.y < 0){
-                                       elPos.h += elPos.y; elPos.y = 0;
-                               }
-                               if(elPos.x < 0){
-                                       elPos.w += elPos.x; elPos.x = 0;
-                               }
-                               if(elPos.y + elPos.h > rootHeight){
-                                       elPos.h = rootHeight - elPos.y;
-                               }
-                               if(elPos.x + elPos.w > rootWidth){
-                                       elPos.w = rootWidth - elPos.x;
+       if(has("ie")){
+               unload.addOnWindowUnload(function(){
+                       var cache = _TemplatedMixin._templateCache;
+                       for(var key in cache){
+                               var value = cache[key];
+                               if(typeof value == "object"){ // value is either a string or a DOM node template
+                                       domConstruct.destroy(value);
                                }
+                               delete cache[key];
                        }
-                       // calculate overflow in all 4 directions
-                       var l = nodePos.x - elPos.x, // beyond left: < 0
-                               t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
-                               r = l + nodePos.w - elPos.w, // beyond right: > 0
-                               bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
-                       if(r * l > 0){
-                               var s = Math[l < 0? "max" : "min"](l, r);
-                               nodePos.x += el.scrollLeft;
-                               el.scrollLeft += (isIE >= 8 && !backCompat && rtl)? -s : s;
-                               nodePos.x -= el.scrollLeft;
-                       }
-                       if(bot * t > 0){
-                               nodePos.y += el.scrollTop;
-                               el.scrollTop += Math[t < 0? "max" : "min"](t, bot);
-                               nodePos.y -= el.scrollTop;
-                       }
-                       el = (el != scrollRoot) && !fixedPos && el.parentNode;
-               }       
-       }catch(error){
-               console.error('scrollIntoView: ' + error);
-               node.scrollIntoView(false);
+               });
        }
-};
 
-}
+       // These arguments can be specified for widgets which are used in templates.
+       // Since any widget can be specified as sub widgets in template, mix it
+       // into the base widget class.  (This is a hack, but it's effective.)
+       lang.extend(_WidgetBase,{
+               dojoAttachEvent: "",
+               dojoAttachPoint: ""
+       });
 
-if(!dojo._hasResource["dijit._base.manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.manager"] = true;
-dojo.provide("dijit._base.manager");
+       return _TemplatedMixin;
+});
+
+},
+'dijit/_CssStateMixin':function(){
+define("dijit/_CssStateMixin", [
+       "dojo/touch",
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/_base/declare",   // declare
+       "dojo/dom-class", // domClass.toggle
+       "dojo/_base/lang", // lang.hitch
+       "dojo/_base/window" // win.body
+], function(touch, array, declare, domClass, lang, win){
+
+// module:
+//             dijit/_CssStateMixin
+// summary:
+//             Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
+//             state changes, and also higher-level state changes such becoming disabled or selected.
 
-dojo.declare("dijit.WidgetSet", null, {
+return declare("dijit._CssStateMixin", [], {
        // summary:
-       //              A set of widgets indexed by id. A default instance of this class is
-       //              available as `dijit.registry`
+       //              Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
+       //              state changes, and also higher-level state changes such becoming disabled or selected.
        //
-       // example:
-       //              Create a small list of widgets:
-       //              |       var ws = new dijit.WidgetSet();
-       //              |       ws.add(dijit.byId("one"));
-       //              |       ws.add(dijit.byId("two"));
-       //              |       // destroy both:
-       //              |       ws.forEach(function(w){ w.destroy(); });
+       // description:
+       //              By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
+       //              maintain CSS classes on the widget root node (this.domNode) depending on hover,
+       //              active, focus, etc. state.   Ex: with a baseClass of dijitButton, it will apply the classes
+       //              dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
        //
-       // example:
-       //              Using dijit.registry:
-       //              |       dijit.registry.forEach(function(w){ /* do something */ });
+       //              It also sets CSS like dijitButtonDisabled based on widget semantic state.
+       //
+       //              By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
+       //              within the widget).
 
-       constructor: function(){
-               this._hash = {};
-               this.length = 0;
-       },
+       // cssStateNodes: [protected] Object
+       //              List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
+       //.
+       //              Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
+       //              (like "dijitUpArrowButton"). Example:
+       //      |               {
+       //      |                       "upArrowButton": "dijitUpArrowButton",
+       //      |                       "downArrowButton": "dijitDownArrowButton"
+       //      |               }
+       //              The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
+       //              is hovered, etc.
+       cssStateNodes: {},
 
-       add: function(/*dijit._Widget*/ widget){
-               // summary:
-               //              Add a widget to this list. If a duplicate ID is detected, a error is thrown.
-               //
-               // widget: dijit._Widget
-               //              Any dijit._Widget subclass.
-               if(this._hash[widget.id]){
-                       throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
-               }
-               this._hash[widget.id] = widget;
-               this.length++;
-       },
+       // hovering: [readonly] Boolean
+       //              True if cursor is over this widget
+       hovering: false,
 
-       remove: function(/*String*/ id){
-               // summary:
-               //              Remove a widget from this WidgetSet. Does not destroy the widget; simply
-               //              removes the reference.
-               if(this._hash[id]){
-                       delete this._hash[id];
-                       this.length--;
-               }
-       },
+       // active: [readonly] Boolean
+       //              True if mouse was pressed while over this widget, and hasn't been released yet
+       active: false,
 
-       forEach: function(/*Function*/ func, /* Object? */thisObj){
-               // summary:
-               //              Call specified function for each widget in this set.
-               //
-               // func:
-               //              A callback function to run for each item. Is passed the widget, the index
-               //              in the iteration, and the full hash, similar to `dojo.forEach`.
-               //
-               // thisObj:
-               //              An optional scope parameter
-               //
-               // example:
-               //              Using the default `dijit.registry` instance:
-               //              |       dijit.registry.forEach(function(widget){
-               //              |               console.log(widget.declaredClass);
-               //              |       });
-               //
-               // returns:
-               //              Returns self, in order to allow for further chaining.
+       _applyAttributes: function(){
+               // This code would typically be in postCreate(), but putting in _applyAttributes() for
+               // performance: so the class changes happen before DOM is inserted into the document.
+               // Change back to postCreate() in 2.0.  See #11635.
 
-               thisObj = thisObj || dojo.global;
-               var i = 0, id;
-               for(id in this._hash){
-                       func.call(thisObj, this._hash[id], i++, this._hash);
-               }
-               return this;    // dijit.WidgetSet
-       },
+               this.inherited(arguments);
 
-       filter: function(/*Function*/ filter, /* Object? */thisObj){
-               // summary:
-               //              Filter down this WidgetSet to a smaller new WidgetSet
-               //              Works the same as `dojo.filter` and `dojo.NodeList.filter`
-               //
-               // filter:
-               //              Callback function to test truthiness. Is passed the widget
-               //              reference and the pseudo-index in the object.
-               //
-               // thisObj: Object?
-               //              Option scope to use for the filter function.
-               //
-               // example:
-               //              Arbitrary: select the odd widgets in this list
-               //              |       dijit.registry.filter(function(w, i){
-               //              |               return i % 2 == 0;
-               //              |       }).forEach(function(w){ /* odd ones */ });
+               // Automatically monitor mouse events (essentially :hover and :active) on this.domNode
+               array.forEach(["onmouseenter", "onmouseleave", touch.press], function(e){
+                       this.connect(this.domNode, e, "_cssMouseEvent");
+               }, this);
 
-               thisObj = thisObj || dojo.global;
-               var res = new dijit.WidgetSet(), i = 0, id;
-               for(id in this._hash){
-                       var w = this._hash[id];
-                       if(filter.call(thisObj, w, i++, this._hash)){
-                               res.add(w);
-                       }
+               // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
+               array.forEach(["disabled", "readOnly", "checked", "selected", "focused", "state", "hovering", "active"], function(attr){
+                       this.watch(attr, lang.hitch(this, "_setStateClass"));
+               }, this);
+
+               // Events on sub nodes within the widget
+               for(var ap in this.cssStateNodes){
+                       this._trackMouseState(this[ap], this.cssStateNodes[ap]);
                }
-               return res; // dijit.WidgetSet
+               // Set state initially; there's probably no hover/active/focus state but widget might be
+               // disabled/readonly/checked/selected so we want to set CSS classes for those conditions.
+               this._setStateClass();
        },
 
-       byId: function(/*String*/ id){
+       _cssMouseEvent: function(/*Event*/ event){
                // summary:
-               //              Find a widget in this list by it's id.
-               // example:
-               //              Test if an id is in a particular WidgetSet
-               //              | var ws = new dijit.WidgetSet();
-               //              | ws.add(dijit.byId("bar"));
-               //              | var t = ws.byId("bar") // returns a widget
-               //              | var x = ws.byId("foo"); // returns undefined
+               //      Sets hovering and active properties depending on mouse state,
+               //      which triggers _setStateClass() to set appropriate CSS classes for this.domNode.
 
-               return this._hash[id];  // dijit._Widget
-       },
+               if(!this.disabled){
+                       switch(event.type){
+                               case "mouseenter":
+                               case "mouseover":       // generated on non-IE browsers even though we connected to mouseenter
+                                       this._set("hovering", true);
+                                       this._set("active", this._mouseDown);
+                                       break;
 
-       byClass: function(/*String*/ cls){
-               // summary:
-               //              Reduce this widgetset to a new WidgetSet of a particular `declaredClass`
-               //
-               // cls: String
-               //              The Class to scan for. Full dot-notated string.
-               //
-               // example:
-               //              Find all `dijit.TitlePane`s in a page:
-               //              |       dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
+                               case "mouseleave":
+                               case "mouseout":        // generated on non-IE browsers even though we connected to mouseleave
+                                       this._set("hovering", false);
+                                       this._set("active", false);
+                                       break;
 
-               var res = new dijit.WidgetSet(), id, widget;
-               for(id in this._hash){
-                       widget = this._hash[id];
-                       if(widget.declaredClass == cls){
-                               res.add(widget);
+                               case "mousedown":
+                               case "touchpress":
+                                       this._set("active", true);
+                                       this._mouseDown = true;
+                                       // Set a global event to handle mouseup, so it fires properly
+                                       // even if the cursor leaves this.domNode before the mouse up event.
+                                       // Alternately could set active=false on mouseout.
+                                       var mouseUpConnector = this.connect(win.body(), touch.release, function(){
+                                               this._mouseDown = false;
+                                               this._set("active", false);
+                                               this.disconnect(mouseUpConnector);
+                                       });
+                                       break;
                        }
-                }
-                return res; // dijit.WidgetSet
-},
-
-       toArray: function(){
-               // summary:
-               //              Convert this WidgetSet into a true Array
-               //
-               // example:
-               //              Work with the widget .domNodes in a real Array
-               //              |       dojo.map(dijit.registry.toArray(), function(w){ return w.domNode; });
-
-               var ar = [];
-               for(var id in this._hash){
-                       ar.push(this._hash[id]);
                }
-               return ar;      // dijit._Widget[]
-},
-
-       map: function(/* Function */func, /* Object? */thisObj){
-               // summary:
-               //              Create a new Array from this WidgetSet, following the same rules as `dojo.map`
-               // example:
-               //              |       var nodes = dijit.registry.map(function(w){ return w.domNode; });
-               //
-               // returns:
-               //              A new array of the returned values.
-               return dojo.map(this.toArray(), func, thisObj); // Array
        },
 
-       every: function(func, thisObj){
+       _setStateClass: function(){
                // summary:
-               //              A synthetic clone of `dojo.every` acting explicitly on this WidgetSet
+               //              Update the visual state of the widget by setting the css classes on this.domNode
+               //              (or this.stateNode if defined) by combining this.baseClass with
+               //              various suffixes that represent the current widget state(s).
+               //
+               // description:
+               //              In the case where a widget has multiple
+               //              states, it sets the class based on all possible
+               //              combinations.  For example, an invalid form widget that is being hovered
+               //              will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
                //
-               // func: Function
-               //              A callback function run for every widget in this list. Exits loop
-               //              when the first false return is encountered.
+               //              The widget may have one or more of the following states, determined
+               //              by this.state, this.checked, this.valid, and this.selected:
+               //                      - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
+               //                      - Incomplete - ValidationTextBox sets this.state to "Incomplete" if the current input value is not finished yet
+               //                      - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
+               //                      - Selected - ex: currently selected tab will have this.selected==true
                //
-               // thisObj: Object?
-               //              Optional scope parameter to use for the callback
+               //              In addition, it may have one or more of the following states,
+               //              based on this.disabled and flags set in _onMouse (this.active, this.hovering) and from focus manager (this.focused):
+               //                      - Disabled      - if the widget is disabled
+               //                      - Active                - if the mouse (or space/enter key?) is being pressed down
+               //                      - Focused               - if the widget has focus
+               //                      - Hover         - if the mouse is over the widget
 
-               thisObj = thisObj || dojo.global;
-               var x = 0, i;
-               for(i in this._hash){
-                       if(!func.call(thisObj, this._hash[i], x++, this._hash)){
-                               return false; // Boolean
-                       }
-               }
-               return true; // Boolean
-       },
+               // Compute new set of classes
+               var newStateClasses = this.baseClass.split(" ");
 
-       some: function(func, thisObj){
-               // summary:
-               //              A synthetic clone of `dojo.some` acting explictly on this WidgetSet
-               //
-               // func: Function
-               //              A callback function run for every widget in this list. Exits loop
-               //              when the first true return is encountered.
-               //
-               // thisObj: Object?
-               //              Optional scope parameter to use for the callback
+               function multiply(modifier){
+                       newStateClasses = newStateClasses.concat(array.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
+               }
 
-               thisObj = thisObj || dojo.global;
-               var x = 0, i;
-               for(i in this._hash){
-                       if(func.call(thisObj, this._hash[i], x++, this._hash)){
-                               return true; // Boolean
-                       }
+               if(!this.isLeftToRight()){
+                       // For RTL mode we need to set an addition class like dijitTextBoxRtl.
+                       multiply("Rtl");
                }
-               return false; // Boolean
-       }
 
-});
-
-(function(){
-
-       /*=====
-       dijit.registry = {
-               // summary:
-               //              A list of widgets on a page.
-               // description:
-               //              Is an instance of `dijit.WidgetSet`
-       };
-       =====*/
-       dijit.registry = new dijit.WidgetSet();
-
-       var hash = dijit.registry._hash,
-               attr = dojo.attr,
-               hasAttr = dojo.hasAttr,
-               style = dojo.style;
-
-       dijit.byId = function(/*String|dijit._Widget*/ id){
-               // summary:
-               //              Returns a widget by it's id, or if passed a widget, no-op (like dojo.byId())
-               return typeof id == "string" ? hash[id] : id; // dijit._Widget
-       };
-
-       var _widgetTypeCtr = {};
-       dijit.getUniqueId = function(/*String*/widgetType){
-               // summary:
-               //              Generates a unique id for a given widgetType
-       
-               var id;
-               do{
-                       id = widgetType + "_" +
-                               (widgetType in _widgetTypeCtr ?
-                                       ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
-               }while(hash[id]);
-               return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
-       };
-       
-       dijit.findWidgets = function(/*DomNode*/ root){
-               // summary:
-               //              Search subtree under root returning widgets found.
-               //              Doesn't search for nested widgets (ie, widgets inside other widgets).
-       
-               var outAry = [];
-       
-               function getChildrenHelper(root){
-                       for(var node = root.firstChild; node; node = node.nextSibling){
-                               if(node.nodeType == 1){
-                                       var widgetId = node.getAttribute("widgetId");
-                                       if(widgetId){
-                                               outAry.push(hash[widgetId]);
-                                       }else{
-                                               getChildrenHelper(node);
-                                       }
-                               }
-                       }
+               var checkedState = this.checked == "mixed" ? "Mixed" : (this.checked ? "Checked" : "");
+               if(this.checked){
+                       multiply(checkedState);
                }
-       
-               getChildrenHelper(root);
-               return outAry;
-       };
-       
-       dijit._destroyAll = function(){
-               // summary:
-               //              Code to destroy all widgets and do other cleanup on page unload
-       
-               // Clean up focus manager lingering references to widgets and nodes
-               dijit._curFocus = null;
-               dijit._prevFocus = null;
-               dijit._activeStack = [];
-       
-               // Destroy all the widgets, top down
-               dojo.forEach(dijit.findWidgets(dojo.body()), function(widget){
-                       // Avoid double destroy of widgets like Menu that are attached to <body>
-                       // even though they are logically children of other widgets.
-                       if(!widget._destroyed){
-                               if(widget.destroyRecursive){
-                                       widget.destroyRecursive();
-                               }else if(widget.destroy){
-                                       widget.destroy();
-                               }
-                       }
-               });
-       };
-       
-       if(dojo.isIE){
-               // Only run _destroyAll() for IE because we think it's only necessary in that case,
-               // and because it causes problems on FF.  See bug #3531 for details.
-               dojo.addOnWindowUnload(function(){
-                       dijit._destroyAll();
-               });
-       }
-       
-       dijit.byNode = function(/*DOMNode*/ node){
-               // summary:
-               //              Returns the widget corresponding to the given DOMNode
-               return hash[node.getAttribute("widgetId")]; // dijit._Widget
-       };
-       
-       dijit.getEnclosingWidget = function(/*DOMNode*/ node){
-               // summary:
-               //              Returns the widget whose DOM tree contains the specified DOMNode, or null if
-               //              the node is not contained within the DOM tree of any widget
-               while(node){
-                       var id = node.getAttribute && node.getAttribute("widgetId");
-                       if(id){
-                               return hash[id];
-                       }
-                       node = node.parentNode;
+               if(this.state){
+                       multiply(this.state);
                }
-               return null;
-       };
-
-       var shown = (dijit._isElementShown = function(/*Element*/ elem){
-               var s = style(elem);
-               return (s.visibility != "hidden")
-                       && (s.visibility != "collapsed")
-                       && (s.display != "none")
-                       && (attr(elem, "type") != "hidden");
-       });
-       
-       dijit.hasDefaultTabStop = function(/*Element*/ elem){
-               // summary:
-               //              Tests if element is tab-navigable even without an explicit tabIndex setting
-       
-               // No explicit tabIndex setting, need to investigate node type
-               switch(elem.nodeName.toLowerCase()){
-                       case "a":
-                               // An <a> w/out a tabindex is only navigable if it has an href
-                               return hasAttr(elem, "href");
-                       case "area":
-                       case "button":
-                       case "input":
-                       case "object":
-                       case "select":
-                       case "textarea":
-                               // These are navigable by default
-                               return true;
-                       case "iframe":
-                               // If it's an editor <iframe> then it's tab navigable.
-                               //TODO: feature detect "designMode" in elem.contentDocument?
-                               if(dojo.isMoz){
-                                       try{
-                                               return elem.contentDocument.designMode == "on";
-                                       }catch(err){
-                                               return false;
-                                       }
-                               }else if(dojo.isWebKit){
-                                       var doc = elem.contentDocument,
-                                               body = doc && doc.body;
-                                       return body && body.contentEditable == 'true';
-                               }else{
-                                       // contentWindow.document isn't accessible within IE7/8
-                                       // if the iframe.src points to a foreign url and this
-                                       // page contains an element, that could get focus
-                                       try{
-                                               doc = elem.contentWindow.document;
-                                               body = doc && doc.body;
-                                               return body && body.firstChild && body.firstChild.contentEditable == 'true';
-                                       }catch(e){
-                                               return false;
-                                       }
-                               }
-                       default:
-                               return elem.contentEditable == 'true';
+               if(this.selected){
+                       multiply("Selected");
                }
-       };
-       
-       var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){
-               // summary:
-               //              Tests if an element is tab-navigable
-       
-               // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
-               if(attr(elem, "disabled")){
-                       return false;
-               }else if(hasAttr(elem, "tabIndex")){
-                       // Explicit tab index setting
-                       return attr(elem, "tabIndex") >= 0; // boolean
+
+               if(this.disabled){
+                       multiply("Disabled");
+               }else if(this.readOnly){
+                       multiply("ReadOnly");
                }else{
-                       // No explicit tabIndex setting, so depends on node type
-                       return dijit.hasDefaultTabStop(elem);
+                       if(this.active){
+                               multiply("Active");
+                       }else if(this.hovering){
+                               multiply("Hover");
+                       }
                }
-       });
-
-       dijit._getTabNavigable = function(/*DOMNode*/ root){
-               // summary:
-               //              Finds descendants of the specified root node.
-               //
-               // description:
-               //              Finds the following descendants of the specified root node:
-               //              * the first tab-navigable element in document order
-               //                without a tabIndex or with tabIndex="0"
-               //              * the last tab-navigable element in document order
-               //                without a tabIndex or with tabIndex="0"
-               //              * the first element in document order with the lowest
-               //                positive tabIndex value
-               //              * the last element in document order with the highest
-               //                positive tabIndex value
-               var first, last, lowest, lowestTabindex, highest, highestTabindex;
-               var walkTree = function(/*DOMNode*/parent){
-                       dojo.query("> *", parent).forEach(function(child){
-                               // Skip hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
-                               // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
-                               if((dojo.isIE && child.scopeName!=="HTML") || !shown(child)){
-                                       return;
-                               }
-
-                               if(isTabNavigable(child)){
-                                       var tabindex = attr(child, "tabIndex");
-                                       if(!hasAttr(child, "tabIndex") || tabindex == 0){
-                                               if(!first){ first = child; }
-                                               last = child;
-                                       }else if(tabindex > 0){
-                                               if(!lowest || tabindex < lowestTabindex){
-                                                       lowestTabindex = tabindex;
-                                                       lowest = child;
-                                               }
-                                               if(!highest || tabindex >= highestTabindex){
-                                                       highestTabindex = tabindex;
-                                                       highest = child;
-                                               }
-                                       }
-                               }
-                               if(child.nodeName.toUpperCase() != 'SELECT'){
-                                       walkTree(child);
-                               }
-                       });
-               };
-               if(shown(root)){ walkTree(root) }
-               return { first: first, last: last, lowest: lowest, highest: highest };
-       }
-       dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){
-               // summary:
-               //              Finds the descendant of the specified root node
-               //              that is first in the tabbing order
-               var elems = dijit._getTabNavigable(dojo.byId(root));
-               return elems.lowest ? elems.lowest : elems.first; // DomNode
-       };
-       
-       dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){
-               // summary:
-               //              Finds the descendant of the specified root node
-               //              that is last in the tabbing order
-               var elems = dijit._getTabNavigable(dojo.byId(root));
-               return elems.last ? elems.last : elems.highest; // DomNode
-       };
-       
-       /*=====
-       dojo.mixin(dijit, {
-               // defaultDuration: Integer
-               //              The default animation speed (in ms) to use for all Dijit
-               //              transitional animations, unless otherwise specified
-               //              on a per-instance basis. Defaults to 200, overrided by
-               //              `djConfig.defaultDuration`
-               defaultDuration: 200
-       });
-       =====*/
-       
-       dijit.defaultDuration = dojo.config["defaultDuration"] || 200;
-
-})();
-
-}
-
-if(!dojo._hasResource["dijit._base.focus"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.focus"] = true;
-dojo.provide("dijit._base.focus");
 
+               if(this.focused){
+                       multiply("Focused");
+               }
 
-       // for dijit.isTabNavigable()
+               // Remove old state classes and add new ones.
+               // For performance concerns we only write into domNode.className once.
+               var tn = this.stateNode || this.domNode,
+                       classHash = {}; // set of all classes (state and otherwise) for node
 
-// summary:
-//             These functions are used to query or set the focus and selection.
-//
-//             Also, they trace when widgets become activated/deactivated,
-//             so that the widget can fire _onFocus/_onBlur events.
-//             "Active" here means something similar to "focused", but
-//             "focus" isn't quite the right word because we keep track of
-//             a whole stack of "active" widgets.  Example: ComboButton --> Menu -->
-//             MenuItem.  The onBlur event for ComboButton doesn't fire due to focusing
-//             on the Menu or a MenuItem, since they are considered part of the
-//             ComboButton widget.  It only happens when focus is shifted
-//             somewhere completely different.
-
-dojo.mixin(dijit, {
-       // _curFocus: DomNode
-       //              Currently focused item on screen
-       _curFocus: null,
-
-       // _prevFocus: DomNode
-       //              Previously focused item on screen
-       _prevFocus: null,
-
-       isCollapsed: function(){
-               // summary:
-               //              Returns true if there is no text selected
-               return dijit.getBookmark().isCollapsed;
-       },
-
-       getBookmark: function(){
-               // summary:
-               //              Retrieves a bookmark that can be used with moveToBookmark to return to the same range
-               var bm, rg, tg, sel = dojo.doc.selection, cf = dijit._curFocus;
-
-               if(dojo.global.getSelection){
-                       //W3C Range API for selections.
-                       sel = dojo.global.getSelection();
-                       if(sel){
-                               if(sel.isCollapsed){
-                                       tg = cf? cf.tagName : "";
-                                       if(tg){
-                                               //Create a fake rangelike item to restore selections.
-                                               tg = tg.toLowerCase();
-                                               if(tg == "textarea" ||
-                                                               (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
-                                                       sel = {
-                                                               start: cf.selectionStart,
-                                                               end: cf.selectionEnd,
-                                                               node: cf,
-                                                               pRange: true
-                                                       };
-                                                       return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
-                                               }
-                                       }
-                                       bm = {isCollapsed:true};
-                               }else{
-                                       rg = sel.getRangeAt(0);
-                                       bm = {isCollapsed: false, mark: rg.cloneRange()};
-                               }
-                       }
-               }else if(sel){
-                       // If the current focus was a input of some sort and no selection, don't bother saving
-                       // a native bookmark.  This is because it causes issues with dialog/page selection restore.
-                       // So, we need to create psuedo bookmarks to work with.
-                       tg = cf ? cf.tagName : "";
-                       tg = tg.toLowerCase();
-                       if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
-                               if(sel.type && sel.type.toLowerCase() == "none"){
-                                       return {
-                                               isCollapsed: true,
-                                               mark: null
-                                       }
-                               }else{
-                                       rg = sel.createRange();
-                                       return {
-                                               isCollapsed: rg.text && rg.text.length?false:true,
-                                               mark: {
-                                                       range: rg,
-                                                       pRange: true
-                                               }
-                                       };
-                               }
-                       }
-                       bm = {};
+               array.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
 
-                       //'IE' way for selections.
-                       try{
-                               // createRange() throws exception when dojo in iframe
-                               //and nothing selected, see #9632
-                               rg = sel.createRange();
-                               bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
-                       }catch(e){
-                               bm.isCollapsed = true;
-                               return bm;
-                       }
-                       if(sel.type.toUpperCase() == 'CONTROL'){
-                               if(rg.length){
-                                       bm.mark=[];
-                                       var i=0,len=rg.length;
-                                       while(i<len){
-                                               bm.mark.push(rg.item(i++));
-                                       }
-                               }else{
-                                       bm.isCollapsed = true;
-                                       bm.mark = null;
-                               }
-                       }else{
-                               bm.mark = rg.getBookmark();
-                       }
-               }else{
-                       console.warn("No idea how to store the current selection for this browser!");
+               if("_stateClasses" in this){
+                       array.forEach(this._stateClasses, function(c){ delete classHash[c]; });
                }
-               return bm; // Object
-       },
 
-       moveToBookmark: function(/*Object*/bookmark){
-               // summary:
-               //              Moves current selection to a bookmark
-               // bookmark:
-               //              This should be a returned object from dijit.getBookmark()
+               array.forEach(newStateClasses, function(c){ classHash[c] = true; });
 
-               var _doc = dojo.doc,
-                       mark = bookmark.mark;
-               if(mark){
-                       if(dojo.global.getSelection){
-                               //W3C Rangi API (FF, WebKit, Opera, etc)
-                               var sel = dojo.global.getSelection();
-                               if(sel && sel.removeAllRanges){
-                                       if(mark.pRange){
-                                               var r = mark;
-                                               var n = r.node;
-                                               n.selectionStart = r.start;
-                                               n.selectionEnd = r.end;
-                                       }else{
-                                               sel.removeAllRanges();
-                                               sel.addRange(mark);
-                                       }
-                               }else{
-                                       console.warn("No idea how to restore selection for this browser!");
-                               }
-                       }else if(_doc.selection && mark){
-                               //'IE' way.
-                               var rg;
-                               if(mark.pRange){
-                                       rg = mark.range;
-                               }else if(dojo.isArray(mark)){
-                                       rg = _doc.body.createControlRange();
-                                       //rg.addElement does not have call/apply method, so can not call it directly
-                                       //rg is not available in "range.addElement(item)", so can't use that either
-                                       dojo.forEach(mark, function(n){
-                                               rg.addElement(n);
-                                       });
-                               }else{
-                                       rg = _doc.body.createTextRange();
-                                       rg.moveToBookmark(mark);
-                               }
-                               rg.select();
-                       }
+               var newClasses = [];
+               for(var c in classHash){
+                       newClasses.push(c);
                }
+               tn.className = newClasses.join(" ");
+
+               this._stateClasses = newStateClasses;
        },
 
-       getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
+       _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
                // summary:
-               //              Called as getFocus(), this returns an Object showing the current focus
-               //              and selected text.
-               //
-               //              Called as getFocus(widget), where widget is a (widget representing) a button
-               //              that was just pressed, it returns where focus was before that button
-               //              was pressed.   (Pressing the button may have either shifted focus to the button,
-               //              or removed focus altogether.)   In this case the selected text is not returned,
-               //              since it can't be accurately determined.
-               //
-               // menu: dijit._Widget or {domNode: DomNode} structure
-               //              The button that was just pressed.  If focus has disappeared or moved
-               //              to this button, returns the previous focus.  In this case the bookmark
-               //              information is already lost, and null is returned.
-               //
-               // openedForWindow:
-               //              iframe in which menu was opened
+               //              Track mouse/focus events on specified node and set CSS class on that node to indicate
+               //              current state.   Usually not called directly, but via cssStateNodes attribute.
+               // description:
+               //              Given class=foo, will set the following CSS class on the node
+               //                      - fooActive: if the user is currently pressing down the mouse button while over the node
+               //                      - fooHover: if the user is hovering the mouse over the node, but not pressing down a button
+               //                      - fooFocus: if the node is focused
                //
-               // returns:
-               //              A handle to restore focus/selection, to be passed to `dijit.focus`
-               var node = !dijit._curFocus || (menu && dojo.isDescendant(dijit._curFocus, menu.domNode)) ? dijit._prevFocus : dijit._curFocus;
-               return {
-                       node: node,
-                       bookmark: (node == dijit._curFocus) && dojo.withGlobal(openedForWindow || dojo.global, dijit.getBookmark),
-                       openedForWindow: openedForWindow
-               }; // Object
-       },
+               //              Note that it won't set any classes if the widget is disabled.
+               // node: DomNode
+               //              Should be a sub-node of the widget, not the top node (this.domNode), since the top node
+               //              is handled specially and automatically just by mixing in this class.
+               // clazz: String
+               //              CSS class name (ex: dijitSliderUpArrow).
 
-       focus: function(/*Object || DomNode */ handle){
-               // summary:
-               //              Sets the focused node and the selection according to argument.
-               //              To set focus to an iframe's content, pass in the iframe itself.
-               // handle:
-               //              object returned by get(), or a DomNode
-
-               if(!handle){ return; }
+               // Current state of node (initially false)
+               // NB: setting specifically to false because domClass.toggle() needs true boolean as third arg
+               var hovering=false, active=false, focused=false;
 
-               var node = "node" in handle ? handle.node : handle,             // because handle is either DomNode or a composite object
-                       bookmark = handle.bookmark,
-                       openedForWindow = handle.openedForWindow,
-                       collapsed = bookmark ? bookmark.isCollapsed : false;
+               var self = this,
+                       cn = lang.hitch(this, "connect", node);
 
-               // Set the focus
-               // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
-               // but we need to set focus to iframe.contentWindow
-               if(node){
-                       var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
-                       if(focusNode && focusNode.focus){
-                               try{
-                                       // Gecko throws sometimes if setting focus is impossible,
-                                       // node not displayed or something like that
-                                       focusNode.focus();
-                               }catch(e){/*quiet*/}
-                       }
-                       dijit._onFocusNode(node);
+               function setClass(){
+                       var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
+                       domClass.toggle(node, clazz+"Hover", hovering && !active && !disabled);
+                       domClass.toggle(node, clazz+"Active", active && !disabled);
+                       domClass.toggle(node, clazz+"Focused", focused && !disabled);
                }
 
-               // set the selection
-               // do not need to restore if current selection is not empty
-               // (use keyboard to select a menu item) or if previous selection was collapsed
-               // as it may cause focus shift (Esp in IE).
-               if(bookmark && dojo.withGlobal(openedForWindow || dojo.global, dijit.isCollapsed) && !collapsed){
-                       if(openedForWindow){
-                               openedForWindow.focus();
-                       }
-                       try{
-                               dojo.withGlobal(openedForWindow || dojo.global, dijit.moveToBookmark, null, [bookmark]);
-                       }catch(e2){
-                               /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
-                       }
-               }
-       },
+               // Mouse
+               cn("onmouseenter", function(){
+                       hovering = true;
+                       setClass();
+               });
+               cn("onmouseleave", function(){
+                       hovering = false;
+                       active = false;
+                       setClass();
+               });
+               cn(touch.press, function(){
+                       active = true;
+                       setClass();
+               });
+               cn(touch.release, function(){
+                       active = false;
+                       setClass();
+               });
+
+               // Focus
+               cn("onfocus", function(){
+                       focused = true;
+                       setClass();
+               });
+               cn("onblur", function(){
+                       focused = false;
+                       setClass();
+               });
 
-       // _activeStack: dijit._Widget[]
-       //              List of currently active widgets (focused widget and it's ancestors)
-       _activeStack: [],
+               // Just in case widget is enabled/disabled while it has focus/hover/active state.
+               // Maybe this is overkill.
+               this.watch("disabled", setClass);
+               this.watch("readOnly", setClass);
+       }
+});
+});
 
-       registerIframe: function(/*DomNode*/ iframe){
-               // summary:
-               //              Registers listeners on the specified iframe so that any click
-               //              or focus event on that iframe (or anything in it) is reported
-               //              as a focus/click event on the <iframe> itself.
-               // description:
-               //              Currently only used by editor.
-               // returns:
-               //              Handle to pass to unregisterIframe()
-               return dijit.registerWin(iframe.contentWindow, iframe);
-       },
+},
+'dijit/DialogUnderlay':function(){
+define("dijit/DialogUnderlay", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/window", // win.body
+       "dojo/window", // winUtils.getBox
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./BackgroundIframe"
+], function(declare, domAttr, win, winUtils, _Widget, _TemplatedMixin, BackgroundIframe){
 
-       unregisterIframe: function(/*Object*/ handle){
-               // summary:
-               //              Unregisters listeners on the specified iframe created by registerIframe.
-               //              After calling be sure to delete or null out the handle itself.
-               // handle:
-               //              Handle returned by registerIframe()
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+=====*/
 
-               dijit.unregisterWin(handle);
-       },
+       // module:
+       //              dijit/DialogUnderlay
+       // summary:
+       //              The component that blocks the screen behind a `dijit.Dialog`
 
-       registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
+       return declare("dijit.DialogUnderlay", [_Widget, _TemplatedMixin], {
                // summary:
-               //              Registers listeners on the specified window (either the main
-               //              window or an iframe's window) to detect when the user has clicked somewhere
-               //              or focused somewhere.
+               //              The component that blocks the screen behind a `dijit.Dialog`
+               //
                // description:
-               //              Users should call registerIframe() instead of this method.
-               // targetWindow:
-               //              If specified this is the window associated with the iframe,
-               //              i.e. iframe.contentWindow.
-               // effectiveNode:
-               //              If specified, report any focus events inside targetWindow as
-               //              an event on effectiveNode, rather than on evt.target.
-               // returns:
-               //              Handle to pass to unregisterWin()
+               //              A component used to block input behind a `dijit.Dialog`. Only a single
+               //              instance of this widget is created by `dijit.Dialog`, and saved as
+               //              a reference to be shared between all Dialogs as `dijit._underlay`
+               //
+               //              The underlay itself can be styled based on and id:
+               //      |       #myDialog_underlay { background-color:red; }
+               //
+               //              In the case of `dijit.Dialog`, this id is based on the id of the Dialog,
+               //              suffixed with _underlay.
 
-               // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
+               // Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
+               // Inner div has opacity specified in CSS file.
+               templateString: "<div class='dijitDialogUnderlayWrapper'><div class='dijitDialogUnderlay' data-dojo-attach-point='node'></div></div>",
 
-               var mousedownListener = function(evt){
-                       dijit._justMouseDowned = true;
-                       setTimeout(function(){ dijit._justMouseDowned = false; }, 0);
-                       
-                       // workaround weird IE bug where the click is on an orphaned node
-                       // (first time clicking a Select/DropDownButton inside a TooltipDialog)
-                       if(dojo.isIE && evt && evt.srcElement && evt.srcElement.parentNode == null){
-                               return;
-                       }
+               // Parameters on creation or updatable later
 
-                       dijit._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
-               };
-               //dojo.connect(targetWindow, "onscroll", ???);
-
-               // Listen for blur and focus events on targetWindow's document.
-               // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble
-               // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers
-               // fire.
-               // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
-               // (at least for FF) the focus event doesn't fire on <html> or <body>.
-               var doc = dojo.isIE ? targetWindow.document.documentElement : targetWindow.document;
-               if(doc){
-                       if(dojo.isIE){
-                               doc.attachEvent('onmousedown', mousedownListener);
-                               var activateListener = function(evt){
-                                       // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
-                                       // Should consider those more like a mouse-click than a focus....
-                                       if(evt.srcElement.tagName.toLowerCase() != "#document" &&
-                                               dijit.isTabNavigable(evt.srcElement)){
-                                               dijit._onFocusNode(effectiveNode || evt.srcElement);
-                                       }else{
-                                               dijit._onTouchNode(effectiveNode || evt.srcElement);
-                                       }
-                               };
-                               doc.attachEvent('onactivate', activateListener);
-                               var deactivateListener =  function(evt){
-                                       dijit._onBlurNode(effectiveNode || evt.srcElement);
-                               };
-                               doc.attachEvent('ondeactivate', deactivateListener);
+               // dialogId: String
+               //              Id of the dialog.... DialogUnderlay's id is based on this id
+               dialogId: "",
 
-                               return function(){
-                                       doc.detachEvent('onmousedown', mousedownListener);
-                                       doc.detachEvent('onactivate', activateListener);
-                                       doc.detachEvent('ondeactivate', deactivateListener);
-                                       doc = null;     // prevent memory leak (apparent circular reference via closure)
-                               };
-                       }else{
-                               doc.addEventListener('mousedown', mousedownListener, true);
-                               var focusListener = function(evt){
-                                       dijit._onFocusNode(effectiveNode || evt.target);
-                               };
-                               doc.addEventListener('focus', focusListener, true);
-                               var blurListener = function(evt){
-                                       dijit._onBlurNode(effectiveNode || evt.target);
-                               };
-                               doc.addEventListener('blur', blurListener, true);
+               // class: String
+               //              This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay
+               "class": "",
 
-                               return function(){
-                                       doc.removeEventListener('mousedown', mousedownListener, true);
-                                       doc.removeEventListener('focus', focusListener, true);
-                                       doc.removeEventListener('blur', blurListener, true);
-                                       doc = null;     // prevent memory leak (apparent circular reference via closure)
-                               };
-                       }
-               }
-       },
+               _setDialogIdAttr: function(id){
+                       domAttr.set(this.node, "id", id + "_underlay");
+                       this._set("dialogId", id);
+               },
 
-       unregisterWin: function(/*Handle*/ handle){
-               // summary:
-               //              Unregisters listeners on the specified window (either the main
-               //              window or an iframe's window) according to handle returned from registerWin().
-               //              After calling be sure to delete or null out the handle itself.
+               _setClassAttr: function(clazz){
+                       this.node.className = "dijitDialogUnderlay " + clazz;
+                       this._set("class", clazz);
+               },
 
-               // Currently our handle is actually a function
-               handle && handle();
-       },
+               postCreate: function(){
+                       // summary:
+                       //              Append the underlay to the body
+                       win.body().appendChild(this.domNode);
+               },
 
-       _onBlurNode: function(/*DomNode*/ node){
-               // summary:
-               //              Called when focus leaves a node.
-               //              Usually ignored, _unless_ it *isn't* follwed by touching another node,
-               //              which indicates that we tabbed off the last field on the page,
-               //              in which case every widget is marked inactive
-               dijit._prevFocus = dijit._curFocus;
-               dijit._curFocus = null;
+               layout: function(){
+                       // summary:
+                       //              Sets the background to the size of the viewport
+                       //
+                       // description:
+                       //              Sets the background to the size of the viewport (rather than the size
+                       //              of the document) since we need to cover the whole browser window, even
+                       //              if the document is only a few lines long.
+                       // tags:
+                       //              private
 
-               if(dijit._justMouseDowned){
-                       // the mouse down caused a new widget to be marked as active; this blur event
-                       // is coming late, so ignore it.
-                       return;
-               }
+                       var is = this.node.style,
+                               os = this.domNode.style;
 
-               // if the blur event isn't followed by a focus event then mark all widgets as inactive.
-               if(dijit._clearActiveWidgetsTimer){
-                       clearTimeout(dijit._clearActiveWidgetsTimer);
-               }
-               dijit._clearActiveWidgetsTimer = setTimeout(function(){
-                       delete dijit._clearActiveWidgetsTimer;
-                       dijit._setStack([]);
-                       dijit._prevFocus = null;
-               }, 100);
-       },
+                       // hide the background temporarily, so that the background itself isn't
+                       // causing scrollbars to appear (might happen when user shrinks browser
+                       // window and then we are called to resize)
+                       os.display = "none";
 
-       _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
-               // summary:
-               //              Callback when node is focused or mouse-downed
-               // node:
-               //              The node that was touched.
-               // by:
-               //              "mouse" if the focus/touch was caused by a mouse down event
+                       // then resize and show
+                       var viewport = winUtils.getBox();
+                       os.top = viewport.t + "px";
+                       os.left = viewport.l + "px";
+                       is.width = viewport.w + "px";
+                       is.height = viewport.h + "px";
+                       os.display = "block";
+               },
 
-               // ignore the recent blurNode event
-               if(dijit._clearActiveWidgetsTimer){
-                       clearTimeout(dijit._clearActiveWidgetsTimer);
-                       delete dijit._clearActiveWidgetsTimer;
-               }
+               show: function(){
+                       // summary:
+                       //              Show the dialog underlay
+                       this.domNode.style.display = "block";
+                       this.layout();
+                       this.bgIframe = new BackgroundIframe(this.domNode);
+               },
 
-               // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
-               var newStack=[];
-               try{
-                       while(node){
-                               var popupParent = dojo.attr(node, "dijitPopupParent");
-                               if(popupParent){
-                                       node=dijit.byId(popupParent).domNode;
-                               }else if(node.tagName && node.tagName.toLowerCase() == "body"){
-                                       // is this the root of the document or just the root of an iframe?
-                                       if(node === dojo.body()){
-                                               // node is the root of the main document
-                                               break;
-                                       }
-                                       // otherwise, find the iframe this node refers to (can't access it via parentNode,
-                                       // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
-                                       node=dojo.window.get(node.ownerDocument).frameElement;
-                               }else{
-                                       // if this node is the root node of a widget, then add widget id to stack,
-                                       // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
-                                       // to support MenuItem)
-                                       var id = node.getAttribute && node.getAttribute("widgetId"),
-                                               widget = id && dijit.byId(id);
-                                       if(widget && !(by == "mouse" && widget.get("disabled"))){
-                                               newStack.unshift(id);
-                                       }
-                                       node=node.parentNode;
-                               }
-                       }
-               }catch(e){ /* squelch */ }
+               hide: function(){
+                       // summary:
+                       //              Hides the dialog underlay
+                       this.bgIframe.destroy();
+                       delete this.bgIframe;
+                       this.domNode.style.display = "none";
+               }
+       });
+});
 
-               dijit._setStack(newStack, by);
-       },
+},
+'dijit/layout/ScrollingTabController':function(){
+require({cache:{
+'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">&#9660;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">&#9664;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">&#9654;</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>",
+'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\">\n\t<div role=\"presentation\" class=\"dijitTabInnerDiv\" data-dojo-attach-point=\"innerDiv,focusNode\">\n\t\t<div role=\"presentation\" class=\"dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"tabContent\">\n\t\t\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n\t\t</div>\n\t</div>\n</div>"}});
+define("dijit/layout/ScrollingTabController", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.contains
+       "dojo/dom-geometry", // domGeometry.contentBox
+       "dojo/dom-style", // domStyle.style
+       "dojo/_base/fx", // Animation
+       "dojo/_base/lang", // lang.hitch
+       "dojo/query", // query
+       "dojo/_base/sniff", // has("ie"), has("webkit"), has("quirks")
+       "../registry",  // registry.byId()
+       "dojo/text!./templates/ScrollingTabController.html",
+       "dojo/text!./templates/_ScrollingTabControllerButton.html",
+       "./TabController",
+       "./utils",      // marginBox2contextBox, layoutChildren
+       "../_WidgetsInTemplateMixin",
+       "../Menu",
+       "../MenuItem",
+       "../form/Button",
+       "../_HasDropDown",
+       "dojo/NodeList-dom" // NodeList.style
+], function(array, declare, domClass, domGeometry, domStyle, fx, lang, query, has,
+       registry, tabControllerTemplate, buttonTemplate, TabController, layoutUtils, _WidgetsInTemplateMixin,
+       Menu, MenuItem, Button, _HasDropDown){
 
-       _onFocusNode: function(/*DomNode*/ node){
-               // summary:
-               //              Callback when node is focused
+/*=====
+var _WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
+var Menu = dijit.Menu;
+var _HasDropDown = dijit._HasDropDown;
+var TabController = dijit.layout.TabController;
+=====*/
 
-               if(!node){
-                       return;
-               }
 
-               if(node.nodeType == 9){
-                       // Ignore focus events on the document itself.  This is here so that
-                       // (for example) clicking the up/down arrows of a spinner
-                       // (which don't get focus) won't cause that widget to blur. (FF issue)
-                       return;
-               }
+// module:
+//             dijit/layout/ScrollingTabController
+// summary:
+//             Set of tabs with left/right arrow keys and a menu to switch between tabs not
+//             all fitting on a single row.
 
-               dijit._onTouchNode(node);
 
-               if(node == dijit._curFocus){ return; }
-               if(dijit._curFocus){
-                       dijit._prevFocus = dijit._curFocus;
-               }
-               dijit._curFocus = node;
-               dojo.publish("focusNode", [node]);
-       },
+var ScrollingTabController = declare("dijit.layout.ScrollingTabController", [TabController, _WidgetsInTemplateMixin], {
+       // summary:
+       //              Set of tabs with left/right arrow keys and a menu to switch between tabs not
+       //              all fitting on a single row.
+       //              Works only for horizontal tabs (either above or below the content, not to the left
+       //              or right).
+       // tags:
+       //              private
 
-       _setStack: function(/*String[]*/ newStack, /*String*/ by){
-               // summary:
-               //              The stack of active widgets has changed.  Send out appropriate events and records new stack.
-               // newStack:
-               //              array of widget id's, starting from the top (outermost) widget
-               // by:
-               //              "mouse" if the focus/touch was caused by a mouse down event
+       baseClass: "dijitTabController dijitScrollingTabController",
 
-               var oldStack = dijit._activeStack;
-               dijit._activeStack = newStack;
+       templateString: tabControllerTemplate,
 
-               // compare old stack to new stack to see how many elements they have in common
-               for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
-                       if(oldStack[nCommon] != newStack[nCommon]){
-                               break;
-                       }
-               }
+       // useMenu: [const] Boolean
+       //              True if a menu should be used to select tabs when they are too
+       //              wide to fit the TabContainer, false otherwise.
+       useMenu: true,
 
-               var widget;
-               // for all elements that have gone out of focus, send blur event
-               for(var i=oldStack.length-1; i>=nCommon; i--){
-                       widget = dijit.byId(oldStack[i]);
-                       if(widget){
-                               widget._focused = false;
-                               widget._hasBeenBlurred = true;
-                               if(widget._onBlur){
-                                       widget._onBlur(by);
-                               }
-                               dojo.publish("widgetBlur", [widget, by]);
-                       }
-               }
+       // useSlider: [const] Boolean
+       //              True if a slider should be used to select tabs when they are too
+       //              wide to fit the TabContainer, false otherwise.
+       useSlider: true,
 
-               // for all element that have come into focus, send focus event
-               for(i=nCommon; i<newStack.length; i++){
-                       widget = dijit.byId(newStack[i]);
-                       if(widget){
-                               widget._focused = true;
-                               if(widget._onFocus){
-                                       widget._onFocus(by);
-                               }
-                               dojo.publish("widgetFocus", [widget, by]);
-                       }
-               }
-       }
-});
+       // tabStripClass: [const] String
+       //              The css class to apply to the tab strip, if it is visible.
+       tabStripClass: "",
 
-// register top window and all the iframes it contains
-dojo.addOnLoad(function(){
-       var handle = dijit.registerWin(window);
-       if(dojo.isIE){
-               dojo.addOnWindowUnload(function(){
-                       dijit.unregisterWin(handle);
-                       handle = null;
-               })
-       }
-});
+       widgetsInTemplate: true,
 
-}
+       // _minScroll: Number
+       //              The distance in pixels from the edge of the tab strip which,
+       //              if a scroll animation is less than, forces the scroll to
+       //              go all the way to the left/right.
+       _minScroll: 5,
 
-if(!dojo._hasResource["dojo.AdapterRegistry"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.AdapterRegistry"] = true;
-dojo.provide("dojo.AdapterRegistry");
+       // Override default behavior mapping class to DOMNode
+       _setClassAttr: { node: "containerNode", type: "class" },
 
-dojo.AdapterRegistry = function(/*Boolean?*/ returnWrappers){
-       //      summary:
-       //              A registry to make contextual calling/searching easier.
-       //      description:
-       //              Objects of this class keep list of arrays in the form [name, check,
-       //              wrap, directReturn] that are used to determine what the contextual
-       //              result of a set of checked arguments is. All check/wrap functions
-       //              in this registry should be of the same arity.
-       //      example:
-       //      |       // create a new registry
-       //      |       var reg = new dojo.AdapterRegistry();
-       //      |       reg.register("handleString",
-       //      |               dojo.isString,
-       //      |               function(str){
-       //      |                       // do something with the string here
-       //      |               }
-       //      |       );
-       //      |       reg.register("handleArr",
-       //      |               dojo.isArray,
-       //      |               function(arr){
-       //      |                       // do something with the array here
-       //      |               }
-       //      |       );
-       //      |
-       //      |       // now we can pass reg.match() *either* an array or a string and
-       //      |       // the value we pass will get handled by the right function
-       //      |       reg.match("someValue"); // will call the first function
-       //      |       reg.match(["someValue"]); // will call the second
+       buildRendering: function(){
+               this.inherited(arguments);
+               var n = this.domNode;
 
-       this.pairs = [];
-       this.returnWrappers = returnWrappers || false; // Boolean
-}
+               this.scrollNode = this.tablistWrapper;
+               this._initButtons();
 
-dojo.extend(dojo.AdapterRegistry, {
-       register: function(/*String*/ name, /*Function*/ check, /*Function*/ wrap, /*Boolean?*/ directReturn, /*Boolean?*/ override){
-               //      summary: 
-               //              register a check function to determine if the wrap function or
-               //              object gets selected
-               //      name:
-               //              a way to identify this matcher.
-               //      check:
-               //              a function that arguments are passed to from the adapter's
-               //              match() function.  The check function should return true if the
-               //              given arguments are appropriate for the wrap function.
-               //      directReturn:
-               //              If directReturn is true, the value passed in for wrap will be
-               //              returned instead of being called. Alternately, the
-               //              AdapterRegistry can be set globally to "return not call" using
-               //              the returnWrappers property. Either way, this behavior allows
-               //              the registry to act as a "search" function instead of a
-               //              function interception library.
-               //      override:
-               //              If override is given and true, the check function will be given
-               //              highest priority. Otherwise, it will be the lowest priority
-               //              adapter.
-               this.pairs[((override) ? "unshift" : "push")]([name, check, wrap, directReturn]);
-       },
-
-       match: function(/* ... */){
-               // summary:
-               //              Find an adapter for the given arguments. If no suitable adapter
-               //              is found, throws an exception. match() accepts any number of
-               //              arguments, all of which are passed to all matching functions
-               //              from the registered pairs.
-               for(var i = 0; i < this.pairs.length; i++){
-                       var pair = this.pairs[i];
-                       if(pair[1].apply(this, arguments)){
-                               if((pair[3])||(this.returnWrappers)){
-                                       return pair[2];
-                               }else{
-                                       return pair[2].apply(this, arguments);
-                               }
-                       }
-               }
-               throw new Error("No match found");
-       },
-
-       unregister: function(name){
-               // summary: Remove a named adapter from the registry
-
-               // FIXME: this is kind of a dumb way to handle this. On a large
-               // registry this will be slow-ish and we can use the name as a lookup
-               // should we choose to trade memory for speed.
-               for(var i = 0; i < this.pairs.length; i++){
-                       var pair = this.pairs[i];
-                       if(pair[0] == name){
-                               this.pairs.splice(i, 1);
-                               return true;
-                       }
+               if(!this.tabStripClass){
+                       this.tabStripClass = "dijitTabContainer" +
+                               this.tabPosition.charAt(0).toUpperCase() +
+                               this.tabPosition.substr(1).replace(/-.*/, "") +
+                               "None";
+                       domClass.add(n, "tabStrip-disabled")
                }
-               return false;
-       }
-});
-
-}
 
-if(!dojo._hasResource["dijit._base.place"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.place"] = true;
-dojo.provide("dijit._base.place");
-
-
-
-
-
-dijit.getViewport = function(){
-       // summary:
-       //              Returns the dimensions and scroll position of the viewable area of a browser window
-
-       return dojo.window.getBox();
-};
+               domClass.add(this.tablistWrapper, this.tabStripClass);
+       },
 
-/*=====
-dijit.__Position = function(){
-       // x: Integer
-       //              horizontal coordinate in pixels, relative to document body
-       // y: Integer
-       //              vertical coordinate in pixels, relative to document body
-
-       thix.x = x;
-       this.y = y;
-}
-=====*/
+       onStartup: function(){
+               this.inherited(arguments);
 
+               // TabController is hidden until it finishes drawing, to give
+               // a less visually jumpy instantiation.   When it's finished, set visibility to ""
+               // to that the tabs are hidden/shown depending on the container's visibility setting.
+               domStyle.set(this.domNode, "visibility", "");
+               this._postStartup = true;
+       },
 
-dijit.placeOnScreen = function(
-       /* DomNode */                   node,
-       /* dijit.__Position */  pos,
-       /* String[] */                  corners,
-       /* dijit.__Position? */ padding){
-       // summary:
-       //              Positions one of the node's corners at specified position
-       //              such that node is fully visible in viewport.
-       // description:
-       //              NOTE: node is assumed to be absolutely or relatively positioned.
-       //      pos:
-       //              Object like {x: 10, y: 20}
-       //      corners:
-       //              Array of Strings representing order to try corners in, like ["TR", "BL"].
-       //              Possible values are:
-       //                      * "BL" - bottom left
-       //                      * "BR" - bottom right
-       //                      * "TL" - top left
-       //                      * "TR" - top right
-       //      padding:
-       //              set padding to put some buffer around the element you want to position.
-       // example:
-       //              Try to place node's top right corner at (10,20).
-       //              If that makes node go (partially) off screen, then try placing
-       //              bottom left corner at (10,20).
-       //      |       placeOnScreen(node, {x: 10, y: 20}, ["TR", "BL"])
-
-       var choices = dojo.map(corners, function(corner){
-               var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
-               if(padding){
-                       c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
-                       c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
-               }
-               return c;
-       });
+       onAddChild: function(page, insertIndex){
+               this.inherited(arguments);
 
-       return dijit._place(node, choices);
-}
+               // changes to the tab button label or iconClass will have changed the width of the
+               // buttons, so do a resize
+               array.forEach(["label", "iconClass"], function(attr){
+                       this.pane2watches[page.id].push(
+                               this.pane2button[page.id].watch(attr, lang.hitch(this, function(){
+                                       if(this._postStartup && this._dim){
+                                               this.resize(this._dim);
+                                       }
+                               }))
+                       );
+               }, this);
 
-dijit._place = function(/*DomNode*/ node, /* Array */ choices, /* Function */ layoutNode){
-       // summary:
-       //              Given a list of spots to put node, put it at the first spot where it fits,
-       //              of if it doesn't fit anywhere then the place with the least overflow
-       // choices: Array
-       //              Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
-       //              Above example says to put the top-left corner of the node at (10,20)
-       // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
-       //              for things like tooltip, they are displayed differently (and have different dimensions)
-       //              based on their orientation relative to the parent.   This adjusts the popup based on orientation.
-
-       // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
-       // viewport over document
-       var view = dojo.window.getBox();
-
-       // This won't work if the node is inside a <div style="position: relative">,
-       // so reattach it to dojo.doc.body.   (Otherwise, the positioning will be wrong
-       // and also it might get cutoff)
-       if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
-               dojo.body().appendChild(node);
-       }
+               // Increment the width of the wrapper when a tab is added
+               // This makes sure that the buttons never wrap.
+               // The value 200 is chosen as it should be bigger than most
+               // Tab button widths.
+               domStyle.set(this.containerNode, "width",
+                       (domStyle.get(this.containerNode, "width") + 200) + "px");
+       },
 
-       var best = null;
-       dojo.some(choices, function(choice){
-               var corner = choice.corner;
-               var pos = choice.pos;
-
-               // configure node to be displayed in given position relative to button
-               // (need to do this in order to get an accurate size for the node, because
-               // a tooltips size changes based on position, due to triangle)
-               if(layoutNode){
-                       layoutNode(node, choice.aroundCorner, corner);
-               }
-
-               // get node's size
-               var style = node.style;
-               var oldDisplay = style.display;
-               var oldVis = style.visibility;
-               style.visibility = "hidden";
-               style.display = "";
-               var mb = dojo.marginBox(node);
-               style.display = oldDisplay;
-               style.visibility = oldVis;
-
-               // coordinates and size of node with specified corner placed at pos,
-               // and clipped by viewport
-               var startX = Math.max(view.l, corner.charAt(1) == 'L' ? pos.x : (pos.x - mb.w)),
-                       startY = Math.max(view.t, corner.charAt(0) == 'T' ? pos.y : (pos.y - mb.h)),
-                       endX = Math.min(view.l + view.w, corner.charAt(1) == 'L' ? (startX + mb.w) : pos.x),
-                       endY = Math.min(view.t + view.h, corner.charAt(0) == 'T' ? (startY + mb.h) : pos.y),
-                       width = endX - startX,
-                       height = endY - startY,
-                       overflow = (mb.w - width) + (mb.h - height);
-
-               if(best == null || overflow < best.overflow){
-                       best = {
-                               corner: corner,
-                               aroundCorner: choice.aroundCorner,
-                               x: startX,
-                               y: startY,
-                               w: width,
-                               h: height,
-                               overflow: overflow
-                       };
+       onRemoveChild: function(page, insertIndex){
+               // null out _selectedTab because we are about to delete that dom node
+               var button = this.pane2button[page.id];
+               if(this._selectedTab === button.domNode){
+                       this._selectedTab = null;
                }
-               return !overflow;
-       });
-
-       node.style.left = best.x + "px";
-       node.style.top = best.y + "px";
-       if(best.overflow && layoutNode){
-               layoutNode(node, best.aroundCorner, best.corner);
-       }
-       return best;
-}
-
-dijit.placeOnScreenAroundNode = function(
-       /* DomNode */           node,
-       /* DomNode */           aroundNode,
-       /* Object */            aroundCorners,
-       /* Function? */         layoutNode){
-
-       // summary:
-       //              Position node adjacent or kitty-corner to aroundNode
-       //              such that it's fully visible in viewport.
-       //
-       // description:
-       //              Place node such that corner of node touches a corner of
-       //              aroundNode, and that node is fully visible.
-       //
-       // aroundCorners:
-       //              Ordered list of pairs of corners to try matching up.
-       //              Each pair of corners is represented as a key/value in the hash,
-       //              where the key corresponds to the aroundNode's corner, and
-       //              the value corresponds to the node's corner:
-       //
-       //      |       { aroundNodeCorner1: nodeCorner1, aroundNodeCorner2: nodeCorner2, ...}
-       //
-       //              The following strings are used to represent the four corners:
-       //                      * "BL" - bottom left
-       //                      * "BR" - bottom right
-       //                      * "TL" - top left
-       //                      * "TR" - top right
-       //
-       // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
-       //              For things like tooltip, they are displayed differently (and have different dimensions)
-       //              based on their orientation relative to the parent.   This adjusts the popup based on orientation.
-       //
-       // example:
-       //      |       dijit.placeOnScreenAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
-       //              This will try to position node such that node's top-left corner is at the same position
-       //              as the bottom left corner of the aroundNode (ie, put node below
-       //              aroundNode, with left edges aligned).  If that fails it will try to put
-       //              the bottom-right corner of node where the top right corner of aroundNode is
-       //              (ie, put node above aroundNode, with right edges aligned)
-       //
-
-       // get coordinates of aroundNode
-       aroundNode = dojo.byId(aroundNode);
-       var oldDisplay = aroundNode.style.display;
-       aroundNode.style.display="";
-       // #3172: use the slightly tighter border box instead of marginBox
-       var aroundNodePos = dojo.position(aroundNode, true);
-       aroundNode.style.display=oldDisplay;
-
-       // place the node around the calculated rectangle
-       return dijit._placeOnScreenAroundRect(node,
-               aroundNodePos.x, aroundNodePos.y, aroundNodePos.w, aroundNodePos.h,     // rectangle
-               aroundCorners, layoutNode);
-};
-
-/*=====
-dijit.__Rectangle = function(){
-       // x: Integer
-       //              horizontal offset in pixels, relative to document body
-       // y: Integer
-       //              vertical offset in pixels, relative to document body
-       // width: Integer
-       //              width in pixels
-       // height: Integer
-       //              height in pixels
-
-       this.x = x;
-       this.y = y;
-       this.width = width;
-       this.height = height;
-}
-=====*/
-
-
-dijit.placeOnScreenAroundRectangle = function(
-       /* DomNode */                   node,
-       /* dijit.__Rectangle */ aroundRect,
-       /* Object */                    aroundCorners,
-       /* Function */                  layoutNode){
 
-       // summary:
-       //              Like dijit.placeOnScreenAroundNode(), except that the "around"
-       //              parameter is an arbitrary rectangle on the screen (x, y, width, height)
-       //              instead of a dom node.
-
-       return dijit._placeOnScreenAroundRect(node,
-               aroundRect.x, aroundRect.y, aroundRect.width, aroundRect.height,        // rectangle
-               aroundCorners, layoutNode);
-};
-
-dijit._placeOnScreenAroundRect = function(
-       /* DomNode */           node,
-       /* Number */            x,
-       /* Number */            y,
-       /* Number */            width,
-       /* Number */            height,
-       /* Object */            aroundCorners,
-       /* Function */          layoutNode){
-
-       // summary:
-       //              Like dijit.placeOnScreenAroundNode(), except it accepts coordinates
-       //              of a rectangle to place node adjacent to.
+               this.inherited(arguments);
+       },
 
-       // TODO: combine with placeOnScreenAroundRectangle()
+       _initButtons: function(){
+               // summary:
+               //              Creates the buttons used to scroll to view tabs that
+               //              may not be visible if the TabContainer is too narrow.
 
-       // Generate list of possible positions for node
-       var choices = [];
-       for(var nodeCorner in aroundCorners){
-               choices.push( {
-                       aroundCorner: nodeCorner,
-                       corner: aroundCorners[nodeCorner],
-                       pos: {
-                               x: x + (nodeCorner.charAt(1) == 'L' ? 0 : width),
-                               y: y + (nodeCorner.charAt(0) == 'T' ? 0 : height)
+               // Make a list of the buttons to display when the tab labels become
+               // wider than the TabContainer, and hide the other buttons.
+               // Also gets the total width of the displayed buttons.
+               this._btnWidth = 0;
+               this._buttons = query("> .tabStripButton", this.domNode).filter(function(btn){
+                       if((this.useMenu && btn == this._menuBtn.domNode) ||
+                               (this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
+                               this._btnWidth += domGeometry.getMarginSize(btn).w;
+                               return true;
+                       }else{
+                               domStyle.set(btn, "display", "none");
+                               return false;
                        }
-               });
-       }
-
-       return dijit._place(node, choices, layoutNode);
-};
-
-dijit.placementRegistry= new dojo.AdapterRegistry();
-dijit.placementRegistry.register("node",
-       function(n, x){
-               return typeof x == "object" &&
-                       typeof x.offsetWidth != "undefined" && typeof x.offsetHeight != "undefined";
-       },
-       dijit.placeOnScreenAroundNode);
-dijit.placementRegistry.register("rect",
-       function(n, x){
-               return typeof x == "object" &&
-                       "x" in x && "y" in x && "width" in x && "height" in x;
+               }, this);
        },
-       dijit.placeOnScreenAroundRectangle);
-
-dijit.placeOnScreenAroundElement = function(
-       /* DomNode */           node,
-       /* Object */            aroundElement,
-       /* Object */            aroundCorners,
-       /* Function */          layoutNode){
-
-       // summary:
-       //              Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
-       //              for the "around" argument and finds a proper processor to place a node.
-
-       return dijit.placementRegistry.match.apply(dijit.placementRegistry, arguments);
-};
 
-dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
-       // summary:
-       //              Transforms the passed array of preferred positions into a format suitable for passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
-       //
-       // position: String[]
-       //              This variable controls the position of the drop down.
-       //              It's an array of strings with the following values:
-       //
-       //                      * before: places drop down to the left of the target node/widget, or to the right in
-       //                        the case of RTL scripts like Hebrew and Arabic
-       //                      * after: places drop down to the right of the target node/widget, or to the left in
-       //                        the case of RTL scripts like Hebrew and Arabic
-       //                      * above: drop down goes above target node
-       //                      * below: drop down goes below target node
-       //
-       //              The list is positions is tried, in order, until a position is found where the drop down fits
-       //              within the viewport.
-       //
-       // leftToRight: Boolean
-       //              Whether the popup will be displaying in leftToRight mode.
-       //
-       var align = {};
-       dojo.forEach(position, function(pos){
-               switch(pos){
-                       case "after":
-                               align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
-                               break;
-                       case "before":
-                               align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
-                               break;
-                       case "below":
-                               // first try to align left borders, next try to align right borders (or reverse for RTL mode)
-                               align[leftToRight ? "BL" : "BR"] = leftToRight ? "TL" : "TR";
-                               align[leftToRight ? "BR" : "BL"] = leftToRight ? "TR" : "TL";
-                               break;
-                       case "above":
-                       default:
-                               // first try to align left borders, next try to align right borders (or reverse for RTL mode)
-                               align[leftToRight ? "TL" : "TR"] = leftToRight ? "BL" : "BR";
-                               align[leftToRight ? "TR" : "TL"] = leftToRight ? "BR" : "BL";
-                               break;
+       _getTabsWidth: function(){
+               var children = this.getChildren();
+               if(children.length){
+                       var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
+                               rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
+                       return rightTab.offsetLeft + domStyle.get(rightTab, "width") - leftTab.offsetLeft;
+               }else{
+                       return 0;
                }
-       });
-       return align;
-};
-
-}
-
-if(!dojo._hasResource["dijit._base.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.window"] = true;
-dojo.provide("dijit._base.window");
-
-
-
-dijit.getDocumentWindow = function(doc){
-       return dojo.window.get(doc);
-};
-
-}
-
-if(!dojo._hasResource["dijit._base.popup"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.popup"] = true;
-dojo.provide("dijit._base.popup");
-
-
+       },
 
+       _enableBtn: function(width){
+               // summary:
+               //              Determines if the tabs are wider than the width of the TabContainer, and
+               //              thus that we need to display left/right/menu navigation buttons.
+               var tabsWidth = this._getTabsWidth();
+               width = width || domStyle.get(this.scrollNode, "width");
+               return tabsWidth > 0 && width < tabsWidth;
+       },
 
+       resize: function(dim){
+               // summary:
+               //              Hides or displays the buttons used to scroll the tab list and launch the menu
+               //              that selects tabs.
 
-/*=====
-dijit.popup.__OpenArgs = function(){
-       // popup: Widget
-       //              widget to display
-       // parent: Widget
-       //              the button etc. that is displaying this popup
-       // around: DomNode
-       //              DOM node (typically a button); place popup relative to this node.  (Specify this *or* "x" and "y" parameters.)
-       // x: Integer
-       //              Absolute horizontal position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
-       // y: Integer
-       //              Absolute vertical position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
-       // orient: Object|String
-       //              When the around parameter is specified, orient should be an
-       //              ordered list of tuples of the form (around-node-corner, popup-node-corner).
-       //              dijit.popup.open() tries to position the popup according to each tuple in the list, in order,
-       //              until the popup appears fully within the viewport.
-       //
-       //              The default value is {BL:'TL', TL:'BL'}, which represents a list of two tuples:
-       //                      1. (BL, TL)
-       //                      2. (TL, BL)
-       //              where BL means "bottom left" and "TL" means "top left".
-       //              So by default, it first tries putting the popup below the around node, left-aligning them,
-       //              and then tries to put it above the around node, still left-aligning them.   Note that the
-       //              default is horizontally reversed when in RTL mode.
-       //
-       //              When an (x,y) position is specified rather than an around node, orient is either
-       //              "R" or "L".  R (for right) means that it tries to put the popup to the right of the mouse,
-       //              specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
-       //              fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
-       //              and the top-right corner.
-       // onCancel: Function
-       //              callback when user has canceled the popup by
-       //                      1. hitting ESC or
-       //                      2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
-       //                         i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
-       // onClose: Function
-       //              callback whenever this popup is closed
-       // onExecute: Function
-       //              callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
-       // padding: dijit.__Position
-       //              adding a buffer around the opening position. This is only useful when around is not set.
-       this.popup = popup;
-       this.parent = parent;
-       this.around = around;
-       this.x = x;
-       this.y = y;
-       this.orient = orient;
-       this.onCancel = onCancel;
-       this.onClose = onClose;
-       this.onExecute = onExecute;
-       this.padding = padding;
-}
-=====*/
+               // Save the dimensions to be used when a child is renamed.
+               this._dim = dim;
 
-dijit.popup = {
-       // summary:
-       //              This singleton is used to show/hide widgets as popups.
+               // Set my height to be my natural height (tall enough for one row of tab labels),
+               // and my content-box width based on margin-box width specified in dim parameter.
+               // But first reset scrollNode.height in case it was set by layoutChildren() call
+               // in a previous run of this method.
+               this.scrollNode.style.height = "auto";
+               var cb = this._contentBox = layoutUtils.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
+               cb.h = this.scrollNode.offsetHeight;
+               domGeometry.setContentSize(this.domNode, cb);
 
-       // _stack: dijit._Widget[]
-       //              Stack of currently popped up widgets.
-       //              (someone opened _stack[0], and then it opened _stack[1], etc.)
-       _stack: [],
-       
-       // _beginZIndex: Number
-       //              Z-index of the first popup.   (If first popup opens other
-       //              popups they get a higher z-index.)
-       _beginZIndex: 1000,
+               // Show/hide the left/right/menu navigation buttons depending on whether or not they
+               // are needed.
+               var enable = this._enableBtn(this._contentBox.w);
+               this._buttons.style("display", enable ? "" : "none");
 
-       _idGen: 1,
+               // Position and size the navigation buttons and the tablist
+               this._leftBtn.layoutAlign = "left";
+               this._rightBtn.layoutAlign = "right";
+               this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left";
+               layoutUtils.layoutChildren(this.domNode, this._contentBox,
+                       [this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]);
 
-       moveOffScreen: function(/*DomNode*/ node){
-               // summary:
-               //              Initialization for nodes that will be used as popups
-               //
-               // description:
-               //              Puts node inside a wrapper <div>, and
-               //              positions wrapper div off screen, but not display:none, so that
-               //              the widget doesn't appear in the page flow and/or cause a blank
-               //              area at the bottom of the viewport (making scrollbar longer), but
-               //              initialization of contained widgets works correctly
-
-               var wrapper = node.parentNode;
-
-               // Create a wrapper widget for when this node (in the future) will be used as a popup.
-               // This is done early because of IE bugs where creating/moving DOM nodes causes focus
-               // to go wonky, see tests/robot/Toolbar.html to reproduce
-               if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){
-                       wrapper = dojo.create("div",{
-                               "class":"dijitPopup",
-                               style:{
-                                       visibility:"hidden",
-                                       top: "-9999px"
-                               }
-                       }, dojo.body());
-                       dijit.setWaiRole(wrapper, "presentation");
-                       wrapper.appendChild(node);
+               // set proper scroll so that selected tab is visible
+               if(this._selectedTab){
+                       if(this._anim && this._anim.status() == "playing"){
+                               this._anim.stop();
+                       }
+                       this.scrollNode.scrollLeft = this._convertToScrollLeft(this._getScrollForSelectedTab());
                }
 
+               // Enable/disabled left right buttons depending on whether or not user can scroll to left or right
+               this._setButtonClass(this._getScroll());
 
-               var s = node.style;
-               s.display = "";
-               s.visibility = "";
-               s.position = "";
-               s.top = "0px";
+               this._postResize = true;
 
-               dojo.style(wrapper, {
-                       visibility: "hidden",
-                       // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
-                       top: "-9999px"
-               });
+               // Return my size so layoutChildren() can use it.
+               // Also avoids IE9 layout glitch on browser resize when scroll buttons present
+               return {h: this._contentBox.h, w: dim.w};
        },
 
-       getTopPopup: function(){
+       _getScroll: function(){
                // summary:
-               //              Compute the closest ancestor popup that's *not* a child of another popup.
-               //              Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
-               var stack = this._stack;
-               for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
-                       /* do nothing, just trying to get right value for pi */
-               }
-               return stack[pi];
+               //              Returns the current scroll of the tabs where 0 means
+               //              "scrolled all the way to the left" and some positive number, based on #
+               //              of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
+               return (this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")) ? this.scrollNode.scrollLeft :
+                               domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width")
+                                        + (has("ie") == 8 ? -1 : 1) * this.scrollNode.scrollLeft;
        },
 
-       open: function(/*dijit.popup.__OpenArgs*/ args){
+       _convertToScrollLeft: function(val){
                // summary:
-               //              Popup the widget at the specified position
-               //
-               // example:
-               //              opening at the mouse position
-               //              |               dijit.popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
-               //
-               // example:
-               //              opening the widget as a dropdown
-               //              |               dijit.popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
+               //              Given a scroll value where 0 means "scrolled all the way to the left"
+               //              and some positive number, based on # of pixels of possible scroll (ex: 1000)
+               //              means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
+               //              to achieve that scroll.
                //
-               //              Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
-               //              (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
-
-               var stack = this._stack,
-                       widget = args.popup,
-                       orient = args.orient || (
-                               (args.parent ? args.parent.isLeftToRight() : dojo._isBodyLtr()) ?
-                               {'BL':'TL', 'BR':'TR', 'TL':'BL', 'TR':'BR'} :
-                               {'BR':'TR', 'BL':'TL', 'TR':'BR', 'TL':'BL'}
-                       ),
-                       around = args.around,
-                       id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
-
-
-               // The wrapper may have already been created, but in case it wasn't, create here
-               var wrapper = widget.domNode.parentNode;
-               if(!wrapper || !dojo.hasClass(wrapper, "dijitPopup")){
-                       this.moveOffScreen(widget.domNode);
-                       wrapper = widget.domNode.parentNode;
+               //              This method is to adjust for RTL funniness in various browsers and versions.
+               if(this.isLeftToRight() || has("ie") < 8 || (has("ie") && has("quirks")) || has("webkit")){
+                       return val;
+               }else{
+                       var maxScroll = domStyle.get(this.containerNode, "width") - domStyle.get(this.scrollNode, "width");
+                       return (has("ie") == 8 ? -1 : 1) * (val - maxScroll);
                }
+       },
 
-               dojo.attr(wrapper, {
-                       id: id,
-                       style: {
-                               zIndex: this._beginZIndex + stack.length
-                       },
-                       "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
-                       dijitPopupParent: args.parent ? args.parent.id : ""
-               });
+       onSelectChild: function(/*dijit._Widget*/ page){
+               // summary:
+               //              Smoothly scrolls to a tab when it is selected.
 
-               if(dojo.isIE || dojo.isMoz){
-                       var iframe = wrapper.childNodes[1];
-                       if(!iframe){
-                               iframe = new dijit.BackgroundIframe(wrapper);
-                       }
-               }
+               var tab = this.pane2button[page.id];
+               if(!tab || !page){return;}
 
-               // position the wrapper node and make it visible
-               var best = around ?
-                       dijit.placeOnScreenAroundElement(wrapper, around, orient, widget.orient ? dojo.hitch(widget, "orient") : null) :
-                       dijit.placeOnScreen(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
+               var node = tab.domNode;
 
-               wrapper.style.visibility = "visible";
-               widget.domNode.style.visibility = "visible";    // counteract effects from _HasDropDown
+               // Save the selection
+               if(node != this._selectedTab){
+                       this._selectedTab = node;
 
-               var handlers = [];
+                       // Scroll to the selected tab, except on startup, when scrolling is handled in resize()
+                       if(this._postResize){
+                               var sl = this._getScroll();
 
-               // provide default escape and tab key handling
-               // (this will work for any widget, not just menu)
-               handlers.push(dojo.connect(wrapper, "onkeypress", this, function(evt){
-                       if(evt.charOrCode == dojo.keys.ESCAPE && args.onCancel){
-                               dojo.stopEvent(evt);
-                               args.onCancel();
-                       }else if(evt.charOrCode === dojo.keys.TAB){
-                               dojo.stopEvent(evt);
-                               var topPopup = this.getTopPopup();
-                               if(topPopup && topPopup.onCancel){
-                                       topPopup.onCancel();
+                               if(sl > node.offsetLeft ||
+                                               sl + domStyle.get(this.scrollNode, "width") <
+                                               node.offsetLeft + domStyle.get(node, "width")){
+                                       this.createSmoothScroll().play();
                                }
                        }
-               }));
-
-               // watch for cancel/execute events on the popup and notify the caller
-               // (for a menu, "execute" means clicking an item)
-               if(widget.onCancel){
-                       handlers.push(dojo.connect(widget, "onCancel", args.onCancel));
-               }
-
-               handlers.push(dojo.connect(widget, widget.onExecute ? "onExecute" : "onChange", this, function(){
-                       var topPopup = this.getTopPopup();
-                       if(topPopup && topPopup.onExecute){
-                               topPopup.onExecute();
-                       }
-               }));
-
-               stack.push({
-                       wrapper: wrapper,
-                       iframe: iframe,
-                       widget: widget,
-                       parent: args.parent,
-                       onExecute: args.onExecute,
-                       onCancel: args.onCancel,
-                       onClose: args.onClose,
-                       handlers: handlers
-               });
-
-               if(widget.onOpen){
-                       // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
-                       widget.onOpen(best);
                }
 
-               return best;
+               this.inherited(arguments);
        },
 
-       close: function(/*dijit._Widget*/ popup){
+       _getScrollBounds: function(){
                // summary:
-               //              Close specified popup and any popups that it parented
-
-               var stack = this._stack;
-
-               // Basically work backwards from the top of the stack closing popups
-               // until we hit the specified popup, but IIRC there was some issue where closing
-               // a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
-               // closing C might close B indirectly and then the while() condition will run where stack==[A]...
-               // so the while condition is constructed defensively.
-               while(dojo.some(stack, function(elem){return elem.widget == popup;})){
-                       var top = stack.pop(),
-                               wrapper = top.wrapper,
-                               iframe = top.iframe,
-                               widget = top.widget,
-                               onClose = top.onClose;
-
-                       if(widget.onClose){
-                               // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
-                               widget.onClose();
-                       }
-                       dojo.forEach(top.handlers, dojo.disconnect);
-
-                       // Move the widget plus it's wrapper off screen, unless it has already been destroyed in above onClose() etc.
-                       if(widget && widget.domNode){
-                               this.moveOffScreen(widget.domNode);
-                       }else{
-                               dojo.destroy(wrapper);
-                       }
-                        
-                       if(onClose){
-                               onClose();
-                       }
-               }
-       }
-};
+               //              Returns the minimum and maximum scroll setting to show the leftmost and rightmost
+               //              tabs (respectively)
+               var children = this.getChildren(),
+                       scrollNodeWidth = domStyle.get(this.scrollNode, "width"),               // about 500px
+                       containerWidth = domStyle.get(this.containerNode, "width"),     // 50,000px
+                       maxPossibleScroll = containerWidth - scrollNodeWidth,   // scrolling until right edge of containerNode visible
+                       tabsWidth = this._getTabsWidth();
 
-dijit._frames = new function(){
-       // summary:
-       //              cache of iframes
-       var queue = [];
-
-       this.pop = function(){
-               var iframe;
-               if(queue.length){
-                       iframe = queue.pop();
-                       iframe.style.display="";
+               if(children.length && tabsWidth > scrollNodeWidth){
+                       // Scrolling should happen
+                       return {
+                               min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft,
+                               max: this.isLeftToRight() ?
+                                       (children[children.length-1].domNode.offsetLeft + domStyle.get(children[children.length-1].domNode, "width")) - scrollNodeWidth :
+                                       maxPossibleScroll
+                       };
                }else{
-                       if(dojo.isIE){
-                               var burl = dojo.config["dojoBlankHtmlUrl"] || (dojo.moduleUrl("dojo", "resources/blank.html")+"") || "javascript:\"\"";
-                               var html="<iframe src='" + burl + "'"
-                                       + " style='position: absolute; left: 0px; top: 0px;"
-                                       + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
-                               iframe = dojo.doc.createElement(html);
-                       }else{
-                               iframe = dojo.create("iframe");
-                               iframe.src = 'javascript:""';
-                               iframe.className = "dijitBackgroundIframe";
-                               dojo.style(iframe, "opacity", 0.1);
-                       }
-                       iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didnt work.
-                       dijit.setWaiRole(iframe,"presentation");
+                       // No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
+                       var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
+                       return {
+                               min: onlyScrollPosition,
+                               max: onlyScrollPosition
+                       };
                }
-               return iframe;
-       };
+       },
 
-       this.push = function(iframe){
-               iframe.style.display="none";
-               queue.push(iframe);
-       }
-}();
+       _getScrollForSelectedTab: function(){
+               // summary:
+               //              Returns the scroll value setting so that the selected tab
+               //              will appear in the center
+               var w = this.scrollNode,
+                       n = this._selectedTab,
+                       scrollNodeWidth = domStyle.get(this.scrollNode, "width"),
+                       scrollBounds = this._getScrollBounds();
 
+               // TODO: scroll minimal amount (to either right or left) so that
+               // selected tab is fully visible, and just return if it's already visible?
+               var pos = (n.offsetLeft + domStyle.get(n, "width")/2) - scrollNodeWidth/2;
+               pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
 
-dijit.BackgroundIframe = function(/* DomNode */node){
-       // summary:
-       //              For IE/FF z-index schenanigans. id attribute is required.
-       //
-       // description:
-       //              new dijit.BackgroundIframe(node)
-       //                      Makes a background iframe as a child of node, that fills
-       //                      area (and position) of node
-
-       if(!node.id){ throw new Error("no id"); }
-       if(dojo.isIE || dojo.isMoz){
-               var iframe = dijit._frames.pop();
-               node.appendChild(iframe);
-               if(dojo.isIE<7){
-                       this.resize(node);
-                       this._conn = dojo.connect(node, 'onresize', this, function(){
-                               this.resize(node);
-                       });
-               }else{
-                       dojo.style(iframe, {
-                               width: '100%',
-                               height: '100%'
-                       });
-               }
-               this.iframe = iframe;
-       }
-};
+               // TODO:
+               // If scrolling close to the left side or right side, scroll
+               // all the way to the left or right.  See this._minScroll.
+               // (But need to make sure that doesn't scroll the tab out of view...)
+               return pos;
+       },
 
-dojo.extend(dijit.BackgroundIframe, {
-       resize: function(node){
+       createSmoothScroll: function(x){
                // summary:
-               //              resize the iframe so its the same size as node
+               //              Creates a dojo._Animation object that smoothly scrolls the tab list
+               //              either to a fixed horizontal pixel value, or to the selected tab.
                // description:
-               //              this function is a no-op in all browsers except
-               //              IE6, which does not support 100% width/height 
-               //              of absolute positioned iframes
-               if(this.iframe && dojo.isIE<7){
-                       dojo.style(this.iframe, {
-                               width: node.offsetWidth + 'px',
-                               height: node.offsetHeight + 'px'
-                       });
+               //              If an number argument is passed to the function, that horizontal
+               //              pixel position is scrolled to.  Otherwise the currently selected
+               //              tab is scrolled to.
+               // x: Integer?
+               //              An optional pixel value to scroll to, indicating distance from left.
+
+               // Calculate position to scroll to
+               if(arguments.length > 0){
+                       // position specified by caller, just make sure it's within bounds
+                       var scrollBounds = this._getScrollBounds();
+                       x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
+               }else{
+                       // scroll to center the current tab
+                       x = this._getScrollForSelectedTab();
                }
+
+               if(this._anim && this._anim.status() == "playing"){
+                       this._anim.stop();
+               }
+
+               var self = this,
+                       w = this.scrollNode,
+                       anim = new fx.Animation({
+                               beforeBegin: function(){
+                                       if(this.curve){ delete this.curve; }
+                                       var oldS = w.scrollLeft,
+                                               newS = self._convertToScrollLeft(x);
+                                       anim.curve = new fx._Line(oldS, newS);
+                               },
+                               onAnimate: function(val){
+                                       w.scrollLeft = val;
+                               }
+                       });
+               this._anim = anim;
+
+               // Disable/enable left/right buttons according to new scroll position
+               this._setButtonClass(x);
+
+               return anim; // dojo._Animation
        },
-       destroy: function(){
+
+       _getBtnNode: function(/*Event*/ e){
                // summary:
-               //              destroy the iframe
-               if(this._conn){
-                       dojo.disconnect(this._conn);
-                       this._conn = null;
-               }
-               if(this.iframe){
-                       dijit._frames.push(this.iframe);
-                       delete this.iframe;
+               //              Gets a button DOM node from a mouse click event.
+               // e:
+               //              The mouse click event.
+               var n = e.target;
+               while(n && !domClass.contains(n, "tabStripButton")){
+                       n = n.parentNode;
                }
-       }
-});
+               return n;
+       },
 
-}
+       doSlideRight: function(/*Event*/ e){
+               // summary:
+               //              Scrolls the menu to the right.
+               // e:
+               //              The mouse click event.
+               this.doSlide(1, this._getBtnNode(e));
+       },
 
-if(!dojo._hasResource["dijit._base.scroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.scroll"] = true;
-dojo.provide("dijit._base.scroll");
+       doSlideLeft: function(/*Event*/ e){
+               // summary:
+               //              Scrolls the menu to the left.
+               // e:
+               //              The mouse click event.
+               this.doSlide(-1,this._getBtnNode(e));
+       },
 
+       doSlide: function(/*Number*/ direction, /*DomNode*/ node){
+               // summary:
+               //              Scrolls the tab list to the left or right by 75% of the widget width.
+               // direction:
+               //              If the direction is 1, the widget scrolls to the right, if it is
+               //              -1, it scrolls to the left.
 
+               if(node && domClass.contains(node, "dijitTabDisabled")){return;}
 
-dijit.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
-       // summary:
-       //              Scroll the passed node into view, if it is not already.
-       //              Deprecated, use `dojo.window.scrollIntoView` instead.
-       
-       dojo.window.scrollIntoView(node, pos);
-};
+               var sWidth = domStyle.get(this.scrollNode, "width");
+               var d = (sWidth * 0.75) * direction;
 
-}
+               var to = this._getScroll() + d;
 
-if(!dojo._hasResource["dojo.uacss"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.uacss"] = true;
-dojo.provide("dojo.uacss");
+               this._setButtonClass(to);
 
-(function(){
-       // summary:
-       //              Applies pre-set CSS classes to the top-level HTML node, based on:
-       //                      - browser (ex: dj_ie)
-       //                      - browser version (ex: dj_ie6)
-       //                      - box model (ex: dj_contentBox)
-       //                      - text direction (ex: dijitRtl)
-       //
-       //              In addition, browser, browser version, and box model are
-       //              combined with an RTL flag when browser text is RTL.  ex: dj_ie-rtl.
+               this.createSmoothScroll(to).play();
+       },
 
-       var d = dojo,
-               html = d.doc.documentElement,
-               ie = d.isIE,
-               opera = d.isOpera,
-               maj = Math.floor,
-               ff = d.isFF,
-               boxModel = d.boxModel.replace(/-/,''),
+       _setButtonClass: function(/*Number*/ scroll){
+               // summary:
+               //              Disables the left scroll button if the tabs are scrolled all the way to the left,
+               //              or the right scroll button in the opposite case.
+               // scroll: Integer
+               //              amount of horizontal scroll
 
-               classes = {
-                       dj_ie: ie,
-                       dj_ie6: maj(ie) == 6,
-                       dj_ie7: maj(ie) == 7,
-                       dj_ie8: maj(ie) == 8,
-                       dj_quirks: d.isQuirks,
-                       dj_iequirks: ie && d.isQuirks,
+               var scrollBounds = this._getScrollBounds();
+               this._leftBtn.set("disabled", scroll <= scrollBounds.min);
+               this._rightBtn.set("disabled", scroll >= scrollBounds.max);
+       }
+});
 
-                       // NOTE: Opera not supported by dijit
-                       dj_opera: opera,
 
-                       dj_khtml: d.isKhtml,
+var ScrollingTabControllerButtonMixin = declare("dijit.layout._ScrollingTabControllerButtonMixin", null, {
+       baseClass: "dijitTab tabStripButton",
 
-                       dj_webkit: d.isWebKit,
-                       dj_safari: d.isSafari,
-                       dj_chrome: d.isChrome,
+       templateString: buttonTemplate,
 
-                       dj_gecko: d.isMozilla,
-                       dj_ff3: maj(ff) == 3
-               }; // no dojo unsupported browsers
+               // Override inherited tabIndex: 0 from dijit.form.Button, because user shouldn't be
+               // able to tab to the left/right/menu buttons
+       tabIndex: "",
 
-       classes["dj_" + boxModel] = true;
+       // Similarly, override FormWidget.isFocusable() because clicking a button shouldn't focus it
+       // either (this override avoids focus() call in FormWidget.js)
+       isFocusable: function(){ return false; }
+});
+/*=====
+ScrollingTabControllerButtonMixin = dijit.layout._ScrollingTabControllerButtonMixin;
+=====*/
 
-       // apply browser, browser version, and box model class names
-       var classStr = "";
-       for(var clz in classes){
-               if(classes[clz]){
-                       classStr += clz + " ";
+// Class used in template
+declare("dijit.layout._ScrollingTabControllerButton",
+       [Button, ScrollingTabControllerButtonMixin]);
+
+// Class used in template
+declare(
+       "dijit.layout._ScrollingTabControllerMenuButton",
+       [Button, _HasDropDown, ScrollingTabControllerButtonMixin],
+{
+       // id of the TabContainer itself
+       containerId: "",
+
+       // -1 so user can't tab into the button, but so that button can still be focused programatically.
+       // Because need to move focus to the button (or somewhere) before the menu is hidden or IE6 will crash.
+       tabIndex: "-1",
+
+       isLoaded: function(){
+               // recreate menu every time, in case the TabContainer's list of children (or their icons/labels) have changed
+               return false;
+       },
+
+       loadDropDown: function(callback){
+               this.dropDown = new Menu({
+                       id: this.containerId + "_menu",
+                       dir: this.dir,
+                       lang: this.lang,
+                       textDir: this.textDir
+               });
+               var container = registry.byId(this.containerId);
+               array.forEach(container.getChildren(), function(page){
+                       var menuItem = new MenuItem({
+                               id: page.id + "_stcMi",
+                               label: page.title,
+                               iconClass: page.iconClass,
+                               dir: page.dir,
+                               lang: page.lang,
+                               textDir: page.textDir,
+                               onClick: function(){
+                                       container.selectChild(page);
+                               }
+                       });
+                       this.dropDown.addChild(menuItem);
+               }, this);
+               callback();
+       },
+
+       closeDropDown: function(/*Boolean*/ focus){
+               this.inherited(arguments);
+               if(this.dropDown){
+                       this.dropDown.destroyRecursive();
+                       delete this.dropDown;
                }
        }
-       html.className = d.trim(html.className + " " + classStr);
+});
 
-       // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
-       // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).  
-       // Unshift() is to run sniff code before the parser.
-       dojo._loaders.unshift(function(){
-               if(!dojo._isBodyLtr()){
-                       var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ")
-                       html.className = d.trim(html.className + " " + rtlClassStr);
-               }
-       });
-})();
+return ScrollingTabController;
+});
 
-}
+},
+'dijit/place':function(){
+define("dijit/place", [
+       "dojo/_base/array", // array.forEach array.map array.some
+       "dojo/dom-geometry", // domGeometry.getMarginBox domGeometry.position
+       "dojo/dom-style", // domStyle.getComputedStyle
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/window", // win.body
+       "dojo/window", // winUtils.getBox
+       "."     // dijit (defining dijit.place to match API doc)
+], function(array, domGeometry, domStyle, kernel, win, winUtils, dijit){
+
+       // module:
+       //              dijit/place
+       // summary:
+       //              Code to place a popup relative to another node
+
+
+       function _place(/*DomNode*/ node, choices, layoutNode, aroundNodeCoords){
+               // summary:
+               //              Given a list of spots to put node, put it at the first spot where it fits,
+               //              of if it doesn't fit anywhere then the place with the least overflow
+               // choices: Array
+               //              Array of elements like: {corner: 'TL', pos: {x: 10, y: 20} }
+               //              Above example says to put the top-left corner of the node at (10,20)
+               // layoutNode: Function(node, aroundNodeCorner, nodeCorner, size)
+               //              for things like tooltip, they are displayed differently (and have different dimensions)
+               //              based on their orientation relative to the parent.       This adjusts the popup based on orientation.
+               //              It also passes in the available size for the popup, which is useful for tooltips to
+               //              tell them that their width is limited to a certain amount.       layoutNode() may return a value expressing
+               //              how much the popup had to be modified to fit into the available space.   This is used to determine
+               //              what the best placement is.
+               // aroundNodeCoords: Object
+               //              Size of aroundNode, ex: {w: 200, h: 50}
+
+               // get {x: 10, y: 10, w: 100, h:100} type obj representing position of
+               // viewport over document
+               var view = winUtils.getBox();
+
+               // This won't work if the node is inside a <div style="position: relative">,
+               // so reattach it to win.doc.body.       (Otherwise, the positioning will be wrong
+               // and also it might get cutoff)
+               if(!node.parentNode || String(node.parentNode.tagName).toLowerCase() != "body"){
+                       win.body().appendChild(node);
+               }
+
+               var best = null;
+               array.some(choices, function(choice){
+                       var corner = choice.corner;
+                       var pos = choice.pos;
+                       var overflow = 0;
+
+                       // calculate amount of space available given specified position of node
+                       var spaceAvailable = {
+                               w: {
+                                       'L': view.l + view.w - pos.x,
+                                       'R': pos.x - view.l,
+                                       'M': view.w
+                                  }[corner.charAt(1)],
+                               h: {
+                                       'T': view.t + view.h - pos.y,
+                                       'B': pos.y - view.t,
+                                       'M': view.h
+                                  }[corner.charAt(0)]
+                       };
 
-if(!dojo._hasResource["dijit._base.sniff"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.sniff"] = true;
-// summary:
-//             Applies pre-set CSS classes to the top-level HTML node, see
-//             `dojo.uacss` for details.
-//
-//             Simply doing a require on this module will
-//             establish this CSS.  Modified version of Morris' CSS hack.
+                       // configure node to be displayed in given position relative to button
+                       // (need to do this in order to get an accurate size for the node, because
+                       // a tooltip's size changes based on position, due to triangle)
+                       if(layoutNode){
+                               var res = layoutNode(node, choice.aroundCorner, corner, spaceAvailable, aroundNodeCoords);
+                               overflow = typeof res == "undefined" ? 0 : res;
+                       }
 
-dojo.provide("dijit._base.sniff");
+                       // get node's size
+                       var style = node.style;
+                       var oldDisplay = style.display;
+                       var oldVis = style.visibility;
+                       if(style.display == "none"){
+                               style.visibility = "hidden";
+                               style.display = "";
+                       }
+                       var mb = domGeometry. getMarginBox(node);
+                       style.display = oldDisplay;
+                       style.visibility = oldVis;
+
+                       // coordinates and size of node with specified corner placed at pos,
+                       // and clipped by viewport
+                       var
+                               startXpos = {
+                                       'L': pos.x,
+                                       'R': pos.x - mb.w,
+                                       'M': Math.max(view.l, Math.min(view.l + view.w, pos.x + (mb.w >> 1)) - mb.w) // M orientation is more flexible
+                               }[corner.charAt(1)],
+                               startYpos = {
+                                       'T': pos.y,
+                                       'B': pos.y - mb.h,
+                                       'M': Math.max(view.t, Math.min(view.t + view.h, pos.y + (mb.h >> 1)) - mb.h)
+                               }[corner.charAt(0)],
+                               startX = Math.max(view.l, startXpos),
+                               startY = Math.max(view.t, startYpos),
+                               endX = Math.min(view.l + view.w, startXpos + mb.w),
+                               endY = Math.min(view.t + view.h, startYpos + mb.h),
+                               width = endX - startX,
+                               height = endY - startY;
+
+                       overflow += (mb.w - width) + (mb.h - height);
+
+                       if(best == null || overflow < best.overflow){
+                               best = {
+                                       corner: corner,
+                                       aroundCorner: choice.aroundCorner,
+                                       x: startX,
+                                       y: startY,
+                                       w: width,
+                                       h: height,
+                                       overflow: overflow,
+                                       spaceAvailable: spaceAvailable
+                               };
+                       }
 
+                       return !overflow;
+               });
 
+               // In case the best position is not the last one we checked, need to call
+               // layoutNode() again.
+               if(best.overflow && layoutNode){
+                       layoutNode(node, best.aroundCorner, best.corner, best.spaceAvailable, aroundNodeCoords);
+               }
 
-}
+               // And then position the node.  Do this last, after the layoutNode() above
+               // has sized the node, due to browser quirks when the viewport is scrolled
+               // (specifically that a Tooltip will shrink to fit as though the window was
+               // scrolled to the left).
+               //
+               // In RTL mode, set style.right rather than style.left so in the common case,
+               // window resizes move the popup along with the aroundNode.
+               var l = domGeometry.isBodyLtr(),
+                       s = node.style;
+               s.top = best.y + "px";
+               s[l ? "left" : "right"] = (l ? best.x : view.w - best.x - best.w) + "px";
+               s[l ? "right" : "left"] = "auto";       // needed for FF or else tooltip goes to far left
 
-if(!dojo._hasResource["dijit._base.typematic"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.typematic"] = true;
-dojo.provide("dijit._base.typematic");
+               return best;
+       }
 
-dijit.typematic = {
-       // summary:
-       //              These functions are used to repetitively call a user specified callback
-       //              method when a specific key or mouse click over a specific DOM node is
-       //              held down for a specific amount of time.
-       //              Only 1 such event is allowed to occur on the browser page at 1 time.
+       /*=====
+       dijit.place.__Position = function(){
+               // x: Integer
+               //              horizontal coordinate in pixels, relative to document body
+               // y: Integer
+               //              vertical coordinate in pixels, relative to document body
+
+               this.x = x;
+               this.y = y;
+       };
+       =====*/
 
-       _fireEventAndReload: function(){
-               this._timer = null;
-               this._callback(++this._count, this._node, this._evt);
-               
-               // Schedule next event, timer is at most minDelay (default 10ms) to avoid
-               // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
-               this._currentTimeout = Math.max(
-                       this._currentTimeout < 0 ? this._initialDelay :
-                               (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
-                       this._minDelay);
-               this._timer = setTimeout(dojo.hitch(this, "_fireEventAndReload"), this._currentTimeout);
-       },
+       /*=====
+       dijit.place.__Rectangle = function(){
+               // x: Integer
+               //              horizontal offset in pixels, relative to document body
+               // y: Integer
+               //              vertical offset in pixels, relative to document body
+               // w: Integer
+               //              width in pixels.   Can also be specified as "width" for backwards-compatibility.
+               // h: Integer
+               //              height in pixels.   Can also be specified as "height" from backwards-compatibility.
+
+               this.x = x;
+               this.y = y;
+               this.w = w;
+               this.h = h;
+       };
+       =====*/
 
-       trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+       return (dijit.place = {
                // summary:
-               //              Start a timed, repeating callback sequence.
-               //              If already started, the function call is ignored.
-               //              This method is not normally called by the user but can be
-               //              when the normal listener code is insufficient.
-               // evt:
-               //              key or mouse event object to pass to the user callback
-               // _this:
-               //              pointer to the user's widget space.
-               // node:
-               //              the DOM node object to pass the the callback function
-               // callback:
-               //              function to call until the sequence is stopped called with 3 parameters:
-               // count:
-               //              integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
-               // node:
-               //              the DOM node object passed in
-               // evt:
-               //              key or mouse event object
-               // obj:
-               //              user space object used to uniquely identify each typematic sequence
-               // subsequentDelay (optional):
-               //              if > 1, the number of milliseconds until the 3->n events occur
-               //              or else the fractional time multiplier for the next event's delay, default=0.9
-               // initialDelay (optional):
-               //              the number of milliseconds until the 2nd event occurs, default=500ms
-               // minDelay (optional):
-               //              the maximum delay in milliseconds for event to fire, default=10ms
-               if(obj != this._obj){
-                       this.stop();
-                       this._initialDelay = initialDelay || 500;
-                       this._subsequentDelay = subsequentDelay || 0.90;
-                       this._minDelay = minDelay || 10;
-                       this._obj = obj;
-                       this._evt = evt;
-                       this._node = node;
-                       this._currentTimeout = -1;
-                       this._count = -1;
-                       this._callback = dojo.hitch(_this, callback);
-                       this._fireEventAndReload();
-                       this._evt = dojo.mixin({faux: true}, evt);
-               }
-       },
-
-       stop: function(){
-               // summary:
-               //              Stop an ongoing timed, repeating callback sequence.
-               if(this._timer){
-                       clearTimeout(this._timer);
-                       this._timer = null;
-               }
-               if(this._obj){
-                       this._callback(-1, this._node, this._evt);
-                       this._obj = null;
-               }
-       },
-
-       addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
-               // summary:
-               //              Start listening for a specific typematic key.
-               //              See also the trigger method for other parameters.
-               // keyObject:
-               //              an object defining the key to listen for:
-               //              charOrCode:
-               //                      the printable character (string) or keyCode (number) to listen for.
-               //              keyCode:
-               //                      (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
-               //              charCode:
-               //                      (deprecated - use charOrCode) the charCode (number) to listen for.
-               //              ctrlKey:
-               //                      desired ctrl key state to initiate the callback sequence:
-               //                      - pressed (true)
-               //                      - released (false)
-               //                      - either (unspecified)
-               //              altKey:
-               //                      same as ctrlKey but for the alt key
-               //              shiftKey:
-               //                      same as ctrlKey but for the shift key
-               // returns:
-               //              an array of dojo.connect handles
-               if(keyObject.keyCode){
-                       keyObject.charOrCode = keyObject.keyCode;
-                       dojo.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
-               }else if(keyObject.charCode){
-                       keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
-                       dojo.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
-               }
-               return [
-                       dojo.connect(node, "onkeypress", this, function(evt){
-                               if(evt.charOrCode == keyObject.charOrCode &&
-                               (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
-                               (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
-                               (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
-                               (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
-                                       dojo.stopEvent(evt);
-                                       dijit.typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
-                               }else if(dijit.typematic._obj == keyObject){
-                                       dijit.typematic.stop();
-                               }
-                       }),
-                       dojo.connect(node, "onkeyup", this, function(evt){
-                               if(dijit.typematic._obj == keyObject){
-                                       dijit.typematic.stop();
-                               }
-                       })
-               ];
-       },
+               //              Code to place a DOMNode relative to another DOMNode.
+               //              Load using require(["dijit/place"], function(place){ ... }).
 
-       addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
-               // summary:
-               //              Start listening for a typematic mouse click.
-               //              See the trigger method for other parameters.
-               // returns:
-               //              an array of dojo.connect handles
-               var dc = dojo.connect;
-               return [
-                       dc(node, "mousedown", this, function(evt){
-                               dojo.stopEvent(evt);
-                               dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
-                       }),
-                       dc(node, "mouseup", this, function(evt){
-                               dojo.stopEvent(evt);
-                               dijit.typematic.stop();
-                       }),
-                       dc(node, "mouseout", this, function(evt){
-                               dojo.stopEvent(evt);
-                               dijit.typematic.stop();
-                       }),
-                       dc(node, "mousemove", this, function(evt){
-                               evt.preventDefault();
-                       }),
-                       dc(node, "dblclick", this, function(evt){
-                               dojo.stopEvent(evt);
-                               if(dojo.isIE){
-                                       dijit.typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
-                                       setTimeout(dojo.hitch(this, dijit.typematic.stop), 50);
+               at: function(node, pos, corners, padding){
+                       // summary:
+                       //              Positions one of the node's corners at specified position
+                       //              such that node is fully visible in viewport.
+                       // description:
+                       //              NOTE: node is assumed to be absolutely or relatively positioned.
+                       // node: DOMNode
+                       //              The node to position
+                       // pos: dijit.place.__Position
+                       //              Object like {x: 10, y: 20}
+                       // corners: String[]
+                       //              Array of Strings representing order to try corners in, like ["TR", "BL"].
+                       //              Possible values are:
+                       //                      * "BL" - bottom left
+                       //                      * "BR" - bottom right
+                       //                      * "TL" - top left
+                       //                      * "TR" - top right
+                       // padding: dijit.place.__Position?
+                       //              optional param to set padding, to put some buffer around the element you want to position.
+                       // example:
+                       //              Try to place node's top right corner at (10,20).
+                       //              If that makes node go (partially) off screen, then try placing
+                       //              bottom left corner at (10,20).
+                       //      |       place(node, {x: 10, y: 20}, ["TR", "BL"])
+                       var choices = array.map(corners, function(corner){
+                               var c = { corner: corner, pos: {x:pos.x,y:pos.y} };
+                               if(padding){
+                                       c.pos.x += corner.charAt(1) == 'L' ? padding.x : -padding.x;
+                                       c.pos.y += corner.charAt(0) == 'T' ? padding.y : -padding.y;
                                }
-                       })
-               ];
-       },
-
-       addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
-               // summary:
-               //              Start listening for a specific typematic key and mouseclick.
-               //              This is a thin wrapper to addKeyListener and addMouseListener.
-               //              See the addMouseListener and addKeyListener methods for other parameters.
-               // mouseNode:
-               //              the DOM node object to listen on for mouse events.
-               // keyNode:
-               //              the DOM node object to listen on for key events.
-               // returns:
-               //              an array of dojo.connect handles
-               return this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay).concat(
-                       this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay));
-       }
-};
-
-}
-
-if(!dojo._hasResource["dijit._base.wai"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base.wai"] = true;
-dojo.provide("dijit._base.wai");
-
-dijit.wai = {
-       onload: function(){
-               // summary:
-               //              Detects if we are in high-contrast mode or not
-
-               // This must be a named function and not an anonymous
-               // function, so that the widget parsing code can make sure it
-               // registers its onload function after this function.
-               // DO NOT USE "this" within this function.
-
-               // create div for testing if high contrast mode is on or images are turned off
-               var div = dojo.create("div",{
-                       id: "a11yTestNode",
-                       style:{
-                               cssText:'border: 1px solid;'
-                                       + 'border-color:red green;'
-                                       + 'position: absolute;'
-                                       + 'height: 5px;'
-                                       + 'top: -999px;'
-                                       + 'background-image: url("' + (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")) + '");'
-                       }
-               }, dojo.body());
-
-               // test it
-               var cs = dojo.getComputedStyle(div);
-               if(cs){
-                       var bkImg = cs.backgroundImage;
-                       var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
-                       dojo[needsA11y ? "addClass" : "removeClass"](dojo.body(), "dijit_a11y");
-                       if(dojo.isIE){
-                               div.outerHTML = "";             // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
-                       }else{
-                               dojo.body().removeChild(div);
-                       }
-               }
-       }
-};
-
-// Test if computer is in high contrast mode.
-// Make sure the a11y test runs first, before widgets are instantiated.
-if(dojo.isIE || dojo.isMoz){   // NOTE: checking in Safari messes things up
-       dojo._loaders.unshift(dijit.wai.onload);
-}
+                               return c;
+                       });
 
-dojo.mixin(dijit, {
-       _XhtmlRoles: /banner|contentinfo|definition|main|navigation|search|note|secondary|seealso/,
+                       return _place(node, choices);
+               },
 
-       hasWaiRole: function(/*Element*/ elem, /*String*/ role){
-               // summary:
-               //              Determines if an element has a particular non-XHTML role.
-               // returns:
-               //              True if elem has the specific non-XHTML role attribute and false if not.
-               //              For backwards compatibility if role parameter not provided,
-               //              returns true if has non XHTML role
-               var waiRole = this.getWaiRole(elem);
-               return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
-       },
+               around: function(
+                       /*DomNode*/             node,
+                       /*DomNode || dijit.place.__Rectangle*/ anchor,
+                       /*String[]*/    positions,
+                       /*Boolean*/             leftToRight,
+                       /*Function?*/   layoutNode){
 
-       getWaiRole: function(/*Element*/ elem){
-               // summary:
-               //              Gets the non-XHTML role for an element (which should be a wai role).
-               // returns:
-               //              The non-XHTML role of elem or an empty string if elem
-               //              does not have a role.
-                return dojo.trim((dojo.attr(elem, "role") || "").replace(this._XhtmlRoles,"").replace("wairole:",""));
-       },
+                       // summary:
+                       //              Position node adjacent or kitty-corner to anchor
+                       //              such that it's fully visible in viewport.
+                       //
+                       // description:
+                       //              Place node such that corner of node touches a corner of
+                       //              aroundNode, and that node is fully visible.
+                       //
+                       // anchor:
+                       //              Either a DOMNode or a __Rectangle (object with x, y, width, height).
+                       //
+                       // positions:
+                       //              Ordered list of positions to try matching up.
+                       //                      * before: places drop down to the left of the anchor node/widget, or to the right in the case
+                       //                              of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
+                       //                              with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
+                       //                      * after: places drop down to the right of the anchor node/widget, or to the left in the case
+                       //                              of RTL scripts like Hebrew and Arabic; aligns either the top of the drop down
+                       //                              with the top of the anchor, or the bottom of the drop down with bottom of the anchor.
+                       //                      * before-centered: centers drop down to the left of the anchor node/widget, or to the right
+                       //                               in the case of RTL scripts like Hebrew and Arabic
+                       //                      * after-centered: centers drop down to the right of the anchor node/widget, or to the left
+                       //                               in the case of RTL scripts like Hebrew and Arabic
+                       //                      * above-centered: drop down is centered above anchor node
+                       //                      * above: drop down goes above anchor node, left sides aligned
+                       //                      * above-alt: drop down goes above anchor node, right sides aligned
+                       //                      * below-centered: drop down is centered above anchor node
+                       //                      * below: drop down goes below anchor node
+                       //                      * below-alt: drop down goes below anchor node, right sides aligned
+                       //
+                       // layoutNode: Function(node, aroundNodeCorner, nodeCorner)
+                       //              For things like tooltip, they are displayed differently (and have different dimensions)
+                       //              based on their orientation relative to the parent.       This adjusts the popup based on orientation.
+                       //
+                       // leftToRight:
+                       //              True if widget is LTR, false if widget is RTL.   Affects the behavior of "above" and "below"
+                       //              positions slightly.
+                       //
+                       // example:
+                       //      |       placeAroundNode(node, aroundNode, {'BL':'TL', 'TR':'BR'});
+                       //              This will try to position node such that node's top-left corner is at the same position
+                       //              as the bottom left corner of the aroundNode (ie, put node below
+                       //              aroundNode, with left edges aligned).   If that fails it will try to put
+                       //              the bottom-right corner of node where the top right corner of aroundNode is
+                       //              (ie, put node above aroundNode, with right edges aligned)
+                       //
 
-       setWaiRole: function(/*Element*/ elem, /*String*/ role){
-               // summary:
-               //              Sets the role on an element.
-               // description:
-               //              Replace existing role attribute with new role.
-               //              If elem already has an XHTML role, append this role to XHTML role
-               //              and remove other ARIA roles.
+                       // if around is a DOMNode (or DOMNode id), convert to coordinates
+                       var aroundNodePos = (typeof anchor == "string" || "offsetWidth" in anchor)
+                               ? domGeometry.position(anchor, true)
+                               : anchor;
+
+                       // Adjust anchor positioning for the case that a parent node has overflw hidden, therefore cuasing the anchor not to be completely visible
+                       if(anchor.parentNode){
+                               var parent = anchor.parentNode;
+                               while(parent && parent.nodeType == 1 && parent.nodeName != "BODY"){  //ignoring the body will help performance
+                                       var parentPos = domGeometry.position(parent, true);
+                                       var parentStyleOverflow = domStyle.getComputedStyle(parent).overflow;
+                                       if(parentStyleOverflow == "hidden" || parentStyleOverflow == "auto" || parentStyleOverflow == "scroll"){
+                                               var bottomYCoord = Math.min(aroundNodePos.y + aroundNodePos.h, parentPos.y + parentPos.h);
+                                               var rightXCoord = Math.min(aroundNodePos.x + aroundNodePos.w, parentPos.x + parentPos.w);
+                                               aroundNodePos.x = Math.max(aroundNodePos.x, parentPos.x);
+                                               aroundNodePos.y = Math.max(aroundNodePos.y, parentPos.y);
+                                               aroundNodePos.h = bottomYCoord - aroundNodePos.y;
+                                               aroundNodePos.w = rightXCoord - aroundNodePos.x;
+                                       }       
+                                       parent = parent.parentNode;
+                               }
+                       }                       
 
-               var curRole = dojo.attr(elem, "role") || "";
-               if(!this._XhtmlRoles.test(curRole)){
-                       dojo.attr(elem, "role", role);
-               }else{
-                       if((" "+ curRole +" ").indexOf(" " + role + " ") < 0){
-                               var clearXhtml = dojo.trim(curRole.replace(this._XhtmlRoles, ""));
-                               var cleanRole = dojo.trim(curRole.replace(clearXhtml, ""));
-                               dojo.attr(elem, "role", cleanRole + (cleanRole ? ' ' : '') + role);
+                       var x = aroundNodePos.x,
+                               y = aroundNodePos.y,
+                               width = "w" in aroundNodePos ? aroundNodePos.w : (aroundNodePos.w = aroundNodePos.width),
+                               height = "h" in aroundNodePos ? aroundNodePos.h : (kernel.deprecated("place.around: dijit.place.__Rectangle: { x:"+x+", y:"+y+", height:"+aroundNodePos.height+", width:"+width+" } has been deprecated.  Please use { x:"+x+", y:"+y+", h:"+aroundNodePos.height+", w:"+width+" }", "", "2.0"), aroundNodePos.h = aroundNodePos.height);
+
+                       // Convert positions arguments into choices argument for _place()
+                       var choices = [];
+                       function push(aroundCorner, corner){
+                               choices.push({
+                                       aroundCorner: aroundCorner,
+                                       corner: corner,
+                                       pos: {
+                                               x: {
+                                                       'L': x,
+                                                       'R': x + width,
+                                                       'M': x + (width >> 1)
+                                                  }[aroundCorner.charAt(1)],
+                                               y: {
+                                                       'T': y,
+                                                       'B': y + height,
+                                                       'M': y + (height >> 1)
+                                                  }[aroundCorner.charAt(0)]
+                                       }
+                               })
                        }
-               }
-       },
+                       array.forEach(positions, function(pos){
+                               var ltr =  leftToRight;
+                               switch(pos){
+                                       case "above-centered":
+                                               push("TM", "BM");
+                                               break;
+                                       case "below-centered":
+                                               push("BM", "TM");
+                                               break;
+                                       case "after-centered":
+                                               ltr = !ltr;
+                                               // fall through
+                                       case "before-centered":
+                                               push(ltr ? "ML" : "MR", ltr ? "MR" : "ML");
+                                               break;
+                                       case "after":
+                                               ltr = !ltr;
+                                               // fall through
+                                       case "before":
+                                               push(ltr ? "TL" : "TR", ltr ? "TR" : "TL");
+                                               push(ltr ? "BL" : "BR", ltr ? "BR" : "BL");
+                                               break;
+                                       case "below-alt":
+                                               ltr = !ltr;
+                                               // fall through
+                                       case "below":
+                                               // first try to align left borders, next try to align right borders (or reverse for RTL mode)
+                                               push(ltr ? "BL" : "BR", ltr ? "TL" : "TR");
+                                               push(ltr ? "BR" : "BL", ltr ? "TR" : "TL");
+                                               break;
+                                       case "above-alt":
+                                               ltr = !ltr;
+                                               // fall through
+                                       case "above":
+                                               // first try to align left borders, next try to align right borders (or reverse for RTL mode)
+                                               push(ltr ? "TL" : "TR", ltr ? "BL" : "BR");
+                                               push(ltr ? "TR" : "TL", ltr ? "BR" : "BL");
+                                               break;
+                                       default:
+                                               // To assist dijit/_base/place, accept arguments of type {aroundCorner: "BL", corner: "TL"}.
+                                               // Not meant to be used directly.
+                                               push(pos.aroundCorner, pos.corner);
+                               }
+                       });
 
-       removeWaiRole: function(/*Element*/ elem, /*String*/ role){
-               // summary:
-               //              Removes the specified non-XHTML role from an element.
-               //              Removes role attribute if no specific role provided (for backwards compat.)
+                       var position = _place(node, choices, layoutNode, {w: width, h: height});
+                       position.aroundNodePos = aroundNodePos;
 
-               var roleValue = dojo.attr(elem, "role");
-               if(!roleValue){ return; }
-               if(role){
-                       var t = dojo.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
-                       dojo.attr(elem, "role", t);
-               }else{
-                       elem.removeAttribute("role");
+                       return position;
                }
-       },
-
-       hasWaiState: function(/*Element*/ elem, /*String*/ state){
-               // summary:
-               //              Determines if an element has a given state.
-               // description:
-               //              Checks for an attribute called "aria-"+state.
-               // returns:
-               //              true if elem has a value for the given state and
-               //              false if it does not.
-
-               return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
-       },
-
-       getWaiState: function(/*Element*/ elem, /*String*/ state){
-               // summary:
-               //              Gets the value of a state on an element.
-               // description:
-               //              Checks for an attribute called "aria-"+state.
-               // returns:
-               //              The value of the requested state on elem
-               //              or an empty string if elem has no value for state.
-
-               return elem.getAttribute("aria-"+state) || "";
-       },
-
-       setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
-               // summary:
-               //              Sets a state on an element.
-               // description:
-               //              Sets an attribute called "aria-"+state.
-
-               elem.setAttribute("aria-"+state, value);
-       },
-
-       removeWaiState: function(/*Element*/ elem, /*String*/ state){
-               // summary:
-               //              Removes a state from an element.
-               // description:
-               //              Sets an attribute called "aria-"+state.
-
-               elem.removeAttribute("aria-"+state);
-       }
+       });
 });
 
-}
-
-if(!dojo._hasResource["dijit._base"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._base"] = true;
-dojo.provide("dijit._base");
+},
+'dijit/_HasDropDown':function(){
+define("dijit/_HasDropDown", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred",
+       "dojo/_base/event", // event.stop
+       "dojo/dom", // dom.isDescendant
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-class", // domClass.add domClass.contains domClass.remove
+       "dojo/dom-geometry", // domGeometry.marginBox domGeometry.position
+       "dojo/dom-style", // domStyle.set
+       "dojo/has",
+       "dojo/keys", // keys.DOWN_ARROW keys.ENTER keys.ESCAPE
+       "dojo/_base/lang", // lang.hitch lang.isFunction
+       "dojo/touch",
+       "dojo/_base/window", // win.doc
+       "dojo/window", // winUtils.getBox
+       "./registry",   // registry.byNode()
+       "./focus",
+       "./popup",
+       "./_FocusMixin"
+], function(declare, Deferred, event,dom, domAttr, domClass, domGeometry, domStyle, has, keys, lang, touch,
+                       win, winUtils, registry, focus, popup, _FocusMixin){
 
+/*=====
+       var _FocusMixin = dijit._FocusMixin;
+=====*/
 
+       // module:
+       //              dijit/_HasDropDown
+       // summary:
+       //              Mixin for widgets that need drop down ability.
 
+       return declare("dijit._HasDropDown", _FocusMixin, {
+               // summary:
+               //              Mixin for widgets that need drop down ability.
 
+               // _buttonNode: [protected] DomNode
+               //              The button/icon/node to click to display the drop down.
+               //              Can be set via a data-dojo-attach-point assignment.
+               //              If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
+               _buttonNode: null,
 
+               // _arrowWrapperNode: [protected] DomNode
+               //              Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
+               //              on where the drop down is set to be positioned.
+               //              Can be set via a data-dojo-attach-point assignment.
+               //              If missing, then _buttonNode will be used.
+               _arrowWrapperNode: null,
 
+               // _popupStateNode: [protected] DomNode
+               //              The node to set the popupActive class on.
+               //              Can be set via a data-dojo-attach-point assignment.
+               //              If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
+               _popupStateNode: null,
 
+               // _aroundNode: [protected] DomNode
+               //              The node to display the popup around.
+               //              Can be set via a data-dojo-attach-point assignment.
+               //              If missing, then domNode will be used.
+               _aroundNode: null,
 
+               // dropDown: [protected] Widget
+               //              The widget to display as a popup.  This widget *must* be
+               //              defined before the startup function is called.
+               dropDown: null,
 
+               // autoWidth: [protected] Boolean
+               //              Set to true to make the drop down at least as wide as this
+               //              widget.  Set to false if the drop down should just be its
+               //              default width
+               autoWidth: true,
 
+               // forceWidth: [protected] Boolean
+               //              Set to true to make the drop down exactly as wide as this
+               //              widget.  Overrides autoWidth.
+               forceWidth: false,
 
-}
+               // maxHeight: [protected] Integer
+               //              The max height for our dropdown.
+               //              Any dropdown taller than this will have scrollbars.
+               //              Set to 0 for no max height, or -1 to limit height to available space in viewport
+               maxHeight: 0,
 
-if(!dojo._hasResource["dijit._Widget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._Widget"] = true;
-dojo.provide("dijit._Widget");
+               // dropDownPosition: [const] String[]
+               //              This variable controls the position of the drop down.
+               //              It's an array of strings with the following values:
+               //
+               //                      * before: places drop down to the left of the target node/widget, or to the right in
+               //                        the case of RTL scripts like Hebrew and Arabic
+               //                      * after: places drop down to the right of the target node/widget, or to the left in
+               //                        the case of RTL scripts like Hebrew and Arabic
+               //                      * above: drop down goes above target node
+               //                      * below: drop down goes below target node
+               //
+               //              The list is positions is tried, in order, until a position is found where the drop down fits
+               //              within the viewport.
+               //
+               dropDownPosition: ["below","above"],
 
-dojo.require( "dijit._base" );
+               // _stopClickEvents: Boolean
+               //              When set to false, the click events will not be stopped, in
+               //              case you want to use them in your subwidget
+               _stopClickEvents: true,
 
+               _onDropDownMouseDown: function(/*Event*/ e){
+                       // summary:
+                       //              Callback when the user mousedown's on the arrow icon
+                       if(this.disabled || this.readOnly){ return; }
 
-// This code is to assist deferring dojo.connect() calls in widgets (connecting to events on the widgets'
-// DOM nodes) until someone actually needs to monitor that event.
-dojo.connect(dojo, "_connect",
-       function(/*dijit._Widget*/ widget, /*String*/ event){
-               if(widget && dojo.isFunction(widget._onConnect)){
-                       widget._onConnect(event);
-               }
-       });
+                       // Prevent default to stop things like text selection, but don't stop propogation, so that:
+                       //              1. TimeTextBox etc. can focusthe <input> on mousedown
+                       //              2. dropDownButtonActive class applied by _CssStateMixin (on button depress)
+                       //              3. user defined onMouseDown handler fires
+                       e.preventDefault();
 
-dijit._connectOnUseEventHandler = function(/*Event*/ event){};
-
-// Keep track of where the last keydown event was, to help avoid generating
-// spurious ondijitclick events when:
-// 1. focus is on a <button> or <a>
-// 2. user presses then releases the ENTER key
-// 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
-// 4. onkeyup event fires, causing the ondijitclick handler to fire
-dijit._lastKeyDownNode = null;
-if(dojo.isIE){
-       (function(){
-               var keydownCallback = function(evt){
-                       dijit._lastKeyDownNode = evt.srcElement;
-               };
-               dojo.doc.attachEvent('onkeydown', keydownCallback);
-               dojo.addOnWindowUnload(function(){
-                       dojo.doc.detachEvent('onkeydown', keydownCallback);
-               });
-       })();
-}else{
-       dojo.doc.addEventListener('keydown', function(evt){
-               dijit._lastKeyDownNode = evt.target;
-       }, true);
-}
+                       this._docHandler = this.connect(win.doc, touch.release, "_onDropDownMouseUp");
 
-(function(){
+                       this.toggleDropDown();
+               },
 
-var _attrReg = {},     // cached results from getSetterAttributes
-       getSetterAttributes = function(widget){
-               // summary:
-               //              Returns list of attributes with custom setters for specified widget
-               var dc = widget.declaredClass;
-               if(!_attrReg[dc]){
-                       var r = [],
-                               attrs,
-                               proto = widget.constructor.prototype;
-                       for(var fxName in proto){
-                               if(dojo.isFunction(proto[fxName]) && (attrs = fxName.match(/^_set([a-zA-Z]*)Attr$/)) && attrs[1]){
-                                       r.push(attrs[1].charAt(0).toLowerCase() + attrs[1].substr(1));
-                               }
+               _onDropDownMouseUp: function(/*Event?*/ e){
+                       // summary:
+                       //              Callback when the user lifts their mouse after mouse down on the arrow icon.
+                       //              If the drop down is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
+                       //              drop down widget.  If the event is missing, then we are not
+                       //              a mouseup event.
+                       //
+                       //              This is useful for the common mouse movement pattern
+                       //              with native browser <select> nodes:
+                       //                      1. mouse down on the select node (probably on the arrow)
+                       //                      2. move mouse to a menu item while holding down the mouse button
+                       //                      3. mouse up.  this selects the menu item as though the user had clicked it.
+                       if(e && this._docHandler){
+                               this.disconnect(this._docHandler);
                        }
-                       _attrReg[dc] = r;
-               }
-               return _attrReg[dc] || [];      // String[]
-       };
+                       var dropDown = this.dropDown, overMenu = false;
 
-dojo.declare("dijit._Widget", null, {
-       // summary:
-       //              Base class for all Dijit widgets.
+                       if(e && this._opened){
+                               // This code deals with the corner-case when the drop down covers the original widget,
+                               // because it's so large.  In that case mouse-up shouldn't select a value from the menu.
+                               // Find out if our target is somewhere in our dropdown widget,
+                               // but not over our _buttonNode (the clickable node)
+                               var c = domGeometry.position(this._buttonNode, true);
+                               if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
+                                       !(e.pageY >= c.y && e.pageY <= c.y + c.h)){
+                                       var t = e.target;
+                                       while(t && !overMenu){
+                                               if(domClass.contains(t, "dijitPopup")){
+                                                       overMenu = true;
+                                               }else{
+                                                       t = t.parentNode;
+                                               }
+                                       }
+                                       if(overMenu){
+                                               t = e.target;
+                                               if(dropDown.onItemClick){
+                                                       var menuItem;
+                                                       while(t && !(menuItem = registry.byNode(t))){
+                                                               t = t.parentNode;
+                                                       }
+                                                       if(menuItem && menuItem.onClick && menuItem.getParent){
+                                                               menuItem.getParent().onItemClick(menuItem, e);
+                                                       }
+                                               }
+                                               return;
+                                       }
+                               }
+                       }
+                       if(this._opened){
+                               if(dropDown.focus && dropDown.autoFocus !== false){
+                                       // Focus the dropdown widget - do it on a delay so that we
+                                       // don't steal our own focus.
+                                       window.setTimeout(lang.hitch(dropDown, "focus"), 1);
+                               }
+                       }else{
+                               // The drop down arrow icon probably can't receive focus, but widget itself should get focus.
+                               // setTimeout() needed to make it work on IE (test DateTextBox)
+                               setTimeout(lang.hitch(this, "focus"), 0);
+                       }
 
-       // id: [const] String
-       //              A unique, opaque ID string that can be assigned by users or by the
-       //              system. If the developer passes an ID which is known not to be
-       //              unique, the specified ID is ignored and the system-generated ID is
-       //              used instead.
-       id: "",
+                       if(has("ios")){
+                               this._justGotMouseUp = true;
+                               setTimeout(lang.hitch(this, function(){
+                                       this._justGotMouseUp = false;
+                               }), 0);
+                       }
+               },
 
-       // lang: [const] String
-       //              Rarely used.  Overrides the default Dojo locale used to render this widget,
-       //              as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
-       //              Value must be among the list of locales specified during by the Dojo bootstrap,
-       //              formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
-       lang: "",
+               _onDropDownClick: function(/*Event*/ e){
+                       if(has("ios") && !this._justGotMouseUp){
+                               // This branch fires on iPhone for ComboBox, because the button node is an <input> and doesn't
+                               // generate touchstart/touchend events.   Pretend we just got a mouse down / mouse up.
+                               // The if(has("ios") is necessary since IE and desktop safari get spurious onclick events
+                               // when there are nested tables (specifically, clicking on a table that holds a dijit.form.Select,
+                               // but not on the Select itself, causes an onclick event on the Select)
+                               this._onDropDownMouseDown(e);
+                               this._onDropDownMouseUp(e);
+                       }
 
-       // dir: [const] String
-       //              Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
-       //              attribute. Either left-to-right "ltr" or right-to-left "rtl".  If undefined, widgets renders in page's
-       //              default direction.
-       dir: "",
+                       // The drop down was already opened on mousedown/keydown; just need to call stopEvent().
+                       if(this._stopClickEvents){
+                               event.stop(e);
+                       }
+               },
 
-       // class: String
-       //              HTML class attribute
-       "class": "",
+               buildRendering: function(){
+                       this.inherited(arguments);
 
-       // style: String||Object
-       //              HTML style attributes as cssText string or name/value hash
-       style: "",
+                       this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
+                       this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
 
-       // title: String
-       //              HTML title attribute.
-       //
-       //              For form widgets this specifies a tooltip to display when hovering over
-       //              the widget (just like the native HTML title attribute).
-       //
-       //              For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
-       //              etc., it's used to specify the tab label, accordion pane title, etc.
-       title: "",
+                       // Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
+                       // based on where drop down will normally appear
+                       var defaultPos = {
+                                       "after" : this.isLeftToRight() ? "Right" : "Left",
+                                       "before" : this.isLeftToRight() ? "Left" : "Right",
+                                       "above" : "Up",
+                                       "below" : "Down",
+                                       "left" : "Left",
+                                       "right" : "Right"
+                       }[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
+                       domClass.add(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
+               },
 
-       // tooltip: String
-       //              When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
-       //              this specifies the tooltip to appear when the mouse is hovered over that text.
-       tooltip: "",
+               postCreate: function(){
+                       // summary:
+                       //              set up nodes and connect our mouse and keypress events
 
-       // baseClass: [protected] String
-       //              Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
-       //              widget state.
-       baseClass: "",
+                       this.inherited(arguments);
 
-       // srcNodeRef: [readonly] DomNode
-       //              pointer to original DOM node
-       srcNodeRef: null,
+                       this.connect(this._buttonNode, touch.press, "_onDropDownMouseDown");
+                       this.connect(this._buttonNode, "onclick", "_onDropDownClick");
+                       this.connect(this.focusNode, "onkeypress", "_onKey");
+                       this.connect(this.focusNode, "onkeyup", "_onKeyUp");
+               },
 
-       // domNode: [readonly] DomNode
-       //              This is our visible representation of the widget! Other DOM
-       //              Nodes may by assigned to other properties, usually through the
-       //              template system's dojoAttachPoint syntax, but the domNode
-       //              property is the canonical "top level" node in widget UI.
-       domNode: null,
+               destroy: function(){
+                       if(this.dropDown){
+                               // Destroy the drop down, unless it's already been destroyed.  This can happen because
+                               // the drop down is a direct child of <body> even though it's logically my child.
+                               if(!this.dropDown._destroyed){
+                                       this.dropDown.destroyRecursive();
+                               }
+                               delete this.dropDown;
+                       }
+                       this.inherited(arguments);
+               },
 
-       // containerNode: [readonly] DomNode
-       //              Designates where children of the source DOM node will be placed.
-       //              "Children" in this case refers to both DOM nodes and widgets.
-       //              For example, for myWidget:
-       //
-       //              |       <div dojoType=myWidget>
-       //              |               <b> here's a plain DOM node
-       //              |               <span dojoType=subWidget>and a widget</span>
-       //              |               <i> and another plain DOM node </i>
-       //              |       </div>
-       //
-       //              containerNode would point to:
-       //
-       //              |               <b> here's a plain DOM node
-       //              |               <span dojoType=subWidget>and a widget</span>
-       //              |               <i> and another plain DOM node </i>
-       //
-       //              In templated widgets, "containerNode" is set via a
-       //              dojoAttachPoint assignment.
-       //
-       //              containerNode must be defined for any widget that accepts innerHTML
-       //              (like ContentPane or BorderContainer or even Button), and conversely
-       //              is null for widgets that don't, like TextBox.
-       containerNode: null,
+               _onKey: function(/*Event*/ e){
+                       // summary:
+                       //              Callback when the user presses a key while focused on the button node
 
-/*=====
-       // _started: Boolean
-       //              startup() has completed.
-       _started: false,
-=====*/
+                       if(this.disabled || this.readOnly){ return; }
 
-       // attributeMap: [protected] Object
-       //              attributeMap sets up a "binding" between attributes (aka properties)
-       //              of the widget and the widget's DOM.
-       //              Changes to widget attributes listed in attributeMap will be
-       //              reflected into the DOM.
-       //
-       //              For example, calling attr('title', 'hello')
-       //              on a TitlePane will automatically cause the TitlePane's DOM to update
-       //              with the new title.
-       //
-       //              attributeMap is a hash where the key is an attribute of the widget,
-       //              and the value reflects a binding to a:
-       //
-       //              - DOM node attribute
-       // |            focus: {node: "focusNode", type: "attribute"}
-       //              Maps this.focus to this.focusNode.focus
-       //
-       //              - DOM node innerHTML
-       //      |               title: { node: "titleNode", type: "innerHTML" }
-       //              Maps this.title to this.titleNode.innerHTML
-       //
-       //              - DOM node innerText
-       //      |               title: { node: "titleNode", type: "innerText" }
-       //              Maps this.title to this.titleNode.innerText
-       //
-       //              - DOM node CSS class
-       // |            myClass: { node: "domNode", type: "class" }
-       //              Maps this.myClass to this.domNode.className
-       //
-       //              If the value is an array, then each element in the array matches one of the
-       //              formats of the above list.
-       //
-       //              There are also some shorthands for backwards compatibility:
-       //              - string --> { node: string, type: "attribute" }, for example:
-       //      |       "focusNode" ---> { node: "focusNode", type: "attribute" }
-       //              - "" --> { node: "domNode", type: "attribute" }
-       attributeMap: {id:"", dir:"", lang:"", "class":"", style:"", title:""},
-
-       // _deferredConnects: [protected] Object
-       //              attributeMap addendum for event handlers that should be connected only on first use
-       _deferredConnects: {
-               onClick: "",
-               onDblClick: "",
-               onKeyDown: "",
-               onKeyPress: "",
-               onKeyUp: "",
-               onMouseMove: "",
-               onMouseDown: "",
-               onMouseOut: "",
-               onMouseOver: "",
-               onMouseLeave: "",
-               onMouseEnter: "",
-               onMouseUp: ""
-       },
-
-       onClick: dijit._connectOnUseEventHandler,
-       /*=====
-       onClick: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of mouse click events.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onDblClick: dijit._connectOnUseEventHandler,
-       /*=====
-       onDblClick: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of mouse double click events.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onKeyDown: dijit._connectOnUseEventHandler,
-       /*=====
-       onKeyDown: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of keys being pressed down.
-               // event:
-               //              key Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onKeyPress: dijit._connectOnUseEventHandler,
-       /*=====
-       onKeyPress: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of printable keys being typed.
-               // event:
-               //              key Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onKeyUp: dijit._connectOnUseEventHandler,
-       /*=====
-       onKeyUp: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of keys being released.
-               // event:
-               //              key Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseDown: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseDown: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse button is pressed down.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseMove: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseMove: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseOut: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseOut: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseOver: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseOver: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseLeave: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseLeave: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse moves off of this widget.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseEnter: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseEnter: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse moves onto this widget.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
-       onMouseUp: dijit._connectOnUseEventHandler,
-       /*=====
-       onMouseUp: function(event){
-               // summary:
-               //              Connect to this function to receive notifications of when the mouse button is released.
-               // event:
-               //              mouse Event
-               // tags:
-               //              callback
-       },
-       =====*/
+                       var d = this.dropDown, target = e.target;
+                       if(d && this._opened && d.handleKey){
+                               if(d.handleKey(e) === false){
+                                       /* false return code means that the drop down handled the key */
+                                       event.stop(e);
+                                       return;
+                               }
+                       }
+                       if(d && this._opened && e.charOrCode == keys.ESCAPE){
+                               this.closeDropDown();
+                               event.stop(e);
+                       }else if(!this._opened &&
+                                       (e.charOrCode == keys.DOWN_ARROW ||
+                                               ( (e.charOrCode == keys.ENTER || e.charOrCode == " ") &&
+                                                 //ignore enter and space if the event is for a text input
+                                                 ((target.tagName || "").toLowerCase() !== 'input' ||
+                                                    (target.type && target.type.toLowerCase() !== 'text'))))){
+                               // Toggle the drop down, but wait until keyup so that the drop down doesn't
+                               // get a stray keyup event, or in the case of key-repeat (because user held
+                               // down key for too long), stray keydown events
+                               this._toggleOnKeyUp = true;
+                               event.stop(e);
+                       }
+               },
+
+               _onKeyUp: function(){
+                       if(this._toggleOnKeyUp){
+                               delete this._toggleOnKeyUp;
+                               this.toggleDropDown();
+                               var d = this.dropDown;  // drop down may not exist until toggleDropDown() call
+                               if(d && d.focus){
+                                       setTimeout(lang.hitch(d, "focus"), 1);
+                               }
+                       }
+               },
 
-       // Constants used in templates
+               _onBlur: function(){
+                       // summary:
+                       //              Called magically when focus has shifted away from this widget and it's dropdown
 
-       // _blankGif: [protected] String
-       //              Path to a blank 1x1 image.
-       //              Used by <img> nodes in templates that really get their image via CSS background-image.
-       _blankGif: (dojo.config.blankGif || dojo.moduleUrl("dojo", "resources/blank.gif")).toString(),
+                       // Don't focus on button if the user has explicitly focused on something else (happens
+                       // when user clicks another control causing the current popup to close)..
+                       // But if focus is inside of the drop down then reset focus to me, because IE doesn't like
+                       // it when you display:none a node with focus.
+                       var focusMe = focus.curNode && this.dropDown && dom.isDescendant(focus.curNode, this.dropDown.domNode);
 
-       //////////// INITIALIZATION METHODS ///////////////////////////////////////
+                       this.closeDropDown(focusMe);
 
-       postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
-               // summary:
-               //              Kicks off widget instantiation.  See create() for details.
-               // tags:
-               //              private
-               this.create(params, srcNodeRef);
-       },
+                       this.inherited(arguments);
+               },
 
-       create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
-               // summary:
-               //              Kick off the life-cycle of a widget
-               // params:
-               //              Hash of initialization parameters for widget, including
-               //              scalar values (like title, duration etc.) and functions,
-               //              typically callbacks like onClick.
-               // srcNodeRef:
-               //              If a srcNodeRef (DOM node) is specified:
-               //                      - use srcNodeRef.innerHTML as my contents
-               //                      - if this is a behavioral widget then apply behavior
-               //                        to that srcNodeRef
-               //                      - otherwise, replace srcNodeRef with my generated DOM
-               //                        tree
-               // description:
-               //              Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
-               //              etc.), some of which of you'll want to override. See http://docs.dojocampus.org/dijit/_Widget
-               //              for a discussion of the widget creation lifecycle.
-               //
-               //              Of course, adventurous developers could override create entirely, but this should
-               //              only be done as a last resort.
-               // tags:
-               //              private
+               isLoaded: function(){
+                       // summary:
+                       //              Returns true if the dropdown exists and it's data is loaded.  This can
+                       //              be overridden in order to force a call to loadDropDown().
+                       // tags:
+                       //              protected
 
-               // store pointer to original DOM tree
-               this.srcNodeRef = dojo.byId(srcNodeRef);
+                       return true;
+               },
 
-               // For garbage collection.  An array of handles returned by Widget.connect()
-               // Each handle returned from Widget.connect() is an array of handles from dojo.connect()
-               this._connects = [];
+               loadDropDown: function(/*Function*/ loadCallback){
+                       // summary:
+                       //              Creates the drop down if it doesn't exist, loads the data
+                       //              if there's an href and it hasn't been loaded yet, and then calls
+                       //              the given callback.
+                       // tags:
+                       //              protected
 
-               // For garbage collection.  An array of handles returned by Widget.subscribe()
-               // The handle returned from Widget.subscribe() is the handle returned from dojo.subscribe()
-               this._subscribes = [];
+                       // TODO: for 2.0, change API to return a Deferred, instead of calling loadCallback?
+                       loadCallback();
+               },
 
-               // To avoid double-connects, remove entries from _deferredConnects
-               // that have been setup manually by a subclass (ex, by dojoAttachEvent).
-               // If a subclass has redefined a callback (ex: onClick) then assume it's being
-               // connected to manually.
-               this._deferredConnects = dojo.clone(this._deferredConnects);
-               for(var attr in this.attributeMap){
-                       delete this._deferredConnects[attr]; // can't be in both attributeMap and _deferredConnects
-               }
-               for(attr in this._deferredConnects){
-                       if(this[attr] !== dijit._connectOnUseEventHandler){
-                               delete this._deferredConnects[attr];    // redefined, probably dojoAttachEvent exists
+               loadAndOpenDropDown: function(){
+                       // summary:
+                       //              Creates the drop down if it doesn't exist, loads the data
+                       //              if there's an href and it hasn't been loaded yet, and
+                       //              then opens the drop down.  This is basically a callback when the
+                       //              user presses the down arrow button to open the drop down.
+                       // returns: Deferred
+                       //              Deferred for the drop down widget that
+                       //              fires when drop down is created and loaded
+                       // tags:
+                       //              protected
+                       var d = new Deferred(),
+                               afterLoad = lang.hitch(this, function(){
+                                       this.openDropDown();
+                                       d.resolve(this.dropDown);
+                               });
+                       if(!this.isLoaded()){
+                               this.loadDropDown(afterLoad);
+                       }else{
+                               afterLoad();
                        }
-               }
+                       return d;
+               },
 
-               //mixin our passed parameters
-               if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
-               if(params){
-                       this.params = params;
-                       dojo.mixin(this,params);
-               }
-               this.postMixInProperties();
+               toggleDropDown: function(){
+                       // summary:
+                       //              Callback when the user presses the down arrow button or presses
+                       //              the down arrow key to open/close the drop down.
+                       //              Toggle the drop-down widget; if it is up, close it, if not, open it
+                       // tags:
+                       //              protected
 
-               // generate an id for the widget if one wasn't specified
-               // (be sure to do this before buildRendering() because that function might
-               // expect the id to be there.)
-               if(!this.id){
-                       this.id = dijit.getUniqueId(this.declaredClass.replace(/\./g,"_"));
-               }
-               dijit.registry.add(this);
+                       if(this.disabled || this.readOnly){ return; }
+                       if(!this._opened){
+                               this.loadAndOpenDropDown();
+                       }else{
+                               this.closeDropDown();
+                       }
+               },
 
-               this.buildRendering();
+               openDropDown: function(){
+                       // summary:
+                       //              Opens the dropdown for this widget.   To be called only when this.dropDown
+                       //              has been created and is ready to display (ie, it's data is loaded).
+                       // returns:
+                       //              return value of dijit.popup.open()
+                       // tags:
+                       //              protected
 
-               if(this.domNode){
-                       // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
-                       this._applyAttributes();
+                       var dropDown = this.dropDown,
+                               ddNode = dropDown.domNode,
+                               aroundNode = this._aroundNode || this.domNode,
+                               self = this;
 
-                       var source = this.srcNodeRef;
-                       if(source && source.parentNode){
-                               source.parentNode.replaceChild(this.domNode, source);
-                       }
+                       // Prepare our popup's height and honor maxHeight if it exists.
 
-                       // If the developer has specified a handler as a widget parameter
-                       // (ex: new Button({onClick: ...})
-                       // then naturally need to connect from DOM node to that handler immediately,
-                       for(attr in this.params){
-                               this._onConnect(attr);
+                       // TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
+                       // ie, dependent on how much space is available (BK)
+
+                       if(!this._preparedNode){
+                               this._preparedNode = true;
+                               // Check if we have explicitly set width and height on the dropdown widget dom node
+                               if(ddNode.style.width){
+                                       this._explicitDDWidth = true;
+                               }
+                               if(ddNode.style.height){
+                                       this._explicitDDHeight = true;
+                               }
                        }
-               }
 
-               if(this.domNode){
-                       this.domNode.setAttribute("widgetId", this.id);
-               }
-               this.postCreate();
+                       // Code for resizing dropdown (height limitation, or increasing width to match my width)
+                       if(this.maxHeight || this.forceWidth || this.autoWidth){
+                               var myStyle = {
+                                       display: "",
+                                       visibility: "hidden"
+                               };
+                               if(!this._explicitDDWidth){
+                                       myStyle.width = "";
+                               }
+                               if(!this._explicitDDHeight){
+                                       myStyle.height = "";
+                               }
+                               domStyle.set(ddNode, myStyle);
+
+                               // Figure out maximum height allowed (if there is a height restriction)
+                               var maxHeight = this.maxHeight;
+                               if(maxHeight == -1){
+                                       // limit height to space available in viewport either above or below my domNode
+                                       // (whichever side has more room)
+                                       var viewport = winUtils.getBox(),
+                                               position = domGeometry.position(aroundNode, false);
+                                       maxHeight = Math.floor(Math.max(position.y, viewport.h - (position.y + position.h)));
+                               }
 
-               // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
-               if(this.srcNodeRef && !this.srcNodeRef.parentNode){
-                       delete this.srcNodeRef;
-               }
+                               // Attach dropDown to DOM and make make visibility:hidden rather than display:none
+                               // so we call startup() and also get the size
+                               popup.moveOffScreen(dropDown);
 
-               this._created = true;
-       },
+                               if(dropDown.startup && !dropDown._started){
+                                       dropDown.startup(); // this has to be done after being added to the DOM
+                               }
+                               // Get size of drop down, and determine if vertical scroll bar needed
+                               var mb = domGeometry.getMarginSize(ddNode);
+                               var overHeight = (maxHeight && mb.h > maxHeight);
+                               domStyle.set(ddNode, {
+                                       overflowX: "hidden",
+                                       overflowY: overHeight ? "auto" : "hidden"
+                               });
+                               if(overHeight){
+                                       mb.h = maxHeight;
+                                       if("w" in mb){
+                                               mb.w += 16;     // room for vertical scrollbar
+                                       }
+                               }else{
+                                       delete mb.h;
+                               }
 
-       _applyAttributes: function(){
-               // summary:
-               //              Step during widget creation to copy all widget attributes to the
-               //              DOM as per attributeMap and _setXXXAttr functions.
-               // description:
-               //              Skips over blank/false attribute values, unless they were explicitly specified
-               //              as parameters to the widget, since those are the default anyway,
-               //              and setting tabIndex="" is different than not setting tabIndex at all.
-               //
-               //              It processes the attributes in the attribute map first, and then
-               //              it goes through and processes the attributes for the _setXXXAttr
-               //              functions that have been specified
-               // tags:
-               //              private
-               var condAttrApply = function(attr, scope){
-                       if((scope.params && attr in scope.params) || scope[attr]){
-                               scope.set(attr, scope[attr]);
+                               // Adjust dropdown width to match or be larger than my width
+                               if(this.forceWidth){
+                                       mb.w = aroundNode.offsetWidth;
+                               }else if(this.autoWidth){
+                                       mb.w = Math.max(mb.w, aroundNode.offsetWidth);
+                               }else{
+                                       delete mb.w;
+                               }
+
+                               // And finally, resize the dropdown to calculated height and width
+                               if(lang.isFunction(dropDown.resize)){
+                                       dropDown.resize(mb);
+                               }else{
+                                       domGeometry.setMarginBox(ddNode, mb);
+                               }
                        }
-               };
 
-               // Do the attributes in attributeMap
-               for(var attr in this.attributeMap){
-                       condAttrApply(attr, this);
-               }
+                       var retVal = popup.open({
+                               parent: this,
+                               popup: dropDown,
+                               around: aroundNode,
+                               orient: this.dropDownPosition,
+                               onExecute: function(){
+                                       self.closeDropDown(true);
+                               },
+                               onCancel: function(){
+                                       self.closeDropDown(true);
+                               },
+                               onClose: function(){
+                                       domAttr.set(self._popupStateNode, "popupActive", false);
+                                       domClass.remove(self._popupStateNode, "dijitHasDropDownOpen");
+                                       self._opened = false;
+                               }
+                       });
+                       domAttr.set(this._popupStateNode, "popupActive", "true");
+                       domClass.add(self._popupStateNode, "dijitHasDropDownOpen");
+                       this._opened=true;
+
+                       // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
+                       return retVal;
+               },
+
+               closeDropDown: function(/*Boolean*/ focus){
+                       // summary:
+                       //              Closes the drop down on this widget
+                       // focus:
+                       //              If true, refocuses the button widget
+                       // tags:
+                       //              protected
 
-               // And also any attributes with custom setters
-               dojo.forEach(getSetterAttributes(this), function(a){
-                       if(!(a in this.attributeMap)){
-                               condAttrApply(a, this);
+                       if(this._opened){
+                               if(focus){ this.focus(); }
+                               popup.close(this.dropDown);
+                               this._opened = false;
                        }
-               }, this);
-       },
+               }
 
-       postMixInProperties: function(){
-               // summary:
-               //              Called after the parameters to the widget have been read-in,
-               //              but before the widget template is instantiated. Especially
-               //              useful to set properties that are referenced in the widget
-               //              template.
-               // tags:
-               //              protected
-       },
+       });
+});
 
-       buildRendering: function(){
-               // summary:
-               //              Construct the UI for this widget, setting this.domNode
-               // description:
-               //              Most widgets will mixin `dijit._Templated`, which implements this
-               //              method.
-               // tags:
-               //              protected
-               this.domNode = this.srcNodeRef || dojo.create('div');
-       },
+},
+'dijit/tree/TreeStoreModel':function(){
+define("dijit/tree/TreeStoreModel", [
+       "dojo/_base/array", // array.filter array.forEach array.indexOf array.some
+       "dojo/aspect", // aspect.after
+       "dojo/_base/declare", // declare
+       "dojo/_base/json", // json.stringify
+       "dojo/_base/lang" // lang.hitch
+], function(array, aspect, declare, json, lang){
+
+       // module:
+       //              dijit/tree/TreeStoreModel
+       // summary:
+       //              Implements dijit.Tree.model connecting to a dojo.data store with a single
+       //              root item.
 
-       postCreate: function(){
+       return declare("dijit.tree.TreeStoreModel", null, {
                // summary:
-               //              Processing after the DOM fragment is created
-               // description:
-               //              Called after the DOM fragment has been created, but not necessarily
-               //              added to the document.  Do not include any operations which rely on
-               //              node dimensions or placement.
-               // tags:
-               //              protected
-
-               // baseClass is a single class name or occasionally a space-separated list of names.
-               // Add those classes to the DOMNod.  If RTL mode then also add with Rtl suffix.         
-               if(this.baseClass){
-                       var classes = this.baseClass.split(" ");
-                       if(!this.isLeftToRight()){
-                               classes = classes.concat( dojo.map(classes, function(name){ return name+"Rtl"; }));
-                       }
-                       dojo.addClass(this.domNode, classes);
-               }
-       },
+               //              Implements dijit.Tree.model connecting to a dojo.data store with a single
+               //              root item.  Any methods passed into the constructor will override
+               //              the ones defined here.
 
-       startup: function(){
-               // summary:
-               //              Processing after the DOM fragment is added to the document
-               // description:
-               //              Called after a widget and its children have been created and added to the page,
-               //              and all related widgets have finished their create() cycle, up through postCreate().
-               //              This is useful for composite widgets that need to control or layout sub-widgets.
-               //              Many layout widgets can use this as a wiring phase.
-               this._started = true;
-       },
+               // store: dojo.data.Store
+               //              Underlying store
+               store: null,
 
-       //////////// DESTROY FUNCTIONS ////////////////////////////////
+               // childrenAttrs: String[]
+               //              One or more attribute names (attributes in the dojo.data item) that specify that item's children
+               childrenAttrs: ["children"],
 
-       destroyRecursive: function(/*Boolean?*/ preserveDom){
-               // summary:
-               //              Destroy this widget and its descendants
-               // description:
-               //              This is the generic "destructor" function that all widget users
-               //              should call to cleanly discard with a widget. Once a widget is
-               //              destroyed, it is removed from the manager object.
-               // preserveDom:
-               //              If true, this method will leave the original DOM structure
-               //              alone of descendant Widgets. Note: This will NOT work with
-               //              dijit._Templated widgets.
+               // newItemIdAttr: String
+               //              Name of attribute in the Object passed to newItem() that specifies the id.
+               //
+               //              If newItemIdAttr is set then it's used when newItem() is called to see if an
+               //              item with the same id already exists, and if so just links to the old item
+               //              (so that the old item ends up with two parents).
+               //
+               //              Setting this to null or "" will make every drop create a new item.
+               newItemIdAttr: "id",
 
-               this._beingDestroyed = true;
-               this.destroyDescendants(preserveDom);
-               this.destroy(preserveDom);
-       },
+               // labelAttr: String
+               //              If specified, get label for tree node from this attribute, rather
+               //              than by calling store.getLabel()
+               labelAttr: "",
 
-       destroy: function(/*Boolean*/ preserveDom){
-               // summary:
-               //              Destroy this widget, but not its descendants.
-               //              This method will, however, destroy internal widgets such as those used within a template.
-               // preserveDom: Boolean
-               //              If true, this method will leave the original DOM structure alone.
-               //              Note: This will not yet work with _Templated widgets
+               // root: [readonly] dojo.data.Item
+               //              Pointer to the root item (read only, not a parameter)
+               root: null,
 
-               this._beingDestroyed = true;
-               this.uninitialize();
-               var d = dojo,
-                       dfe = d.forEach,
-                       dun = d.unsubscribe;
-               dfe(this._connects, function(array){
-                       dfe(array, d.disconnect);
-               });
-               dfe(this._subscribes, function(handle){
-                       dun(handle);
-               });
+               // query: anything
+               //              Specifies datastore query to return the root item for the tree.
+               //              Must only return a single item.   Alternately can just pass in pointer
+               //              to root item.
+               // example:
+               //      |       {id:'ROOT'}
+               query: null,
 
-               // destroy widgets created as part of template, etc.
-               dfe(this._supportingWidgets || [], function(w){
-                       if(w.destroyRecursive){
-                               w.destroyRecursive();
-                       }else if(w.destroy){
-                               w.destroy();
-                       }
-               });
+               // deferItemLoadingUntilExpand: Boolean
+               //              Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
+               //              until they are expanded. This allows for lazying loading where only one
+               //              loadItem (and generally one network call, consequently) per expansion
+               //              (rather than one for each child).
+               //              This relies on partial loading of the children items; each children item of a
+               //              fully loaded item should contain the label and info about having children.
+               deferItemLoadingUntilExpand: false,
 
-               this.destroyRendering(preserveDom);
-               dijit.registry.remove(this.id);
-               this._destroyed = true;
-       },
+               constructor: function(/* Object */ args){
+                       // summary:
+                       //              Passed the arguments listed above (store, etc)
+                       // tags:
+                       //              private
 
-       destroyRendering: function(/*Boolean?*/ preserveDom){
-               // summary:
-               //              Destroys the DOM nodes associated with this widget
-               // preserveDom:
-               //              If true, this method will leave the original DOM structure alone
-               //              during tear-down. Note: this will not work with _Templated
-               //              widgets yet.
-               // tags:
-               //              protected
+                       lang.mixin(this, args);
 
-               if(this.bgIframe){
-                       this.bgIframe.destroy(preserveDom);
-                       delete this.bgIframe;
-               }
+                       this.connects = [];
 
-               if(this.domNode){
-                       if(preserveDom){
-                               dojo.removeAttr(this.domNode, "widgetId");
-                       }else{
-                               dojo.destroy(this.domNode);
+                       var store = this.store;
+                       if(!store.getFeatures()['dojo.data.api.Identity']){
+                               throw new Error("dijit.Tree: store must support dojo.data.Identity");
                        }
-                       delete this.domNode;
-               }
 
-               if(this.srcNodeRef){
-                       if(!preserveDom){
-                               dojo.destroy(this.srcNodeRef);
+                       // if the store supports Notification, subscribe to the notification events
+                       if(store.getFeatures()['dojo.data.api.Notification']){
+                               this.connects = this.connects.concat([
+                                       aspect.after(store, "onNew", lang.hitch(this, "onNewItem"), true),
+                                       aspect.after(store, "onDelete", lang.hitch(this, "onDeleteItem"), true),
+                                       aspect.after(store, "onSet", lang.hitch(this, "onSetItem"), true)
+                               ]);
                        }
-                       delete this.srcNodeRef;
-               }
-       },
-
-       destroyDescendants: function(/*Boolean?*/ preserveDom){
-               // summary:
-               //              Recursively destroy the children of this widget and their
-               //              descendants.
-               // preserveDom:
-               //              If true, the preserveDom attribute is passed to all descendant
-               //              widget's .destroy() method. Not for use with _Templated
-               //              widgets.
+               },
 
-               // get all direct descendants and destroy them recursively
-               dojo.forEach(this.getChildren(), function(widget){
-                       if(widget.destroyRecursive){
-                               widget.destroyRecursive(preserveDom);
-                       }
-               });
-       },
+               destroy: function(){
+                       var h;
+                       while(h = this.connects.pop()){ h.remove(); }
+                       // TODO: should cancel any in-progress processing of getRoot(), getChildren()
+               },
 
+               // =======================================================================
+               // Methods for traversing hierarchy
 
-       uninitialize: function(){
-               // summary:
-               //              Stub function. Override to implement custom widget tear-down
-               //              behavior.
-               // tags:
-               //              protected
-               return false;
-       },
+               getRoot: function(onItem, onError){
+                       // summary:
+                       //              Calls onItem with the root item for the tree, possibly a fabricated item.
+                       //              Calls onError on error.
+                       if(this.root){
+                               onItem(this.root);
+                       }else{
+                               this.store.fetch({
+                                       query: this.query,
+                                       onComplete: lang.hitch(this, function(items){
+                                               if(items.length != 1){
+                                                       throw new Error(this.declaredClass + ": query " + json.stringify(this.query) + " returned " + items.length +
+                                                               " items, but must return exactly one item");
+                                               }
+                                               this.root = items[0];
+                                               onItem(this.root);
+                                       }),
+                                       onError: onError
+                               });
+                       }
+               },
 
-       ////////////////// MISCELLANEOUS METHODS ///////////////////
+               mayHaveChildren: function(/*dojo.data.Item*/ item){
+                       // summary:
+                       //              Tells if an item has or may have children.  Implementing logic here
+                       //              avoids showing +/- expando icon for nodes that we know don't have children.
+                       //              (For efficiency reasons we may not want to check if an element actually
+                       //              has children until user clicks the expando node)
+                       return array.some(this.childrenAttrs, function(attr){
+                               return this.store.hasAttribute(item, attr);
+                       }, this);
+               },
 
-       onFocus: function(){
-               // summary:
-               //              Called when the widget becomes "active" because
-               //              it or a widget inside of it either has focus, or has recently
-               //              been clicked.
-               // tags:
-               //              callback
-       },
+               getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
+                       // summary:
+                       //              Calls onComplete() with array of child items of given parent item, all loaded.
 
-       onBlur: function(){
-               // summary:
-               //              Called when the widget stops being "active" because
-               //              focus moved to something outside of it, or the user
-               //              clicked somewhere outside of it, or the widget was
-               //              hidden.
-               // tags:
-               //              callback
-       },
+                       var store = this.store;
+                       if(!store.isItemLoaded(parentItem)){
+                               // The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
+                               // mode, so we will load it and just return the children (without loading each
+                               // child item)
+                               var getChildren = lang.hitch(this, arguments.callee);
+                               store.loadItem({
+                                       item: parentItem,
+                                       onItem: function(parentItem){
+                                               getChildren(parentItem, onComplete, onError);
+                                       },
+                                       onError: onError
+                               });
+                               return;
+                       }
+                       // get children of specified item
+                       var childItems = [];
+                       for(var i=0; i<this.childrenAttrs.length; i++){
+                               var vals = store.getValues(parentItem, this.childrenAttrs[i]);
+                               childItems = childItems.concat(vals);
+                       }
 
-       _onFocus: function(e){
-               // summary:
-               //              This is where widgets do processing for when they are active,
-               //              such as changing CSS classes.  See onFocus() for more details.
-               // tags:
-               //              protected
-               this.onFocus();
-       },
+                       // count how many items need to be loaded
+                       var _waitCount = 0;
+                       if(!this.deferItemLoadingUntilExpand){
+                               array.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
+                       }
 
-       _onBlur: function(){
-               // summary:
-               //              This is where widgets do processing for when they stop being active,
-               //              such as changing CSS classes.  See onBlur() for more details.
-               // tags:
-               //              protected
-               this.onBlur();
-       },
-
-       _onConnect: function(/*String*/ event){
-               // summary:
-               //              Called when someone connects to one of my handlers.
-               //              "Turn on" that handler if it isn't active yet.
-               //
-               //              This is also called for every single initialization parameter
-               //              so need to do nothing for parameters like "id".
-               // tags:
-               //              private
-               if(event in this._deferredConnects){
-                       var mapNode = this[this._deferredConnects[event] || 'domNode'];
-                       this.connect(mapNode, event.toLowerCase(), event);
-                       delete this._deferredConnects[event];
-               }
-       },
+                       if(_waitCount == 0){
+                               // all items are already loaded (or we aren't loading them).  proceed...
+                               onComplete(childItems);
+                       }else{
+                               // still waiting for some or all of the items to load
+                               array.forEach(childItems, function(item, idx){
+                                       if(!store.isItemLoaded(item)){
+                                               store.loadItem({
+                                                       item: item,
+                                                       onItem: function(item){
+                                                               childItems[idx] = item;
+                                                               if(--_waitCount == 0){
+                                                                       // all nodes have been loaded, send them to the tree
+                                                                       onComplete(childItems);
+                                                               }
+                                                       },
+                                                       onError: onError
+                                               });
+                                       }
+                               });
+                       }
+               },
 
-       _setClassAttr: function(/*String*/ value){
-               // summary:
-               //              Custom setter for the CSS "class" attribute
-               // tags:
-               //              protected
-               var mapNode = this[this.attributeMap["class"] || 'domNode'];
-               dojo.removeClass(mapNode, this["class"])
-               this["class"] = value;
-               dojo.addClass(mapNode, value);
-       },
+               // =======================================================================
+               // Inspecting items
 
-       _setStyleAttr: function(/*String||Object*/ value){
-               // summary:
-               //              Sets the style attribut of the widget according to value,
-               //              which is either a hash like {height: "5px", width: "3px"}
-               //              or a plain string
-               // description:
-               //              Determines which node to set the style on based on style setting
-               //              in attributeMap.
-               // tags:
-               //              protected
+               isItem: function(/* anything */ something){
+                       return this.store.isItem(something);    // Boolean
+               },
 
-               var mapNode = this[this.attributeMap.style || 'domNode'];
+               fetchItemByIdentity: function(/* object */ keywordArgs){
+                       this.store.fetchItemByIdentity(keywordArgs);
+               },
 
-               // Note: technically we should revert any style setting made in a previous call
-               // to his method, but that's difficult to keep track of.
+               getIdentity: function(/* item */ item){
+                       return this.store.getIdentity(item);    // Object
+               },
 
-               if(dojo.isObject(value)){
-                       dojo.style(mapNode, value);
-               }else{
-                       if(mapNode.style.cssText){
-                               mapNode.style.cssText += "; " + value;
+               getLabel: function(/*dojo.data.Item*/ item){
+                       // summary:
+                       //              Get the label for an item
+                       if(this.labelAttr){
+                               return this.store.getValue(item,this.labelAttr);        // String
                        }else{
-                               mapNode.style.cssText = value;
+                               return this.store.getLabel(item);       // String
                        }
-               }
+               },
 
-               this.style = value;
-       },
+               // =======================================================================
+               // Write interface
 
-       setAttribute: function(/*String*/ attr, /*anything*/ value){
-               // summary:
-               //              Deprecated.  Use set() instead.
-               // tags:
-               //              deprecated
-               dojo.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
-               this.set(attr, value);
-       },
+               newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+                       // summary:
+                       //              Creates a new item.   See `dojo.data.api.Write` for details on args.
+                       //              Used in drag & drop when item from external source dropped onto tree.
+                       // description:
+                       //              Developers will need to override this method if new items get added
+                       //              to parents with multiple children attributes, in order to define which
+                       //              children attribute points to the new item.
 
-       _attrToDom: function(/*String*/ attr, /*String*/ value){
-               // summary:
-               //              Reflect a widget attribute (title, tabIndex, duration etc.) to
-               //              the widget DOM, as specified in attributeMap.
-               //
-               // description:
-               //              Also sets this["attr"] to the new value.
-               //              Note some attributes like "type"
-               //              cannot be processed this way as they are not mutable.
-               //
-               // tags:
-               //              private
+                       var pInfo = {parent: parent, attribute: this.childrenAttrs[0]}, LnewItem;
 
-               var commands = this.attributeMap[attr];
-               dojo.forEach(dojo.isArray(commands) ? commands : [commands], function(command){
+                       if(this.newItemIdAttr && args[this.newItemIdAttr]){
+                               // Maybe there's already a corresponding item in the store; if so, reuse it.
+                               this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
+                                       if(item){
+                                               // There's already a matching item in store, use it
+                                               this.pasteItem(item, null, parent, true, insertIndex);
+                                       }else{
+                                               // Create new item in the tree, based on the drag source.
+                                               LnewItem=this.store.newItem(args, pInfo);
+                                               if(LnewItem && (insertIndex!=undefined)){
+                                                       // Move new item to desired position
+                                                       this.pasteItem(LnewItem, parent, parent, false, insertIndex);
+                                               }
+                                       }
+                               }});
+                       }else{
+                               // [as far as we know] there is no id so we must assume this is a new item
+                               LnewItem=this.store.newItem(args, pInfo);
+                               if(LnewItem && (insertIndex!=undefined)){
+                                       // Move new item to desired position
+                                       this.pasteItem(LnewItem, parent, parent, false, insertIndex);
+                               }
+                       }
+               },
 
-                       // Get target node and what we are doing to that node
-                       var mapNode = this[command.node || command || "domNode"];       // DOM node
-                       var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
+               pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
+                       // summary:
+                       //              Move or copy an item from one parent item to another.
+                       //              Used in drag & drop
+                       var store = this.store,
+                               parentAttr = this.childrenAttrs[0];     // name of "children" attr in parent item
 
-                       switch(type){
-                               case "attribute":
-                                       if(dojo.isFunction(value)){ // functions execute in the context of the widget
-                                               value = dojo.hitch(this, value);
+                       // remove child from source item, and record the attribute that child occurred in
+                       if(oldParentItem){
+                               array.forEach(this.childrenAttrs, function(attr){
+                                       if(store.containsValue(oldParentItem, attr, childItem)){
+                                               if(!bCopy){
+                                                       var values = array.filter(store.getValues(oldParentItem, attr), function(x){
+                                                               return x != childItem;
+                                                       });
+                                                       store.setValues(oldParentItem, attr, values);
+                                               }
+                                               parentAttr = attr;
                                        }
+                               });
+                       }
 
-                                       // Get the name of the DOM node attribute; usually it's the same
-                                       // as the name of the attribute in the widget (attr), but can be overridden.
-                                       // Also maps handler names to lowercase, like onSubmit --> onsubmit
-                                       var attrName = command.attribute ? command.attribute :
-                                               (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
+                       // modify target item's children attribute to include this item
+                       if(newParentItem){
+                               if(typeof insertIndex == "number"){
+                                       // call slice() to avoid modifying the original array, confusing the data store
+                                       var childItems = store.getValues(newParentItem, parentAttr).slice();
+                                       childItems.splice(insertIndex, 0, childItem);
+                                       store.setValues(newParentItem, parentAttr, childItems);
+                               }else{
+                                       store.setValues(newParentItem, parentAttr,
+                                               store.getValues(newParentItem, parentAttr).concat(childItem));
+                               }
+                       }
+               },
 
-                                       dojo.attr(mapNode, attrName, value);
-                                       break;
-                               case "innerText":
-                                       mapNode.innerHTML = "";
-                                       mapNode.appendChild(dojo.doc.createTextNode(value));
-                                       break;
-                               case "innerHTML":
-                                       mapNode.innerHTML = value;
-                                       break;
-                               case "class":
-                                       dojo.removeClass(mapNode, this[attr]);
-                                       dojo.addClass(mapNode, value);
-                                       break;
+               // =======================================================================
+               // Callbacks
+
+               onChange: function(/*dojo.data.Item*/ /*===== item =====*/){
+                       // summary:
+                       //              Callback whenever an item has changed, so that Tree
+                       //              can update the label, icon, etc.   Note that changes
+                       //              to an item's children or parent(s) will trigger an
+                       //              onChildrenChange() so you can ignore those changes here.
+                       // tags:
+                       //              callback
+               },
+
+               onChildrenChange: function(/*===== parent, newChildrenList =====*/){
+                       // summary:
+                       //              Callback to do notifications about new, updated, or deleted items.
+                       // parent: dojo.data.Item
+                       // newChildrenList: dojo.data.Item[]
+                       // tags:
+                       //              callback
+               },
+
+               onDelete: function(/*dojo.data.Item*/ /*===== item =====*/){
+                       // summary:
+                       //              Callback when an item has been deleted.
+                       // description:
+                       //              Note that there will also be an onChildrenChange() callback for the parent
+                       //              of this item.
+                       // tags:
+                       //              callback
+               },
+
+               // =======================================================================
+               // Events from data store
+
+               onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
+                       // summary:
+                       //              Handler for when new items appear in the store, either from a drop operation
+                       //              or some other way.   Updates the tree view (if necessary).
+                       // description:
+                       //              If the new item is a child of an existing item,
+                       //              calls onChildrenChange() with the new list of children
+                       //              for that existing item.
+                       //
+                       // tags:
+                       //              extension
+
+                       // We only care about the new item if it has a parent that corresponds to a TreeNode
+                       // we are currently displaying
+                       if(!parentInfo){
+                               return;
                        }
-               }, this);
-               this[attr] = value;
-       },
 
-       attr: function(/*String|Object*/name, /*Object?*/value){
-               // summary:
-               //              Set or get properties on a widget instance.
-               //      name:
-               //              The property to get or set. If an object is passed here and not
-               //              a string, its keys are used as names of attributes to be set
-               //              and the value of the object as values to set in the widget.
-               //      value:
-               //              Optional. If provided, attr() operates as a setter. If omitted,
-               //              the current value of the named property is returned.
-               // description:
-               //              This method is deprecated, use get() or set() directly.
+                       // Call onChildrenChange() on parent (ie, existing) item with new list of children
+                       // In the common case, the new list of children is simply parentInfo.newValue or
+                       // [ parentInfo.newValue ], although if items in the store has multiple
+                       // child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
+                       // so call getChildren() to be sure to get right answer.
+                       this.getChildren(parentInfo.item, lang.hitch(this, function(children){
+                               this.onChildrenChange(parentInfo.item, children);
+                       }));
+               },
 
-               // Print deprecation warning but only once per calling function
-               if(dojo.config.isDebug){
-                       var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
-                               caller = (arguments.callee.caller || "unknown caller").toString();
-                       if(!alreadyCalledHash[caller]){
-                               dojo.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
-                               caller, "", "2.0");
-                               alreadyCalledHash[caller] = true;
+               onDeleteItem: function(/*Object*/ item){
+                       // summary:
+                       //              Handler for delete notifications from underlying store
+                       this.onDelete(item);
+               },
+
+               onSetItem: function(item, attribute /*===== , oldValue, newValue =====*/){
+                       // summary:
+                       //              Updates the tree view according to changes in the data store.
+                       // description:
+                       //              Handles updates to an item's children by calling onChildrenChange(), and
+                       //              other updates to an item by calling onChange().
+                       //
+                       //              See `onNewItem` for more details on handling updates to an item's children.
+                       // item: Item
+                       // attribute: attribute-name-string
+                       // oldValue: object | array
+                       // newValue: object | array
+                       // tags:
+                       //              extension
+
+                       if(array.indexOf(this.childrenAttrs, attribute) != -1){
+                               // item's children list changed
+                               this.getChildren(item, lang.hitch(this, function(children){
+                                       // See comments in onNewItem() about calling getChildren()
+                                       this.onChildrenChange(item, children);
+                               }));
+                       }else{
+                               // item's label/icon/etc. changed.
+                               this.onChange(item);
                        }
                }
+       });
+});
 
-               var args = arguments.length;
-               if(args >= 2 || typeof name === "object"){ // setter
-                       return this.set.apply(this, arguments);
-               }else{ // getter
-                       return this.get(name);
-               }
+},
+'dijit/_MenuBase':function(){
+define("dijit/_MenuBase", [
+       "./popup",
+       "dojo/window",
+       "./_Widget",
+       "./_KeyNavContainer",
+       "./_TemplatedMixin",
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.isDescendant domClass.replace
+       "dojo/dom-attr",
+       "dojo/dom-class", // domClass.replace
+       "dojo/_base/lang", // lang.hitch
+       "dojo/_base/array"      // array.indexOf
+], function(pm, winUtils, _Widget, _KeyNavContainer, _TemplatedMixin,
+       declare, dom, domAttr, domClass, lang, array){
+
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _KeyNavContainer = dijit._KeyNavContainer;
+=====*/
+
+// module:
+//             dijit/_MenuBase
+// summary:
+//             Base class for Menu and MenuBar
+
+return declare("dijit._MenuBase",
+       [_Widget, _TemplatedMixin, _KeyNavContainer],
+{
+       // summary:
+       //              Base class for Menu and MenuBar
+
+       // parentMenu: [readonly] Widget
+       //              pointer to menu that displayed me
+       parentMenu: null,
+
+       // popupDelay: Integer
+       //              number of milliseconds before hovering (without clicking) causes the popup to automatically open.
+       popupDelay: 500,
+
+       onExecute: function(){
+               // summary:
+               //              Attach point for notification about when a menu item has been executed.
+               //              This is an internal mechanism used for Menus to signal to their parent to
+               //              close them, because they are about to execute the onClick handler.  In
+               //              general developers should not attach to or override this method.
+               // tags:
+               //              protected
        },
-       
-       get: function(name){
+
+       onCancel: function(/*Boolean*/ /*===== closeAll =====*/){
                // summary:
-               //              Get a property from a widget.
-               //      name:
-               //              The property to get.
-               // description:
-               //              Get a named property from a widget. The property may
-               //              potentially be retrieved via a getter method. If no getter is defined, this
-               //              just retrieves the object's property.  
-               //              For example, if the widget has a properties "foo"
-               //              and "bar" and a method named "_getFooAttr", calling:
-               //      |       myWidget.get("foo");
-               //              would be equivalent to writing:
-               //      |       widget._getFooAttr();
-               //              and:
-               //      |       myWidget.get("bar");
-               //              would be equivalent to writing:
-               //      |       widget.bar;
-               var names = this._getAttrNames(name);
-               return this[names.g] ? this[names.g]() : this[name];
+               //              Attach point for notification about when the user cancels the current menu
+               //              This is an internal mechanism used for Menus to signal to their parent to
+               //              close them.  In general developers should not attach to or override this method.
+               // tags:
+               //              protected
        },
-       
-       set: function(name, value){
+
+       _moveToPopup: function(/*Event*/ evt){
                // summary:
-               //              Set a property on a widget
-               //      name:
-               //              The property to set. 
-               //      value:
-               //              The value to set in the property.
-               // description:
-               //              Sets named properties on a widget which may potentially be handled by a 
-               //              setter in the widget.
-               //              For example, if the widget has a properties "foo"
-               //              and "bar" and a method named "_setFooAttr", calling:
-               //      |       myWidget.set("foo", "Howdy!");
-               //              would be equivalent to writing:
-               //      |       widget._setFooAttr("Howdy!");
-               //              and:
-               //      |       myWidget.set("bar", 3);
-               //              would be equivalent to writing:
-               //      |       widget.bar = 3;
-               //
-               //      set() may also be called with a hash of name/value pairs, ex:
-               //      |       myWidget.set({
-               //      |               foo: "Howdy",
-               //      |               bar: 3
-               //      |       })
-               //      This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
+               //              This handles the right arrow key (left arrow key on RTL systems),
+               //              which will either open a submenu, or move to the next item in the
+               //              ancestor MenuBar
+               // tags:
+               //              private
 
-               if(typeof name === "object"){
-                       for(var x in name){
-                               this.set(x, name[x]); 
-                       }
-                       return this;
-               }
-               var names = this._getAttrNames(name);
-               if(this[names.s]){
-                       // use the explicit setter
-                       var result = this[names.s].apply(this, Array.prototype.slice.call(arguments, 1));
+               if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){
+                       this.focusedChild._onClick(evt);
                }else{
-                       // if param is specified as DOM node attribute, copy it
-                       if(name in this.attributeMap){
-                               this._attrToDom(name, value);
+                       var topMenu = this._getTopMenu();
+                       if(topMenu && topMenu._isMenuBar){
+                               topMenu.focusNext();
                        }
-                       var oldValue = this[name];
-                       // FIXME: what about function assignments? Any way to connect() here?
-                       this[name] = value;
                }
-               return result || this;
        },
-       
-       _attrPairNames: {},             // shared between all widgets
-       _getAttrNames: function(name){
+
+       _onPopupHover: function(/*Event*/ /*===== evt =====*/){
                // summary:
-               //              Helper function for get() and set().
-               //              Caches attribute name values so we don't do the string ops every time.
+               //              This handler is called when the mouse moves over the popup.
                // tags:
                //              private
 
-               var apn = this._attrPairNames;
-               if(apn[name]){ return apn[name]; }
-               var uc = name.charAt(0).toUpperCase() + name.substr(1);
-               return (apn[name] = {
-                       n: name+"Node",
-                       s: "_set"+uc+"Attr",
-                       g: "_get"+uc+"Attr"
-               });
-       },
-
-       toString: function(){
-               // summary:
-               //              Returns a string that represents the widget
-               // description:
-               //              When a widget is cast to a string, this method will be used to generate the
-               //              output. Currently, it does not implement any sort of reversible
-               //              serialization.
-               return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
+               // if the mouse hovers over a menu popup that is in pending-close state,
+               // then stop the close operation.
+               // This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
+               if(this.currentPopup && this.currentPopup._pendingClose_timer){
+                       var parentMenu = this.currentPopup.parentMenu;
+                       // highlight the parent menu item pointing to this popup
+                       if(parentMenu.focusedChild){
+                               parentMenu.focusedChild._setSelected(false);
+                       }
+                       parentMenu.focusedChild = this.currentPopup.from_item;
+                       parentMenu.focusedChild._setSelected(true);
+                       // cancel the pending close
+                       this._stopPendingCloseTimer(this.currentPopup);
+               }
        },
 
-       getDescendants: function(){
+       onItemHover: function(/*MenuItem*/ item){
                // summary:
-               //              Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
-               //              This method should generally be avoided as it returns widgets declared in templates, which are
-               //              supposed to be internal/hidden, but it's left here for back-compat reasons.
+               //              Called when cursor is over a MenuItem.
+               // tags:
+               //              protected
 
-               return this.containerNode ? dojo.query('[widgetId]', this.containerNode).map(dijit.byNode) : []; // dijit._Widget[]
+               // Don't do anything unless user has "activated" the menu by:
+               //              1) clicking it
+               //              2) opening it from a parent menu (which automatically focuses it)
+               if(this.isActive){
+                       this.focusChild(item);
+                       if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
+                               this.hover_timer = setTimeout(lang.hitch(this, "_openPopup"), this.popupDelay);
+                       }
+               }
+               // if the user is mixing mouse and keyboard navigation,
+               // then the menu may not be active but a menu item has focus,
+               // but it's not the item that the mouse just hovered over.
+               // To avoid both keyboard and mouse selections, use the latest.
+               if(this.focusedChild){
+                       this.focusChild(item);
+               }
+               this._hoveredChild = item;
        },
 
-       getChildren: function(){
+       _onChildBlur: function(item){
                // summary:
-               //              Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
-               //              Does not return nested widgets, nor widgets that are part of this widget's template.
-               return this.containerNode ? dijit.findWidgets(this.containerNode) : []; // dijit._Widget[]
+               //              Called when a child MenuItem becomes inactive because focus
+               //              has been removed from the MenuItem *and* it's descendant menus.
+               // tags:
+               //              private
+               this._stopPopupTimer();
+               item._setSelected(false);
+               // Close all popups that are open and descendants of this menu
+               var itemPopup = item.popup;
+               if(itemPopup){
+                       this._stopPendingCloseTimer(itemPopup);
+                       itemPopup._pendingClose_timer = setTimeout(function(){
+                               itemPopup._pendingClose_timer = null;
+                               if(itemPopup.parentMenu){
+                                       itemPopup.parentMenu.currentPopup = null;
+                               }
+                               pm.close(itemPopup); // this calls onClose
+                       }, this.popupDelay);
+               }
        },
 
-       // nodesWithKeyClick: [private] String[]
-       //              List of nodes that correctly handle click events via native browser support,
-       //              and don't need dijit's help
-       nodesWithKeyClick: ["input", "button"],
-
-       connect: function(
-                       /*Object|null*/ obj,
-                       /*String|Function*/ event,
-                       /*String|Function*/ method){
+       onItemUnhover: function(/*MenuItem*/ item){
                // summary:
-               //              Connects specified obj/event to specified method of this object
-               //              and registers for disconnect() on widget destroy.
-               // description:
-               //              Provide widget-specific analog to dojo.connect, except with the
-               //              implicit use of this widget as the target object.
-               //              This version of connect also provides a special "ondijitclick"
-               //              event which triggers on a click or space or enter keyup
-               // returns:
-               //              A handle that can be passed to `disconnect` in order to disconnect before
-               //              the widget is destroyed.
-               // example:
-               //      |       var btn = new dijit.form.Button();
-               //      |       // when foo.bar() is called, call the listener we're going to
-               //      |       // provide in the scope of btn
-               //      |       btn.connect(foo, "bar", function(){
-               //      |               console.debug(this.toString());
-               //      |       });
+               //              Callback fires when mouse exits a MenuItem
                // tags:
                //              protected
 
-               var d = dojo,
-                       dc = d._connect,
-                       handles = [];
-               if(event == "ondijitclick"){
-                       // add key based click activation for unsupported nodes.
-                       // do all processing onkey up to prevent spurious clicks
-                       // for details see comments at top of this file where _lastKeyDownNode is defined
-                       if(dojo.indexOf(this.nodesWithKeyClick, obj.nodeName.toLowerCase()) == -1){ // is NOT input or button
-                               var m = d.hitch(this, method);
-                               handles.push(
-                                       dc(obj, "onkeydown", this, function(e){
-                                               //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-                                               if((e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-                                                       !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-                                                       // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
-                                                       dijit._lastKeyDownNode = e.target;
-                                                       e.preventDefault();             // stop event to prevent scrolling on space key in IE
-                                               }
-                                       }),
-                                       dc(obj, "onkeyup", this, function(e){
-                                               //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", dijit._lastKeyDownNode, ", equality is ", (e.target === dijit._lastKeyDownNode));
-                                               if( (e.keyCode == d.keys.ENTER || e.keyCode == d.keys.SPACE) &&
-                                                       e.target === dijit._lastKeyDownNode &&
-                                                       !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey){
-                                                               //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
-                                                               dijit._lastKeyDownNode = null;
-                                                               return m(e);
-                                               }
-                                       })
-                               );
-                       }
-                       event = "onclick";
+               if(this.isActive){
+                       this._stopPopupTimer();
                }
-               handles.push(dc(obj, event, this, method));
-
-               this._connects.push(handles);
-               return handles;         // _Widget.Handle
+               if(this._hoveredChild == item){ this._hoveredChild = null; }
        },
 
-       disconnect: function(/* _Widget.Handle */ handles){
+       _stopPopupTimer: function(){
                // summary:
-               //              Disconnects handle created by `connect`.
-               //              Also removes handle from this widget's list of connects.
+               //              Cancels the popup timer because the user has stop hovering
+               //              on the MenuItem, etc.
                // tags:
-               //              protected
-               for(var i=0; i<this._connects.length; i++){
-                       if(this._connects[i] == handles){
-                               dojo.forEach(handles, dojo.disconnect);
-                               this._connects.splice(i, 1);
-                               return;
-                       }
+               //              private
+               if(this.hover_timer){
+                       clearTimeout(this.hover_timer);
+                       this.hover_timer = null;
                }
        },
 
-       subscribe: function(
-                       /*String*/ topic,
-                       /*String|Function*/ method){
+       _stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
                // summary:
-               //              Subscribes to the specified topic and calls the specified method
-               //              of this object and registers for unsubscribe() on widget destroy.
-               // description:
-               //              Provide widget-specific analog to dojo.subscribe, except with the
-               //              implicit use of this widget as the target object.
-               // example:
-               //      |       var btn = new dijit.form.Button();
-               //      |       // when /my/topic is published, this button changes its label to
-               //      |   // be the parameter of the topic.
-               //      |       btn.subscribe("/my/topic", function(v){
-               //      |               this.set("label", v);
-               //      |       });
-               var d = dojo,
-                       handle = d.subscribe(topic, this, method);
-
-               // return handles for Any widget that may need them
-               this._subscribes.push(handle);
-               return handle;
+               //              Cancels the pending-close timer because the close has been preempted
+               // tags:
+               //              private
+               if(popup._pendingClose_timer){
+                       clearTimeout(popup._pendingClose_timer);
+                       popup._pendingClose_timer = null;
+               }
        },
 
-       unsubscribe: function(/*Object*/ handle){
+       _stopFocusTimer: function(){
                // summary:
-               //              Unsubscribes handle created by this.subscribe.
-               //              Also removes handle from this widget's list of subscriptions
-               for(var i=0; i<this._subscribes.length; i++){
-                       if(this._subscribes[i] == handle){
-                               dojo.unsubscribe(handle);
-                               this._subscribes.splice(i, 1);
-                               return;
-                       }
+               //              Cancels the pending-focus timer because the menu was closed before focus occured
+               // tags:
+               //              private
+               if(this._focus_timer){
+                       clearTimeout(this._focus_timer);
+                       this._focus_timer = null;
                }
        },
 
-       isLeftToRight: function(){
+       _getTopMenu: function(){
                // summary:
-               //              Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
+               //              Returns the top menu in this chain of Menus
                // tags:
-               //              protected
-               return this.dir ? (this.dir == "ltr") : dojo._isBodyLtr(); //Boolean
+               //              private
+               for(var top=this; top.parentMenu; top=top.parentMenu);
+               return top;
        },
 
-       isFocusable: function(){
+       onItemClick: function(/*dijit._Widget*/ item, /*Event*/ evt){
                // summary:
-               //              Return true if this widget can currently be focused
-               //              and false if not
-               return this.focus && (dojo.style(this.domNode, "display") != "none");
-       },
-
-       placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
-               // summary:
-               //              Place this widget's domNode reference somewhere in the DOM based
-               //              on standard dojo.place conventions, or passing a Widget reference that
-               //              contains and addChild member.
-               //
-               // description:
-               //              A convenience function provided in all _Widgets, providing a simple
-               //              shorthand mechanism to put an existing (or newly created) Widget
-               //              somewhere in the dom, and allow chaining.
-               //
-               // reference:
-               //              The String id of a domNode, a domNode reference, or a reference to a Widget posessing
-               //              an addChild method.
-               //
-               // position:
-               //              If passed a string or domNode reference, the position argument
-               //              accepts a string just as dojo.place does, one of: "first", "last",
-               //              "before", or "after".
-               //
-               //              If passed a _Widget reference, and that widget reference has an ".addChild" method,
-               //              it will be called passing this widget instance into that method, supplying the optional
-               //              position index passed.
-               //
-               // returns:
-               //              dijit._Widget
-               //              Provides a useful return of the newly created dijit._Widget instance so you
-               //              can "chain" this function by instantiating, placing, then saving the return value
-               //              to a variable.
-               //
-               // example:
-               // |    // create a Button with no srcNodeRef, and place it in the body:
-               // |    var button = new dijit.form.Button({ label:"click" }).placeAt(dojo.body());
-               // |    // now, 'button' is still the widget reference to the newly created button
-               // |    dojo.connect(button, "onClick", function(e){ console.log('click'); });
-               //
-               // example:
-               // |    // create a button out of a node with id="src" and append it to id="wrapper":
-               // |    var button = new dijit.form.Button({},"src").placeAt("wrapper");
-               //
-               // example:
-               // |    // place a new button as the first element of some div
-               // |    var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
-               //
-               // example:
-               // |    // create a contentpane and add it to a TabContainer
-               // |    var tc = dijit.byId("myTabs");
-               // |    new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
+               //              Handle clicks on an item.
+               // tags:
+               //              private
 
-               if(reference.declaredClass && reference.addChild){
-                       reference.addChild(this, position);
+               // this can't be done in _onFocus since the _onFocus events occurs asynchronously
+               if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
+                       this._markActive();
+               }
+
+               this.focusChild(item);
+
+               if(item.disabled){ return false; }
+
+               if(item.popup){
+                       this._openPopup();
                }else{
-                       dojo.place(this.domNode, reference, position);
+                       // before calling user defined handler, close hierarchy of menus
+                       // and restore focus to place it was when menu was opened
+                       this.onExecute();
+
+                       // user defined handler for click
+                       item.onClick(evt);
                }
-               return this;
        },
 
-       _onShow: function(){
+       _openPopup: function(){
                // summary:
-               //              Internal method called when this widget is made visible.
-               //              See `onShow` for details.
-               this.onShow();
+               //              Open the popup to the side of/underneath the current menu item
+               // tags:
+               //              protected
+
+               this._stopPopupTimer();
+               var from_item = this.focusedChild;
+               if(!from_item){ return; } // the focused child lost focus since the timer was started
+               var popup = from_item.popup;
+               if(popup.isShowingNow){ return; }
+               if(this.currentPopup){
+                       this._stopPendingCloseTimer(this.currentPopup);
+                       pm.close(this.currentPopup);
+               }
+               popup.parentMenu = this;
+               popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
+               var self = this;
+               pm.open({
+                       parent: this,
+                       popup: popup,
+                       around: from_item.domNode,
+                       orient: this._orient || ["after", "before"],
+                       onCancel: function(){ // called when the child menu is canceled
+                               // set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
+                               // which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
+                               self.focusChild(from_item);     // put focus back on my node
+                               self._cleanUp();                        // close the submenu (be sure this is done _after_ focus is moved)
+                               from_item._setSelected(true); // oops, _cleanUp() deselected the item
+                               self.focusedChild = from_item;  // and unset focusedChild
+                       },
+                       onExecute: lang.hitch(this, "_cleanUp")
+               });
+
+               this.currentPopup = popup;
+               // detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
+               popup.connect(popup.domNode, "onmouseenter", lang.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close
+
+               if(popup.focus){
+                       // If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar),
+                       // if the cursor happens to collide with the popup, it will generate an onmouseover event
+                       // even though the mouse wasn't moved.  Use a setTimeout() to call popup.focus so that
+                       // our focus() call overrides the onmouseover event, rather than vice-versa.  (#8742)
+                       popup._focus_timer = setTimeout(lang.hitch(popup, function(){
+                               this._focus_timer = null;
+                               this.focus();
+                       }), 0);
+               }
        },
 
-       onShow: function(){
+       _markActive: function(){
                // summary:
-               //              Called when this widget becomes the selected pane in a
-               //              `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-               //              `dijit.layout.AccordionContainer`, etc.
-               //
-               //              Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
+               //              Mark this menu's state as active.
+               //              Called when this Menu gets focus from:
+               //                      1) clicking it (mouse or via space/arrow key)
+               //                      2) being opened by a parent menu.
+               //              This is not called just from mouse hover.
+               //              Focusing a menu via TAB does NOT automatically set isActive
+               //              since TAB is a navigation operation and not a selection one.
+               //              For Windows apps, pressing the ALT key focuses the menubar
+               //              menus (similar to TAB navigation) but the menu is not active
+               //              (ie no dropdown) until an item is clicked.
+               this.isActive = true;
+               domClass.replace(this.domNode, "dijitMenuActive", "dijitMenuPassive");
+       },
+
+       onOpen: function(/*Event*/ /*===== e =====*/){
+               // summary:
+               //              Callback when this menu is opened.
+               //              This is called by the popup manager as notification that the menu
+               //              was opened.
                // tags:
-               //              callback
+               //              private
+
+               this.isShowingNow = true;
+               this._markActive();
        },
 
-       onHide: function(){
+       _markInactive: function(){
                // summary:
-                       //              Called when another widget becomes the selected pane in a
-                       //              `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
-                       //              `dijit.layout.AccordionContainer`, etc.
-                       //
-                       //              Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
-                       // tags:
-                       //              callback
+               //              Mark this menu's state as inactive.
+               this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
+               domClass.replace(this.domNode, "dijitMenuPassive", "dijitMenuActive");
        },
 
        onClose: function(){
                // summary:
-               //              Called when this widget is being displayed as a popup (ex: a Calendar popped
-               //              up from a DateTextBox), and it is hidden.
-               //              This is called from the dijit.popup code, and should not be called directly.
-               //
-               //              Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
-               //              Callback if a user tries to close the child.   Child will be closed if this function returns true.
+               //              Callback when this menu is closed.
+               //              This is called by the popup manager as notification that the menu
+               //              was closed.
                // tags:
-               //              extension
-
-               return true;            // Boolean
-       }
-});
+               //              private
 
-})();
+               this._stopFocusTimer();
+               this._markInactive();
+               this.isShowingNow = false;
+               this.parentMenu = null;
+       },
 
-}
+       _closeChild: function(){
+               // summary:
+               //              Called when submenu is clicked or focus is lost.  Close hierarchy of menus.
+               // tags:
+               //              private
+               this._stopPopupTimer();
 
-if(!dojo._hasResource["dojo.string"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.string"] = true;
-dojo.provide("dojo.string");
+               if(this.currentPopup){
+                       // If focus is on a descendant MenuItem then move focus to me,
+                       // because IE doesn't like it when you display:none a node with focus,
+                       // and also so keyboard users don't lose control.
+                       // Likely, immediately after a user defined onClick handler will move focus somewhere
+                       // else, like a Dialog.
+                       if(array.indexOf(this._focusManager.activeStack, this.id) >= 0){
+                               domAttr.set(this.focusedChild.focusNode, "tabIndex", this.tabIndex);
+                               this.focusedChild.focusNode.focus();
+                       }
+                       // Close all popups that are open and descendants of this menu
+                       pm.close(this.currentPopup);
+                       this.currentPopup = null;
+               }
 
-/*=====
-dojo.string = { 
-       // summary: String utilities for Dojo
-};
-=====*/
+               if(this.focusedChild){ // unhighlight the focused item
+                       this.focusedChild._setSelected(false);
+                       this.focusedChild._onUnhover();
+                       this.focusedChild = null;
+               }
+       },
 
-dojo.string.rep = function(/*String*/str, /*Integer*/num){
-       //      summary:
-       //              Efficiently replicate a string `n` times.
-       //      str:
-       //              the string to replicate
-       //      num:
-       //              number of times to replicate the string
-       
-       if(num <= 0 || !str){ return ""; }
-       
-       var buf = [];
-       for(;;){
-               if(num & 1){
-                       buf.push(str);
+       _onItemFocus: function(/*MenuItem*/ item){
+               // summary:
+               //              Called when child of this Menu gets focus from:
+               //                      1) clicking it
+               //                      2) tabbing into it
+               //                      3) being opened by a parent menu.
+               //              This is not called just from mouse hover.
+               if(this._hoveredChild && this._hoveredChild != item){
+                       this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
                }
-               if(!(num >>= 1)){ break; }
-               str += str;
-       }
-       return buf.join("");    // String
-};
+       },
 
-dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
-       //      summary:
-       //              Pad a string to guarantee that it is at least `size` length by
-       //              filling with the character `ch` at either the start or end of the
-       //              string. Pads at the start, by default.
-       //      text:
-       //              the string to pad
-       //      size:
-       //              length to provide padding
-       //      ch:
-       //              character to pad, defaults to '0'
-       //      end:
-       //              adds padding at the end if true, otherwise pads at start
-       //      example:
-       //      |       // Fill the string to length 10 with "+" characters on the right.  Yields "Dojo++++++".
-       //      |       dojo.string.pad("Dojo", 10, "+", true);
+       _onBlur: function(){
+               // summary:
+               //              Called when focus is moved away from this Menu and it's submenus.
+               // tags:
+               //              protected
+               this._cleanUp();
+               this.inherited(arguments);
+       },
 
-       if(!ch){
-               ch = '0';
+       _cleanUp: function(){
+               // summary:
+               //              Called when the user is done with this menu.  Closes hierarchy of menus.
+               // tags:
+               //              private
+
+               this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
+               if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
+                       this._markInactive();
+               }
        }
-       var out = String(text),
-               pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
-       return end ? out + pad : pad + out;     // String
-};
+});
 
-dojo.string.substitute = function(     /*String*/              template, 
-                                                                       /*Object|Array*/map, 
-                                                                       /*Function?*/   transform, 
-                                                                       /*Object?*/             thisObject){
-       //      summary:
-       //              Performs parameterized substitutions on a string. Throws an
-       //              exception if any parameter is unmatched.
-       //      template: 
-       //              a string with expressions in the form `${key}` to be replaced or
-       //              `${key:format}` which specifies a format function. keys are case-sensitive. 
-       //      map:
-       //              hash to search for substitutions
-       //      transform: 
-       //              a function to process all parameters before substitution takes
-       //              place, e.g. mylib.encodeXML
-       //      thisObject: 
-       //              where to look for optional format function; default to the global
-       //              namespace
-       //      example:
-       //              Substitutes two expressions in a string from an Array or Object
-       //      |       // returns "File 'foo.html' is not found in directory '/temp'."
-       //      |       // by providing substitution data in an Array
-       //      |       dojo.string.substitute(
-       //      |               "File '${0}' is not found in directory '${1}'.",
-       //      |               ["foo.html","/temp"]
-       //      |       );
-       //      |
-       //      |       // also returns "File 'foo.html' is not found in directory '/temp'."
-       //      |       // but provides substitution data in an Object structure.  Dotted
-       //      |       // notation may be used to traverse the structure.
-       //      |       dojo.string.substitute(
-       //      |               "File '${name}' is not found in directory '${info.dir}'.",
-       //      |               { name: "foo.html", info: { dir: "/temp" } }
-       //      |       );
-       //      example:
-       //              Use a transform function to modify the values:
-       //      |       // returns "file 'foo.html' is not found in directory '/temp'."
-       //      |       dojo.string.substitute(
-       //      |               "${0} is not found in ${1}.",
-       //      |               ["foo.html","/temp"],
-       //      |               function(str){
-       //      |                       // try to figure out the type
-       //      |                       var prefix = (str.charAt(0) == "/") ? "directory": "file";
-       //      |                       return prefix + " '" + str + "'";
-       //      |               }
-       //      |       );
-       //      example:
-       //              Use a formatter
-       //      |       // returns "thinger -- howdy"
-       //      |       dojo.string.substitute(
-       //      |               "${0:postfix}", ["thinger"], null, {
-       //      |                       postfix: function(value, key){
-       //      |                               return value + " -- howdy";
-       //      |                       }
-       //      |               }
-       //      |       );
-
-       thisObject = thisObject || dojo.global;
-       transform = transform ? 
-               dojo.hitch(thisObject, transform) : function(v){ return v; };
-
-       return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
-               function(match, key, format){
-                       var value = dojo.getObject(key, false, map);
-                       if(format){
-                               value = dojo.getObject(format, false, thisObject).call(thisObject, value, key);
-                       }
-                       return transform(value, key).toString();
-               }); // String
-};
-
-/*=====
-dojo.string.trim = function(str){
-       //      summary:
-       //              Trims whitespace from both sides of the string
-       //      str: String
-       //              String to be trimmed
-       //      returns: String
-       //              Returns the trimmed string
-       //      description:
-       //              This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
-       //              The short yet performant version of this function is dojo.trim(),
-       //              which is part of Dojo base.  Uses String.prototype.trim instead, if available.
-       return "";      // String
-}
-=====*/
-
-dojo.string.trim = String.prototype.trim ?
-       dojo.trim : // aliasing to the native function
-       function(str){
-               str = str.replace(/^\s+/, '');
-               for(var i = str.length - 1; i >= 0; i--){
-                       if(/\S/.test(str.charAt(i))){
-                               str = str.substring(0, i + 1);
-                               break;
-                       }
-               }
-               return str;
-       };
-
-}
-
-if(!dojo._hasResource["dojo.cache"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cache"] = true;
-dojo.provide("dojo.cache");
+});
 
-/*=====
-dojo.cache = { 
+},
+'dijit/focus':function(){
+define("dijit/focus", [
+       "dojo/aspect",
+       "dojo/_base/declare", // declare
+       "dojo/dom", // domAttr.get dom.isDescendant
+       "dojo/dom-attr", // domAttr.get dom.isDescendant
+       "dojo/dom-construct", // connect to domConstruct.empty, domConstruct.destroy
+       "dojo/Evented",
+       "dojo/_base/lang", // lang.hitch
+       "dojo/on",
+       "dojo/ready",
+       "dojo/_base/sniff", // has("ie")
+       "dojo/Stateful",
+       "dojo/_base/unload", // unload.addOnWindowUnload
+       "dojo/_base/window", // win.body
+       "dojo/window", // winUtils.get
+       "./a11y",       // a11y.isTabNavigable
+       "./registry",   // registry.byId
+       "."             // to set dijit.focus
+], function(aspect, declare, dom, domAttr, domConstruct, Evented, lang, on, ready, has, Stateful, unload, win, winUtils,
+                       a11y, registry, dijit){
+
+       // module:
+       //              dijit/focus
        // summary:
-       //              A way to cache string content that is fetchable via `dojo.moduleUrl`.
-};
-=====*/
+       //              Returns a singleton that tracks the currently focused node, and which widgets are currently "active".
 
-(function(){
-       var cache = {};
-       dojo.cache = function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
+/*=====
+       dijit.focus = {
                // summary:
-               //              A getter and setter for storing the string content associated with the
-               //              module and url arguments.
-               // description:
-               //              module and url are used to call `dojo.moduleUrl()` to generate a module URL.
-               //              If value is specified, the cache value for the moduleUrl will be set to
-               //              that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
-               //              in its internal cache and return that cached value for the URL. To clear
-               //              a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
-               //              the URL contents, only modules on the same domain of the page can use this capability.
-               //              The build system can inline the cache values though, to allow for xdomain hosting.
-               // module: String||Object
-               //              If a String, the module name to use for the base part of the URL, similar to module argument
-               //              to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
-               //              generates a valid path for the cache item. For example, a dojo._Url object.
-               // url: String
-               //              The rest of the path to append to the path derived from the module argument. If
-               //              module is an object, then this second argument should be the "value" argument instead.
-               // value: String||Object?
-               //              If a String, the value to use in the cache for the module/url combination.
-               //              If an Object, it can have two properties: value and sanitize. The value property
-               //              should be the value to use in the cache, and sanitize can be set to true or false,
-               //              to indicate if XML declarations should be removed from the value and if the HTML
-               //              inside a body tag in the value should be extracted as the real value. The value argument
-               //              or the value property on the value argument are usually only used by the build system
-               //              as it inlines cache content.
-               //      example:
-               //              To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
-               //              of call is used to avoid an issue with the build system erroneously trying to intern
-               //              this example. To get the build system to intern your dojo.cache calls, use the
-               //              "dojo.cache" style of call):
-               //              |       //If template.html contains "<h1>Hello</h1>" that will be
-               //              |       //the value for the text variable.
-               //              |       var text = dojo["cache"]("my.module", "template.html");
-               //      example:
-               //              To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
-               //               (the dojo["cache"] style of call is used to avoid an issue with the build system 
-               //              erroneously trying to intern this example. To get the build system to intern your
-               //              dojo.cache calls, use the "dojo.cache" style of call):
-               //              |       //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-               //              |       //text variable will contain just "<h1>Hello</h1>".
-               //              |       var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
-               //      example:
-               //              Same example as previous, but demostrates how an object can be passed in as
-               //              the first argument, then the value argument can then be the second argument.
-               //              |       //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
-               //              |       //text variable will contain just "<h1>Hello</h1>".
-               //              |       var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
-
-               //Module could be a string, or an object that has a toString() method
-               //that will return a useful path. If it is an object, then the "url" argument
-               //will actually be the value argument.
-               if(typeof module == "string"){
-                       var pathObj = dojo.moduleUrl(module, url);
-               }else{
-                       pathObj = module;
-                       value = url;
-               }
-               var key = pathObj.toString();
+               //              Tracks the currently focused node, and which widgets are currently "active".
+               //              Access via require(["dijit/focus"], function(focus){ ... }).
+               //
+               //              A widget is considered active if it or a descendant widget has focus,
+               //              or if a non-focusable node of this widget or a descendant was recently clicked.
+               //
+               //              Call focus.watch("curNode", callback) to track the current focused DOMNode,
+               //              or focus.watch("activeStack", callback) to track the currently focused stack of widgets.
+               //
+               //              Call focus.on("widget-blur", func) or focus.on("widget-focus", ...) to monitor when
+               //              when widgets become active/inactive
+               //
+               //              Finally, focus(node) will focus a node, suppressing errors if the node doesn't exist.
 
-               var val = value;
-               if(value != undefined && !dojo.isString(value)){
-                       val = ("value" in value ? value.value : undefined);
-               }
+               // curNode: DomNode
+               //              Currently focused item on screen
+               curNode: null,
 
-               var sanitize = value && value.sanitize ? true : false;
+               // activeStack: dijit._Widget[]
+               //              List of currently active widgets (focused widget and it's ancestors)
+               activeStack: [],
 
-               if(typeof val == "string"){
-                       //We have a string, set cache value
-                       val = cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-               }else if(val === null){
-                       //Remove cached value
-                       delete cache[key];
-               }else{
-                       //Allow cache values to be empty strings. If key property does
-                       //not exist, fetch it.
-                       if(!(key in cache)){
-                               val = dojo._getText(key);
-                               cache[key] = sanitize ? dojo.cache._sanitize(val) : val;
-                       }
-                       val = cache[key];
-               }
-               return val; //String
-       };
+               registerIframe: function(iframe){
+                       // summary:
+                       //              Registers listeners on the specified iframe so that any click
+                       //              or focus event on that iframe (or anything in it) is reported
+                       //              as a focus/click event on the <iframe> itself.
+                       // description:
+                       //              Currently only used by editor.
+                       // returns:
+                       //              Handle with remove() method to deregister.
+               },
 
-       dojo.cache._sanitize = function(/*String*/val){
-               // summary: 
-               //              Strips <?xml ...?> declarations so that external SVG and XML
-               //              documents can be added to a document without worry. Also, if the string
-               //              is an HTML document, only the part inside the body tag is returned.
-               // description:
-               //              Copied from dijit._Templated._sanitizeTemplateString.
-               if(val){
-                       val = val.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
-                       var matches = val.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-                       if(matches){
-                               val = matches[1];
-                       }
-               }else{
-                       val = "";
+               registerWin: function(targetWindow, effectiveNode){
+                       // summary:
+                       //              Registers listeners on the specified window (either the main
+                       //              window or an iframe's window) to detect when the user has clicked somewhere
+                       //              or focused somewhere.
+                       // description:
+                       //              Users should call registerIframe() instead of this method.
+                       // targetWindow: Window?
+                       //              If specified this is the window associated with the iframe,
+                       //              i.e. iframe.contentWindow.
+                       // effectiveNode: DOMNode?
+                       //              If specified, report any focus events inside targetWindow as
+                       //              an event on effectiveNode, rather than on evt.target.
+                       // returns:
+                       //              Handle with remove() method to deregister.
                }
-               return val; //String
        };
-})();
-
-}
-
-if(!dojo._hasResource["dijit._Templated"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._Templated"] = true;
-dojo.provide("dijit._Templated");
-
+=====*/
 
+       var FocusManager = declare([Stateful, Evented], {
+               // curNode: DomNode
+               //              Currently focused item on screen
+               curNode: null,
 
+               // activeStack: dijit._Widget[]
+               //              List of currently active widgets (focused widget and it's ancestors)
+               activeStack: [],
 
+               constructor: function(){
+                       // Don't leave curNode/prevNode pointing to bogus elements
+                       var check = lang.hitch(this, function(node){
+                               if(dom.isDescendant(this.curNode, node)){
+                                       this.set("curNode", null);
+                               }
+                               if(dom.isDescendant(this.prevNode, node)){
+                                       this.set("prevNode", null);
+                               }
+                       });
+                       aspect.before(domConstruct, "empty", check);
+                       aspect.before(domConstruct, "destroy", check);
+               },
 
+               registerIframe: function(/*DomNode*/ iframe){
+                       // summary:
+                       //              Registers listeners on the specified iframe so that any click
+                       //              or focus event on that iframe (or anything in it) is reported
+                       //              as a focus/click event on the <iframe> itself.
+                       // description:
+                       //              Currently only used by editor.
+                       // returns:
+                       //              Handle with remove() method to deregister.
+                       return this.registerWin(iframe.contentWindow, iframe);
+               },
 
-dojo.declare("dijit._Templated",
-       null,
-       {
-               // summary:
-               //              Mixin for widgets that are instantiated from a template
+               registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
+                       // summary:
+                       //              Registers listeners on the specified window (either the main
+                       //              window or an iframe's window) to detect when the user has clicked somewhere
+                       //              or focused somewhere.
+                       // description:
+                       //              Users should call registerIframe() instead of this method.
+                       // targetWindow:
+                       //              If specified this is the window associated with the iframe,
+                       //              i.e. iframe.contentWindow.
+                       // effectiveNode:
+                       //              If specified, report any focus events inside targetWindow as
+                       //              an event on effectiveNode, rather than on evt.target.
+                       // returns:
+                       //              Handle with remove() method to deregister.
 
-               // templateString: [protected] String
-               //              A string that represents the widget template. Pre-empts the
-               //              templatePath. In builds that have their strings "interned", the
-               //              templatePath is converted to an inline templateString, thereby
-               //              preventing a synchronous network call.
-               //
-               //              Use in conjunction with dojo.cache() to load from a file.
-               templateString: null,
+                       // TODO: make this function private in 2.0; Editor/users should call registerIframe(),
 
-               // templatePath: [protected deprecated] String
-               //              Path to template (HTML file) for this widget relative to dojo.baseUrl.
-               //              Deprecated: use templateString with dojo.cache() instead.
-               templatePath: null,
+                       var _this = this;
+                       var mousedownListener = function(evt){
+                               _this._justMouseDowned = true;
+                               setTimeout(function(){ _this._justMouseDowned = false; }, 0);
 
-               // widgetsInTemplate: [protected] Boolean
-               //              Should we parse the template to find widgets that might be
-               //              declared in markup inside it?  False by default.
-               widgetsInTemplate: false,
+                               // workaround weird IE bug where the click is on an orphaned node
+                               // (first time clicking a Select/DropDownButton inside a TooltipDialog)
+                               if(has("ie") && evt && evt.srcElement && evt.srcElement.parentNode == null){
+                                       return;
+                               }
 
-               // skipNodeCache: [protected] Boolean
-               //              If using a cached widget template node poses issues for a
-               //              particular widget class, it can set this property to ensure
-               //              that its template is always re-built from a string
-               _skipNodeCache: false,
+                               _this._onTouchNode(effectiveNode || evt.target || evt.srcElement, "mouse");
+                       };
 
-               // _earlyTemplatedStartup: Boolean
-               //              A fallback to preserve the 1.0 - 1.3 behavior of children in
-               //              templates having their startup called before the parent widget
-               //              fires postCreate. Defaults to 'false', causing child widgets to
-               //              have their .startup() called immediately before a parent widget
-               //              .startup(), but always after the parent .postCreate(). Set to
-               //              'true' to re-enable to previous, arguably broken, behavior.
-               _earlyTemplatedStartup: false,
+                       // Listen for blur and focus events on targetWindow's document.
+                       // IIRC, I'm using attachEvent() rather than dojo.connect() because focus/blur events don't bubble
+                       // through dojo.connect(), and also maybe to catch the focus events early, before onfocus handlers
+                       // fire.
+                       // Connect to <html> (rather than document) on IE to avoid memory leaks, but document on other browsers because
+                       // (at least for FF) the focus event doesn't fire on <html> or <body>.
+                       var doc = has("ie") ? targetWindow.document.documentElement : targetWindow.document;
+                       if(doc){
+                               if(has("ie")){
+                                       targetWindow.document.body.attachEvent('onmousedown', mousedownListener);
+                                       var activateListener = function(evt){
+                                               // IE reports that nodes like <body> have gotten focus, even though they have tabIndex=-1,
+                                               // ignore those events
+                                               var tag = evt.srcElement.tagName.toLowerCase();
+                                               if(tag == "#document" || tag == "body"){ return; }
+
+                                               // Previous code called _onTouchNode() for any activate event on a non-focusable node.   Can
+                                               // probably just ignore such an event as it will be handled by onmousedown handler above, but
+                                               // leaving the code for now.
+                                               if(a11y.isTabNavigable(evt.srcElement)){
+                                                       _this._onFocusNode(effectiveNode || evt.srcElement);
+                                               }else{
+                                                       _this._onTouchNode(effectiveNode || evt.srcElement);
+                                               }
+                                       };
+                                       doc.attachEvent('onactivate', activateListener);
+                                       var deactivateListener =  function(evt){
+                                               _this._onBlurNode(effectiveNode || evt.srcElement);
+                                       };
+                                       doc.attachEvent('ondeactivate', deactivateListener);
 
-               // _attachPoints: [private] String[]
-               //              List of widget attribute names associated with dojoAttachPoint=... in the
-               //              template, ex: ["containerNode", "labelNode"]
-/*=====
-               _attachPoints: [],
- =====*/
+                                       return {
+                                               remove: function(){
+                                                       targetWindow.document.detachEvent('onmousedown', mousedownListener);
+                                                       doc.detachEvent('onactivate', activateListener);
+                                                       doc.detachEvent('ondeactivate', deactivateListener);
+                                                       doc = null;     // prevent memory leak (apparent circular reference via closure)
+                                               }
+                                       };
+                               }else{
+                                       doc.body.addEventListener('mousedown', mousedownListener, true);
+                                       doc.body.addEventListener('touchstart', mousedownListener, true);
+                                       var focusListener = function(evt){
+                                               _this._onFocusNode(effectiveNode || evt.target);
+                                       };
+                                       doc.addEventListener('focus', focusListener, true);
+                                       var blurListener = function(evt){
+                                               _this._onBlurNode(effectiveNode || evt.target);
+                                       };
+                                       doc.addEventListener('blur', blurListener, true);
 
-               constructor: function(){
-                       this._attachPoints = [];
+                                       return {
+                                               remove: function(){
+                                                       doc.body.removeEventListener('mousedown', mousedownListener, true);
+                                                       doc.body.removeEventListener('touchstart', mousedownListener, true);
+                                                       doc.removeEventListener('focus', focusListener, true);
+                                                       doc.removeEventListener('blur', blurListener, true);
+                                                       doc = null;     // prevent memory leak (apparent circular reference via closure)
+                                               }
+                                       };
+                               }
+                       }
                },
 
-               _stringRepl: function(tmpl){
+               _onBlurNode: function(/*DomNode*/ /*===== node =====*/){
                        // summary:
-                       //              Does substitution of ${foo} type properties in template string
-                       // tags:
-                       //              private
-                       var className = this.declaredClass, _this = this;
-                       // Cache contains a string because we need to do property replacement
-                       // do the property replacement
-                       return dojo.string.substitute(tmpl, this, function(value, key){
-                               if(key.charAt(0) == '!'){ value = dojo.getObject(key.substr(1), false, _this); }
-                               if(typeof value == "undefined"){ throw new Error(className+" template:"+key); } // a debugging aide
-                               if(value == null){ return ""; }
+                       //              Called when focus leaves a node.
+                       //              Usually ignored, _unless_ it *isn't* followed by touching another node,
+                       //              which indicates that we tabbed off the last field on the page,
+                       //              in which case every widget is marked inactive
+                       this.set("prevNode", this.curNode);
+                       this.set("curNode", null);
+
+                       if(this._justMouseDowned){
+                               // the mouse down caused a new widget to be marked as active; this blur event
+                               // is coming late, so ignore it.
+                               return;
+                       }
 
-                               // Substitution keys beginning with ! will skip the transform step,
-                               // in case a user wishes to insert unescaped markup, e.g. ${!foo}
-                               return key.charAt(0) == "!" ? value :
-                                       // Safer substitution, see heading "Attribute values" in
-                                       // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
-                                       value.toString().replace(/"/g,"&quot;"); //TODO: add &amp? use encodeXML method?
-                       }, this);
+                       // if the blur event isn't followed by a focus event then mark all widgets as inactive.
+                       if(this._clearActiveWidgetsTimer){
+                               clearTimeout(this._clearActiveWidgetsTimer);
+                       }
+                       this._clearActiveWidgetsTimer = setTimeout(lang.hitch(this, function(){
+                               delete this._clearActiveWidgetsTimer;
+                               this._setStack([]);
+                               this.prevNode = null;
+                       }), 100);
                },
 
-               // method over-ride
-               buildRendering: function(){
+               _onTouchNode: function(/*DomNode*/ node, /*String*/ by){
                        // summary:
-                       //              Construct the UI for this widget from a template, setting this.domNode.
-                       // tags:
-                       //              protected
-
-                       // Lookup cached version of template, and download to cache if it
-                       // isn't there already.  Returns either a DomNode or a string, depending on
-                       // whether or not the template contains ${foo} replacement parameters.
-                       var cached = dijit._Templated.getCachedTemplate(this.templatePath, this.templateString, this._skipNodeCache);
+                       //              Callback when node is focused or mouse-downed
+                       // node:
+                       //              The node that was touched.
+                       // by:
+                       //              "mouse" if the focus/touch was caused by a mouse down event
 
-                       var node;
-                       if(dojo.isString(cached)){
-                               node = dojo._toDom(this._stringRepl(cached));
-                               if(node.nodeType != 1){
-                                       // Flag common problems such as templates with multiple top level nodes (nodeType == 11)
-                                       throw new Error("Invalid template: " + cached);
-                               }
-                       }else{
-                               // if it's a node, all we have to do is clone it
-                               node = cached.cloneNode(true);
+                       // ignore the recent blurNode event
+                       if(this._clearActiveWidgetsTimer){
+                               clearTimeout(this._clearActiveWidgetsTimer);
+                               delete this._clearActiveWidgetsTimer;
                        }
 
-                       this.domNode = node;
-
-                       // recurse through the node, looking for, and attaching to, our
-                       // attachment points and events, which should be defined on the template node.
-                       this._attachTemplateNodes(node);
+                       // compute stack of active widgets (ex: ComboButton --> Menu --> MenuItem)
+                       var newStack=[];
+                       try{
+                               while(node){
+                                       var popupParent = domAttr.get(node, "dijitPopupParent");
+                                       if(popupParent){
+                                               node=registry.byId(popupParent).domNode;
+                                       }else if(node.tagName && node.tagName.toLowerCase() == "body"){
+                                               // is this the root of the document or just the root of an iframe?
+                                               if(node === win.body()){
+                                                       // node is the root of the main document
+                                                       break;
+                                               }
+                                               // otherwise, find the iframe this node refers to (can't access it via parentNode,
+                                               // need to do this trick instead). window.frameElement is supported in IE/FF/Webkit
+                                               node=winUtils.get(node.ownerDocument).frameElement;
+                                       }else{
+                                               // if this node is the root node of a widget, then add widget id to stack,
+                                               // except ignore clicks on disabled widgets (actually focusing a disabled widget still works,
+                                               // to support MenuItem)
+                                               var id = node.getAttribute && node.getAttribute("widgetId"),
+                                                       widget = id && registry.byId(id);
+                                               if(widget && !(by == "mouse" && widget.get("disabled"))){
+                                                       newStack.unshift(id);
+                                               }
+                                               node=node.parentNode;
+                                       }
+                               }
+                       }catch(e){ /* squelch */ }
 
-                       if(this.widgetsInTemplate){
-                               // Make sure dojoType is used for parsing widgets in template.
-                               // The dojo.parser.query could be changed from multiversion support.
-                               var parser = dojo.parser, qry, attr;
-                               if(parser._query != "[dojoType]"){
-                                       qry = parser._query;
-                                       attr = parser._attrName;
-                                       parser._query = "[dojoType]";
-                                       parser._attrName = "dojoType";
-                               }
-
-                               // Store widgets that we need to start at a later point in time
-                               var cw = (this._startupWidgets = dojo.parser.parse(node, {
-                                       noStart: !this._earlyTemplatedStartup,
-                                       inherited: {dir: this.dir, lang: this.lang}
-                               }));
+                       this._setStack(newStack, by);
+               },
 
-                               // Restore the query.
-                               if(qry){
-                                       parser._query = qry;
-                                       parser._attrName = attr;
-                               }
+               _onFocusNode: function(/*DomNode*/ node){
+                       // summary:
+                       //              Callback when node is focused
 
-                               this._supportingWidgets = dijit.findWidgets(node);
+                       if(!node){
+                               return;
+                       }
 
-                               this._attachTemplateNodes(cw, function(n,p){
-                                       return n[p];
-                               });
+                       if(node.nodeType == 9){
+                               // Ignore focus events on the document itself.  This is here so that
+                               // (for example) clicking the up/down arrows of a spinner
+                               // (which don't get focus) won't cause that widget to blur. (FF issue)
+                               return;
                        }
 
-                       this._fillContent(this.srcNodeRef);
+                       this._onTouchNode(node);
+
+                       if(node == this.curNode){ return; }
+                       this.set("curNode", node);
                },
 
-               _fillContent: function(/*DomNode*/ source){
+               _setStack: function(/*String[]*/ newStack, /*String*/ by){
                        // summary:
-                       //              Relocate source contents to templated container node.
-                       //              this.containerNode must be able to receive children, or exceptions will be thrown.
-                       // tags:
-                       //              protected
-                       var dest = this.containerNode;
-                       if(source && dest){
-                               while(source.hasChildNodes()){
-                                       dest.appendChild(source.firstChild);
+                       //              The stack of active widgets has changed.  Send out appropriate events and records new stack.
+                       // newStack:
+                       //              array of widget id's, starting from the top (outermost) widget
+                       // by:
+                       //              "mouse" if the focus/touch was caused by a mouse down event
+
+                       var oldStack = this.activeStack;
+                       this.set("activeStack", newStack);
+
+                       // compare old stack to new stack to see how many elements they have in common
+                       for(var nCommon=0; nCommon<Math.min(oldStack.length, newStack.length); nCommon++){
+                               if(oldStack[nCommon] != newStack[nCommon]){
+                                       break;
                                }
                        }
-               },
-
-               _attachTemplateNodes: function(rootNode, getAttrFunc){
-                       // summary:
-                       //              Iterate through the template and attach functions and nodes accordingly.
-                       // description:
-                       //              Map widget properties and functions to the handlers specified in
-                       //              the dom node and it's descendants. This function iterates over all
-                       //              nodes and looks for these properties:
-                       //                      * dojoAttachPoint
-                       //                      * dojoAttachEvent
-                       //                      * waiRole
-                       //                      * waiState
-                       // rootNode: DomNode|Array[Widgets]
-                       //              the node to search for properties. All children will be searched.
-                       // getAttrFunc: Function?
-                       //              a function which will be used to obtain property for a given
-                       //              DomNode/Widget
-                       // tags:
-                       //              private
-
-                       getAttrFunc = getAttrFunc || function(n,p){ return n.getAttribute(p); };
 
-                       var nodes = dojo.isArray(rootNode) ? rootNode : (rootNode.all || rootNode.getElementsByTagName("*"));
-                       var x = dojo.isArray(rootNode) ? 0 : -1;
-                       for(; x<nodes.length; x++){
-                               var baseNode = (x == -1) ? rootNode : nodes[x];
-                               if(this.widgetsInTemplate && getAttrFunc(baseNode, "dojoType")){
-                                       continue;
-                               }
-                               // Process dojoAttachPoint
-                               var attachPoint = getAttrFunc(baseNode, "dojoAttachPoint");
-                               if(attachPoint){
-                                       var point, points = attachPoint.split(/\s*,\s*/);
-                                       while((point = points.shift())){
-                                               if(dojo.isArray(this[point])){
-                                                       this[point].push(baseNode);
-                                               }else{
-                                                       this[point]=baseNode;
-                                               }
-                                               this._attachPoints.push(point);
+                       var widget;
+                       // for all elements that have gone out of focus, set focused=false
+                       for(var i=oldStack.length-1; i>=nCommon; i--){
+                               widget = registry.byId(oldStack[i]);
+                               if(widget){
+                                       widget._hasBeenBlurred = true;          // TODO: used by form widgets, should be moved there
+                                       widget.set("focused", false);
+                                       if(widget._focusManager == this){
+                                               widget._onBlur(by);
                                        }
+                                       this.emit("widget-blur", widget, by);
                                }
+                       }
 
-                               // Process dojoAttachEvent
-                               var attachEvent = getAttrFunc(baseNode, "dojoAttachEvent");
-                               if(attachEvent){
-                                       // NOTE: we want to support attributes that have the form
-                                       // "domEvent: nativeEvent; ..."
-                                       var event, events = attachEvent.split(/\s*,\s*/);
-                                       var trim = dojo.trim;
-                                       while((event = events.shift())){
-                                               if(event){
-                                                       var thisFunc = null;
-                                                       if(event.indexOf(":") != -1){
-                                                               // oh, if only JS had tuple assignment
-                                                               var funcNameArr = event.split(":");
-                                                               event = trim(funcNameArr[0]);
-                                                               thisFunc = trim(funcNameArr[1]);
-                                                       }else{
-                                                               event = trim(event);
-                                                       }
-                                                       if(!thisFunc){
-                                                               thisFunc = event;
-                                                       }
-                                                       this.connect(baseNode, event, thisFunc);
-                                               }
+                       // for all element that have come into focus, set focused=true
+                       for(i=nCommon; i<newStack.length; i++){
+                               widget = registry.byId(newStack[i]);
+                               if(widget){
+                                       widget.set("focused", true);
+                                       if(widget._focusManager == this){
+                                               widget._onFocus(by);
                                        }
-                               }
-
-                               // waiRole, waiState
-                               var role = getAttrFunc(baseNode, "waiRole");
-                               if(role){
-                                       dijit.setWaiRole(baseNode, role);
-                               }
-                               var values = getAttrFunc(baseNode, "waiState");
-                               if(values){
-                                       dojo.forEach(values.split(/\s*,\s*/), function(stateValue){
-                                               if(stateValue.indexOf('-') != -1){
-                                                       var pair = stateValue.split('-');
-                                                       dijit.setWaiState(baseNode, pair[0], pair[1]);
-                                               }
-                                       });
+                                       this.emit("widget-focus", widget, by);
                                }
                        }
                },
 
-               startup: function(){
-                       dojo.forEach(this._startupWidgets, function(w){
-                               if(w && !w._started && w.startup){
-                                       w.startup();
-                               }
-                       });
-                       this.inherited(arguments);
-               },
-
-               destroyRendering: function(){
-                       // Delete all attach points to prevent IE6 memory leaks.
-                       dojo.forEach(this._attachPoints, function(point){
-                               delete this[point];
-                       }, this);
-                       this._attachPoints = [];
-
-                       this.inherited(arguments);
-               }
-       }
-);
-
-// key is either templatePath or templateString; object is either string or DOM tree
-dijit._Templated._templateCache = {};
-
-dijit._Templated.getCachedTemplate = function(templatePath, templateString, alwaysUseString){
-       // summary:
-       //              Static method to get a template based on the templatePath or
-       //              templateString key
-       // templatePath: String||dojo.uri.Uri
-       //              The URL to get the template from.
-       // templateString: String?
-       //              a string to use in lieu of fetching the template from a URL. Takes precedence
-       //              over templatePath
-       // returns: Mixed
-       //              Either string (if there are ${} variables that need to be replaced) or just
-       //              a DOM tree (if the node can be cloned directly)
-
-       // is it already cached?
-       var tmplts = dijit._Templated._templateCache;
-       var key = templateString || templatePath;
-       var cached = tmplts[key];
-       if(cached){
-               try{
-                       // if the cached value is an innerHTML string (no ownerDocument) or a DOM tree created within the current document, then use the current cached value
-                       if(!cached.ownerDocument || cached.ownerDocument == dojo.doc){
-                               // string or node of the same document
-                               return cached;
+               focus: function(node){
+                       // summary:
+                       //              Focus the specified node, suppressing errors if they occur
+                       if(node){
+                               try{ node.focus(); }catch(e){/*quiet*/}
                        }
-               }catch(e){ /* squelch */ } // IE can throw an exception if cached.ownerDocument was reloaded
-               dojo.destroy(cached);
-       }
+               }
+       });
 
-       // If necessary, load template string from template path
-       if(!templateString){
-               templateString = dojo.cache(templatePath, {sanitize: true});
-       }
-       templateString = dojo.string.trim(templateString);
+       var singleton = new FocusManager();
 
-       if(alwaysUseString || templateString.match(/\$\{([^\}]+)\}/g)){
-               // there are variables in the template so all we can do is cache the string
-               return (tmplts[key] = templateString); //String
-       }else{
-               // there are no variables in the template so we can cache the DOM tree
-               var node = dojo._toDom(templateString);
-               if(node.nodeType != 1){
-                       throw new Error("Invalid template: " + templateString);
+       // register top window and all the iframes it contains
+       ready(function(){
+               var handle = singleton.registerWin(win.doc.parentWindow || win.doc.defaultView);
+               if(has("ie")){
+                       unload.addOnWindowUnload(function(){
+                               handle.remove();
+                               handle = null;
+                       })
                }
-               return (tmplts[key] = node); //Node
-       }
-};
+       });
 
-if(dojo.isIE){
-       dojo.addOnWindowUnload(function(){
-               var cache = dijit._Templated._templateCache;
-               for(var key in cache){
-                       var value = cache[key];
-                       if(typeof value == "object"){ // value is either a string or a DOM node template
-                               dojo.destroy(value);
-                       }
-                       delete cache[key];
+       // Setup dijit.focus as a pointer to the singleton but also (for backwards compatibility)
+       // as a function to set focus.
+       dijit.focus = function(node){
+               singleton.focus(node);  // indirection here allows dijit/_base/focus.js to override behavior
+       };
+       for(var attr in singleton){
+               if(!/^_/.test(attr)){
+                       dijit.focus[attr] = typeof singleton[attr] == "function" ? lang.hitch(singleton, attr) : singleton[attr];
                }
+       }
+       singleton.watch(function(attr, oldVal, newVal){
+               dijit.focus[attr] = newVal;
        });
-}
 
-// These arguments can be specified for widgets which are used in templates.
-// Since any widget can be specified as sub widgets in template, mix it
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget,{
-       dojoAttachEvent: "",
-       dojoAttachPoint: "",
-       waiRole: "",
-       waiState:""
+       return singleton;
 });
 
-}
-
-if(!dojo._hasResource["dijit._Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._Container"] = true;
-dojo.provide("dijit._Container");
+},
+'dojo/i18n':function(){
+define("dojo/i18n", ["./_base/kernel", "require", "./has", "./_base/array", "./_base/config", "./_base/lang", "./_base/xhr", "./json"],
+       function(dojo, require, has, array, config, lang, xhr, json) {
+       // module:
+       //              dojo/i18n
+       // summary:
+       //              This module implements the !dojo/i18n plugin and the v1.6- i18n API
+       // description:
+       //              We choose to include our own plugin to leverage functionality already contained in dojo
+       //              and thereby reduce the size of the plugin compared to various loader implementations. Also, this
+       //              allows foreign AMD loaders to be used without their plugins.
 
-dojo.declare("dijit._Container",
-       null,
-       {
-               // summary:
-               //              Mixin for widgets that contain a set of widget children.
-               // description:
-               //              Use this mixin for widgets that needs to know about and
-               //              keep track of their widget children. Suitable for widgets like BorderContainer
-               //              and TabContainer which contain (only) a set of child widgets.
-               //
-               //              It's not suitable for widgets like ContentPane
-               //              which contains mixed HTML (plain DOM nodes in addition to widgets),
-               //              and where contained widgets are not necessarily directly below
-               //              this.containerNode.   In that case calls like addChild(node, position)
-               //              wouldn't make sense.
 
-               // isContainer: [protected] Boolean
-               //              Indicates that this widget acts as a "parent" to the descendant widgets.
-               //              When the parent is started it will call startup() on the child widgets.
-               //              See also `isLayoutContainer`.
-               isContainer: true,
+       has.add("dojo-preload-i18n-Api",
+               // if true, define the preload localizations machinery
+               1
+       );
 
-               buildRendering: function(){
-                       this.inherited(arguments);
-                       if(!this.containerNode){
-                               // all widgets with descendants must set containerNode
-                                       this.containerNode = this.domNode;
-                       }
-               },
+       true || has.add("dojo-v1x-i18n-Api",
+               // if true, define the v1.x i18n functions
+               1
+       );
 
-               addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
-                       // summary:
-                       //              Makes the given widget a child of this widget.
-                       // description:
-                       //              Inserts specified child widget's dom node as a child of this widget's
-                       //              container node, and possibly does other processing (such as layout).
+       var
+               thisModule= dojo.i18n=
+                       // the dojo.i18n module
+                       {},
+
+               nlsRe=
+                       // regexp for reconstructing the master bundle name from parts of the regexp match
+                       // nlsRe.exec("foo/bar/baz/nls/en-ca/foo") gives:
+                       // ["foo/bar/baz/nls/en-ca/foo", "foo/bar/baz/nls/", "/", "/", "en-ca", "foo"]
+                       // nlsRe.exec("foo/bar/baz/nls/foo") gives:
+                       // ["foo/bar/baz/nls/foo", "foo/bar/baz/nls/", "/", "/", "foo", ""]
+                       // so, if match[5] is blank, it means this is the top bundle definition.
+                       // courtesy of http://requirejs.org
+                       /(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,
+
+               getAvailableLocales= function(
+                       root,
+                       locale,
+                       bundlePath,
+                       bundleName
+               ){
+                       // return a vector of module ids containing all available locales with respect to the target locale
+                       // For example, assuming:
+                       //       * the root bundle indicates specific bundles for "fr" and "fr-ca",
+                       //       * bundlePath is "myPackage/nls"
+                       //       * bundleName is "myBundle"
+                       // Then a locale argument of "fr-ca" would return
+                       //       ["myPackage/nls/myBundle", "myPackage/nls/fr/myBundle", "myPackage/nls/fr-ca/myBundle"]
+                       // Notice that bundles are returned least-specific to most-specific, starting with the root.
+                       //
+                       // If root===false indicates we're working with a pre-AMD i18n bundle that doesn't tell about the available locales;
+                       // therefore, assume everything is available and get 404 errors that indicate a particular localization is not available
+                       //
 
-                       var refNode = this.containerNode;
-                       if(insertIndex && typeof insertIndex == "number"){
-                               var children = this.getChildren();
-                               if(children && children.length >= insertIndex){
-                                       refNode = children[insertIndex-1].domNode;
-                                       insertIndex = "after";
+                       for(var result= [bundlePath + bundleName], localeParts= locale.split("-"), current= "", i= 0; i<localeParts.length; i++){
+                               current+= (current ? "-" : "") + localeParts[i];
+                               if(!root || root[current]){
+                                       result.push(bundlePath + current + "/" + bundleName);
                                }
                        }
-                       dojo.place(widget.domNode, refNode, insertIndex);
-
-                       // If I've been started but the child widget hasn't been started,
-                       // start it now.  Make sure to do this after widget has been
-                       // inserted into the DOM tree, so it can see that it's being controlled by me,
-                       // so it doesn't try to size itself.
-                       if(this._started && !widget._started){
-                               widget.startup();
-                       }
+                       return result;
                },
 
-               removeChild: function(/*Widget or int*/ widget){
-                       // summary:
-                       //              Removes the passed widget instance from this widget but does
-                       //              not destroy it.  You can also pass in an integer indicating
-                       //              the index within the container to remove
-
-                       if(typeof widget == "number" && widget > 0){
-                               widget = this.getChildren()[widget];
-                       }
-
-                       if(widget){
-                               var node = widget.domNode;
-                               if(node && node.parentNode){
-                                       node.parentNode.removeChild(node); // detach but don't destroy
-                               }
-                       }
-               },
+               cache= {},
 
-               hasChildren: function(){
-                       // summary:
-                       //              Returns true if widget has children, i.e. if this.containerNode contains something.
-                       return this.getChildren().length > 0;   // Boolean
+               getL10nName= dojo.getL10nName = function(moduleName, bundleName, locale){
+                       locale = locale ? locale.toLowerCase() : dojo.locale;
+                       moduleName = "dojo/i18n!" + moduleName.replace(/\./g, "/");
+                       bundleName = bundleName.replace(/\./g, "/");
+                       return (/root/i.test(locale)) ?
+                               (moduleName + "/nls/" + bundleName) :
+                               (moduleName + "/nls/" + locale + "/" + bundleName);
                },
 
-               destroyDescendants: function(/*Boolean*/ preserveDom){
-                       // summary:
-                       //      Destroys all the widgets inside this.containerNode,
-                       //      but not this widget itself
-                       dojo.forEach(this.getChildren(), function(child){ child.destroyRecursive(preserveDom); });
+               doLoad = function(require, bundlePathAndName, bundlePath, bundleName, locale, load){
+                       // get the root bundle which instructs which other bundles are required to construct the localized bundle
+                       require([bundlePathAndName], function(root){
+                               var current= lang.clone(root.root),
+                                       availableLocales= getAvailableLocales(!root._v1x && root, locale, bundlePath, bundleName);
+                               require(availableLocales, function(){
+                                       for (var i= 1; i<availableLocales.length; i++){
+                                               current= lang.mixin(lang.clone(current), arguments[i]);
+                                       }
+                                       // target may not have been resolve (e.g., maybe only "fr" exists when "fr-ca" was requested)
+                                       var target= bundlePathAndName + "/" + locale;
+                                       cache[target]= current;
+                                       load();
+                               });
+                       });
                },
 
-               _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
-                       // summary:
-                       //              Get the next or previous widget sibling of child
-                       // dir:
-                       //              if 1, get the next sibling
-                       //              if -1, get the previous sibling
-                       // tags:
-                       //      private
-                       var node = child.domNode,
-                               which = (dir>0 ? "nextSibling" : "previousSibling");
-                       do{
-                               node = node[which];
-                       }while(node && (node.nodeType != 1 || !dijit.byNode(node)));
-                       return node && dijit.byNode(node);      // dijit._Widget
+               normalize = function(id, toAbsMid){
+                       // id may be relative
+                       // preload has form *preload*<path>/nls/<module>*<flattened locales> and
+                       // therefore never looks like a relative
+                       return /^\./.test(id) ? toAbsMid(id) : id;
                },
 
-               getIndexOfChild: function(/*dijit._Widget*/ child){
-                       // summary:
-                       //              Gets the index of the child in this container or -1 if not found
-                       return dojo.indexOf(this.getChildren(), child); // int
+               getLocalesToLoad = function(targetLocale){
+                       var list = config.extraLocale || [];
+                       list = lang.isArray(list) ? list : [list];
+                       list.push(targetLocale);
+                       return list;
                },
 
-               startup: function(){
-                       // summary:
-                       //              Called after all the widgets have been instantiated and their
-                       //              dom nodes have been inserted somewhere under dojo.doc.body.
+               load = function(id, require, load){
                        //
-                       //              Widgets should override this method to do any initialization
-                       //              dependent on other widgets existing, and then call
-                       //              this superclass method to finish things off.
+                       // id is in one of the following formats
                        //
-                       //              startup() in subclasses shouldn't do anything
-                       //              size related because the size of the widget hasn't been set yet.
-
-                       if(this._started){ return; }
+                       //      1. <path>/nls/<bundle>
+                       //              => load the bundle, localized to config.locale; load all bundles localized to
+                       //      config.extraLocale (if any); return the loaded bundle localized to config.locale.
+                       //
+                       //  2. <path>/nls/<locale>/<bundle>
+                       //              => load then return the bundle localized to <locale>
+                       //
+                       //  3. *preload*<path>/nls/<module>*<JSON array of available locales>
+                       //              => for config.locale and all config.extraLocale, load all bundles found
+                       //                 in the best-matching bundle rollup. A value of 1 is returned, which
+                       //         is meaningless other than to say the plugin is executing the requested
+                       //         preloads
+                       //
+                       // In cases 1 and 2, <path> is always normalized to an absolute module id upon entry; see
+                       // normalize. In case 3, it <path> is assumed to be absolue; this is arranged by the builder.
+                       //
+                       // To load a bundle means to insert the bundle into the plugin's cache and publish the bundle
+                       // value to the loader. Given <path>, <bundle>, and a particular <locale>, the cache key
+                       //
+                       //   <path>/nls/<bundle>/<locale>
+                       //
+                       // will hold the value. Similarly, then plugin will publish this value to the loader by
+                       //
+                       //   define("<path>/nls/<bundle>/<locale>", <bundle-value>);
+                       //
+                       // Given this algorithm, other machinery can provide fast load paths be preplacing
+                       // values in the plugin's cache, which is public. When a load is demanded the
+                       // cache is inspected before starting any loading. Explicitly placing values in the plugin
+                       // cache is an advanced/experimental feature that should not be needed; use at your own risk.
+                       //
+                       // For the normal AMD algorithm, the root bundle is loaded first, which instructs the
+                       // plugin what additional localized bundles are required for a particular locale. These
+                       // additional locales are loaded and a mix of the root and each progressively-specific
+                       // locale is returned. For example:
+                       //
+                       // 1. The client demands "dojo/i18n!some/path/nls/someBundle
+                       //
+                       // 2. The loader demands load(some/path/nls/someBundle)
+                       //
+                       // 3. This plugin require's "some/path/nls/someBundle", which is the root bundle.
+                       //
+                       // 4. Assuming config.locale is "ab-cd-ef" and the root bundle indicates that localizations
+                       //    are available for "ab" and "ab-cd-ef" (note the missing "ab-cd", then the plugin
+                       //    requires "some/path/nls/ab/someBundle" and "some/path/nls/ab-cd-ef/someBundle"
+                       //
+                       // 5. Upon receiving all required bundles, the plugin constructs the value of the bundle
+                       //    ab-cd-ef as...
+                       //
+                       //      mixin(mixin(mixin({}, require("some/path/nls/someBundle"),
+                       //        require("some/path/nls/ab/someBundle")),
+                       //          require("some/path/nls/ab-cd-ef/someBundle"));
+                       //
+                       //    This value is inserted into the cache and published to the loader at the
+                       //    key/module-id some/path/nls/someBundle/ab-cd-ef.
+                       //
+                       // The special preload signature (case 3) instructs the plugin to stop servicing all normal requests
+                       // (further preload requests will be serviced) until all ongoing preloading has completed.
+                       //
+                       // The preload signature instructs the plugin that a special rollup module is available that contains
+                       // one or more flattened, localized bundles. The JSON array of available locales indicates which locales
+                       // are available. Here is an example:
+                       //
+                       //   *preload*some/path/nls/someModule*["root", "ab", "ab-cd-ef"]
+                       //
+                       // This indicates the following rollup modules are available:
+                       //
+                       //   some/path/nls/someModule_ROOT
+                       //   some/path/nls/someModule_ab
+                       //   some/path/nls/someModule_ab-cd-ef
+                       //
+                       // Each of these modules is a normal AMD module that contains one or more flattened bundles in a hash.
+                       // For example, assume someModule contained the bundles some/bundle/path/someBundle and
+                       // some/bundle/path/someOtherBundle, then some/path/nls/someModule_ab would be expressed as folllows:
+                       //
+                       // define({
+                       //   some/bundle/path/someBundle:<value of someBundle, flattened with respect to locale ab>,
+                       //   some/bundle/path/someOtherBundle:<value of someOtherBundle, flattened with respect to locale ab>,
+                       // });
+                       //
+                       // E.g., given this design, preloading for locale=="ab" can execute the following algorithm:
+                       //
+                       // require(["some/path/nls/someModule_ab"], function(rollup){
+                       //   for(var p in rollup){
+                       //     var id = p + "/ab",
+                       //     cache[id] = rollup[p];
+                       //     define(id, rollup[p]);
+                       //   }
+                       // });
+                       //
+                       // Similarly, if "ab-cd" is requested, the algorithm can determine that "ab" is the best available and
+                       // load accordingly.
+                       //
+                       // The builder will write such rollups for every layer if a non-empty localeList  profile property is
+                       // provided. Further, the builder will include the following cache entry in the cache associated with
+                       // any layer.
+                       //
+                       //   "*now":function(r){r(['dojo/i18n!*preload*<path>/nls/<module>*<JSON array of available locales>']);}
+                       //
+                       // The *now special cache module instructs the loader to apply the provided function to context-require
+                       // with respect to the particular layer being defined. This causes the plugin to hold all normal service
+                       // requests until all preloading is complete.
+                       //
+                       // Notice that this algorithm is rarely better than the standard AMD load algorithm. Consider the normal case
+                       // where the target locale has a single segment and a layer depends on a single bundle:
+                       //
+                       // Without Preloads:
+                       //
+                       //   1. Layer loads root bundle.
+                       //   2. bundle is demanded; plugin loads single localized bundle.
+                       //
+                       // With Preloads:
+                       //
+                       //   1. Layer causes preloading of target bundle.
+                       //   2. bundle is demanded; service is delayed until preloading complete; bundle is returned.
+                       //
+                       // In each case a single transaction is required to load the target bundle. In cases where multiple bundles
+                       // are required and/or the locale has multiple segments, preloads still requires a single transaction whereas
+                       // the normal path requires an additional transaction for each additional bundle/locale-segment. However all
+                       // of these additional transactions can be done concurrently. Owing to this analysis, the entire preloading
+                       // algorithm can be discard during a build by setting the has feature dojo-preload-i18n-Api to false.
+                       //
+                       if(has("dojo-preload-i18n-Api")){
+                               var split = id.split("*"),
+                                       preloadDemand = split[1]=="preload";
+                               if(preloadDemand){
+                                       if(!cache[id]){
+                                               // use cache[id] to prevent multiple preloads of the same preload; this shouldn't happen, but
+                                               // who knows what over-aggressive human optimizers may attempt
+                                               cache[id] = 1;
+                                               preloadL10n(split[2], json.parse(split[3]), 1);
+                                       }
+                                       // don't stall the loader!
+                                       load(1);
+                               }
+                               if(preloadDemand || waitForPreloads(id, require, load)){
+                                       return;
+                               }
+                       }
 
-                       // Startup all children of this widget
-                       dojo.forEach(this.getChildren(), function(child){ child.startup(); });
+                       var match= nlsRe.exec(id),
+                               bundlePath= match[1] + "/",
+                               bundleName= match[5] || match[4],
+                               bundlePathAndName= bundlePath + bundleName,
+                               localeSpecified = (match[5] && match[4]),
+                               targetLocale=  localeSpecified || dojo.locale,
+                               loadTarget= bundlePathAndName + "/" + targetLocale,
+                               loadList = localeSpecified ? [targetLocale] : getLocalesToLoad(targetLocale),
+                               remaining = loadList.length,
+                               finish = function(){
+                                       if(!--remaining){
+                                               load(lang.delegate(cache[loadTarget]));
+                                       }
+                               };
+                       array.forEach(loadList, function(locale){
+                               var target = bundlePathAndName + "/" + locale;
+                               if(has("dojo-preload-i18n-Api")){
+                                       checkForLegacyModules(target);
+                               }
+                               if(!cache[target]){
+                                       doLoad(require, bundlePathAndName, bundlePath, bundleName, locale, finish);
+                               }else{
+                                       finish();
+                               }
+                       });
+               };
 
-                       this.inherited(arguments);
-               }
+       if(has("dojo-unit-tests")){
+               var unitTests = thisModule.unitTests = [];
        }
-);
 
-}
+       if(has("dojo-preload-i18n-Api") || 1){
+               var normalizeLocale = thisModule.normalizeLocale= function(locale){
+                               var result = locale ? locale.toLowerCase() : dojo.locale;
+                               return result == "root" ? "ROOT" : result;
+                       },
 
-if(!dojo._hasResource["dijit._Contained"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._Contained"] = true;
-dojo.provide("dijit._Contained");
+                       isXd = function(mid){
+                               return (1 && 1) ?
+                                       require.isXdUrl(require.toUrl(mid + ".js")) :
+                                       true;
+                       },
 
-dojo.declare("dijit._Contained",
-               null,
-               {
-                       // summary:
-                       //              Mixin for widgets that are children of a container widget
-                       //
-                       // example:
-                       // |    // make a basic custom widget that knows about it's parents
-                       // |    dojo.declare("my.customClass",[dijit._Widget,dijit._Contained],{});
+                       preloading = 0,
 
-                       getParent: function(){
-                               // summary:
-                               //              Returns the parent widget of this widget, assuming the parent
-                               //              specifies isContainer
-                               var parent = dijit.getEnclosingWidget(this.domNode.parentNode);
-                               return parent && parent.isContainer ? parent : null;
-                       },
+                       preloadWaitQueue = [],
 
-                       _getSibling: function(/*String*/ which){
-                               // summary:
-                               //      Returns next or previous sibling
-                               // which:
-                               //      Either "next" or "previous"
-                               // tags:
-                               //      private
-                               var node = this.domNode;
-                               do{
-                                       node = node[which+"Sibling"];
-                               }while(node && node.nodeType != 1);
-                               return node && dijit.byNode(node);      // dijit._Widget
-                       },
+                       preloadL10n = thisModule._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated, /*boolean*/ guaranteedAmdFormat){
+                               //      summary:
+                               //              Load available flattened resource bundles associated with a particular module for dojo.locale and all dojo.config.extraLocale (if any)
+                               //
+                               //  descirption:
+                               //              Only called by built layer files. The entire locale hierarchy is loaded. For example,
+                               //              if locale=="ab-cd", then ROOT, "ab", and "ab-cd" are loaded. This is different than v1.6-
+                               //              in that the v1.6- would lonly load ab-cd...which was *always* flattened.
+                               //
+                               //              If guaranteedAmdFormat is true, then the module can be loaded with require thereby circumventing the detection algorithm
+                               //              and the extra possible extra transaction.
+                               //
+
+                               function forEachLocale(locale, func){
+                                       // given locale= "ab-cd-ef", calls func on "ab-cd-ef", "ab-cd", "ab", "ROOT"; stops calling the first time func returns truthy
+                                       var parts = locale.split("-");
+                                       while(parts.length){
+                                               if(func(parts.join("-"))){
+                                                       return true;
+                                               }
+                                               parts.pop();
+                                       }
+                                       return func("ROOT");
+                               }
 
-                       getPreviousSibling: function(){
-                               // summary:
-                               //              Returns null if this is the first child of the parent,
-                               //              otherwise returns the next element sibling to the "left".
+                               function preload(locale){
+                                       locale = normalizeLocale(locale);
+                                       forEachLocale(locale, function(loc){
+                                               if(array.indexOf(localesGenerated, loc)>=0){
+                                                       var mid = bundlePrefix.replace(/\./g, "/")+"_"+loc;
+                                                       preloading++;
+                                                       (isXd(mid) || guaranteedAmdFormat ? require : syncRequire)([mid], function(rollup){
+                                                               for(var p in rollup){
+                                                                       cache[p + "/" + locale] = rollup[p];
+                                                               }
+                                                               --preloading;
+                                                               while(!preloading && preloadWaitQueue.length){
+                                                                       load.apply(null, preloadWaitQueue.shift());
+                                                               }
+                                                       });
+                                                       return true;
+                                               }
+                                               return false;
+                                       });
+                               }
 
-                               return this._getSibling("previous"); // dijit._Widget
+                               preload();
+                               array.forEach(dojo.config.extraLocale, preload);
                        },
 
-                       getNextSibling: function(){
-                               // summary:
-                               //              Returns null if this is the last child of the parent,
-                               //              otherwise returns the next element sibling to the "right".
+                       waitForPreloads = function(id, require, load){
+                               if(preloading){
+                                       preloadWaitQueue.push([id, require, load]);
+                               }
+                               return preloading;
+                       };
+       }
 
-                               return this._getSibling("next"); // dijit._Widget
-                       },
+       if(1){
+               // this code path assumes the dojo loader and won't work with a standard AMD loader
+               var evalBundle=
+                               // use the function ctor to keep the minifiers away (also come close to global scope, but this is secondary)
+                               new Function(
+                                       "__bundle",                // the bundle to evalutate
+                                       "__checkForLegacyModules", // a function that checks if __bundle defined __mid in the global space
+                                       "__mid",                   // the mid that __bundle is intended to define
+
+                                       // returns one of:
+                                       //              1 => the bundle was an AMD bundle
+                                       //              a legacy bundle object that is the value of __mid
+                                       //              instance of Error => could not figure out how to evaluate bundle
+
+                                         // used to detect when __bundle calls define
+                                         "var define = function(){define.called = 1;},"
+                                       + "    require = function(){define.called = 1;};"
+
+                                       + "try{"
+                                       +               "define.called = 0;"
+                                       +               "eval(__bundle);"
+                                       +               "if(define.called==1)"
+                                                               // bundle called define; therefore signal it's an AMD bundle
+                                       +                       "return 1;"
+
+                                       +               "if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"
+                                                               // bundle was probably a v1.6- built NLS flattened NLS bundle that defined __mid in the global space
+                                       +                       "return __checkForLegacyModules;"
+
+                                       + "}catch(e){}"
+                                       // evaulating the bundle was *neither* an AMD *nor* a legacy flattened bundle
+                                       // either way, re-eval *after* surrounding with parentheses
+
+                                       + "try{"
+                                       +               "return eval('('+__bundle+')');"
+                                       + "}catch(e){"
+                                       +               "return e;"
+                                       + "}"
+                               ),
+
+                       syncRequire= function(deps, callback){
+                               var results= [];
+                               array.forEach(deps, function(mid){
+                                       var url= require.toUrl(mid + ".js");
+
+                                       function load(text){
+                                               var result = evalBundle(text, checkForLegacyModules, mid);
+                                               if(result===1){
+                                                       // the bundle was an AMD module; re-inject it through the normal AMD path
+                                                       // we gotta do this since it could be an anonymous module and simply evaluating
+                                                       // the text here won't provide the loader with the context to know what
+                                                       // module is being defined()'d. With browser caching, this should be free; further
+                                                       // this entire code path can be circumvented by using the AMD format to begin with
+                                                       require([mid], function(bundle){
+                                                               results.push(cache[url]= bundle);
+                                                       });
+                                               }else{
+                                                       if(result instanceof Error){
+                                                               console.error("failed to evaluate i18n bundle; url=" + url, result);
+                                                               result = {};
+                                                       }
+                                                       // nls/<locale>/<bundle-name> indicates not the root.
+                                                       results.push(cache[url] = (/nls\/[^\/]+\/[^\/]+$/.test(url) ? result : {root:result, _v1x:1}));
+                                               }
+                                       }
 
-                       getIndexInParent: function(){
-                               // summary:
-                               //              Returns the index of this widget within its container parent.
-                               //              It returns -1 if the parent does not exist, or if the parent
-                               //              is not a dijit._Container
+                                       if(cache[url]){
+                                               results.push(cache[url]);
+                                       }else{
+                                               var bundle= require.syncLoadNls(mid);
+                                               // don't need to check for legacy since syncLoadNls returns a module if the module
+                                               // (1) was already loaded, or (2) was in the cache. In case 1, if syncRequire is called
+                                               // from getLocalization --> load, then load will have called checkForLegacyModules() before
+                                               // calling syncRequire; if syncRequire is called from preloadLocalizations, then we
+                                               // don't care about checkForLegacyModules() because that will be done when a particular
+                                               // bundle is actually demanded. In case 2, checkForLegacyModules() is never relevant
+                                               // because cached modules are always v1.7+ built modules.
+                                               if(bundle){
+                                                       results.push(bundle);
+                                               }else{
+                                                       if(!xhr){
+                                                               try{
+                                                                       require.getText(url, true, load);
+                                                               }catch(e){
+                                                                       results.push(cache[url]= {});
+                                                               }
+                                                       }else{
+                                                               xhr.get({
+                                                                       url:url,
+                                                                       sync:true,
+                                                                       load:load,
+                                                                       error:function(){
+                                                                               results.push(cache[url]= {});
+                                                                       }
+                                                               });
+                                                       }
+                                               }
+                                       }
+                               });
+                               callback && callback.apply(null, results);
+                       },
 
-                               var p = this.getParent();
-                               if(!p || !p.getIndexOfChild){
-                                       return -1; // int
+                       checkForLegacyModules = function(target){
+                               // legacy code may have already loaded [e.g] the raw bundle x/y/z at x.y.z; when true, push into the cache
+                               for(var result, names = target.split("/"), object = dojo.global[names[0]], i = 1; object && i<names.length-1; object = object[names[i++]]){}
+                               if(object){
+                                       result = object[names[i]];
+                                       if(!result){
+                                               // fallback for incorrect bundle build of 1.6
+                                               result = object[names[i].replace(/-/g,"_")];
+                                       }
+                                       if(result){
+                                               cache[target] = result;
+                                       }
                                }
-                               return p.getIndexOfChild(this); // int
-                       }
-               }
-       );
-
-
-}
+                               return result;
+                       };
 
-if(!dojo._hasResource["dijit.layout._LayoutWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout._LayoutWidget"] = true;
-dojo.provide("dijit.layout._LayoutWidget");
+               thisModule.getLocalization= function(moduleName, bundleName, locale){
+                       var result,
+                               l10nName= getL10nName(moduleName, bundleName, locale).substring(10);
+                       load(l10nName, (!isXd(l10nName) ? syncRequire : require), function(result_){ result= result_; });
+                       return result;
+               };
 
+               if(has("dojo-unit-tests")){
+                       unitTests.push(function(doh){
+                               doh.register("tests.i18n.unit", function(t){
+                                       var check;
 
+                                       check = evalBundle("{prop:1}");
+                                       t.is({prop:1}, check); t.is(undefined, check[1]);
 
+                                       check = evalBundle("({prop:1})");
+                                       t.is({prop:1}, check); t.is(undefined, check[1]);
 
+                                       check = evalBundle("{'prop-x':1}");
+                                       t.is({'prop-x':1}, check); t.is(undefined, check[1]);
 
-dojo.declare("dijit.layout._LayoutWidget",
-       [dijit._Widget, dijit._Container, dijit._Contained],
-       {
-               // summary:
-               //              Base class for a _Container widget which is responsible for laying out its children.
-               //              Widgets which mixin this code must define layout() to manage placement and sizing of the children.
+                                       check = evalBundle("({'prop-x':1})");
+                                       t.is({'prop-x':1}, check); t.is(undefined, check[1]);
 
-               // baseClass: [protected extension] String
-               //              This class name is applied to the widget's domNode
-               //              and also may be used to generate names for sub nodes,
-               //              for example dijitTabContainer-content.
-               baseClass: "dijitLayoutContainer",
+                                       check = evalBundle("define({'prop-x':1})");
+                                       t.is(1, check);
 
-               // isLayoutContainer: [protected] Boolean
-               //              Indicates that this widget is going to call resize() on its
-               //              children widgets, setting their size, when they become visible.
-               isLayoutContainer: true,
+                                       check = evalBundle("this is total nonsense and should throw an error");
+                                       t.is(check instanceof Error, true);
+                               });
+                       });
+               }
+       }
 
-               postCreate: function(){
-                       dojo.addClass(this.domNode, "dijitContainer");
+       return lang.mixin(thisModule, {
+               dynamic:true,
+               normalize:normalize,
+               load:load,
+               cache:cache
+       });
+});
 
-                       this.inherited(arguments);
-               },
+},
+'dijit/hccss':function(){
+define("dijit/hccss", [
+       "require",                      // require.toUrl
+       "dojo/_base/config", // config.blankGif
+       "dojo/dom-class", // domClass.add domConstruct.create domStyle.getComputedStyle
+       "dojo/dom-construct", // domClass.add domConstruct.create domStyle.getComputedStyle
+       "dojo/dom-style", // domClass.add domConstruct.create domStyle.getComputedStyle
+       "dojo/ready", // ready
+       "dojo/_base/sniff", // has("ie") has("mozilla")
+       "dojo/_base/window" // win.body
+], function(require, config, domClass, domConstruct, domStyle, ready, has, win){
+
+       // module:
+       //              dijit/hccss
+       // summary:
+       //              Test if computer is in high contrast mode, and sets dijit_a11y flag on <body> if it is.
 
-               startup: function(){
+       if(has("ie") || has("mozilla")){        // NOTE: checking in Safari messes things up
+               // priority is 90 to run ahead of parser priority of 100
+               ready(90, function(){
                        // summary:
-                       //              Called after all the widgets have been instantiated and their
-                       //              dom nodes have been inserted somewhere under dojo.doc.body.
-                       //
-                       //              Widgets should override this method to do any initialization
-                       //              dependent on other widgets existing, and then call
-                       //              this superclass method to finish things off.
-                       //
-                       //              startup() in subclasses shouldn't do anything
-                       //              size related because the size of the widget hasn't been set yet.
+                       //              Detects if we are in high-contrast mode or not
 
-                       if(this._started){ return; }
-
-                       // Need to call inherited first - so that child widgets get started
-                       // up correctly
-                       this.inherited(arguments);
+                       // create div for testing if high contrast mode is on or images are turned off
+                       var div = domConstruct.create("div",{
+                               id: "a11yTestNode",
+                               style:{
+                                       cssText:'border: 1px solid;'
+                                               + 'border-color:red green;'
+                                               + 'position: absolute;'
+                                               + 'height: 5px;'
+                                               + 'top: -999px;'
+                                               + 'background-image: url("' + (config.blankGif || require.toUrl("dojo/resources/blank.gif")) + '");'
+                               }
+                       }, win.body());
+
+                       // test it
+                       var cs = domStyle.getComputedStyle(div);
+                       if(cs){
+                               var bkImg = cs.backgroundImage;
+                               var needsA11y = (cs.borderTopColor == cs.borderRightColor) || (bkImg != null && (bkImg == "none" || bkImg == "url(invalid-url:)" ));
+                               if(needsA11y){
+                                       domClass.add(win.body(), "dijit_a11y");
+                               }
+                               if(has("ie")){
+                                       div.outerHTML = "";             // prevent mixed-content warning, see http://support.microsoft.com/kb/925014
+                               }else{
+                                       win.body().removeChild(div);
+                               }
+                       }
+               });
+       }
+});
 
-                       // If I am a not being controlled by a parent layout widget...
-                       var parent = this.getParent && this.getParent()
-                       if(!(parent && parent.isLayoutContainer)){
-                               // Do recursive sizing and layout of all my descendants
-                               // (passing in no argument to resize means that it has to glean the size itself)
-                               this.resize();
+},
+'dijit/tree/ForestStoreModel':function(){
+define("dijit/tree/ForestStoreModel", [
+       "dojo/_base/array", // array.indexOf array.some
+       "dojo/_base/declare", // declare
+       "dojo/_base/lang", // lang.hitch
+       "dojo/_base/window", // win.global
+       "./TreeStoreModel"
+], function(array, declare, lang, win, TreeStoreModel){
 
-                               // Since my parent isn't a layout container, and my style *may be* width=height=100%
-                               // or something similar (either set directly or via a CSS class),
-                               // monitor when my size changes so that I can re-layout.
-                               // For browsers where I can't directly monitor when my size changes,
-                               // monitor when the viewport changes size, which *may* indicate a size change for me.
-                               this.connect(dojo.isIE ? this.domNode : dojo.global, 'onresize', function(){
-                                       // Using function(){} closure to ensure no arguments to resize.
-                                       this.resize();
-                               });
-                       }
-               },
+/*=====
+var TreeStoreModel = dijit.tree.TreeStoreModel;
+=====*/
 
-               resize: function(changeSize, resultSize){
-                       // summary:
-                       //              Call this to resize a widget, or after its size has changed.
-                       // description:
-                       //              Change size mode:
-                       //                      When changeSize is specified, changes the marginBox of this widget
-                       //                      and forces it to relayout its contents accordingly.
-                       //                      changeSize may specify height, width, or both.
-                       //
-                       //                      If resultSize is specified it indicates the size the widget will
-                       //                      become after changeSize has been applied.
-                       //
-                       //              Notification mode:
-                       //                      When changeSize is null, indicates that the caller has already changed
-                       //                      the size of the widget, or perhaps it changed because the browser
-                       //                      window was resized.  Tells widget to relayout its contents accordingly.
-                       //
-                       //                      If resultSize is also specified it indicates the size the widget has
-                       //                      become.
-                       //
-                       //              In either mode, this method also:
-                       //                      1. Sets this._borderBox and this._contentBox to the new size of
-                       //                              the widget.  Queries the current domNode size if necessary.
-                       //                      2. Calls layout() to resize contents (and maybe adjust child widgets).
-                       //
-                       // changeSize: Object?
-                       //              Sets the widget to this margin-box size and position.
-                       //              May include any/all of the following properties:
-                       //      |       {w: int, h: int, l: int, t: int}
-                       //
-                       // resultSize: Object?
-                       //              The margin-box size of this widget after applying changeSize (if
-                       //              changeSize is specified).  If caller knows this size and
-                       //              passes it in, we don't need to query the browser to get the size.
-                       //      |       {w: int, h: int}
+// module:
+//             dijit/tree/ForestStoreModel
+// summary:
+//             Interface between a dijit.Tree and a dojo.data store that doesn't have a root item,
+//             a.k.a. a store that has multiple "top level" items.
 
-                       var node = this.domNode;
+return declare("dijit.tree.ForestStoreModel", TreeStoreModel, {
+       // summary:
+       //              Interface between a dijit.Tree and a dojo.data store that doesn't have a root item,
+       //              a.k.a. a store that has multiple "top level" items.
+       //
+       // description
+       //              Use this class to wrap a dojo.data store, making all the items matching the specified query
+       //              appear as children of a fabricated "root item".  If no query is specified then all the
+       //              items returned by fetch() on the underlying store become children of the root item.
+       //              This class allows dijit.Tree to assume a single root item, even if the store doesn't have one.
+       //
+       //              When using this class the developer must override a number of methods according to their app and
+       //              data, including:
+       //                      - onNewRootItem
+       //                      - onAddToRoot
+       //                      - onLeaveRoot
+       //                      - onNewItem
+       //                      - onSetItem
 
-                       // set margin box size, unless it wasn't specified, in which case use current size
-                       if(changeSize){
-                               dojo.marginBox(node, changeSize);
+       // Parameters to constructor
 
-                               // set offset of the node
-                               if(changeSize.t){ node.style.top = changeSize.t + "px"; }
-                               if(changeSize.l){ node.style.left = changeSize.l + "px"; }
-                       }
+       // rootId: String
+       //              ID of fabricated root item
+       rootId: "$root$",
 
-                       // If either height or width wasn't specified by the user, then query node for it.
-                       // But note that setting the margin box and then immediately querying dimensions may return
-                       // inaccurate results, so try not to depend on it.
-                       var mb = resultSize || {};
-                       dojo.mixin(mb, changeSize || {});       // changeSize overrides resultSize
-                       if( !("h" in mb) || !("w" in mb) ){
-                               mb = dojo.mixin(dojo.marginBox(node), mb);      // just use dojo.marginBox() to fill in missing values
-                       }
+       // rootLabel: String
+       //              Label of fabricated root item
+       rootLabel: "ROOT",
 
-                       // Compute and save the size of my border box and content box
-                       // (w/out calling dojo.contentBox() since that may fail if size was recently set)
-                       var cs = dojo.getComputedStyle(node);
-                       var me = dojo._getMarginExtents(node, cs);
-                       var be = dojo._getBorderExtents(node, cs);
-                       var bb = (this._borderBox = {
-                               w: mb.w - (me.w + be.w),
-                               h: mb.h - (me.h + be.h)
-                       });
-                       var pe = dojo._getPadExtents(node, cs);
-                       this._contentBox = {
-                               l: dojo._toPixelValue(node, cs.paddingLeft),
-                               t: dojo._toPixelValue(node, cs.paddingTop),
-                               w: bb.w - pe.w,
-                               h: bb.h - pe.h
-                       };
+       // query: String
+       //              Specifies the set of children of the root item.
+       // example:
+       //      |       {type:'continent'}
+       query: null,
 
-                       // Callback for widget to adjust size of its children
-                       this.layout();
-               },
+       // End of parameters to constructor
 
-               layout: function(){
-                       // summary:
-                       //              Widgets override this method to size and position their contents/children.
-                       //              When this is called this._contentBox is guaranteed to be set (see resize()).
-                       //
-                       //              This is called after startup(), and also when the widget's size has been
-                       //              changed.
-                       // tags:
-                       //              protected extension
-               },
+       constructor: function(params){
+               // summary:
+               //              Sets up variables, etc.
+               // tags:
+               //              private
 
-               _setupChild: function(/*dijit._Widget*/child){
-                       // summary:
-                       //              Common setup for initial children and children which are added after startup
-                       // tags:
-                       //              protected extension
+               // Make dummy root item
+               this.root = {
+                       store: this,
+                       root: true,
+                       id: params.rootId,
+                       label: params.rootLabel,
+                       children: params.rootChildren   // optional param
+               };
+       },
 
-                       dojo.addClass(child.domNode, this.baseClass+"-child");
-                       if(child.baseClass){
-                               dojo.addClass(child.domNode, this.baseClass+"-"+child.baseClass);
-                       }
-               },
+       // =======================================================================
+       // Methods for traversing hierarchy
 
-               addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-                       // Overrides _Container.addChild() to call _setupChild()
-                       this.inherited(arguments);
-                       if(this._started){
-                               this._setupChild(child);
-                       }
-               },
+       mayHaveChildren: function(/*dojo.data.Item*/ item){
+               // summary:
+               //              Tells if an item has or may have children.  Implementing logic here
+               //              avoids showing +/- expando icon for nodes that we know don't have children.
+               //              (For efficiency reasons we may not want to check if an element actually
+               //              has children until user clicks the expando node)
+               // tags:
+               //              extension
+               return item === this.root || this.inherited(arguments);
+       },
 
-               removeChild: function(/*dijit._Widget*/ child){
-                       // Overrides _Container.removeChild() to remove class added by _setupChild()
-                       dojo.removeClass(child.domNode, this.baseClass+"-child");
-                       if(child.baseClass){
-                               dojo.removeClass(child.domNode, this.baseClass+"-"+child.baseClass);
+       getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
+               // summary:
+               //              Calls onComplete() with array of child items of given parent item, all loaded.
+               if(parentItem === this.root){
+                       if(this.root.children){
+                               // already loaded, just return
+                               callback(this.root.children);
+                       }else{
+                               this.store.fetch({
+                                       query: this.query,
+                                       onComplete: lang.hitch(this, function(items){
+                                               this.root.children = items;
+                                               callback(items);
+                                       }),
+                                       onError: onError
+                               });
                        }
+               }else{
                        this.inherited(arguments);
                }
-       }
-);
+       },
 
-dijit.layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
-       // summary:
-       //              Given the margin-box size of a node, return its content box size.
-       //              Functions like dojo.contentBox() but is more reliable since it doesn't have
-       //              to wait for the browser to compute sizes.
-       var cs = dojo.getComputedStyle(node);
-       var me = dojo._getMarginExtents(node, cs);
-       var pb = dojo._getPadBorderExtents(node, cs);
-       return {
-               l: dojo._toPixelValue(node, cs.paddingLeft),
-               t: dojo._toPixelValue(node, cs.paddingTop),
-               w: mb.w - (me.w + pb.w),
-               h: mb.h - (me.h + pb.h)
-       };
-};
+       // =======================================================================
+       // Inspecting items
 
-(function(){
-       var capitalize = function(word){
-               return word.substring(0,1).toUpperCase() + word.substring(1);
-       };
+       isItem: function(/* anything */ something){
+               return (something === this.root) ? true : this.inherited(arguments);
+       },
 
-       var size = function(widget, dim){
-               // size the child
-               widget.resize ? widget.resize(dim) : dojo.marginBox(widget.domNode, dim);
+       fetchItemByIdentity: function(/* object */ keywordArgs){
+               if(keywordArgs.identity == this.root.id){
+                       var scope = keywordArgs.scope?keywordArgs.scope:win.global;
+                       if(keywordArgs.onItem){
+                               keywordArgs.onItem.call(scope, this.root);
+                       }
+               }else{
+                       this.inherited(arguments);
+               }
+       },
 
-               // record child's size, but favor our own numbers when we have them.
-               // the browser lies sometimes
-               dojo.mixin(widget, dojo.marginBox(widget.domNode));
-               dojo.mixin(widget, dim);
-       };
+       getIdentity: function(/* item */ item){
+               return (item === this.root) ? this.root.id : this.inherited(arguments);
+       },
 
-       dijit.layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Object[]*/ children){
-               // summary
-               //              Layout a bunch of child dom nodes within a parent dom node
-               // container:
-               //              parent node
-               // dim:
-               //              {l, t, w, h} object specifying dimensions of container into which to place children
-               // children:
-               //              an array like [ {domNode: foo, layoutAlign: "bottom" }, {domNode: bar, layoutAlign: "client"} ]
+       getLabel: function(/* item */ item){
+               return  (item === this.root) ? this.root.label : this.inherited(arguments);
+       },
 
-               // copy dim because we are going to modify it
-               dim = dojo.mixin({}, dim);
+       // =======================================================================
+       // Write interface
 
-               dojo.addClass(container, "dijitLayoutContainer");
+       newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
+               // summary:
+               //              Creates a new item.   See dojo.data.api.Write for details on args.
+               //              Used in drag & drop when item from external source dropped onto tree.
+               if(parent === this.root){
+                       this.onNewRootItem(args);
+                       return this.store.newItem(args);
+               }else{
+                       return this.inherited(arguments);
+               }
+       },
 
-               // Move "client" elements to the end of the array for layout.  a11y dictates that the author
-               // needs to be able to put them in the document in tab-order, but this algorithm requires that
-               // client be last.
-               children = dojo.filter(children, function(item){ return item.layoutAlign != "client"; })
-                       .concat(dojo.filter(children, function(item){ return item.layoutAlign == "client"; }));
+       onNewRootItem: function(/* dojo.dnd.Item */ /*===== args =====*/){
+               // summary:
+               //              User can override this method to modify a new element that's being
+               //              added to the root of the tree, for example to add a flag like root=true
+       },
 
-               // set positions/sizes
-               dojo.forEach(children, function(child){
-                       var elm = child.domNode,
-                               pos = child.layoutAlign;
+       pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
+               // summary:
+               //              Move or copy an item from one parent item to another.
+               //              Used in drag & drop
+               if(oldParentItem === this.root){
+                       if(!bCopy){
+                               // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
+                               // this.query... thus triggering an onChildrenChange() event to notify the Tree
+                               // that this element is no longer a child of the root node
+                               this.onLeaveRoot(childItem);
+                       }
+               }
+               this.inherited(arguments, [childItem,
+                       oldParentItem === this.root ? null : oldParentItem,
+                       newParentItem === this.root ? null : newParentItem,
+                       bCopy,
+                       insertIndex
+               ]);
+               if(newParentItem === this.root){
+                       // It's onAddToRoot()'s responsibility to modify the item so it matches
+                       // this.query... thus triggering an onChildrenChange() event to notify the Tree
+                       // that this element is now a child of the root node
+                       this.onAddToRoot(childItem);
+               }
+       },
 
-                       // set elem to upper left corner of unused space; may move it later
-                       var elmStyle = elm.style;
-                       elmStyle.left = dim.l+"px";
-                       elmStyle.top = dim.t+"px";
-                       elmStyle.bottom = elmStyle.right = "auto";
+       // =======================================================================
+       // Handling for top level children
+
+       onAddToRoot: function(/* item */ item){
+               // summary:
+               //              Called when item added to root of tree; user must override this method
+               //              to modify the item so that it matches the query for top level items
+               // example:
+               //      |       store.setValue(item, "root", true);
+               // tags:
+               //              extension
+               console.log(this, ": item ", item, " added to root");
+       },
 
-                       dojo.addClass(elm, "dijitAlign" + capitalize(pos));
+       onLeaveRoot: function(/* item */ item){
+               // summary:
+               //              Called when item removed from root of tree; user must override this method
+               //              to modify the item so it doesn't match the query for top level items
+               // example:
+               //      |       store.unsetAttribute(item, "root");
+               // tags:
+               //              extension
+               console.log(this, ": item ", item, " removed from root");
+       },
 
-                       // set size && adjust record of remaining space.
-                       // note that setting the width of a <div> may affect its height.
-                       if(pos == "top" || pos == "bottom"){
-                               size(child, { w: dim.w });
-                               dim.h -= child.h;
-                               if(pos == "top"){
-                                       dim.t += child.h;
-                               }else{
-                                       elmStyle.top = dim.t + dim.h + "px";
-                               }
-                       }else if(pos == "left" || pos == "right"){
-                               size(child, { h: dim.h });
-                               dim.w -= child.w;
-                               if(pos == "left"){
-                                       dim.l += child.w;
-                               }else{
-                                       elmStyle.left = dim.l + dim.w + "px";
+       // =======================================================================
+       // Events from data store
+
+       _requeryTop: function(){
+               // reruns the query for the children of the root node,
+               // sending out an onSet notification if those children have changed
+               var oldChildren = this.root.children || [];
+               this.store.fetch({
+                       query: this.query,
+                       onComplete: lang.hitch(this, function(newChildren){
+                               this.root.children = newChildren;
+
+                               // If the list of children or the order of children has changed...
+                               if(oldChildren.length != newChildren.length ||
+                                       array.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
+                                       this.onChildrenChange(this.root, newChildren);
                                }
-                       }else if(pos == "client"){
-                               size(child, dim);
-                       }
+                       })
                });
-       };
+       },
 
-})();
+       onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
+               // summary:
+               //              Handler for when new items appear in the store.  Developers should override this
+               //              method to be more efficient based on their app/data.
+               // description:
+               //              Note that the default implementation requeries the top level items every time
+               //              a new item is created, since any new item could be a top level item (even in
+               //              addition to being a child of another item, since items can have multiple parents).
+               //
+               //              If developers can detect which items are possible top level items (based on the item and the
+               //              parentInfo parameters), they should override this method to only call _requeryTop() for top
+               //              level items.  Often all top level items have parentInfo==null, but
+               //              that will depend on which store you use and what your data is like.
+               // tags:
+               //              extension
+               this._requeryTop();
 
-}
+               this.inherited(arguments);
+       },
 
-if(!dojo._hasResource["dijit._CssStateMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._CssStateMixin"] = true;
-dojo.provide("dijit._CssStateMixin");
+       onDeleteItem: function(/*Object*/ item){
+               // summary:
+               //              Handler for delete notifications from underlying store
 
+               // check if this was a child of root, and if so send notification that root's children
+               // have changed
+               if(array.indexOf(this.root.children, item) != -1){
+                       this._requeryTop();
+               }
 
-dojo.declare("dijit._CssStateMixin", [], {
-       // summary:
-       //              Mixin for widgets to set CSS classes on the widget DOM nodes depending on hover/mouse press/focus
-       //              state changes, and also higher-level state changes such becoming disabled or selected.
-       //
-       // description:
-       //              By mixing this class into your widget, and setting the this.baseClass attribute, it will automatically
-       //              maintain CSS classes on the widget root node (this.domNode) depending on hover,
-       //              active, focus, etc. state.   Ex: with a baseClass of dijitButton, it will apply the classes
-       //              dijitButtonHovered and dijitButtonActive, as the user moves the mouse over the widget and clicks it.
-       //
-       //              It also sets CSS like dijitButtonDisabled based on widget semantic state.
-       //
-       //              By setting the cssStateNodes attribute, a widget can also track events on subnodes (like buttons
-       //              within the widget).
+               this.inherited(arguments);
+       },
 
-       // cssStateNodes: [protected] Object
-       //              List of sub-nodes within the widget that need CSS classes applied on mouse hover/press and focus
-       //.
-       //              Each entry in the hash is a an attachpoint names (like "upArrowButton") mapped to a CSS class names
-       //              (like "dijitUpArrowButton"). Example:
-       //      |               {
-       //      |                       "upArrowButton": "dijitUpArrowButton",
-       //      |                       "downArrowButton": "dijitDownArrowButton"
-       //      |               }
-       //              The above will set the CSS class dijitUpArrowButton to the this.upArrowButton DOMNode when it
-       //              is hovered, etc.
-       cssStateNodes: {},
+       onSetItem: function(/* item */ item,
+                                       /* attribute-name-string */ attribute,
+                                       /* object | array */ oldValue,
+                                       /* object | array */ newValue){
+               // summary:
+               //              Updates the tree view according to changes to an item in the data store.
+               //              Developers should override this method to be more efficient based on their app/data.
+               // description:
+               //              Handles updates to an item's children by calling onChildrenChange(), and
+               //              other updates to an item by calling onChange().
+               //
+               //              Also, any change to any item re-executes the query for the tree's top-level items,
+               //              since this modified item may have started/stopped matching the query for top level items.
+               //
+               //              If possible, developers should override this function to only call _requeryTop() when
+               //              the change to the item has caused it to stop/start being a top level item in the tree.
+               // tags:
+               //              extension
 
-       postCreate: function(){
+               this._requeryTop();
                this.inherited(arguments);
+       }
 
-               // Automatically monitor mouse events (essentially :hover and :active) on this.domNode
-               dojo.forEach(["onmouseenter", "onmouseleave", "onmousedown"], function(e){
-                       this.connect(this.domNode, e, "_cssMouseEvent");
-               }, this);
-               
-               // Monitoring changes to disabled, readonly, etc. state, and update CSS class of root node
-               this.connect(this, "set", function(name, value){
-                       if(arguments.length >= 2 && {disabled: true, readOnly: true, checked:true, selected:true}[name]){
-                               this._setStateClass();
-                       }
-               });
+});
 
-               // The widget coming in/out of the focus change affects it's state
-               dojo.forEach(["_onFocus", "_onBlur"], function(ap){
-                       this.connect(this, ap, "_setStateClass");
-               }, this);
+});
 
-               // Events on sub nodes within the widget
-               for(var ap in this.cssStateNodes){
-                       this._trackMouseState(this[ap], this.cssStateNodes[ap]);
-               }
-               // Set state initially; there's probably no hover/active/focus state but widget might be
-               // disabled/readonly so we want to set CSS classes for those conditions.
-               this._setStateClass();
+},
+'url:dijit/layout/templates/AccordionButton.html':"<div data-dojo-attach-event='onclick:_onTitleClick' class='dijitAccordionTitle' role=\"presentation\">\n\t<div data-dojo-attach-point='titleNode,focusNode' data-dojo-attach-event='onkeypress:_onTitleKeyPress'\n\t\t\tclass='dijitAccordionTitleFocus' role=\"tab\" aria-expanded=\"false\"\n\t\t><span class='dijitInline dijitAccordionArrow' role=\"presentation\"></span\n\t\t><span class='arrowTextUp' role=\"presentation\">+</span\n\t\t><span class='arrowTextDown' role=\"presentation\">-</span\n\t\t><img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" data-dojo-attach-point='iconNode' style=\"vertical-align: middle\" role=\"presentation\"/>\n\t\t<span role=\"presentation\" data-dojo-attach-point='titleTextNode' class='dijitAccordionText'></span>\n\t</div>\n</div>\n",
+'dijit/form/_ComboBoxMenuMixin':function(){
+define("dijit/form/_ComboBoxMenuMixin", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/window", // win.doc.createTextNode
+       "dojo/i18n!./nls/ComboBox"
+], function(array, declare, domAttr, i18n, win){
+
+// module:
+//             dijit/form/_ComboBoxMenuMixin
+// summary:
+//             Focus-less menu for internal use in `dijit.form.ComboBox`
+
+return declare( "dijit.form._ComboBoxMenuMixin", null, {
+       // summary:
+       //              Focus-less menu for internal use in `dijit.form.ComboBox`
+       // tags:
+       //              private
+
+       // _messages: Object
+       //              Holds "next" and "previous" text for paging buttons on drop down
+       _messages: null,
+
+       postMixInProperties: function(){
+               this.inherited(arguments);
+               this._messages = i18n.getLocalization("dijit.form", "ComboBox", this.lang);
        },
 
-       _cssMouseEvent: function(/*Event*/ event){
-               // summary:
-               //      Sets _hovering and _active properties depending on mouse state,
-               //      then calls _setStateClass() to set appropriate CSS classes for this.domNode.
+       buildRendering: function(){
+               this.inherited(arguments);
 
-               if(!this.disabled){
-                       switch(event.type){
-                               case "mouseenter":
-                               case "mouseover":       // generated on non-IE browsers even though we connected to mouseenter
-                                       this._hovering = true;
-                                       this._active = this._mouseDown;
-                                       break;
+               // fill in template with i18n messages
+               this.previousButton.innerHTML = this._messages["previousMessage"];
+               this.nextButton.innerHTML = this._messages["nextMessage"];
+       },
 
-                               case "mouseleave":
-                               case "mouseout":        // generated on non-IE browsers even though we connected to mouseleave
-                                       this._hovering = false;
-                                       this._active = false;
-                                       break;
+       _setValueAttr: function(/*Object*/ value){
+               this.value = value;
+               this.onChange(value);
+       },
 
-                               case "mousedown" :
-                                       this._active = true;
-                                       this._mouseDown = true;
-                                       // Set a global event to handle mouseup, so it fires properly
-                                       // even if the cursor leaves this.domNode before the mouse up event.
-                                       // Alternately could set active=false on mouseout.
-                                       var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
-                                               this._active = false;
-                                               this._mouseDown = false;
-                                               this._setStateClass();
-                                               this.disconnect(mouseUpConnector);
-                                       });
-                                       break;
-                       }
-                       this._setStateClass();
+       onClick: function(/*DomNode*/ node){
+               if(node == this.previousButton){
+                       this._setSelectedAttr(null);
+                       this.onPage(-1);
+               }else if(node == this.nextButton){
+                       this._setSelectedAttr(null);
+                       this.onPage(1);
+               }else{
+                       this.onChange(node);
                }
        },
 
-       _setStateClass: function(){
+       // stubs
+       onChange: function(/*Number*/ /*===== direction =====*/){
                // summary:
-               //              Update the visual state of the widget by setting the css classes on this.domNode
-               //              (or this.stateNode if defined) by combining this.baseClass with
-               //              various suffixes that represent the current widget state(s).
-               //
-               // description:
-               //              In the case where a widget has multiple
-               //              states, it sets the class based on all possible
-               //              combinations.  For example, an invalid form widget that is being hovered
-               //              will be "dijitInput dijitInputInvalid dijitInputHover dijitInputInvalidHover".
-               //
-               //              The widget may have one or more of the following states, determined
-               //              by this.state, this.checked, this.valid, and this.selected:
-               //                      - Error - ValidationTextBox sets this.state to "Error" if the current input value is invalid
-               //                      - Checked - ex: a checkmark or a ToggleButton in a checked state, will have this.checked==true
-               //                      - Selected - ex: currently selected tab will have this.selected==true
-               //
-               //              In addition, it may have one or more of the following states,
-               //              based on this.disabled and flags set in _onMouse (this._active, this._hovering, this._focused):
-               //                      - Disabled      - if the widget is disabled
-               //                      - Active                - if the mouse (or space/enter key?) is being pressed down
-               //                      - Focused               - if the widget has focus
-               //                      - Hover         - if the mouse is over the widget
-
-               // Compute new set of classes
-               var newStateClasses = this.baseClass.split(" ");
+               //              Notifies ComboBox/FilteringSelect that user selected an option.
+               // tags:
+               //              callback
+       },
 
-               function multiply(modifier){
-                       newStateClasses = newStateClasses.concat(dojo.map(newStateClasses, function(c){ return c+modifier; }), "dijit"+modifier);
-               }
+       onPage: function(/*Number*/ /*===== direction =====*/){
+               // summary:
+               //              Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page.
+               // tags:
+               //              callback
+       },
 
-               if(!this.isLeftToRight()){
-                       // For RTL mode we need to set an addition class like dijitTextBoxRtl.
-                       multiply("Rtl");
-               }
+       onClose: function(){
+               // summary:
+               //              Callback from dijit.popup code to this widget, notifying it that it closed
+               // tags:
+               //              private
+               this._setSelectedAttr(null);
+       },
 
-               if(this.checked){
-                       multiply("Checked");
-               }
-               if(this.state){
-                       multiply(this.state);
-               }
-               if(this.selected){
-                       multiply("Selected");
-               }
+       _createOption: function(/*Object*/ item, labelFunc){
+               // summary:
+               //              Creates an option to appear on the popup menu subclassed by
+               //              `dijit.form.FilteringSelect`.
 
-               if(this.disabled){
-                       multiply("Disabled");
-               }else if(this.readOnly){
-                       multiply("ReadOnly");
+               var menuitem = this._createMenuItem();
+               var labelObject = labelFunc(item);
+               if(labelObject.html){
+                       menuitem.innerHTML = labelObject.label;
                }else{
-                       if(this._active){
-                               multiply("Active");
-                       }else if(this._hovering){
-                               multiply("Hover");
-                       }
+                       menuitem.appendChild(
+                               win.doc.createTextNode(labelObject.label)
+                       );
                }
-
-               if(this._focused){
-                       multiply("Focused");
+               // #3250: in blank options, assign a normal height
+               if(menuitem.innerHTML == ""){
+                       menuitem.innerHTML = "&#160;";  // &nbsp;
                }
 
-               // Remove old state classes and add new ones.
-               // For performance concerns we only write into domNode.className once.
-               var tn = this.stateNode || this.domNode,
-                       classHash = {}; // set of all classes (state and otherwise) for node
+               // update menuitem.dir if BidiSupport was required
+               this.applyTextDir(menuitem, (menuitem.innerText || menuitem.textContent || ""));
 
-               dojo.forEach(tn.className.split(" "), function(c){ classHash[c] = true; });
+               menuitem.item=item;
+               return menuitem;
+       },
 
-               if("_stateClasses" in this){
-                       dojo.forEach(this._stateClasses, function(c){ delete classHash[c]; });
+       createOptions: function(results, options, labelFunc){
+               // summary:
+               //              Fills in the items in the drop down list
+               // results:
+               //              Array of items
+               // options:
+               //              The options to the query function of the store
+               //
+               // labelFunc:
+               //              Function to produce a label in the drop down list from a dojo.data item
+
+               // display "Previous . . ." button
+               this.previousButton.style.display = (options.start == 0) ? "none" : "";
+               domAttr.set(this.previousButton, "id", this.id + "_prev");
+               // create options using _createOption function defined by parent
+               // ComboBox (or FilteringSelect) class
+               // #2309:
+               //              iterate over cache nondestructively
+               array.forEach(results, function(item, i){
+                       var menuitem = this._createOption(item, labelFunc);
+                       domAttr.set(menuitem, "id", this.id + i);
+                       this.nextButton.parentNode.insertBefore(menuitem, this.nextButton);
+               }, this);
+               // display "Next . . ." button
+               var displayMore = false;
+               // Try to determine if we should show 'more'...
+               if(results.total && !results.total.then && results.total != -1){
+                       if((options.start + options.count) < results.total){
+                               displayMore = true;
+                       }else if((options.start + options.count) > results.total && options.count == results.length){
+                               // Weird return from a data store, where a start + count > maxOptions
+                               // implies maxOptions isn't really valid and we have to go into faking it.
+                               // And more or less assume more if count == results.length
+                               displayMore = true;
+                       }
+               }else if(options.count == results.length){
+                       //Don't know the size, so we do the best we can based off count alone.
+                       //So, if we have an exact match to count, assume more.
+                       displayMore = true;
                }
 
-               dojo.forEach(newStateClasses, function(c){ classHash[c] = true; });
+               this.nextButton.style.display = displayMore ? "" : "none";
+               domAttr.set(this.nextButton,"id", this.id + "_next");
+               return this.containerNode.childNodes;
+       },
 
-               var newClasses = [];
-               for(var c in classHash){
-                       newClasses.push(c);
+       clearResultList: function(){
+               // summary:
+               //              Clears the entries in the drop down list, but of course keeps the previous and next buttons.
+               var container = this.containerNode;
+               while(container.childNodes.length > 2){
+                       container.removeChild(container.childNodes[container.childNodes.length-2]);
                }
-               tn.className = newClasses.join(" ");
-
-               this._stateClasses = newStateClasses;
+               this._setSelectedAttr(null);
        },
 
-       _trackMouseState: function(/*DomNode*/ node, /*String*/ clazz){
+       highlightFirstOption: function(){
                // summary:
-               //              Track mouse/focus events on specified node and set CSS class on that node to indicate
-               //              current state.   Usually not called directly, but via cssStateNodes attribute.
-               // description:
-               //              Given class=foo, will set the following CSS class on the node
-               //                      - fooActive: if the user is currently pressing down the mouse button while over the node
-               //                      - fooHover: if the user is hovering the mouse over the node, but not pressing down a button
-               //                      - fooFocus: if the node is focused
-               //
-               //              Note that it won't set any classes if the widget is disabled.
-               // node: DomNode
-               //              Should be a sub-node of the widget, not the top node (this.domNode), since the top node
-               //              is handled specially and automatically just by mixing in this class.
-               // clazz: String
-               //              CSS class name (ex: dijitSliderUpArrow).
-
-               // Current state of node (initially false)
-               // NB: setting specifically to false because dojo.toggleClass() needs true boolean as third arg
-               var hovering=false, active=false, focused=false;
+               //              Highlight the first real item in the list (not Previous Choices).
+               this.selectFirstNode();
+       },
 
-               var self = this,
-                       cn = dojo.hitch(this, "connect", node);
+       highlightLastOption: function(){
+               // summary:
+               //              Highlight the last real item in the list (not More Choices).
+               this.selectLastNode();
+       },
 
-               function setClass(){
-                       var disabled = ("disabled" in self && self.disabled) || ("readonly" in self && self.readonly);
-                       dojo.toggleClass(node, clazz+"Hover", hovering && !active && !disabled);
-                       dojo.toggleClass(node, clazz+"Active", active && !disabled);
-                       dojo.toggleClass(node, clazz+"Focused", focused && !disabled);
+       selectFirstNode: function(){
+               this.inherited(arguments);
+               if(this.getHighlightedOption() == this.previousButton){
+                       this.selectNextNode();
                }
+       },
 
-               // Mouse
-               cn("onmouseenter", function(){
-                       hovering = true;
-                       setClass();
-               });
-               cn("onmouseleave", function(){
-                       hovering = false;
-                       active = false;
-                       setClass();
-               });
-               cn("onmousedown", function(){
-                       active = true;
-                       setClass();
-               });
-               cn("onmouseup", function(){
-                       active = false;
-                       setClass();
-               });
-
-               // Focus
-               cn("onfocus", function(){
-                       focused = true;
-                       setClass();
-               });
-               cn("onblur", function(){
-                       focused = false;
-                       setClass();
-               });
+       selectLastNode: function(){
+               this.inherited(arguments);
+               if(this.getHighlightedOption() == this.nextButton){
+                       this.selectPreviousNode();
+               }
+       },
 
-               // Just in case widget is enabled/disabled while it has focus/hover/active state.
-               // Maybe this is overkill.
-               this.connect(this, "set", function(name, value){
-                       if(name == "disabled" || name == "readOnly"){
-                               setClass();
-                       }
-               });
+       getHighlightedOption: function(){
+               return this._getSelectedAttr();
        }
 });
 
-}
+});
 
-if(!dojo._hasResource["dijit.form._FormWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form._FormWidget"] = true;
-dojo.provide("dijit.form._FormWidget");
+},
+'dojo/parser':function(){
+define(
+       "dojo/parser", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/html", "./_base/window", "./_base/url",
+               "./_base/json", "./aspect", "./date/stamp", "./query", "./on", "./ready"],
+       function(dojo, dlang, darray, dhtml, dwindow, _Url, djson, aspect, dates, query, don){
+
+// module:
+//             dojo/parser
+// summary:
+//             The Dom/Widget parsing package
 
+new Date("X"); // workaround for #11279, new Date("") == NaN
 
+var features = {
+       // Feature detection for when node.attributes only lists the attributes specified in the markup
+       // rather than old IE/quirks behavior where it lists every default value too
+       "dom-attributes-explicit": document.createElement("div").attributes.length < 40
+};
+function has(feature){
+       return features[feature];
+}
 
 
+dojo.parser = new function(){
+       // summary:
+       //              The Dom/Widget parsing package
+
+       var _nameMap = {
+               // Map from widget name (ex: "dijit.form.Button") to structure mapping
+               // lowercase version of attribute names to the version in the widget ex:
+               //      {
+               //              label: "label",
+               //              onclick: "onClick"
+               //      }
+       };
+       function getNameMap(proto){
+               // summary:
+               //              Returns map from lowercase name to attribute name in class, ex: {onclick: "onClick"}
+               var map = {};
+               for(var name in proto){
+                       if(name.charAt(0)=="_"){ continue; }    // skip internal properties
+                       map[name.toLowerCase()] = name;
+               }
+               return map;
+       }
+       // Widgets like BorderContainer add properties to _Widget via dojo.extend().
+       // If BorderContainer is loaded after _Widget's parameter list has been cached,
+       // we need to refresh that parameter list (for _Widget and all widgets that extend _Widget).
+       aspect.after(dlang, "extend", function(){
+               _nameMap = {};
+       }, true);
 
+       // Map from widget name (ex: "dijit.form.Button") to constructor
+       var _ctorMap = {};
 
+       this._functionFromScript = function(script, attrData){
+               // summary:
+               //              Convert a <script type="dojo/method" args="a, b, c"> ... </script>
+               //              into a function
+               // script: DOMNode
+               //              The <script> DOMNode
+               // attrData: String
+               //              For HTML5 compliance, searches for attrData + "args" (typically
+               //              "data-dojo-args") instead of "args"
+               var preamble = "";
+               var suffix = "";
+               var argsStr = (script.getAttribute(attrData + "args") || script.getAttribute("args"));
+               if(argsStr){
+                       darray.forEach(argsStr.split(/\s*,\s*/), function(part, idx){
+                               preamble += "var "+part+" = arguments["+idx+"]; ";
+                       });
+               }
+               var withStr = script.getAttribute("with");
+               if(withStr && withStr.length){
+                       darray.forEach(withStr.split(/\s*,\s*/), function(part){
+                               preamble += "with("+part+"){";
+                               suffix += "}";
+                       });
+               }
+               return new Function(preamble+script.innerHTML+suffix);
+       };
 
-dojo.declare("dijit.form._FormWidget", [dijit._Widget, dijit._Templated, dijit._CssStateMixin],
-       {
-       // summary:
-       //              Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
-       //              which can be children of a <form> node or a `dijit.form.Form` widget.
-       //
-       // description:
-       //              Represents a single HTML element.
-       //              All these widgets should have these attributes just like native HTML input elements.
-       //              You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
-       //
-       //              They also share some common methods.
+       this.instantiate = /*====== dojo.parser.instantiate= ======*/function(nodes, mixin, args){
+               // summary:
+               //              Takes array of nodes, and turns them into class instances and
+               //              potentially calls a startup method to allow them to connect with
+               //              any children.
+               // nodes: Array
+               //              Array of nodes or objects like
+               //      |               {
+               //      |                       type: "dijit.form.Button",
+               //      |                       node: DOMNode,
+               //      |                       scripts: [ ... ],       // array of <script type="dojo/..."> children of node
+               //      |                       inherited: { ... }      // settings inherited from ancestors like dir, theme, etc.
+               //      |               }
+               // mixin: Object?
+               //              An object that will be mixed in with each node in the array.
+               //              Values in the mixin will override values in the node, if they
+               //              exist.
+               // args: Object?
+               //              An object used to hold kwArgs for instantiation.
+               //              See parse.args argument for details.
 
-       // name: String
-       //              Name used when submitting form; same as "name" attribute or plain HTML elements
-       name: "",
+               var thelist = [],
+               mixin = mixin||{};
+               args = args||{};
 
-       // alt: String
-       //              Corresponds to the native HTML <input> element's attribute.
-       alt: "",
+               // Precompute names of special attributes we are looking for
+               // TODO: for 2.0 default to data-dojo- regardless of scopeName (or maybe scopeName won't exist in 2.0)
+               var dojoType = (args.scope || dojo._scopeName) + "Type",                // typically "dojoType"
+                       attrData = "data-" + (args.scope || dojo._scopeName) + "-",// typically "data-dojo-"
+                       dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
+                       dataDojoProps = attrData + "props",                                             // typically "data-dojo-props"
+                       dataDojoAttachPoint = attrData + "attach-point",
+                       dataDojoAttachEvent = attrData + "attach-event",
+                       dataDojoId = attrData + "id";
+
+               // And make hash to quickly check if a given attribute is special, and to map the name to something friendly
+               var specialAttrs = {};
+               darray.forEach([dataDojoProps, dataDojoType, dojoType, dataDojoId, "jsId", dataDojoAttachPoint,
+                               dataDojoAttachEvent, "dojoAttachPoint", "dojoAttachEvent", "class", "style"], function(name){
+                       specialAttrs[name.toLowerCase()] = name.replace(args.scope, "dojo");
+               });
 
-       // value: String
-       //              Corresponds to the native HTML <input> element's attribute.
-       value: "",
+               darray.forEach(nodes, function(obj){
+                       if(!obj){ return; }
 
-       // type: String
-       //              Corresponds to the native HTML <input> element's attribute.
-       type: "text",
+                       var node = obj.node || obj,
+                               type = dojoType in mixin ? mixin[dojoType] : obj.node ? obj.type : (node.getAttribute(dataDojoType) || node.getAttribute(dojoType)),
+                               ctor = _ctorMap[type] || (_ctorMap[type] = dlang.getObject(type)),
+                               proto = ctor && ctor.prototype;
+                       if(!ctor){
+                               throw new Error("Could not load class '" + type);
+                       }
 
-       // tabIndex: Integer
-       //              Order fields are traversed when user hits the tab key
-       tabIndex: "0",
+                       // Setup hash to hold parameter settings for this widget.       Start with the parameter
+                       // settings inherited from ancestors ("dir" and "lang").
+                       // Inherited setting may later be overridden by explicit settings on node itself.
+                       var params = {};
 
-       // disabled: Boolean
-       //              Should this widget respond to user input?
-       //              In markup, this is specified as "disabled='disabled'", or just "disabled".
-       disabled: false,
+                       if(args.defaults){
+                               // settings for the document itself (or whatever subtree is being parsed)
+                               dlang.mixin(params, args.defaults);
+                       }
+                       if(obj.inherited){
+                               // settings from dir=rtl or lang=... on a node above this node
+                               dlang.mixin(params, obj.inherited);
+                       }
 
-       // intermediateChanges: Boolean
-       //              Fires onChange for each value change or only on demand
-       intermediateChanges: false,
+                       // Get list of attributes explicitly listed in the markup
+                       var attributes;
+                       if(has("dom-attributes-explicit")){
+                               // Standard path to get list of user specified attributes
+                               attributes = node.attributes;
+                       }else{
+                               // Special path for IE, avoid (sometimes >100) bogus entries in node.attributes
+                               var clone = /^input$|^img$/i.test(node.nodeName) ? node : node.cloneNode(false),
+                                       attrs = clone.outerHTML.replace(/=[^\s"']+|="[^"]*"|='[^']*'/g, "").replace(/^\s*<[a-zA-Z0-9]*/, "").replace(/>.*$/, "");
 
-       // scrollOnFocus: Boolean
-       //              On focus, should this widget scroll into view?
-       scrollOnFocus: true,
+                               attributes = darray.map(attrs.split(/\s+/), function(name){
+                                       var lcName = name.toLowerCase();
+                                       return {
+                                               name: name,
+                                               // getAttribute() doesn't work for button.value, returns innerHTML of button.
+                                               // but getAttributeNode().value doesn't work for the form.encType or li.value
+                                               value: (node.nodeName == "LI" && name == "value") || lcName == "enctype" ?
+                                                               node.getAttribute(lcName) : node.getAttributeNode(lcName).value,
+                                               specified: true
+                                       };
+                               });
+                       }
 
-       // These mixins assume that the focus node is an INPUT, as many but not all _FormWidgets are.
-       attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-               value: "focusNode",
-               id: "focusNode",
-               tabIndex: "focusNode",
-               alt: "focusNode",
-               title: "focusNode"
-       }),
+                       // Read in attributes and process them, including data-dojo-props, data-dojo-type,
+                       // dojoAttachPoint, etc., as well as normal foo=bar attributes.
+                       var i=0, item;
+                       while(item = attributes[i++]){
+                               if(!item || !item.specified){
+                                       continue;
+                               }
 
-       postMixInProperties: function(){
-               // Setup name=foo string to be referenced from the template (but only if a name has been specified)
-               // Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660
-               // Regarding escaping, see heading "Attribute values" in
-               // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
-               this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, "&quot;") + '"') : '';
-               this.inherited(arguments);
-       },
+                               var name = item.name,
+                                       lcName = name.toLowerCase(),
+                                       value = item.value;
 
-       postCreate: function(){
-               this.inherited(arguments);
-               this.connect(this.domNode, "onmousedown", "_onMouseDown");
-       },
+                               if(lcName in specialAttrs){
+                                       switch(specialAttrs[lcName]){
 
-       _setDisabledAttr: function(/*Boolean*/ value){
-               this.disabled = value;
-               dojo.attr(this.focusNode, 'disabled', value);
-               if(this.valueNode){
-                       dojo.attr(this.valueNode, 'disabled', value);
-               }
-               dijit.setWaiState(this.focusNode, "disabled", value);
-
-               if(value){
-                       // reset these, because after the domNode is disabled, we can no longer receive
-                       // mouse related events, see #4200
-                       this._hovering = false;
-                       this._active = false;
+                                       // Data-dojo-props.   Save for later to make sure it overrides direct foo=bar settings
+                                       case "data-dojo-props":
+                                               var extra = value;
+                                               break;
 
-                       // clear tab stop(s) on this widget's focusable node(s)  (ComboBox has two focusable nodes)
-                       var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex : "focusNode";
-                       dojo.forEach(dojo.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
-                               var node = this[attachPointName];
-                               // complex code because tabIndex=-1 on a <div> doesn't work on FF
-                               if(dojo.isWebKit || dijit.hasDefaultTabStop(node)){     // see #11064 about webkit bug
-                                       node.setAttribute('tabIndex', "-1");
-                               }else{
-                                       node.removeAttribute('tabIndex');                               
-                               }
-                       }, this);
-               }else{
-                       this.focusNode.setAttribute('tabIndex', this.tabIndex);
-               }
-       },
+                                       // data-dojo-id or jsId. TODO: drop jsId in 2.0
+                                       case "data-dojo-id":
+                                       case "jsId":
+                                               var jsname = value;
+                                               break;
 
-       setDisabled: function(/*Boolean*/ disabled){
-               // summary:
-               //              Deprecated.   Use set('disabled', ...) instead.
-               dojo.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
-               this.set('disabled', disabled);
-       },
+                                       // For the benefit of _Templated
+                                       case "data-dojo-attach-point":
+                                       case "dojoAttachPoint":
+                                               params.dojoAttachPoint = value;
+                                               break;
+                                       case "data-dojo-attach-event":
+                                       case "dojoAttachEvent":
+                                               params.dojoAttachEvent = value;
+                                               break;
 
-       _onFocus: function(e){
-               if(this.scrollOnFocus){
-                       dojo.window.scrollIntoView(this.domNode);
-               }
-               this.inherited(arguments);
-       },
+                                       // Special parameter handling needed for IE
+                                       case "class":
+                                               params["class"] = node.className;
+                                               break;
+                                       case "style":
+                                               params["style"] = node.style && node.style.cssText;
+                                               break;
+                                       }
+                               }else{
+                                       // Normal attribute, ex: value="123"
 
-       isFocusable: function(){
-               // summary:
-               //              Tells if this widget is focusable or not.   Used internally by dijit.
-               // tags:
-               //              protected
-               return !this.disabled && !this.readOnly && this.focusNode && (dojo.style(this.domNode, "display") != "none");
-       },
+                                       // Find attribute in widget corresponding to specified name.
+                                       // May involve case conversion, ex: onclick --> onClick
+                                       if(!(name in proto)){
+                                               var map = (_nameMap[type] || (_nameMap[type] = getNameMap(proto)));
+                                               name = map[lcName] || name;
+                                       }
 
-       focus: function(){
-               // summary:
-               //              Put focus on this widget
-               dijit.focus(this.focusNode);
-       },
+                                       // Set params[name] to value, doing type conversion
+                                       if(name in proto){
+                                               switch(typeof proto[name]){
+                                               case "string":
+                                                       params[name] = value;
+                                                       break;
+                                               case "number":
+                                                       params[name] = value.length ? Number(value) : NaN;
+                                                       break;
+                                               case "boolean":
+                                                       // for checked/disabled value might be "" or "checked".  interpret as true.
+                                                       params[name] = value.toLowerCase() != "false";
+                                                       break;
+                                               case "function":
+                                                       if(value === "" || value.search(/[^\w\.]+/i) != -1){
+                                                               // The user has specified some text for a function like "return x+5"
+                                                               params[name] = new Function(value);
+                                                       }else{
+                                                               // The user has specified the name of a function like "myOnClick"
+                                                               // or a single word function "return"
+                                                               params[name] = dlang.getObject(value, false) || new Function(value);
+                                                       }
+                                                       break;
+                                               default:
+                                                       var pVal = proto[name];
+                                                       params[name] =
+                                                               (pVal && "length" in pVal) ? (value ? value.split(/\s*,\s*/) : []) :    // array
+                                                                       (pVal instanceof Date) ?
+                                                                               (value == "" ? new Date("") :   // the NaN of dates
+                                                                               value == "now" ? new Date() :   // current date
+                                                                               dates.fromISOString(value)) :
+                                                               (pVal instanceof dojo._Url) ? (dojo.baseUrl + value) :
+                                                               djson.fromJson(value);
+                                               }
+                                       }else{
+                                               params[name] = value;
+                                       }
+                               }
+                       }
 
-       compare: function(/*anything*/val1, /*anything*/val2){
-               // summary:
-               //              Compare 2 values (as returned by attr('value') for this widget).
-               // tags:
-               //              protected
-               if(typeof val1 == "number" && typeof val2 == "number"){
-                       return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
-               }else if(val1 > val2){
-                       return 1;
-               }else if(val1 < val2){
-                       return -1;
-               }else{
-                       return 0;
-               }
-       },
+                       // Mix things found in data-dojo-props into the params, overriding any direct settings
+                       if(extra){
+                               try{
+                                       extra = djson.fromJson.call(args.propsThis, "{" + extra + "}");
+                                       dlang.mixin(params, extra);
+                               }catch(e){
+                                       // give the user a pointer to their invalid parameters. FIXME: can we kill this in production?
+                                       throw new Error(e.toString() + " in data-dojo-props='" + extra + "'");
+                               }
+                       }
 
-       onChange: function(newValue){
-               // summary:
-               //              Callback when this widget's value is changed.
-               // tags:
-               //              callback
-       },
+                       // Any parameters specified in "mixin" override everything else.
+                       dlang.mixin(params, mixin);
 
-       // _onChangeActive: [private] Boolean
-       //              Indicates that changes to the value should call onChange() callback.
-       //              This is false during widget initialization, to avoid calling onChange()
-       //              when the initial value is set.
-       _onChangeActive: false,
+                       var scripts = obj.node ? obj.scripts : (ctor && (ctor._noScript || proto._noScript) ? [] :
+                                               query("> script[type^='dojo/']", node));
 
-       _handleOnChange: function(/*anything*/ newValue, /* Boolean? */ priorityChange){
-               // summary:
-               //              Called when the value of the widget is set.  Calls onChange() if appropriate
-               // newValue:
-               //              the new value
-               // priorityChange:
-               //              For a slider, for example, dragging the slider is priorityChange==false,
-               //              but on mouse up, it's priorityChange==true.  If intermediateChanges==true,
-               //              onChange is only called form priorityChange=true events.
-               // tags:
-               //              private
-               this._lastValue = newValue;
-               if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
-                       // this block executes not for a change, but during initialization,
-                       // and is used to store away the original value (or for ToggleButton, the original checked state)
-                       this._resetValue = this._lastValueReported = newValue;
-               }
-               if((this.intermediateChanges || priorityChange || priorityChange === undefined) &&
-                       ((typeof newValue != typeof this._lastValueReported) ||
-                               this.compare(newValue, this._lastValueReported) != 0)){
-                       this._lastValueReported = newValue;
-                       if(this._onChangeActive){
-                               if(this._onChangeHandle){
-                                       clearTimeout(this._onChangeHandle);
+                       // Process <script type="dojo/*"> script tags
+                       // <script type="dojo/method" event="foo"> tags are added to params, and passed to
+                       // the widget on instantiation.
+                       // <script type="dojo/method"> tags (with no event) are executed after instantiation
+                       // <script type="dojo/connect" data-dojo-event="foo"> tags are dojo.connected after instantiation
+                       // <script type="dojo/watch" data-dojo-prop="foo"> tags are dojo.watch after instantiation
+                       // <script type="dojo/on" data-dojo-event="foo"> tags are dojo.on after instantiation
+                       // note: dojo/* script tags cannot exist in self closing widgets, like <input />
+                       var connects = [],      // functions to connect after instantiation
+                               calls = [],             // functions to call after instantiation
+                               watch = [],  //functions to watch after instantiation
+                               on = []; //functions to on after instantiation
+
+                       if(scripts){
+                               for(i=0; i<scripts.length; i++){
+                                       var script = scripts[i];
+                                       node.removeChild(script);
+                                       // FIXME: drop event="" support in 2.0. use data-dojo-event="" instead
+                                       var event = (script.getAttribute(attrData + "event") || script.getAttribute("event")),
+                                               prop = script.getAttribute(attrData + "prop"),
+                                               type = script.getAttribute("type"),
+                                               nf = this._functionFromScript(script, attrData);
+                                       if(event){
+                                               if(type == "dojo/connect"){
+                                                       connects.push({event: event, func: nf});
+                                               }else if(type == "dojo/on"){
+                                                       on.push({event: event, func: nf});
+                                               }else{
+                                                       params[event] = nf;
+                                               }
+                                       }else if(type == "dojo/watch"){
+                                               watch.push({prop: prop, func: nf});
+                                       }else{
+                                               calls.push(nf);
+                                       }
                                }
-                               // setTimout allows hidden value processing to run and
-                               // also the onChange handler can safely adjust focus, etc
-                               this._onChangeHandle = setTimeout(dojo.hitch(this,
-                                       function(){
-                                               this._onChangeHandle = null;
-                                               this.onChange(newValue);
-                                       }), 0); // try to collapse multiple onChange's fired faster than can be processed
                        }
-               }
-       },
 
-       create: function(){
-               // Overrides _Widget.create()
-               this.inherited(arguments);
-               this._onChangeActive = true;
-       },
+                       // create the instance
+                       var markupFactory = ctor.markupFactory || proto.markupFactory;
+                       var instance = markupFactory ? markupFactory(params, node, ctor) : new ctor(params, node);
+                       thelist.push(instance);
 
-       destroy: function(){
-               if(this._onChangeHandle){ // destroy called before last onChange has fired
-                       clearTimeout(this._onChangeHandle);
-                       this.onChange(this._lastValueReported);
-               }
-               this.inherited(arguments);
-       },
+                       // map it to the JS namespace if that makes sense
+                       if(jsname){
+                               dlang.setObject(jsname, instance);
+                       }
 
-       setValue: function(/*String*/ value){
-               // summary:
-               //              Deprecated.   Use set('value', ...) instead.
-               dojo.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated.  Use set('value',"+value+") instead.", "", "2.0");
-               this.set('value', value);
-       },
+                       // process connections and startup functions
+                       for(i=0; i<connects.length; i++){
+                               aspect.after(instance, connects[i].event, dojo.hitch(instance, connects[i].func), true);
+                       }
+                       for(i=0; i<calls.length; i++){
+                               calls[i].call(instance);
+                       }
+                       for(i=0; i<watch.length; i++){
+                               instance.watch(watch[i].prop, watch[i].func);
+                       }
+                       for(i=0; i<on.length; i++){
+                               don(instance, on[i].event, on[i].func);
+                       }
+               }, this);
 
-       getValue: function(){
-               // summary:
-               //              Deprecated.   Use get('value') instead.
-               dojo.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
-               return this.get('value');
-       },
-       
-       _onMouseDown: function(e){
-               // If user clicks on the button, even if the mouse is released outside of it,
-               // this button should get focus (to mimics native browser buttons).
-               // This is also needed on chrome because otherwise buttons won't get focus at all,
-               // which leads to bizarre focus restore on Dialog close etc.
-               if(!e.ctrlKey && this.isFocusable()){ // !e.ctrlKey to ignore right-click on mac
-                       // Set a global event to handle mouseup, so it fires properly
-                       // even if the cursor leaves this.domNode before the mouse up event.
-                       var mouseUpConnector = this.connect(dojo.body(), "onmouseup", function(){
-                               if (this.isFocusable()) {
-                                       this.focus();
+               // Call startup on each top level instance if it makes sense (as for
+               // widgets).  Parent widgets will recursively call startup on their
+               // (non-top level) children
+               if(!mixin._started){
+                       darray.forEach(thelist, function(instance){
+                               if( !args.noStart && instance  &&
+                                       dlang.isFunction(instance.startup) &&
+                                       !instance._started
+                               ){
+                                       instance.startup();
                                }
-                               this.disconnect(mouseUpConnector);
                        });
                }
-       }
-});
+               return thelist;
+       };
 
-dojo.declare("dijit.form._FormValueWidget", dijit.form._FormWidget,
-{
-       // summary:
-       //              Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
-       // description:
-       //              Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
-       //              to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
-       //              works as expected.
+       this.parse = /*====== dojo.parser.parse= ======*/ function(rootNode, args){
+               // summary:
+               //              Scan the DOM for class instances, and instantiate them.
+               //
+               // description:
+               //              Search specified node (or root node) recursively for class instances,
+               //              and instantiate them. Searches for either data-dojo-type="Class" or
+               //              dojoType="Class" where "Class" is a a fully qualified class name,
+               //              like `dijit.form.Button`
+               //
+               //              Using `data-dojo-type`:
+               //              Attributes using can be mixed into the parameters used to instantiate the
+               //              Class by using a `data-dojo-props` attribute on the node being converted.
+               //              `data-dojo-props` should be a string attribute to be converted from JSON.
+               //
+               //              Using `dojoType`:
+               //              Attributes are read from the original domNode and converted to appropriate
+               //              types by looking up the Class prototype values. This is the default behavior
+               //              from Dojo 1.0 to Dojo 1.5. `dojoType` support is deprecated, and will
+               //              go away in Dojo 2.0.
+               //
+               // rootNode: DomNode?
+               //              A default starting root node from which to start the parsing. Can be
+               //              omitted, defaulting to the entire document. If omitted, the `args`
+               //              object can be passed in this place. If the `args` object has a
+               //              `rootNode` member, that is used.
+               //
+               // args: Object
+               //              a kwArgs object passed along to instantiate()
+               //
+               //                      * noStart: Boolean?
+               //                              when set will prevent the parser from calling .startup()
+               //                              when locating the nodes.
+               //                      * rootNode: DomNode?
+               //                              identical to the function's `rootNode` argument, though
+               //                              allowed to be passed in via this `args object.
+               //                      * template: Boolean
+               //                              If true, ignores ContentPane's stopParser flag and parses contents inside of
+               //                              a ContentPane inside of a template.   This allows dojoAttachPoint on widgets/nodes
+               //                              nested inside the ContentPane to work.
+               //                      * inherited: Object
+               //                              Hash possibly containing dir and lang settings to be applied to
+               //                              parsed widgets, unless there's another setting on a sub-node that overrides
+               //                      * scope: String
+               //                              Root for attribute names to search for.   If scopeName is dojo,
+               //                              will search for data-dojo-type (or dojoType).   For backwards compatibility
+               //                              reasons defaults to dojo._scopeName (which is "dojo" except when
+               //                              multi-version support is used, when it will be something like dojo16, dojo20, etc.)
+               //                      * propsThis: Object
+               //                              If specified, "this" referenced from data-dojo-props will refer to propsThis.
+               //                              Intended for use from the widgets-in-template feature of `dijit._WidgetsInTemplateMixin`
+               //
+               // example:
+               //              Parse all widgets on a page:
+               //      |               dojo.parser.parse();
+               //
+               // example:
+               //              Parse all classes within the node with id="foo"
+               //      |               dojo.parser.parse(dojo.byId('foo'));
+               //
+               // example:
+               //              Parse all classes in a page, but do not call .startup() on any
+               //              child
+               //      |               dojo.parser.parse({ noStart: true })
+               //
+               // example:
+               //              Parse all classes in a node, but do not call .startup()
+               //      |               dojo.parser.parse(someNode, { noStart:true });
+               //      |               // or
+               //      |               dojo.parser.parse({ noStart:true, rootNode: someNode });
 
-       // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
-       // directly in the template as read by the parser in order to function. IE is known to specifically
-       // require the 'name' attribute at element creation time.   See #8484, #8660.
-       // TODO: unclear what that {value: ""} is for; FormWidget.attributeMap copies value to focusNode,
-       // so maybe {value: ""} is so the value *doesn't* get copied to focusNode?
-       // Seems like we really want value removed from attributeMap altogether
-       // (although there's no easy way to do that now)
+               // determine the root node based on the passed arguments.
+               var root;
+               if(!args && rootNode && rootNode.rootNode){
+                       args = rootNode;
+                       root = args.rootNode;
+               }else{
+                       root = rootNode;
+               }
+               root = root ? dhtml.byId(root) : dwindow.body();
+               args = args || {};
 
-       // readOnly: Boolean
-       //              Should this widget respond to user input?
-       //              In markup, this is specified as "readOnly".
-       //              Similar to disabled except readOnly form values are submitted.
-       readOnly: false,
+               var dojoType = (args.scope || dojo._scopeName) + "Type",                // typically "dojoType"
+                       attrData = "data-" + (args.scope || dojo._scopeName) + "-",     // typically "data-dojo-"
+                       dataDojoType = attrData + "type",                                               // typically "data-dojo-type"
+                       dataDojoTextDir = attrData + "textdir";                                 // typically "data-dojo-textdir"
 
-       attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-               value: "",
-               readOnly: "focusNode"
-       }),
+               // List of all nodes on page w/dojoType specified
+               var list = [];
 
-       _setReadOnlyAttr: function(/*Boolean*/ value){
-               this.readOnly = value;
-               dojo.attr(this.focusNode, 'readOnly', value);
-               dijit.setWaiState(this.focusNode, "readonly", value);
-       },
+               // Info on DOMNode currently being processed
+               var node = root.firstChild;
+
+               // Info on parent of DOMNode currently being processed
+               //      - inherited: dir, lang, and textDir setting of parent, or inherited by parent
+               //      - parent: pointer to identical structure for my parent (or null if no parent)
+               //      - scripts: if specified, collects <script type="dojo/..."> type nodes from children
+               var inherited = args && args.inherited;
+               if(!inherited){
+                       function findAncestorAttr(node, attr){
+                               return (node.getAttribute && node.getAttribute(attr)) ||
+                                       (node !== dwindow.doc && node !== dwindow.doc.documentElement && node.parentNode ? findAncestorAttr(node.parentNode, attr) : null);
+                       }
+                       inherited = {
+                               dir: findAncestorAttr(root, "dir"),
+                               lang: findAncestorAttr(root, "lang"),
+                               textDir: findAncestorAttr(root, dataDojoTextDir)
+                       };
+                       for(var key in inherited){
+                               if(!inherited[key]){ delete inherited[key]; }
+                       }
+               }
+               var parent = {
+                       inherited: inherited
+               };
 
-       postCreate: function(){
-               this.inherited(arguments);
+               // For collecting <script type="dojo/..."> type nodes (when null, we don't need to collect)
+               var scripts;
 
-               if(dojo.isIE){ // IE won't stop the event with keypress
-                       this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
-               }
-               // Update our reset value if it hasn't yet been set (because this.set()
-               // is only called when there *is* a value)
-               if(this._resetValue === undefined){
-                       this._resetValue = this.value;
+               // when true, only look for <script type="dojo/..."> tags, and don't recurse to children
+               var scriptsOnly;
+
+               function getEffective(parent){
+                       // summary:
+                       //              Get effective dir, lang, textDir settings for specified obj
+                       //              (matching "parent" object structure above), and do caching.
+                       //              Take care not to return null entries.
+                       if(!parent.inherited){
+                               parent.inherited = {};
+                               var node = parent.node,
+                                       grandparent = getEffective(parent.parent);
+                               var inherited  = {
+                                       dir: node.getAttribute("dir") || grandparent.dir,
+                                       lang: node.getAttribute("lang") || grandparent.lang,
+                                       textDir: node.getAttribute(dataDojoTextDir) || grandparent.textDir
+                               };
+                               for(var key in inherited){
+                                       if(inherited[key]){
+                                               parent.inherited[key] = inherited[key];
+                                       }
+                               }
+                       }
+                       return parent.inherited;
                }
-       },
 
-       _setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
-               // summary:
-               //              Hook so attr('value', value) works.
-               // description:
-               //              Sets the value of the widget.
-               //              If the value has changed, then fire onChange event, unless priorityChange
-               //              is specified as null (or false?)
-               this.value = newValue;
-               this._handleOnChange(newValue, priorityChange);
-       },
+               // DFS on DOM tree, collecting nodes with data-dojo-type specified.
+               while(true){
+                       if(!node){
+                               // Finished this level, continue to parent's next sibling
+                               if(!parent || !parent.node){
+                                       break;
+                               }
+                               node = parent.node.nextSibling;
+                               scripts = parent.scripts;
+                               scriptsOnly = false;
+                               parent = parent.parent;
+                               continue;
+                       }
 
-       _getValueAttr: function(){
-               // summary:
-               //              Hook so attr('value') works.
-               return this._lastValue;
-       },
+                       if(node.nodeType != 1){
+                               // Text or comment node, skip to next sibling
+                               node = node.nextSibling;
+                               continue;
+                       }
 
-       undo: function(){
-               // summary:
-               //              Restore the value to the last value passed to onChange
-               this._setValueAttr(this._lastValueReported, false);
-       },
+                       if(scripts && node.nodeName.toLowerCase() == "script"){
+                               // Save <script type="dojo/..."> for parent, then continue to next sibling
+                               type = node.getAttribute("type");
+                               if(type && /^dojo\/\w/i.test(type)){
+                                       scripts.push(node);
+                               }
+                               node = node.nextSibling;
+                               continue;
+                       }
+                       if(scriptsOnly){
+                               node = node.nextSibling;
+                               continue;
+                       }
 
-       reset: function(){
-               // summary:
-               //              Reset the widget's value to what it was at initialization time
-               this._hasBeenBlurred = false;
-               this._setValueAttr(this._resetValue, true);
-       },
+                       // Check for data-dojo-type attribute, fallback to backward compatible dojoType
+                       var type = node.getAttribute(dataDojoType) || node.getAttribute(dojoType);
 
-       _onKeyDown: function(e){
-               if(e.keyCode == dojo.keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
-                       var te;
-                       if(dojo.isIE){
-                               e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
-                               te = document.createEventObject();
-                               te.keyCode = dojo.keys.ESCAPE;
-                               te.shiftKey = e.shiftKey;
-                               e.srcElement.fireEvent('onkeypress', te);
+                       // Short circuit for leaf nodes containing nothing [but text]
+                       var firstChild = node.firstChild;
+                       if(!type && (!firstChild || (firstChild.nodeType == 3 && !firstChild.nextSibling))){
+                               node = node.nextSibling;
+                               continue;
                        }
-               }
+
+                       // Setup data structure to save info on current node for when we return from processing descendant nodes
+                       var current = {
+                               node: node,
+                               scripts: scripts,
+                               parent: parent
+                       };
+
+                       // If dojoType/data-dojo-type specified, add to output array of nodes to instantiate
+                       var ctor = type && (_ctorMap[type] || (_ctorMap[type] = dlang.getObject(type))), // note: won't find classes declared via dojo.Declaration
+                               childScripts = ctor && !ctor.prototype._noScript ? [] : null; // <script> nodes that are parent's children
+                       if(type){
+                               list.push({
+                                       "type": type,
+                                       node: node,
+                                       scripts: childScripts,
+                                       inherited: getEffective(current) // dir & lang settings for current node, explicit or inherited
+                               });
+                       }
+
+                       // Recurse, collecting <script type="dojo/..."> children, and also looking for
+                       // descendant nodes with dojoType specified (unless the widget has the stopParser flag).
+                       // When finished with children, go to my next sibling.
+                       node = firstChild;
+                       scripts = childScripts;
+                       scriptsOnly = ctor && ctor.prototype.stopParser && !(args && args.template);
+                       parent = current;
+
+               }
+
+               // go build the object instances
+               var mixin = args && args.template ? {template: true} : null;
+               return this.instantiate(list, mixin, args); // Array
+       };
+}();
+
+
+//Register the parser callback. It should be the first callback
+//after the a11y test.
+if(dojo.config.parseOnLoad){
+       dojo.ready(100, dojo.parser, "parse");
+}
+
+return dojo.parser;
+});
+
+},
+'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\"\n/></span>\n",
+'dojo/dnd/Manager':function(){
+define("dojo/dnd/Manager", ["../main", "../Evented", "./common", "./autoscroll", "./Avatar"], function(dojo, Evented) {
+       // module:
+       //              dojo/dnd/Manager
+       // summary:
+       //              TODOC
+
+
+var Manager = dojo.declare("dojo.dnd.Manager", [Evented], {
+       // summary:
+       //              the manager of DnD operations (usually a singleton)
+       constructor: function(){
+               this.avatar  = null;
+               this.source = null;
+               this.nodes = [];
+               this.copy  = true;
+               this.target = null;
+               this.canDropFlag = false;
+               this.events = [];
        },
 
-       _layoutHackIE7: function(){
+       // avatar's offset from the mouse
+       OFFSET_X: 16,
+       OFFSET_Y: 16,
+
+       // methods
+       overSource: function(source){
                // summary:
-               //              Work around table sizing bugs on IE7 by forcing redraw
+               //              called when a source detected a mouse-over condition
+               // source: Object
+               //              the reporter
+               if(this.avatar){
+                       this.target = (source && source.targetState != "Disabled") ? source : null;
+                       this.canDropFlag = Boolean(this.target);
+                       this.avatar.update();
+               }
+               dojo.publish("/dnd/source/over", [source]);
+       },
+       outSource: function(source){
+               // summary:
+               //              called when a source detected a mouse-out condition
+               // source: Object
+               //              the reporter
+               if(this.avatar){
+                       if(this.target == source){
+                               this.target = null;
+                               this.canDropFlag = false;
+                               this.avatar.update();
+                               dojo.publish("/dnd/source/over", [null]);
+                       }
+               }else{
+                       dojo.publish("/dnd/source/over", [null]);
+               }
+       },
+       startDrag: function(source, nodes, copy){
+               // summary:
+               //              called to initiate the DnD operation
+               // source: Object
+               //              the source which provides items
+               // nodes: Array
+               //              the list of transferred items
+               // copy: Boolean
+               //              copy items, if true, move items otherwise
+               this.source = source;
+               this.nodes  = nodes;
+               this.copy   = Boolean(copy); // normalizing to true boolean
+               this.avatar = this.makeAvatar();
+               dojo.body().appendChild(this.avatar.node);
+               dojo.publish("/dnd/start", [source, nodes, this.copy]);
+               this.events = [
+                       dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
+                       dojo.connect(dojo.doc, "onmouseup",   this, "onMouseUp"),
+                       dojo.connect(dojo.doc, "onkeydown",   this, "onKeyDown"),
+                       dojo.connect(dojo.doc, "onkeyup",     this, "onKeyUp"),
+                       // cancel text selection and text dragging
+                       dojo.connect(dojo.doc, "ondragstart",   dojo.stopEvent),
+                       dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
+               ];
+               var c = "dojoDnd" + (copy ? "Copy" : "Move");
+               dojo.addClass(dojo.body(), c);
+       },
+       canDrop: function(flag){
+               // summary:
+               //              called to notify if the current target can accept items
+               var canDropFlag = Boolean(this.target && flag);
+               if(this.canDropFlag != canDropFlag){
+                       this.canDropFlag = canDropFlag;
+                       this.avatar.update();
+               }
+       },
+       stopDrag: function(){
+               // summary:
+               //              stop the DnD in progress
+               dojo.removeClass(dojo.body(), ["dojoDndCopy", "dojoDndMove"]);
+               dojo.forEach(this.events, dojo.disconnect);
+               this.events = [];
+               this.avatar.destroy();
+               this.avatar = null;
+               this.source = this.target = null;
+               this.nodes = [];
+       },
+       makeAvatar: function(){
+               // summary:
+               //              makes the avatar; it is separate to be overwritten dynamically, if needed
+               return new dojo.dnd.Avatar(this);
+       },
+       updateAvatar: function(){
+               // summary:
+               //              updates the avatar; it is separate to be overwritten dynamically, if needed
+               this.avatar.update();
+       },
 
-               if(dojo.isIE == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
-                       var domNode = this.domNode;
-                       var parent = domNode.parentNode;
-                       var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
-                       var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
-                       var _this = this;
-                       while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
-                               (function ping(){
-                                       var disconnectHandle = _this.connect(parent, "onscroll",
-                                               function(e){
-                                                       _this.disconnect(disconnectHandle); // only call once
-                                                       pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
-                                                       setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
-                                               }
-                                       );
-                               })();
-                               parent = parent.parentNode;
+       // mouse event processors
+       onMouseMove: function(e){
+               // summary:
+               //              event processor for onmousemove
+               // e: Event
+               //              mouse event
+               var a = this.avatar;
+               if(a){
+                       dojo.dnd.autoScrollNodes(e);
+                       //dojo.dnd.autoScroll(e);
+                       var s = a.node.style;
+                       s.left = (e.pageX + this.OFFSET_X) + "px";
+                       s.top  = (e.pageY + this.OFFSET_Y) + "px";
+                       var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
+                       if(this.copy != copy){
+                               this._setCopyStatus(copy);
+                       }
+               }
+       },
+       onMouseUp: function(e){
+               // summary:
+               //              event processor for onmouseup
+               // e: Event
+               //              mouse event
+               if(this.avatar){
+                       if(this.target && this.canDropFlag){
+                               var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
+                               params = [this.source, this.nodes, copy, this.target, e];
+                               dojo.publish("/dnd/drop/before", params);
+                               dojo.publish("/dnd/drop", params);
+                       }else{
+                               dojo.publish("/dnd/cancel");
+                       }
+                       this.stopDrag();
+               }
+       },
+
+       // keyboard event processors
+       onKeyDown: function(e){
+               // summary:
+               //              event processor for onkeydown:
+               //              watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
+               // e: Event
+               //              keyboard event
+               if(this.avatar){
+                       switch(e.keyCode){
+                               case dojo.keys.CTRL:
+                                       var copy = Boolean(this.source.copyState(true));
+                                       if(this.copy != copy){
+                                               this._setCopyStatus(copy);
+                                       }
+                                       break;
+                               case dojo.keys.ESCAPE:
+                                       dojo.publish("/dnd/cancel");
+                                       this.stopDrag();
+                                       break;
+                       }
+               }
+       },
+       onKeyUp: function(e){
+               // summary:
+               //              event processor for onkeyup, watching for CTRL for copy/move status
+               // e: Event
+               //              keyboard event
+               if(this.avatar && e.keyCode == dojo.keys.CTRL){
+                       var copy = Boolean(this.source.copyState(false));
+                       if(this.copy != copy){
+                               this._setCopyStatus(copy);
                        }
                }
+       },
+
+       // utilities
+       _setCopyStatus: function(copy){
+               // summary:
+               //              changes the copy status
+               // copy: Boolean
+               //              the copy status
+               this.copy = copy;
+               this.source._markDndStatus(this.copy);
+               this.updateAvatar();
+               dojo.replaceClass(dojo.body(),
+                       "dojoDnd" + (this.copy ? "Copy" : "Move"),
+                       "dojoDnd" + (this.copy ? "Move" : "Copy"));
        }
 });
 
-}
-
-if(!dojo._hasResource["dijit.dijit"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.dijit"] = true;
-dojo.provide("dijit.dijit");
+// dojo.dnd._manager:
+//             The manager singleton variable. Can be overwritten if needed.
+dojo.dnd._manager = null;
 
-/*=====
-dijit.dijit = {
+Manager.manager = dojo.dnd.manager = function(){
        // summary:
-       //              A roll-up for common dijit methods
-       // description:
-       //      A rollup file for the build system including the core and common
-       //      dijit files.
-       //
-       // example:
-       // | <script type="text/javascript" src="js/dojo/dijit/dijit.js"></script>
-       //
+       //              Returns the current DnD manager.  Creates one if it is not created yet.
+       if(!dojo.dnd._manager){
+               dojo.dnd._manager = new dojo.dnd.Manager();
+       }
+       return dojo.dnd._manager;       // Object
 };
-=====*/
 
-// All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
+return Manager;
+});
 
+},
+'dijit/form/ToggleButton':function(){
+define("dijit/form/ToggleButton", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/kernel", // kernel.deprecated
+       "./Button",
+       "./_ToggleButtonMixin"
+], function(declare, kernel, Button, _ToggleButtonMixin){
 
-// And some other stuff that we tend to pull in all the time anyway
+/*=====
+       var Button = dijit.form.Button;
+       var _ToggleButtonMixin = dijit.form._ToggleButtonMixin;
+=====*/
 
+       // module:
+       //              dijit/form/ToggleButton
+       // summary:
+       //              A templated button widget that can be in two states (checked or not).
 
 
+       return declare("dijit.form.ToggleButton", [Button, _ToggleButtonMixin], {
+               // summary:
+               //              A templated button widget that can be in two states (checked or not).
+               //              Can be base class for things like tabs or checkbox or radio buttons
 
+               baseClass: "dijitToggleButton",
 
+               setChecked: function(/*Boolean*/ checked){
+                       // summary:
+                       //              Deprecated.  Use set('checked', true/false) instead.
+                       kernel.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0");
+                       this.set('checked', checked);
+               }
+       });
+});
 
+},
+'dojo/date/stamp':function(){
+define("dojo/date/stamp", ["../_base/kernel", "../_base/lang", "../_base/array"], function(dojo, lang, array) {
+       // module:
+       //              dojo/date/stamp
+       // summary:
+       //              TODOC
 
-}
+lang.getObject("date.stamp", true, dojo);
 
-if(!dojo._hasResource["dojo.fx.Toggler"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.fx.Toggler"] = true;
-dojo.provide("dojo.fx.Toggler");
+// Methods to convert dates to or from a wire (string) format using well-known conventions
 
-dojo.declare("dojo.fx.Toggler", null, {
-       // summary:
-       //              A simple `dojo.Animation` toggler API.
-       //
-       // description:
-       //              class constructor for an animation toggler. It accepts a packed
-       //              set of arguments about what type of animation to use in each
-       //              direction, duration, etc. All available members are mixed into 
-       //              these animations from the constructor (for example, `node`, 
-       //              `showDuration`, `hideDuration`). 
+dojo.date.stamp.fromISOString = function(/*String*/formattedString, /*Number?*/defaultTime){
+       //      summary:
+       //              Returns a Date object given a string formatted according to a subset of the ISO-8601 standard.
        //
-       // example:
-       //      |       var t = new dojo.fx.Toggler({
-       //      |               node: "nodeId",
-       //      |               showDuration: 500,
-       //      |               // hideDuration will default to "200"
-       //      |               showFunc: dojo.fx.wipeIn, 
-       //      |               // hideFunc will default to "fadeOut"
-       //      |       });
-       //      |       t.show(100); // delay showing for 100ms
-       //      |       // ...time passes...
-       //      |       t.hide();
-
-       // node: DomNode
-       //              the node to target for the showing and hiding animations
-       node: null,
+       //      description:
+       //              Accepts a string formatted according to a profile of ISO8601 as defined by
+       //              [RFC3339](http://www.ietf.org/rfc/rfc3339.txt), except that partial input is allowed.
+       //              Can also process dates as specified [by the W3C](http://www.w3.org/TR/NOTE-datetime)
+       //              The following combinations are valid:
+       //
+       //                      * dates only
+       //                      |       * yyyy
+       //                      |       * yyyy-MM
+       //                      |       * yyyy-MM-dd
+       //                      * times only, with an optional time zone appended
+       //                      |       * THH:mm
+       //                      |       * THH:mm:ss
+       //                      |       * THH:mm:ss.SSS
+       //                      * and "datetimes" which could be any combination of the above
+       //
+       //              timezones may be specified as Z (for UTC) or +/- followed by a time expression HH:mm
+       //              Assumes the local time zone if not specified.  Does not validate.  Improperly formatted
+       //              input may return null.  Arguments which are out of bounds will be handled
+       //              by the Date constructor (e.g. January 32nd typically gets resolved to February 1st)
+       //              Only years between 100 and 9999 are supported.
+       //
+       //      formattedString:
+       //              A string such as 2005-06-30T08:05:00-07:00 or 2005-06-30 or T08:05:00
+       //
+       //      defaultTime:
+       //              Used for defaults for fields omitted in the formattedString.
+       //              Uses 1970-01-01T00:00:00.0Z by default.
 
-       // showFunc: Function
-       //              The function that returns the `dojo.Animation` to show the node
-       showFunc: dojo.fadeIn,
+       if(!dojo.date.stamp._isoRegExp){
+               dojo.date.stamp._isoRegExp =
+//TODO: could be more restrictive and check for 00-59, etc.
+                       /^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(.\d+)?)?((?:[+-](\d{2}):(\d{2}))|Z)?)?$/;
+       }
 
-       // hideFunc: Function   
-       //              The function that returns the `dojo.Animation` to hide the node
-       hideFunc: dojo.fadeOut,
+       var match = dojo.date.stamp._isoRegExp.exec(formattedString),
+               result = null;
 
-       // showDuration:
-       //              Time in milliseconds to run the show Animation
-       showDuration: 200,
+       if(match){
+               match.shift();
+               if(match[1]){match[1]--;} // Javascript Date months are 0-based
+               if(match[6]){match[6] *= 1000;} // Javascript Date expects fractional seconds as milliseconds
 
-       // hideDuration:
-       //              Time in milliseconds to run the hide Animation
-       hideDuration: 200,
+               if(defaultTime){
+                       // mix in defaultTime.  Relatively expensive, so use || operators for the fast path of defaultTime === 0
+                       defaultTime = new Date(defaultTime);
+                       array.forEach(array.map(["FullYear", "Month", "Date", "Hours", "Minutes", "Seconds", "Milliseconds"], function(prop){
+                               return defaultTime["get" + prop]();
+                       }), function(value, index){
+                               match[index] = match[index] || value;
+                       });
+               }
+               result = new Date(match[0]||1970, match[1]||0, match[2]||1, match[3]||0, match[4]||0, match[5]||0, match[6]||0); //TODO: UTC defaults
+               if(match[0] < 100){
+                       result.setFullYear(match[0] || 1970);
+               }
 
-       // FIXME: need a policy for where the toggler should "be" the next
-       // time show/hide are called if we're stopped somewhere in the
-       // middle.
-       // FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
-       // each animation individually. 
-       // FIXME: also would be nice to have events from the animations exposed/bridged
+               var offset = 0,
+                       zoneSign = match[7] && match[7].charAt(0);
+               if(zoneSign != 'Z'){
+                       offset = ((match[8] || 0) * 60) + (Number(match[9]) || 0);
+                       if(zoneSign != '-'){ offset *= -1; }
+               }
+               if(zoneSign){
+                       offset -= result.getTimezoneOffset();
+               }
+               if(offset){
+                       result.setTime(result.getTime() + offset * 60000);
+               }
+       }
 
-       /*=====
-       _showArgs: null,
-       _showAnim: null,
+       return result; // Date or null
+};
 
-       _hideArgs: null,
-       _hideAnim: null,
+/*=====
+       dojo.date.stamp.__Options = function(){
+               //      selector: String
+               //              "date" or "time" for partial formatting of the Date object.
+               //              Both date and time will be formatted by default.
+               //      zulu: Boolean
+               //              if true, UTC/GMT is used for a timezone
+               //      milliseconds: Boolean
+               //              if true, output milliseconds
+               this.selector = selector;
+               this.zulu = zulu;
+               this.milliseconds = milliseconds;
+       }
+=====*/
 
-       _isShowing: false,
-       _isHiding: false,
-       =====*/
+dojo.date.stamp.toISOString = function(/*Date*/dateObject, /*dojo.date.stamp.__Options?*/options){
+       //      summary:
+       //              Format a Date object as a string according a subset of the ISO-8601 standard
+       //
+       //      description:
+       //              When options.selector is omitted, output follows [RFC3339](http://www.ietf.org/rfc/rfc3339.txt)
+       //              The local time zone is included as an offset from GMT, except when selector=='time' (time without a date)
+       //              Does not check bounds.  Only years between 100 and 9999 are supported.
+       //
+       //      dateObject:
+       //              A Date object
 
-       constructor: function(args){
-               var _t = this;
+       var _ = function(n){ return (n < 10) ? "0" + n : n; };
+       options = options || {};
+       var formattedDate = [],
+               getter = options.zulu ? "getUTC" : "get",
+               date = "";
+       if(options.selector != "time"){
+               var year = dateObject[getter+"FullYear"]();
+               date = ["0000".substr((year+"").length)+year, _(dateObject[getter+"Month"]()+1), _(dateObject[getter+"Date"]())].join('-');
+       }
+       formattedDate.push(date);
+       if(options.selector != "date"){
+               var time = [_(dateObject[getter+"Hours"]()), _(dateObject[getter+"Minutes"]()), _(dateObject[getter+"Seconds"]())].join(':');
+               var millis = dateObject[getter+"Milliseconds"]();
+               if(options.milliseconds){
+                       time += "."+ (millis < 100 ? "0" : "") + _(millis);
+               }
+               if(options.zulu){
+                       time += "Z";
+               }else if(options.selector != "time"){
+                       var timezoneOffset = dateObject.getTimezoneOffset();
+                       var absOffset = Math.abs(timezoneOffset);
+                       time += (timezoneOffset > 0 ? "-" : "+") +
+                               _(Math.floor(absOffset/60)) + ":" + _(absOffset%60);
+               }
+               formattedDate.push(time);
+       }
+       return formattedDate.join('T'); // String
+};
 
-               dojo.mixin(_t, args);
-               _t.node = args.node;
-               _t._showArgs = dojo.mixin({}, args);
-               _t._showArgs.node = _t.node;
-               _t._showArgs.duration = _t.showDuration;
-               _t.showAnim = _t.showFunc(_t._showArgs);
+return dojo.date.stamp;
+});
 
-               _t._hideArgs = dojo.mixin({}, args);
-               _t._hideArgs.node = _t.node;
-               _t._hideArgs.duration = _t.hideDuration;
-               _t.hideAnim = _t.hideFunc(_t._hideArgs);
+},
+'dojo/Stateful':function(){
+define("dojo/Stateful", ["./_base/kernel", "./_base/declare", "./_base/lang", "./_base/array"], function(dojo, declare, lang, array) {
+       // module:
+       //              dojo/Stateful
+       // summary:
+       //              TODOC
 
-               dojo.connect(_t.showAnim, "beforeBegin", dojo.hitch(_t.hideAnim, "stop", true));
-               dojo.connect(_t.hideAnim, "beforeBegin", dojo.hitch(_t.showAnim, "stop", true));
+return dojo.declare("dojo.Stateful", null, {
+       // summary:
+       //              Base class for objects that provide named properties with optional getter/setter
+       //              control and the ability to watch for property changes
+       // example:
+       //      |       var obj = new dojo.Stateful();
+       //      |       obj.watch("foo", function(){
+       //      |               console.log("foo changed to " + this.get("foo"));
+       //      |       });
+       //      |       obj.set("foo","bar");
+       postscript: function(mixin){
+               if(mixin){
+                       lang.mixin(this, mixin);
+               }
        },
 
-       show: function(delay){
-               // summary: Toggle the node to showing
-               // delay: Integer?
-               //              Ammount of time to stall playing the show animation
-               return this.showAnim.play(delay || 0);
-       },
+       get: function(/*String*/name){
+               // summary:
+               //              Get a property on a Stateful instance.
+               //      name:
+               //              The property to get.
+               //      returns:
+               //              The property value on this Stateful instance.
+               // description:
+               //              Get a named property on a Stateful object. The property may
+               //              potentially be retrieved via a getter method in subclasses. In the base class
+               //              this just retrieves the object's property.
+               //              For example:
+               //      |       stateful = new dojo.Stateful({foo: 3});
+               //      |       stateful.get("foo") // returns 3
+               //      |       stateful.foo // returns 3
 
-       hide: function(delay){
-               // summary: Toggle the node to hidden
-               // delay: Integer?
-               //              Ammount of time to stall playing the hide animation
-               return this.hideAnim.play(delay || 0);
+               return this[name]; //Any
+       },
+       set: function(/*String*/name, /*Object*/value){
+               // summary:
+               //              Set a property on a Stateful instance
+               //      name:
+               //              The property to set.
+               //      value:
+               //              The value to set in the property.
+               //      returns:
+               //              The function returns this dojo.Stateful instance.
+               // description:
+               //              Sets named properties on a stateful object and notifies any watchers of
+               //              the property. A programmatic setter may be defined in subclasses.
+               //              For example:
+               //      |       stateful = new dojo.Stateful();
+               //      |       stateful.watch(function(name, oldValue, value){
+               //      |               // this will be called on the set below
+               //      |       }
+               //      |       stateful.set(foo, 5);
+               //
+               //      set() may also be called with a hash of name/value pairs, ex:
+               //      |       myObj.set({
+               //      |               foo: "Howdy",
+               //      |               bar: 3
+               //      |       })
+               //      This is equivalent to calling set(foo, "Howdy") and set(bar, 3)
+               if(typeof name === "object"){
+                       for(var x in name){
+                               this.set(x, name[x]);
+                       }
+                       return this;
+               }
+               var oldValue = this[name];
+               this[name] = value;
+               if(this._watchCallbacks){
+                       this._watchCallbacks(name, oldValue, value);
+               }
+               return this; //dojo.Stateful
+       },
+       watch: function(/*String?*/name, /*Function*/callback){
+               // summary:
+               //              Watches a property for changes
+               //      name:
+               //              Indicates the property to watch. This is optional (the callback may be the
+               //              only parameter), and if omitted, all the properties will be watched
+               // returns:
+               //              An object handle for the watch. The unwatch method of this object
+               //              can be used to discontinue watching this property:
+               //              |       var watchHandle = obj.watch("foo", callback);
+               //              |       watchHandle.unwatch(); // callback won't be called now
+               //      callback:
+               //              The function to execute when the property changes. This will be called after
+               //              the property has been changed. The callback will be called with the |this|
+               //              set to the instance, the first argument as the name of the property, the
+               //              second argument as the old value and the third argument as the new value.
+
+               var callbacks = this._watchCallbacks;
+               if(!callbacks){
+                       var self = this;
+                       callbacks = this._watchCallbacks = function(name, oldValue, value, ignoreCatchall){
+                               var notify = function(propertyCallbacks){
+                                       if(propertyCallbacks){
+                        propertyCallbacks = propertyCallbacks.slice();
+                                               for(var i = 0, l = propertyCallbacks.length; i < l; i++){
+                                                       try{
+                                                               propertyCallbacks[i].call(self, name, oldValue, value);
+                                                       }catch(e){
+                                                               console.error(e);
+                                                       }
+                                               }
+                                       }
+                               };
+                               notify(callbacks['_' + name]);
+                               if(!ignoreCatchall){
+                                       notify(callbacks["*"]); // the catch-all
+                               }
+                       }; // we use a function instead of an object so it will be ignored by JSON conversion
+               }
+               if(!callback && typeof name === "function"){
+                       callback = name;
+                       name = "*";
+               }else{
+                       // prepend with dash to prevent name conflicts with function (like "name" property)
+                       name = '_' + name;
+               }
+               var propertyCallbacks = callbacks[name];
+               if(typeof propertyCallbacks !== "object"){
+                       propertyCallbacks = callbacks[name] = [];
+               }
+               propertyCallbacks.push(callback);
+               return {
+                       unwatch: function(){
+                               propertyCallbacks.splice(array.indexOf(propertyCallbacks, callback), 1);
+                       }
+               }; //Object
        }
+
 });
 
-}
+});
+
+},
+'dijit/layout/AccordionContainer':function(){
+require({cache:{
+'url:dijit/layout/templates/AccordionButton.html':"<div data-dojo-attach-event='onclick:_onTitleClick' class='dijitAccordionTitle' role=\"presentation\">\n\t<div data-dojo-attach-point='titleNode,focusNode' data-dojo-attach-event='onkeypress:_onTitleKeyPress'\n\t\t\tclass='dijitAccordionTitleFocus' role=\"tab\" aria-expanded=\"false\"\n\t\t><span class='dijitInline dijitAccordionArrow' role=\"presentation\"></span\n\t\t><span class='arrowTextUp' role=\"presentation\">+</span\n\t\t><span class='arrowTextDown' role=\"presentation\">-</span\n\t\t><img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" data-dojo-attach-point='iconNode' style=\"vertical-align: middle\" role=\"presentation\"/>\n\t\t<span role=\"presentation\" data-dojo-attach-point='titleTextNode' class='dijitAccordionText'></span>\n\t</div>\n</div>\n"}});
+define("dijit/layout/AccordionContainer", [
+       "require",
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/_base/fx", // fx.Animation
+       "dojo/dom", // dom.setSelectable
+       "dojo/dom-attr", // domAttr.attr
+       "dojo/dom-class", // domClass.remove
+       "dojo/dom-construct", // domConstruct.place
+       "dojo/dom-geometry",
+       "dojo/_base/kernel",
+       "dojo/keys", // keys
+       "dojo/_base/lang", // lang.getObject lang.hitch
+       "dojo/_base/sniff", // has("ie")
+       "dojo/topic", // publish
+       "../focus",                     // focus.focus()
+       "../_base/manager",     // manager.defaultDuration
+       "dojo/ready",
+       "../_Widget",
+       "../_Container",
+       "../_TemplatedMixin",
+       "../_CssStateMixin",
+       "./StackContainer",
+       "./ContentPane",
+       "dojo/text!./templates/AccordionButton.html"
+], function(require, array, declare, event, fx, dom, domAttr, domClass, domConstruct, domGeometry,
+                       kernel, keys, lang, has, topic, focus, manager, ready,
+                       _Widget, _Container, _TemplatedMixin, _CssStateMixin, StackContainer, ContentPane, template){
 
-if(!dojo._hasResource["dojo.fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.fx"] = true;
-dojo.provide("dojo.fx");
- // FIXME: remove this back-compat require in 2.0 
 /*=====
-dojo.fx = {
-       // summary: Effects library on top of Base animations
-};
+       var _Widget = dijit._Widget;
+       var _Container = dijit._Container;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _CssStateMixin = dijit._CssStateMixin;
+       var StackContainer = dijit.layout.StackContainer;
+       var ContentPane = dijit.layout.ContentPane;
 =====*/
-(function(){
-       
-       var d = dojo, 
-               _baseObj = {
-                       _fire: function(evt, args){
-                               if(this[evt]){
-                                       this[evt].apply(this, args||[]);
-                               }
-                               return this;
-                       }
-               };
 
-       var _chain = function(animations){
-               this._index = -1;
-               this._animations = animations||[];
-               this._current = this._onAnimateCtx = this._onEndCtx = null;
+       // module:
+       //              dijit/layout/AccordionContainer
+       // summary:
+       //              Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
+       //              and switching between panes is visualized by sliding the other panes up/down.
 
-               this.duration = 0;
-               d.forEach(this._animations, function(a){
-                       this.duration += a.duration;
-                       if(a.delay){ this.duration += a.delay; }
-               }, this);
-       };
-       d.extend(_chain, {
-               _onAnimate: function(){
-                       this._fire("onAnimate", arguments);
-               },
-               _onEnd: function(){
-                       d.disconnect(this._onAnimateCtx);
-                       d.disconnect(this._onEndCtx);
-                       this._onAnimateCtx = this._onEndCtx = null;
-                       if(this._index + 1 == this._animations.length){
-                               this._fire("onEnd");
-                       }else{
-                               // switch animations
-                               this._current = this._animations[++this._index];
-                               this._onAnimateCtx = d.connect(this._current, "onAnimate", this, "_onAnimate");
-                               this._onEndCtx = d.connect(this._current, "onEnd", this, "_onEnd");
-                               this._current.play(0, true);
-                       }
-               },
-               play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
-                       if(!this._current){ this._current = this._animations[this._index = 0]; }
-                       if(!gotoStart && this._current.status() == "playing"){ return this; }
-                       var beforeBegin = d.connect(this._current, "beforeBegin", this, function(){
-                                       this._fire("beforeBegin");
-                               }),
-                               onBegin = d.connect(this._current, "onBegin", this, function(arg){
-                                       this._fire("onBegin", arguments);
-                               }),
-                               onPlay = d.connect(this._current, "onPlay", this, function(arg){
-                                       this._fire("onPlay", arguments);
-                                       d.disconnect(beforeBegin);
-                                       d.disconnect(onBegin);
-                                       d.disconnect(onPlay);
-                               });
-                       if(this._onAnimateCtx){
-                               d.disconnect(this._onAnimateCtx);
-                       }
-                       this._onAnimateCtx = d.connect(this._current, "onAnimate", this, "_onAnimate");
-                       if(this._onEndCtx){
-                               d.disconnect(this._onEndCtx);
-                       }
-                       this._onEndCtx = d.connect(this._current, "onEnd", this, "_onEnd");
-                       this._current.play.apply(this._current, arguments);
-                       return this;
+
+       // Design notes:
+       //
+       // An AccordionContainer is a StackContainer, but each child (typically ContentPane)
+       // is wrapped in a _AccordionInnerContainer.   This is hidden from the caller.
+       //
+       // The resulting markup will look like:
+       //
+       //      <div class=dijitAccordionContainer>
+       //              <div class=dijitAccordionInnerContainer>        (one pane)
+       //                              <div class=dijitAccordionTitle>         (title bar) ... </div>
+       //                              <div class=dijtAccordionChildWrapper>   (content pane) </div>
+       //              </div>
+       //      </div>
+       //
+       // Normally the dijtAccordionChildWrapper is hidden for all but one child (the shown
+       // child), so the space for the content pane is all the title bars + the one dijtAccordionChildWrapper,
+       // which on claro has a 1px border plus a 2px bottom margin.
+       //
+       // During animation there are two dijtAccordionChildWrapper's shown, so we need
+       // to compensate for that.
+
+
+       var AccordionButton = declare("dijit.layout._AccordionButton", [_Widget, _TemplatedMixin, _CssStateMixin], {
+               // summary:
+               //              The title bar to click to open up an accordion pane.
+               //              Internal widget used by AccordionContainer.
+               // tags:
+               //              private
+
+               templateString: template,
+
+               // label: String
+               //              Title of the pane
+               label: "",
+               _setLabelAttr: {node: "titleTextNode", type: "innerHTML" },
+
+               // title: String
+               //              Tooltip that appears on hover
+               title: "",
+               _setTitleAttr: {node: "titleTextNode", type: "attribute", attribute: "title"},
+
+               // iconClassAttr: String
+               //              CSS class for icon to left of label
+               iconClassAttr: "",
+               _setIconClassAttr: { node: "iconNode", type: "class" },
+
+               baseClass: "dijitAccordionTitle",
+
+               getParent: function(){
+                       // summary:
+                       //              Returns the AccordionContainer parent.
+                       // tags:
+                       //              private
+                       return this.parent;
                },
-               pause: function(){
-                       if(this._current){
-                               var e = d.connect(this._current, "onPause", this, function(arg){
-                                               this._fire("onPause", arguments);
-                                               d.disconnect(e);
-                                       });
-                               this._current.pause();
-                       }
-                       return this;
+
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       var titleTextNodeId = this.id.replace(' ','_');
+                       domAttr.set(this.titleTextNode, "id", titleTextNodeId+"_title");
+                       this.focusNode.setAttribute("aria-labelledby", domAttr.get(this.titleTextNode, "id"));
+                       dom.setSelectable(this.domNode, false);
                },
-               gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
-                       this.pause();
-                       var offset = this.duration * percent;
-                       this._current = null;
-                       d.some(this._animations, function(a){
-                               if(a.duration <= offset){
-                                       this._current = a;
-                                       return true;
-                               }
-                               offset -= a.duration;
-                               return false;
-                       });
-                       if(this._current){
-                               this._current.gotoPercent(offset / this._current.duration, andPlay);
-                       }
-                       return this;
+
+               getTitleHeight: function(){
+                       // summary:
+                       //              Returns the height of the title dom node.
+                       return domGeometry.getMarginSize(this.domNode).h;       // Integer
                },
-               stop: function(/*boolean?*/ gotoEnd){
-                       if(this._current){
-                               if(gotoEnd){
-                                       for(; this._index + 1 < this._animations.length; ++this._index){
-                                               this._animations[this._index].stop(true);
-                                       }
-                                       this._current = this._animations[this._index];
-                               }
-                               var e = d.connect(this._current, "onStop", this, function(arg){
-                                               this._fire("onStop", arguments);
-                                               d.disconnect(e);
-                                       });
-                               this._current.stop();
-                       }
-                       return this;
+
+               // TODO: maybe the parent should set these methods directly rather than forcing the code
+               // into the button widget?
+               _onTitleClick: function(){
+                       // summary:
+                       //              Callback when someone clicks my title.
+                       var parent = this.getParent();
+                               parent.selectChild(this.contentWidget, true);
+                               focus.focus(this.focusNode);
                },
-               status: function(){
-                       return this._current ? this._current.status() : "stopped";
+
+               _onTitleKeyPress: function(/*Event*/ evt){
+                       return this.getParent()._onKeyPress(evt, this.contentWidget);
                },
-               destroy: function(){
-                       if(this._onAnimateCtx){ d.disconnect(this._onAnimateCtx); }
-                       if(this._onEndCtx){ d.disconnect(this._onEndCtx); }
+
+               _setSelectedAttr: function(/*Boolean*/ isSelected){
+                       this._set("selected", isSelected);
+                       this.focusNode.setAttribute("aria-expanded", isSelected);
+                       this.focusNode.setAttribute("aria-selected", isSelected);
+                       this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");
                }
        });
-       d.extend(_chain, _baseObj);
 
-       dojo.fx.chain = function(/*dojo.Animation[]*/ animations){
-               // summary: 
-               //              Chain a list of `dojo.Animation`s to run in sequence
-               //
-               // description:
-               //              Return a `dojo.Animation` which will play all passed
-               //              `dojo.Animation` instances in sequence, firing its own
-               //              synthesized events simulating a single animation. (eg:
-               //              onEnd of this animation means the end of the chain, 
-               //              not the individual animations within)
-               //
-               // example:
-               //      Once `node` is faded out, fade in `otherNode`
-               //      |       dojo.fx.chain([
-               //      |               dojo.fadeIn({ node:node }),
-               //      |               dojo.fadeOut({ node:otherNode })
-               //      |       ]).play();
-               //
-               return new _chain(animations) // dojo.Animation
-       };
+       var AccordionInnerContainer = declare("dijit.layout._AccordionInnerContainer", [_Widget, _CssStateMixin], {
+               // summary:
+               //              Internal widget placed as direct child of AccordionContainer.containerNode.
+               //              When other widgets are added as children to an AccordionContainer they are wrapped in
+               //              this widget.
 
-       var _combine = function(animations){
-               this._animations = animations||[];
-               this._connects = [];
-               this._finished = 0;
+/*=====
+               // buttonWidget: Function || String
+               //              Class to use to instantiate title
+               //              (Wish we didn't have a separate widget for just the title but maintaining it
+               //              for backwards compatibility, is it worth it?)
+                buttonWidget: null,
+=====*/
 
-               this.duration = 0;
-               d.forEach(animations, function(a){
-                       var duration = a.duration;
-                       if(a.delay){ duration += a.delay; }
-                       if(this.duration < duration){ this.duration = duration; }
-                       this._connects.push(d.connect(a, "onEnd", this, "_onEnd"));
-               }, this);
-               
-               this._pseudoAnimation = new d.Animation({curve: [0, 1], duration: this.duration});
-               var self = this;
-               d.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"], 
-                       function(evt){
-                               self._connects.push(d.connect(self._pseudoAnimation, evt,
-                                       function(){ self._fire(evt, arguments); }
-                               ));
-                       }
-               );
-       };
-       d.extend(_combine, {
-               _doAction: function(action, args){
-                       d.forEach(this._animations, function(a){
-                               a[action].apply(a, args);
-                       });
-                       return this;
-               },
-               _onEnd: function(){
-                       if(++this._finished > this._animations.length){
-                               this._fire("onEnd");
-                       }
-               },
-               _call: function(action, args){
-                       var t = this._pseudoAnimation;
-                       t[action].apply(t, args);
-               },
-               play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
-                       this._finished = 0;
-                       this._doAction("play", arguments);
-                       this._call("play", arguments);
-                       return this;
-               },
-               pause: function(){
-                       this._doAction("pause", arguments);
-                       this._call("pause", arguments);
-                       return this;
+/*=====
+               // contentWidget: dijit._Widget
+               //              Pointer to the real child widget
+               contentWidget: null,
+=====*/
+
+               baseClass: "dijitAccordionInnerContainer",
+
+               // tell nested layout widget that we will take care of sizing
+               isLayoutContainer: true,
+
+               buildRendering: function(){
+                       // Builds a template like:
+                       //      <div class=dijitAccordionInnerContainer>
+                       //              Button
+                       //              <div class=dijitAccordionChildWrapper>
+                       //                      ContentPane
+                       //              </div>
+                       //      </div>
+
+                       // Create wrapper div, placed where the child is now
+                       this.domNode = domConstruct.place("<div class='" + this.baseClass +
+                               "' role='presentation'>", this.contentWidget.domNode, "after");
+
+                       // wrapper div's first child is the button widget (ie, the title bar)
+                       var child = this.contentWidget,
+                               cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget;
+                       this.button = child._buttonWidget = (new cls({
+                               contentWidget: child,
+                               label: child.title,
+                               title: child.tooltip,
+                               dir: child.dir,
+                               lang: child.lang,
+                               textDir: child.textDir,
+                               iconClass: child.iconClass,
+                               id: child.id + "_button",
+                               parent: this.parent
+                       })).placeAt(this.domNode);
+
+                       // and then the actual content widget (changing it from prior-sibling to last-child),
+                       // wrapped by a <div class=dijitAccordionChildWrapper>
+                       this.containerNode = domConstruct.place("<div class='dijitAccordionChildWrapper' style='display:none'>", this.domNode);
+                       domConstruct.place(this.contentWidget.domNode, this.containerNode);
                },
-               gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
-                       var ms = this.duration * percent;
-                       d.forEach(this._animations, function(a){
-                               a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
-                       });
-                       this._call("gotoPercent", arguments);
-                       return this;
+
+               postCreate: function(){
+                       this.inherited(arguments);
+
+                       // Map changes in content widget's title etc. to changes in the button
+                       var button = this.button;
+                       this._contentWidgetWatches = [
+                               this.contentWidget.watch('title', lang.hitch(this, function(name, oldValue, newValue){
+                                       button.set("label", newValue);
+                               })),
+                               this.contentWidget.watch('tooltip', lang.hitch(this, function(name, oldValue, newValue){
+                                       button.set("title", newValue);
+                               })),
+                               this.contentWidget.watch('iconClass', lang.hitch(this, function(name, oldValue, newValue){
+                                       button.set("iconClass", newValue);
+                               }))
+                       ];
                },
-               stop: function(/*boolean?*/ gotoEnd){
-                       this._doAction("stop", arguments);
-                       this._call("stop", arguments);
-                       return this;
+
+               _setSelectedAttr: function(/*Boolean*/ isSelected){
+                       this._set("selected", isSelected);
+                       this.button.set("selected", isSelected);
+                       if(isSelected){
+                               var cw = this.contentWidget;
+                               if(cw.onSelected){ cw.onSelected(); }
+                       }
                },
-               status: function(){
-                       return this._pseudoAnimation.status();
+
+               startup: function(){
+                       // Called by _Container.addChild()
+                       this.contentWidget.startup();
                },
+
                destroy: function(){
-                       d.forEach(this._connects, dojo.disconnect);
+                       this.button.destroyRecursive();
+
+                       array.forEach(this._contentWidgetWatches || [], function(w){ w.unwatch(); });
+
+                       delete this.contentWidget._buttonWidget;
+                       delete this.contentWidget._wrapperWidget;
+
+                       this.inherited(arguments);
+               },
+
+               destroyDescendants: function(/*Boolean*/ preserveDom){
+                       // since getChildren isn't working for me, have to code this manually
+                       this.contentWidget.destroyRecursive(preserveDom);
                }
        });
-       d.extend(_combine, _baseObj);
 
-       dojo.fx.combine = function(/*dojo.Animation[]*/ animations){
-               // summary: 
-               //              Combine a list of `dojo.Animation`s to run in parallel
-               //
-               // description:
-               //              Combine an array of `dojo.Animation`s to run in parallel, 
-               //              providing a new `dojo.Animation` instance encompasing each
-               //              animation, firing standard animation events.
-               //
-               // example:
-               //      Fade out `node` while fading in `otherNode` simultaneously
-               //      |       dojo.fx.combine([
-               //      |               dojo.fadeIn({ node:node }),
-               //      |               dojo.fadeOut({ node:otherNode })
-               //      |       ]).play();
-               //
+       var AccordionContainer = declare("dijit.layout.AccordionContainer", StackContainer, {
+               // summary:
+               //              Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
+               //              and switching between panes is visualized by sliding the other panes up/down.
                // example:
-               //      When the longest animation ends, execute a function:
-               //      |       var anim = dojo.fx.combine([
-               //      |               dojo.fadeIn({ node: n, duration:700 }),
-               //      |               dojo.fadeOut({ node: otherNode, duration: 300 })
-               //      |       ]);
-               //      |       dojo.connect(anim, "onEnd", function(){
-               //      |               // overall animation is done.
-               //      |       });
-               //      |       anim.play(); // play the animation
-               //
-               return new _combine(animations); // dojo.Animation
-       };
+               //      |       <div data-dojo-type="dijit.layout.AccordionContainer">
+               //      |               <div data-dojo-type="dijit.layout.ContentPane" title="pane 1">
+               //      |               </div>
+               //      |               <div data-dojo-type="dijit.layout.ContentPane" title="pane 2">
+               //      |                       <p>This is some text</p>
+               //      |               </div>
+               //      |       </div>
 
-       dojo.fx.wipeIn = function(/*Object*/ args){
-               // summary:
-               //              Expand a node to it's natural height.
-               //
-               // description:
-               //              Returns an animation that will expand the
-               //              node defined in 'args' object from it's current height to
-               //              it's natural height (with no scrollbar).
-               //              Node must have no margin/border/padding.
-               //
-               // args: Object
-               //              A hash-map of standard `dojo.Animation` constructor properties
-               //              (such as easing: node: duration: and so on)
-               //
-               // example:
-               //      |       dojo.fx.wipeIn({
-               //      |               node:"someId"
-               //      |       }).play()
-               var node = args.node = d.byId(args.node), s = node.style, o;
+               // duration: Integer
+               //              Amount of time (in ms) it takes to slide panes
+               duration: manager.defaultDuration,
 
-               var anim = d.animateProperty(d.mixin({
-                       properties: {
-                               height: {
-                                       // wrapped in functions so we wait till the last second to query (in case value has changed)
-                                       start: function(){
-                                               // start at current [computed] height, but use 1px rather than 0
-                                               // because 0 causes IE to display the whole panel
-                                               o = s.overflow;
-                                               s.overflow = "hidden";
-                                               if(s.visibility == "hidden" || s.display == "none"){
-                                                       s.height = "1px";
-                                                       s.display = "";
-                                                       s.visibility = "";
-                                                       return 1;
-                                               }else{
-                                                       var height = d.style(node, "height");
-                                                       return Math.max(height, 1);
-                                               }
-                                       },
-                                       end: function(){
-                                               return node.scrollHeight;
-                                       }
-                               }
-                       }
-               }, args));
+               // buttonWidget: [const] String
+               //              The name of the widget used to display the title of each pane
+               buttonWidget: AccordionButton,
 
-               d.connect(anim, "onEnd", function(){ 
-                       s.height = "auto";
-                       s.overflow = o;
-               });
+/*=====
+               // _verticalSpace: Number
+               //              Pixels of space available for the open pane
+               //              (my content box size minus the cumulative size of all the title bars)
+               _verticalSpace: 0,
+=====*/
+               baseClass: "dijitAccordionContainer",
 
-               return anim; // dojo.Animation
-       }
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       this.domNode.style.overflow = "hidden";         // TODO: put this in dijit.css
+                       this.domNode.setAttribute("role", "tablist");   // TODO: put this in template
+               },
 
-       dojo.fx.wipeOut = function(/*Object*/ args){
-               // summary:
-               //              Shrink a node to nothing and hide it. 
-               //
-               // description:
-               //              Returns an animation that will shrink node defined in "args"
-               //              from it's current height to 1px, and then hide it.
-               //
-               // args: Object
-               //              A hash-map of standard `dojo.Animation` constructor properties
-               //              (such as easing: node: duration: and so on)
-               // 
-               // example:
-               //      |       dojo.fx.wipeOut({ node:"someId" }).play()
-               
-               var node = args.node = d.byId(args.node), s = node.style, o;
-               
-               var anim = d.animateProperty(d.mixin({
-                       properties: {
-                               height: {
-                                       end: 1 // 0 causes IE to display the whole panel
-                               }
+               startup: function(){
+                       if(this._started){ return; }
+                       this.inherited(arguments);
+                       if(this.selectedChildWidget){
+                               var style = this.selectedChildWidget.containerNode.style;
+                               style.display = "";
+                               style.overflow = "auto";
+                               this.selectedChildWidget._wrapperWidget.set("selected", true);
                        }
-               }, args));
+               },
 
-               d.connect(anim, "beforeBegin", function(){
-                       o = s.overflow;
-                       s.overflow = "hidden";
-                       s.display = "";
-               });
-               d.connect(anim, "onEnd", function(){
-                       s.overflow = o;
-                       s.height = "auto";
-                       s.display = "none";
-               });
+               layout: function(){
+                       // Implement _LayoutWidget.layout() virtual method.
+                       // Set the height of the open pane based on what room remains.
 
-               return anim; // dojo.Animation
-       }
+                       var openPane = this.selectedChildWidget;
 
-       dojo.fx.slideTo = function(/*Object*/ args){
-               // summary:
-               //              Slide a node to a new top/left position
-               //
-               // description:
-               //              Returns an animation that will slide "node" 
-               //              defined in args Object from its current position to
-               //              the position defined by (args.left, args.top).
-               //
-               // args: Object
-               //              A hash-map of standard `dojo.Animation` constructor properties
-               //              (such as easing: node: duration: and so on). Special args members
-               //              are `top` and `left`, which indicate the new position to slide to.
-               //
-               // example:
-               //      |       dojo.fx.slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
+                       if(!openPane){ return;}
 
-               var node = args.node = d.byId(args.node), 
-                       top = null, left = null;
+                       // space taken up by title, plus wrapper div (with border/margin) for open pane
+                       var wrapperDomNode = openPane._wrapperWidget.domNode,
+                               wrapperDomNodeMargin = domGeometry.getMarginExtents(wrapperDomNode),
+                               wrapperDomNodePadBorder = domGeometry.getPadBorderExtents(wrapperDomNode),
+                               wrapperContainerNode = openPane._wrapperWidget.containerNode,
+                               wrapperContainerNodeMargin = domGeometry.getMarginExtents(wrapperContainerNode),
+                               wrapperContainerNodePadBorder = domGeometry.getPadBorderExtents(wrapperContainerNode),
+                               mySize = this._contentBox;
 
-               var init = (function(n){
-                       return function(){
-                               var cs = d.getComputedStyle(n);
-                               var pos = cs.position;
-                               top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
-                               left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
-                               if(pos != 'absolute' && pos != 'relative'){
-                                       var ret = d.position(n, true);
-                                       top = ret.y;
-                                       left = ret.x;
-                                       n.style.position="absolute";
-                                       n.style.top=top+"px";
-                                       n.style.left=left+"px";
+                       // get cumulative height of all the unselected title bars
+                       var totalCollapsedHeight = 0;
+                       array.forEach(this.getChildren(), function(child){
+                   if(child != openPane){
+                                       // Using domGeometry.getMarginSize() rather than domGeometry.position() since claro has 1px bottom margin
+                                       // to separate accordion panes.  Not sure that works perfectly, it's probably putting a 1px
+                                       // margin below the bottom pane (even though we don't want one).
+                                       totalCollapsedHeight += domGeometry.getMarginSize(child._wrapperWidget.domNode).h;
                                }
+                       });
+                       this._verticalSpace = mySize.h - totalCollapsedHeight - wrapperDomNodeMargin.h
+                               - wrapperDomNodePadBorder.h - wrapperContainerNodeMargin.h - wrapperContainerNodePadBorder.h
+                               - openPane._buttonWidget.getTitleHeight();
+
+                       // Memo size to make displayed child
+                       this._containerContentBox = {
+                               h: this._verticalSpace,
+                               w: this._contentBox.w - wrapperDomNodeMargin.w - wrapperDomNodePadBorder.w
+                                       - wrapperContainerNodeMargin.w - wrapperContainerNodePadBorder.w
                        };
-               })(node);
-               init();
 
-               var anim = d.animateProperty(d.mixin({
-                       properties: {
-                               top: args.top || 0,
-                               left: args.left || 0
+                       if(openPane){
+                               openPane.resize(this._containerContentBox);
                        }
-               }, args));
-               d.connect(anim, "beforeBegin", anim, init);
+               },
 
-               return anim; // dojo.Animation
-       }
+               _setupChild: function(child){
+                       // Overrides _LayoutWidget._setupChild().
+                       // Put wrapper widget around the child widget, showing title
 
-})();
+                       child._wrapperWidget = AccordionInnerContainer({
+                               contentWidget: child,
+                               buttonWidget: this.buttonWidget,
+                               id: child.id + "_wrapper",
+                               dir: child.dir,
+                               lang: child.lang,
+                               textDir: child.textDir,
+                               parent: this
+                       });
 
-}
+                       this.inherited(arguments);
+               },
 
-if(!dojo._hasResource["dojo.NodeList-fx"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.NodeList-fx"] = true;
-dojo.provide("dojo.NodeList-fx");
+               addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+                       if(this._started){
+                               // Adding a child to a started Accordion is complicated because children have
+                               // wrapper widgets.  Default code path (calling this.inherited()) would add
+                               // the new child inside another child's wrapper.
 
+                               // First add in child as a direct child of this AccordionContainer
+                               var refNode = this.containerNode;
+                               if(insertIndex && typeof insertIndex == "number"){
+                                       var children = _Widget.prototype.getChildren.call(this);        // get wrapper panes
+                                       if(children && children.length >= insertIndex){
+                                               refNode = children[insertIndex-1].domNode;
+                                               insertIndex = "after";
+                                       }
+                               }
+                               domConstruct.place(child.domNode, refNode, insertIndex);
 
-/*=====
-dojo["NodeList-fx"] = {
-       // summary: Adds dojo.fx animation support to dojo.query()
-};
-=====*/
+                               if(!child._started){
+                                       child.startup();
+                               }
 
-dojo.extend(dojo.NodeList, {
-       _anim: function(obj, method, args){
-               args = args||{};
-               var a = dojo.fx.combine(
-                       this.map(function(item){
-                               var tmpArgs = { node: item };
-                               dojo.mixin(tmpArgs, args);
-                               return obj[method](tmpArgs);
-                       })
-               ); 
-               return args.auto ? a.play() && this : a; // dojo.Animation|dojo.NodeList
-       },
+                               // Then stick the wrapper widget around the child widget
+                               this._setupChild(child);
 
-       wipeIn: function(args){
-               //      summary:
-               //              wipe in all elements of this NodeList via `dojo.fx.wipeIn`
-               //
-               //      args: Object?
-               //              Additional dojo.Animation arguments to mix into this set with the addition of 
-               //              an `auto` parameter.
-               //
-               //      returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //              Fade in all tables with class "blah":
-               //              |       dojo.query("table.blah").wipeIn().play();
-               //
-               //      example:
-               //              Utilizing `auto` to get the NodeList back:
-               //              |       dojo.query(".titles").wipeIn({ auto:true }).onclick(someFunction);
-               //
-               return this._anim(dojo.fx, "wipeIn", args); // dojo.Animation|dojo.NodeList
-       },
+                               // Code below copied from StackContainer
+                               topic.publish(this.id+"-addChild", child, insertIndex); // publish
+                               this.layout();
+                               if(!this.selectedChildWidget){
+                                       this.selectChild(child);
+                               }
+                       }else{
+                               // We haven't been started yet so just add in the child widget directly,
+                               // and the wrapper will be created on startup()
+                               this.inherited(arguments);
+                       }
+               },
 
-       wipeOut: function(args){
-               //      summary:
-               //              wipe out all elements of this NodeList via `dojo.fx.wipeOut`
-               //
-               //      args: Object?
-               //              Additional dojo.Animation arguments to mix into this set with the addition of 
-               //              an `auto` parameter.
-               //
-               //      returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //              Wipe out all tables with class "blah":
-               //              |       dojo.query("table.blah").wipeOut().play();
-               return this._anim(dojo.fx, "wipeOut", args); // dojo.Animation|dojo.NodeList
-       },
+               removeChild: function(child){
+                       // Overrides _LayoutWidget.removeChild().
 
-       slideTo: function(args){
-               //      summary:
-               //              slide all elements of the node list to the specified place via `dojo.fx.slideTo`
-               //
-               //      args: Object?
-               //              Additional dojo.Animation arguments to mix into this set with the addition of 
-               //              an `auto` parameter.
-               //
-               //      returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //              |       Move all tables with class "blah" to 300/300:
-               //              |       dojo.query("table.blah").slideTo({
-               //              |               left: 40,
-               //              |               top: 50
-               //              |       }).play();
-               return this._anim(dojo.fx, "slideTo", args); // dojo.Animation|dojo.NodeList
-       },
+                       // Destroy wrapper widget first, before StackContainer.getChildren() call.
+                       // Replace wrapper widget with true child widget (ContentPane etc.).
+                       // This step only happens if the AccordionContainer has been started; otherwise there's no wrapper.
+                       if(child._wrapperWidget){
+                               domConstruct.place(child.domNode, child._wrapperWidget.domNode, "after");
+                               child._wrapperWidget.destroy();
+                               delete child._wrapperWidget;
+                       }
 
+                       domClass.remove(child.domNode, "dijitHidden");
 
-       fadeIn: function(args){
-               //      summary:
-               //              fade in all elements of this NodeList via `dojo.fadeIn`
-               //
-               //      args: Object?
-               //              Additional dojo.Animation arguments to mix into this set with the addition of 
-               //              an `auto` parameter.
-               //
-               //      returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //              Fade in all tables with class "blah":
-               //              |       dojo.query("table.blah").fadeIn().play();
-               return this._anim(dojo, "fadeIn", args); // dojo.Animation|dojo.NodeList
-       },
-
-       fadeOut: function(args){
-               //      summary:
-               //              fade out all elements of this NodeList via `dojo.fadeOut`
-               //
-               //      args: Object?
-               //              Additional dojo.Animation arguments to mix into this set with the addition of 
-               //              an `auto` parameter.
-               //
-               //      returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //              Fade out all elements with class "zork":
-               //              |       dojo.query(".zork").fadeOut().play();
-               //      example:
-               //              Fade them on a delay and do something at the end:
-               //              |       var fo = dojo.query(".zork").fadeOut();
-               //              |       dojo.connect(fo, "onEnd", function(){ /*...*/ });
-               //              |       fo.play();
-               //      example:
-               //              Using `auto`:
-               //              |       dojo.query("li").fadeOut({ auto:true }).filter(filterFn).forEach(doit);
-               //
-               return this._anim(dojo, "fadeOut", args); // dojo.Animation|dojo.NodeList
-       },
-
-       animateProperty: function(args){
-               //      summary:
-               //              Animate all elements of this NodeList across the properties specified.
-               //              syntax identical to `dojo.animateProperty`
-               //
-               // returns: dojo.Animation|dojo.NodeList
-               //              A special args member `auto` can be passed to automatically play the animation.
-               //              If args.auto is present, the original dojo.NodeList will be returned for further
-               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
-               //
-               //      example:
-               //      |       dojo.query(".zork").animateProperty({
-               //      |               duration: 500,
-               //      |               properties: { 
-               //      |                       color:          { start: "black", end: "white" },
-               //      |                       left:           { end: 300 } 
-               //      |               } 
-               //      |       }).play();
-               //
-               //      example:
-               //      |       dojo.query(".grue").animateProperty({ 
-               //      |               auto:true,
-               //      |               properties: {
-               //      |                       height:240
-               //      |               }
-               //      |       }).onclick(handler);
-               return this._anim(dojo, "animateProperty", args); // dojo.Animation|dojo.NodeList
-       },
-
-       anim: function( /*Object*/                      properties, 
-                                       /*Integer?*/            duration, 
-                                       /*Function?*/           easing, 
-                                       /*Function?*/           onEnd,
-                                       /*Integer?*/            delay){
-               //      summary:
-               //              Animate one or more CSS properties for all nodes in this list.
-               //              The returned animation object will already be playing when it
-               //              is returned. See the docs for `dojo.anim` for full details.
-               //      properties: Object
-               //              the properties to animate. does NOT support the `auto` parameter like other 
-               //              NodeList-fx methods. 
-               //      duration: Integer?
-               //              Optional. The time to run the animations for
-               //      easing: Function?
-               //              Optional. The easing function to use.
-               //      onEnd: Function?
-               //              A function to be called when the animation ends
-               //      delay:
-               //              how long to delay playing the returned animation
-               //      example:
-               //              Another way to fade out:
-               //      |       dojo.query(".thinger").anim({ opacity: 0 });
-               //      example:
-               //              animate all elements with the "thigner" class to a width of 500
-               //              pixels over half a second
-               //      |       dojo.query(".thinger").anim({ width: 500 }, 700);
-               var canim = dojo.fx.combine(
-                       this.map(function(item){
-                               return dojo.animateProperty({
-                                       node: item,
-                                       properties: properties,
-                                       duration: duration||350,
-                                       easing: easing
-                               });
-                       })
-               ); 
-               if(onEnd){
-                       dojo.connect(canim, "onEnd", onEnd);
-               }
-               return canim.play(delay||0); // dojo.Animation
-       }
-});
-
-}
-
-if(!dojo._hasResource["dojo.colors"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.colors"] = true;
-dojo.provide("dojo.colors");
-
-//TODO: this module appears to break naming conventions
+                       this.inherited(arguments);
+               },
 
-/*=====
-dojo.colors = {
-       // summary: Color utilities
-}
-=====*/
+               getChildren: function(){
+                       // Overrides _Container.getChildren() to return content panes rather than internal AccordionInnerContainer panes
+                       return array.map(this.inherited(arguments), function(child){
+                               return child.declaredClass == "dijit.layout._AccordionInnerContainer" ? child.contentWidget : child;
+                       }, this);
+               },
 
-(function(){
-       // this is a standard conversion prescribed by the CSS3 Color Module
-       var hue2rgb = function(m1, m2, h){
-               if(h < 0){ ++h; }
-               if(h > 1){ --h; }
-               var h6 = 6 * h;
-               if(h6 < 1){ return m1 + (m2 - m1) * h6; }
-               if(2 * h < 1){ return m2; }
-               if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
-               return m1;
-       };
-       
-       dojo.colorFromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
-               // summary:
-               //              get rgb(a) array from css-style color declarations
-               // description:
-               //              this function can handle all 4 CSS3 Color Module formats: rgb,
-               //              rgba, hsl, hsla, including rgb(a) with percentage values.
-               var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
-               if(m){
-                       var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a;
-                       if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){
-                               var r = c[0];
-                               if(r.charAt(r.length - 1) == "%"){
-                                       // 3 rgb percentage values
-                                       a = dojo.map(c, function(x){
-                                               return parseFloat(x) * 2.56;
-                                       });
-                                       if(l == 4){ a[3] = c[3]; }
-                                       return dojo.colorFromArray(a, obj);     // dojo.Color
+               destroy: function(){
+                       if(this._animation){
+                               this._animation.stop();
+                       }
+                       array.forEach(this.getChildren(), function(child){
+                               // If AccordionContainer has been started, then each child has a wrapper widget which
+                               // also needs to be destroyed.
+                               if(child._wrapperWidget){
+                                       child._wrapperWidget.destroy();
+                               }else{
+                                       child.destroyRecursive();
                                }
-                               return dojo.colorFromArray(c, obj);     // dojo.Color
-                       }
-                       if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){
-                               // normalize hsl values
-                               var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,
-                                       S = parseFloat(c[1]) / 100,
-                                       L = parseFloat(c[2]) / 100,
-                                       // calculate rgb according to the algorithm 
-                                       // recommended by the CSS3 Color Module 
-                                       m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S, 
-                                       m1 = 2 * L - m2;
-                               a = [
-                                       hue2rgb(m1, m2, H + 1 / 3) * 256,
-                                       hue2rgb(m1, m2, H) * 256,
-                                       hue2rgb(m1, m2, H - 1 / 3) * 256,
-                                       1
-                               ];
-                               if(l == 4){ a[3] = c[3]; }
-                               return dojo.colorFromArray(a, obj);     // dojo.Color
-                       }
-               }
-               return null;    // dojo.Color
-       };
-       
-       var confine = function(c, low, high){
-               // summary:
-               //              sanitize a color component by making sure it is a number,
-               //              and clamping it to valid values
-               c = Number(c);
-               return isNaN(c) ? high : c < low ? low : c > high ? high : c;   // Number
-       };
-       
-       dojo.Color.prototype.sanitize = function(){
-               // summary: makes sure that the object has correct attributes
-               var t = this;
-               t.r = Math.round(confine(t.r, 0, 255));
-               t.g = Math.round(confine(t.g, 0, 255));
-               t.b = Math.round(confine(t.b, 0, 255));
-               t.a = confine(t.a, 0, 1);
-               return this;    // dojo.Color
-       };
-})();
-
-
-dojo.colors.makeGrey = function(/*Number*/ g, /*Number?*/ a){
-       // summary: creates a greyscale color with an optional alpha
-       return dojo.colorFromArray([g, g, g, a]);
-};
+                       });
+                       this.inherited(arguments);
+               },
 
-// mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings
-dojo.mixin(dojo.Color.named, {
-       aliceblue:      [240,248,255],
-       antiquewhite:   [250,235,215],
-       aquamarine:     [127,255,212],
-       azure:  [240,255,255],
-       beige:  [245,245,220],
-       bisque: [255,228,196],
-       blanchedalmond: [255,235,205],
-       blueviolet:     [138,43,226],
-       brown:  [165,42,42],
-       burlywood:      [222,184,135],
-       cadetblue:      [95,158,160],
-       chartreuse:     [127,255,0],
-       chocolate:      [210,105,30],
-       coral:  [255,127,80],
-       cornflowerblue: [100,149,237],
-       cornsilk:       [255,248,220],
-       crimson:        [220,20,60],
-       cyan:   [0,255,255],
-       darkblue:       [0,0,139],
-       darkcyan:       [0,139,139],
-       darkgoldenrod:  [184,134,11],
-       darkgray:       [169,169,169],
-       darkgreen:      [0,100,0],
-       darkgrey:       [169,169,169],
-       darkkhaki:      [189,183,107],
-       darkmagenta:    [139,0,139],
-       darkolivegreen: [85,107,47],
-       darkorange:     [255,140,0],
-       darkorchid:     [153,50,204],
-       darkred:        [139,0,0],
-       darksalmon:     [233,150,122],
-       darkseagreen:   [143,188,143],
-       darkslateblue:  [72,61,139],
-       darkslategray:  [47,79,79],
-       darkslategrey:  [47,79,79],
-       darkturquoise:  [0,206,209],
-       darkviolet:     [148,0,211],
-       deeppink:       [255,20,147],
-       deepskyblue:    [0,191,255],
-       dimgray:        [105,105,105],
-       dimgrey:        [105,105,105],
-       dodgerblue:     [30,144,255],
-       firebrick:      [178,34,34],
-       floralwhite:    [255,250,240],
-       forestgreen:    [34,139,34],
-       gainsboro:      [220,220,220],
-       ghostwhite:     [248,248,255],
-       gold:   [255,215,0],
-       goldenrod:      [218,165,32],
-       greenyellow:    [173,255,47],
-       grey:   [128,128,128],
-       honeydew:       [240,255,240],
-       hotpink:        [255,105,180],
-       indianred:      [205,92,92],
-       indigo: [75,0,130],
-       ivory:  [255,255,240],
-       khaki:  [240,230,140],
-       lavender:       [230,230,250],
-       lavenderblush:  [255,240,245],
-       lawngreen:      [124,252,0],
-       lemonchiffon:   [255,250,205],
-       lightblue:      [173,216,230],
-       lightcoral:     [240,128,128],
-       lightcyan:      [224,255,255],
-       lightgoldenrodyellow:   [250,250,210],
-       lightgray:      [211,211,211],
-       lightgreen:     [144,238,144],
-       lightgrey:      [211,211,211],
-       lightpink:      [255,182,193],
-       lightsalmon:    [255,160,122],
-       lightseagreen:  [32,178,170],
-       lightskyblue:   [135,206,250],
-       lightslategray: [119,136,153],
-       lightslategrey: [119,136,153],
-       lightsteelblue: [176,196,222],
-       lightyellow:    [255,255,224],
-       limegreen:      [50,205,50],
-       linen:  [250,240,230],
-       magenta:        [255,0,255],
-       mediumaquamarine:       [102,205,170],
-       mediumblue:     [0,0,205],
-       mediumorchid:   [186,85,211],
-       mediumpurple:   [147,112,219],
-       mediumseagreen: [60,179,113],
-       mediumslateblue:        [123,104,238],
-       mediumspringgreen:      [0,250,154],
-       mediumturquoise:        [72,209,204],
-       mediumvioletred:        [199,21,133],
-       midnightblue:   [25,25,112],
-       mintcream:      [245,255,250],
-       mistyrose:      [255,228,225],
-       moccasin:       [255,228,181],
-       navajowhite:    [255,222,173],
-       oldlace:        [253,245,230],
-       olivedrab:      [107,142,35],
-       orange: [255,165,0],
-       orangered:      [255,69,0],
-       orchid: [218,112,214],
-       palegoldenrod:  [238,232,170],
-       palegreen:      [152,251,152],
-       paleturquoise:  [175,238,238],
-       palevioletred:  [219,112,147],
-       papayawhip:     [255,239,213],
-       peachpuff:      [255,218,185],
-       peru:   [205,133,63],
-       pink:   [255,192,203],
-       plum:   [221,160,221],
-       powderblue:     [176,224,230],
-       rosybrown:      [188,143,143],
-       royalblue:      [65,105,225],
-       saddlebrown:    [139,69,19],
-       salmon: [250,128,114],
-       sandybrown:     [244,164,96],
-       seagreen:       [46,139,87],
-       seashell:       [255,245,238],
-       sienna: [160,82,45],
-       skyblue:        [135,206,235],
-       slateblue:      [106,90,205],
-       slategray:      [112,128,144],
-       slategrey:      [112,128,144],
-       snow:   [255,250,250],
-       springgreen:    [0,255,127],
-       steelblue:      [70,130,180],
-       tan:    [210,180,140],
-       thistle:        [216,191,216],
-       tomato: [255,99,71],
-       transparent: [0, 0, 0, 0],
-       turquoise:      [64,224,208],
-       violet: [238,130,238],
-       wheat:  [245,222,179],
-       whitesmoke:     [245,245,245],
-       yellowgreen:    [154,205,50]
-});
+               _showChild: function(child){
+                       // Override StackContainer._showChild() to set visibility of _wrapperWidget.containerNode
+                       child._wrapperWidget.containerNode.style.display="block";
+                       return this.inherited(arguments);
+               },
 
-}
+               _hideChild: function(child){
+                       // Override StackContainer._showChild() to set visibility of _wrapperWidget.containerNode
+                       child._wrapperWidget.containerNode.style.display="none";
+                       this.inherited(arguments);
+               },
 
-if(!dojo._hasResource["dojo.i18n"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.i18n"] = true;
-dojo.provide("dojo.i18n");
+               _transition: function(/*dijit._Widget?*/ newWidget, /*dijit._Widget?*/ oldWidget, /*Boolean*/ animate){
+                       // Overrides StackContainer._transition() to provide sliding of title bars etc.
 
-/*=====
-dojo.i18n = {
-       // summary: Utility classes to enable loading of resources for internationalization (i18n)
-};
-=====*/
+                       if(has("ie") < 8){
+                               // workaround animation bugs by not animating; not worth supporting animation for IE6 & 7
+                               animate = false;
+                       }
 
-dojo.i18n.getLocalization = function(/*String*/packageName, /*String*/bundleName, /*String?*/locale){
-       //      summary:
-       //              Returns an Object containing the localization for a given resource
-       //              bundle in a package, matching the specified locale.
-       //      description:
-       //              Returns a hash containing name/value pairs in its prototypesuch
-       //              that values can be easily overridden.  Throws an exception if the
-       //              bundle is not found.  Bundle must have already been loaded by
-       //              `dojo.requireLocalization()` or by a build optimization step.  NOTE:
-       //              try not to call this method as part of an object property
-       //              definition (`var foo = { bar: dojo.i18n.getLocalization() }`).  In
-       //              some loading situations, the bundle may not be available in time
-       //              for the object definition.  Instead, call this method inside a
-       //              function that is run after all modules load or the page loads (like
-       //              in `dojo.addOnLoad()`), or in a widget lifecycle method.
-       //      packageName:
-       //              package which is associated with this resource
-       //      bundleName:
-       //              the base filename of the resource bundle (without the ".js" suffix)
-       //      locale:
-       //              the variant to load (optional).  By default, the locale defined by
-       //              the host environment: dojo.locale
-
-       locale = dojo.i18n.normalizeLocale(locale);
-
-       // look for nearest locale match
-       var elements = locale.split('-');
-       var module = [packageName,"nls",bundleName].join('.');
-       var bundle = dojo._loadedModules[module];
-       if(bundle){
-               var localization;
-               for(var i = elements.length; i > 0; i--){
-                       var loc = elements.slice(0, i).join('_');
-                       if(bundle[loc]){
-                               localization = bundle[loc];
-                               break;
+                       if(this._animation){
+                               // there's an in-progress animation.  speedily end it so we can do the newly requested one
+                               this._animation.stop(true);
+                               delete this._animation;
                        }
-               }
-               if(!localization){
-                       localization = bundle.ROOT;
-               }
 
-               // make a singleton prototype so that the caller won't accidentally change the values globally
-               if(localization){
-                       var clazz = function(){};
-                       clazz.prototype = localization;
-                       return new clazz(); // Object
-               }
-       }
+                       var self = this;
 
-       throw new Error("Bundle not found: " + bundleName + " in " + packageName+" , locale=" + locale);
-};
+                       if(newWidget){
+                               newWidget._wrapperWidget.set("selected", true);
 
-dojo.i18n.normalizeLocale = function(/*String?*/locale){
-       //      summary:
-       //              Returns canonical form of locale, as used by Dojo.
-       //
-       //  description:
-       //              All variants are case-insensitive and are separated by '-' as specified in [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt).
-       //              If no locale is specified, the dojo.locale is returned.  dojo.locale is defined by
-       //              the user agent's locale unless overridden by djConfig.
-
-       var result = locale ? locale.toLowerCase() : dojo.locale;
-       if(result == "root"){
-               result = "ROOT";
-       }
-       return result; // String
-};
+                               var d = this._showChild(newWidget);     // prepare widget to be slid in
 
-dojo.i18n._requireLocalization = function(/*String*/moduleName, /*String*/bundleName, /*String?*/locale, /*String?*/availableFlatLocales){
-       //      summary:
-       //              See dojo.requireLocalization()
-       //      description:
-       //              Called by the bootstrap, but factored out so that it is only
-       //              included in the build when needed.
-
-       var targetLocale = dojo.i18n.normalizeLocale(locale);
-       var bundlePackage = [moduleName, "nls", bundleName].join(".");
-       // NOTE: 
-       //              When loading these resources, the packaging does not match what is
-       //              on disk.  This is an implementation detail, as this is just a
-       //              private data structure to hold the loaded resources.  e.g.
-       //              `tests/hello/nls/en-us/salutations.js` is loaded as the object
-       //              `tests.hello.nls.salutations.en_us={...}` The structure on disk is
-       //              intended to be most convenient for developers and translators, but
-       //              in memory it is more logical and efficient to store in a different
-       //              order.  Locales cannot use dashes, since the resulting path will
-       //              not evaluate as valid JS, so we translate them to underscores.
-       
-       //Find the best-match locale to load if we have available flat locales.
-       var bestLocale = "";
-       if(availableFlatLocales){
-               var flatLocales = availableFlatLocales.split(",");
-               for(var i = 0; i < flatLocales.length; i++){
-                       //Locale must match from start of string.
-                       //Using ["indexOf"] so customBase builds do not see
-                       //this as a dojo._base.array dependency.
-                       if(targetLocale["indexOf"](flatLocales[i]) == 0){
-                               if(flatLocales[i].length > bestLocale.length){
-                                       bestLocale = flatLocales[i];
-                               }
-                       }
-               }
-               if(!bestLocale){
-                       bestLocale = "ROOT";
-               }               
-       }
+                               // Size the new widget, in case this is the first time it's being shown,
+                               // or I have been resized since the last time it was shown.
+                               // Note that page must be visible for resizing to work.
+                               if(this.doLayout && newWidget.resize){
+                                       newWidget.resize(this._containerContentBox);
+                               }
+                       }
 
-       //See if the desired locale is already loaded.
-       var tempLocale = availableFlatLocales ? bestLocale : targetLocale;
-       var bundle = dojo._loadedModules[bundlePackage];
-       var localizedBundle = null;
-       if(bundle){
-               if(dojo.config.localizationComplete && bundle._built){return;}
-               var jsLoc = tempLocale.replace(/-/g, '_');
-               var translationPackage = bundlePackage+"."+jsLoc;
-               localizedBundle = dojo._loadedModules[translationPackage];
-       }
+                       if(oldWidget){
+                               oldWidget._wrapperWidget.set("selected", false);
+                               if(!animate){
+                                       this._hideChild(oldWidget);
+                               }
+                       }
 
-       if(!localizedBundle){
-               bundle = dojo["provide"](bundlePackage);
-               var syms = dojo._getModuleSymbols(moduleName);
-               var modpath = syms.concat("nls").join("/");
-               var parent;
-
-               dojo.i18n._searchLocalePath(tempLocale, availableFlatLocales, function(loc){
-                       var jsLoc = loc.replace(/-/g, '_');
-                       var translationPackage = bundlePackage + "." + jsLoc;
-                       var loaded = false;
-                       if(!dojo._loadedModules[translationPackage]){
-                               // Mark loaded whether it's found or not, so that further load attempts will not be made
-                               dojo["provide"](translationPackage);
-                               var module = [modpath];
-                               if(loc != "ROOT"){module.push(loc);}
-                               module.push(bundleName);
-                               var filespec = module.join("/") + '.js';
-                               loaded = dojo._loadPath(filespec, null, function(hash){
-                                       // Use singleton with prototype to point to parent bundle, then mix-in result from loadPath
-                                       var clazz = function(){};
-                                       clazz.prototype = parent;
-                                       bundle[jsLoc] = new clazz();
-                                       for(var j in hash){ bundle[jsLoc][j] = hash[j]; }
+                       if(animate){
+                               var newContents = newWidget._wrapperWidget.containerNode,
+                                       oldContents = oldWidget._wrapperWidget.containerNode;
+
+                               // During the animation we will be showing two dijitAccordionChildWrapper nodes at once,
+                               // which on claro takes up 4px extra space (compared to stable AccordionContainer).
+                               // Have to compensate for that by immediately shrinking the pane being closed.
+                               var wrapperContainerNode = newWidget._wrapperWidget.containerNode,
+                                       wrapperContainerNodeMargin = domGeometry.getMarginExtents(wrapperContainerNode),
+                                       wrapperContainerNodePadBorder = domGeometry.getPadBorderExtents(wrapperContainerNode),
+                                       animationHeightOverhead = wrapperContainerNodeMargin.h + wrapperContainerNodePadBorder.h;
+
+                               oldContents.style.height = (self._verticalSpace - animationHeightOverhead) + "px";
+
+                               this._animation = new fx.Animation({
+                                       node: newContents,
+                                       duration: this.duration,
+                                       curve: [1, this._verticalSpace - animationHeightOverhead - 1],
+                                       onAnimate: function(value){
+                                               value = Math.floor(value);      // avoid fractional values
+                                               newContents.style.height = value + "px";
+                                               oldContents.style.height = (self._verticalSpace - animationHeightOverhead - value) + "px";
+                                       },
+                                       onEnd: function(){
+                                               delete self._animation;
+                                               newContents.style.height = "auto";
+                                               oldWidget._wrapperWidget.containerNode.style.display = "none";
+                                               oldContents.style.height = "auto";
+                                               self._hideChild(oldWidget);
+                                       }
                                });
-                       }else{
-                               loaded = true;
+                               this._animation.onStop = this._animation.onEnd;
+                               this._animation.play();
                        }
-                       if(loaded && bundle[jsLoc]){
-                               parent = bundle[jsLoc];
-                       }else{
-                               bundle[jsLoc] = parent;
+
+                       return d;       // If child has an href, promise that fires when the widget has finished loading
+               },
+
+               // note: we are treating the container as controller here
+               _onKeyPress: function(/*Event*/ e, /*dijit._Widget*/ fromTitle){
+                       // summary:
+                       //              Handle keypress events
+                       // description:
+                       //              This is called from a handler on AccordionContainer.domNode
+                       //              (setup in StackContainer), and is also called directly from
+                       //              the click handler for accordion labels
+                       if(this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){
+                               return;
                        }
-                       
-                       if(availableFlatLocales){
-                               //Stop the locale path searching if we know the availableFlatLocales, since
-                               //the first call to this function will load the only bundle that is needed.
-                               return true;
+                       var c = e.charOrCode;
+                       if((fromTitle && (c == keys.LEFT_ARROW || c == keys.UP_ARROW)) ||
+                                       (e.ctrlKey && c == keys.PAGE_UP)){
+                               this._adjacent(false)._buttonWidget._onTitleClick();
+                               event.stop(e);
+                       }else if((fromTitle && (c == keys.RIGHT_ARROW || c == keys.DOWN_ARROW)) ||
+                                       (e.ctrlKey && (c == keys.PAGE_DOWN || c == keys.TAB))){
+                               this._adjacent(true)._buttonWidget._onTitleClick();
+                               event.stop(e);
                        }
+               }
+       });
+
+       // Back compat w/1.6, remove for 2.0
+       if(!kernel.isAsync){
+               ready(0, function(){
+                       var requires = ["dijit/layout/AccordionPane"];
+                       require(requires);      // use indirection so modules not rolled into a build
                });
        }
 
-       //Save the best locale bundle as the target locale bundle when we know the
-       //the available bundles.
-       if(availableFlatLocales && targetLocale != bestLocale){
-               bundle[targetLocale.replace(/-/g, '_')] = bundle[bestLocale.replace(/-/g, '_')];
-       }
-};
+       // For monkey patching
+       AccordionContainer._InnerContainer = AccordionInnerContainer;
+       AccordionContainer._Button = AccordionButton;
 
-(function(){
-       // If other locales are used, dojo.requireLocalization should load them as
-       // well, by default. 
-       // 
-       // Override dojo.requireLocalization to do load the default bundle, then
-       // iterate through the extraLocale list and load those translations as
-       // well, unless a particular locale was requested.
+       return AccordionContainer;
+});
 
-       var extra = dojo.config.extraLocale;
-       if(extra){
-               if(!extra instanceof Array){
-                       extra = [extra];
-               }
+},
+'dijit/form/_AutoCompleterMixin':function(){
+define("dijit/form/_AutoCompleterMixin", [
+       "dojo/_base/connect", // keys keys.SHIFT
+       "dojo/data/util/filter", // patternToRegExp
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred", // Deferred.when
+       "dojo/dom-attr", // domAttr.get
+       "dojo/_base/event", // event.stop
+       "dojo/keys",
+       "dojo/_base/lang", // lang.clone lang.hitch
+       "dojo/query", // query
+       "dojo/regexp", // regexp.escapeString
+       "dojo/_base/sniff", // has("ie")
+       "dojo/string", // string.substitute
+       "dojo/_base/window", // win.doc.selection.createRange
+       "./DataList",
+       "../registry",  // registry.byId
+       "./_TextBoxMixin"       // defines _TextBoxMixin.selectInputText
+], function(connect, filter, declare, Deferred, domAttr, event, keys, lang, query, regexp, has, string, win,
+                       DataList, registry, _TextBoxMixin){
+
+       // module:
+       //              dijit/form/_AutoCompleterMixin
+       // summary:
+       //              A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect`
 
-               var req = dojo.i18n._requireLocalization;
-               dojo.i18n._requireLocalization = function(m, b, locale, availableFlatLocales){
-                       req(m,b,locale, availableFlatLocales);
-                       if(locale){return;}
-                       for(var i=0; i<extra.length; i++){
-                               req(m,b,extra[i], availableFlatLocales);
-                       }
-               };
-       }
-})();
 
-dojo.i18n._searchLocalePath = function(/*String*/locale, /*Boolean*/down, /*Function*/searchFunc){
-       //      summary:
-       //              A helper method to assist in searching for locale-based resources.
-       //              Will iterate through the variants of a particular locale, either up
-       //              or down, executing a callback function.  For example, "en-us" and
-       //              true will try "en-us" followed by "en" and finally "ROOT".
+       return declare("dijit.form._AutoCompleterMixin", null, {
+               // summary:
+               //              A mixin that implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect`
+               // description:
+               //              All widgets that mix in dijit.form._AutoCompleterMixin must extend `dijit.form._FormValueWidget`.
+               // tags:
+               //              protected
 
-       locale = dojo.i18n.normalizeLocale(locale);
+               // item: Object
+               //              This is the item returned by the dojo.data.store implementation that
+               //              provides the data for this ComboBox, it's the currently selected item.
+               item: null,
 
-       var elements = locale.split('-');
-       var searchlist = [];
-       for(var i = elements.length; i > 0; i--){
-               searchlist.push(elements.slice(0, i).join('-'));
-       }
-       searchlist.push(false);
-       if(down){searchlist.reverse();}
+               // pageSize: Integer
+               //              Argument to data provider.
+               //              Specifies number of search results per page (before hitting "next" button)
+               pageSize: Infinity,
 
-       for(var j = searchlist.length - 1; j >= 0; j--){
-               var loc = searchlist[j] || "ROOT";
-               var stop = searchFunc(loc);
-               if(stop){ break; }
-       }
-};
+               // store: [const] dojo.store.api.Store
+               //              Reference to data provider object used by this ComboBox
+               store: null,
 
-dojo.i18n._preloadLocalizations = function(/*String*/bundlePrefix, /*Array*/localesGenerated){
-       //      summary:
-       //              Load built, flattened resource bundles, if available for all
-       //              locales used in the page. Only called by built layer files.
-
-       function preload(locale){
-               locale = dojo.i18n.normalizeLocale(locale);
-               dojo.i18n._searchLocalePath(locale, true, function(loc){
-                       for(var i=0; i<localesGenerated.length;i++){
-                               if(localesGenerated[i] == loc){
-                                       dojo["require"](bundlePrefix+"_"+loc);
-                                       return true; // Boolean
-                               }
-                       }
-                       return false; // Boolean
-               });
-       }
-       preload();
-       var extra = dojo.config.extraLocale||[];
-       for(var i=0; i<extra.length; i++){
-               preload(extra[i]);
-       }
-};
-
-}
-
-if(!dojo._hasResource["dijit._PaletteMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._PaletteMixin"] = true;
-dojo.provide("dijit._PaletteMixin");
-
-
-dojo.declare("dijit._PaletteMixin",
-       [dijit._CssStateMixin],
-       {
-       // summary:
-       //              A keyboard accessible palette, for picking a color/emoticon/etc.
-       // description:
-       //              A mixin for a grid showing various entities, so the user can pick a certain entity.
-
-       // defaultTimeout: Number
-       //              Number of milliseconds before a held key or button becomes typematic
-       defaultTimeout: 500,
-
-       // timeoutChangeRate: Number
-       //              Fraction of time used to change the typematic timer between events
-       //              1.0 means that each typematic event fires at defaultTimeout intervals
-       //              < 1.0 means that each typematic event fires at an increasing faster rate
-       timeoutChangeRate: 0.90,
+               // fetchProperties: Object
+               //              Mixin to the store's fetch.
+               //              For example, to set the sort order of the ComboBox menu, pass:
+               //      |       { sort: [{attribute:"name",descending: true}] }
+               //              To override the default queryOptions so that deep=false, do:
+               //      |       { queryOptions: {ignoreCase: true, deep: false} }
+               fetchProperties:{},
 
-       // value: String
-       //              Currently selected color/emoticon/etc.
-       value: null,
-       
-       // _selectedCell: [private] Integer
-       //              Index of the currently selected cell. Initially, none selected
-       _selectedCell: -1,
+               // query: Object
+               //              A query that can be passed to 'store' to initially filter the items,
+               //              before doing further filtering based on `searchAttr` and the key.
+               //              Any reference to the `searchAttr` is ignored.
+               query: {},
 
-       // _currentFocus: [private] DomNode
-       //              The currently focused cell (if the palette itself has focus), or otherwise
-       //              the cell to be focused when the palette itself gets focus.
-       //              Different from value, which represents the selected (i.e. clicked) cell.
-/*=====
-       _currentFocus: null,
-=====*/
+               // autoComplete: Boolean
+               //              If user types in a partial string, and then tab out of the `<input>` box,
+               //              automatically copy the first entry displayed in the drop down list to
+               //              the `<input>` field
+               autoComplete: true,
 
-       // _xDim: [protected] Integer
-       //              This is the number of cells horizontally across.
-/*=====
-       _xDim: null,
-=====*/
+               // highlightMatch: String
+               //              One of: "first", "all" or "none".
+               //
+               //              If the ComboBox/FilteringSelect opens with the search results and the searched
+               //              string can be found, it will be highlighted.  If set to "all"
+               //              then will probably want to change `queryExpr` parameter to '*${0}*'
+               //
+               //              Highlighting is only performed when `labelType` is "text", so as to not
+               //              interfere with any HTML markup an HTML label might contain.
+               highlightMatch: "first",
 
-       // _yDim: [protected] Integer
-       //              This is the number of cells vertically down.
-/*=====
-       _yDim: null,
-=====*/
+               // searchDelay: Integer
+               //              Delay in milliseconds between when user types something and we start
+               //              searching based on that value
+               searchDelay: 100,
 
-       // tabIndex: String
-       //              Widget tab index.
-       tabIndex: "0",
+               // searchAttr: String
+               //              Search for items in the data store where this attribute (in the item)
+               //              matches what the user typed
+               searchAttr: "name",
 
-       // cellClass: [protected] String
-       //              CSS class applied to each cell in the palette
-       cellClass: "dijitPaletteCell",
+               // labelAttr: String?
+               //              The entries in the drop down list come from this attribute in the
+               //              dojo.data items.
+               //              If not specified, the searchAttr attribute is used instead.
+               labelAttr: "",
 
-       // dyeClass: [protected] String
-       //       Name of javascript class for Object created for each cell of the palette.
-       //       dyeClass should implements dijit.Dye interface
-       dyeClass: '',
+               // labelType: String
+               //              Specifies how to interpret the labelAttr in the data store items.
+               //              Can be "html" or "text".
+               labelType: "text",
 
-       _preparePalette: function(choices, titles) {
-               // summary:
-               //              Subclass must call _preparePalette() from postCreate(), passing in the tooltip
-               //              for each cell
-               // choices: String[][]
-               //              id's for each cell of the palette, used to create Dye JS object for each cell
-               // titles: String[]
-               //              Localized tooltip for each cell
+               // queryExpr: String
+               //              This specifies what query ComboBox/FilteringSelect sends to the data store,
+               //              based on what the user has typed.  Changing this expression will modify
+               //              whether the drop down shows only exact matches, a "starting with" match,
+               //              etc.  Use it in conjunction with highlightMatch.
+               //              dojo.data query expression pattern.
+               //              `${0}` will be substituted for the user text.
+               //              `*` is used for wildcards.
+               //              `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is"
+               queryExpr: "${0}*",
 
-               this._cells = [];
-               var url = this._blankGif;
-               
-               var dyeClassObj = dojo.getObject(this.dyeClass);
+               // ignoreCase: Boolean
+               //              Set true if the ComboBox/FilteringSelect should ignore case when matching possible items
+               ignoreCase: true,
 
-               for(var row=0; row < choices.length; row++){
-                       var rowNode = dojo.create("tr", {tabIndex: "-1"}, this.gridNode);
-                       for(var col=0; col < choices[row].length; col++){
-                               var value = choices[row][col];
-                               if(value){
-                                       var cellObject = new dyeClassObj(value);
-                                       
-                                       var cellNode = dojo.create("td", {
-                                               "class": this.cellClass,
-                                               tabIndex: "-1",
-                                               title: titles[value]
-                                       });
+               // Flags to _HasDropDown to limit height of drop down to make it fit in viewport
+               maxHeight: -1,
 
-                                       // prepare cell inner structure
-                                       cellObject.fillCell(cellNode, url);
+               // For backwards compatibility let onClick events propagate, even clicks on the down arrow button
+               _stopClickEvents: false,
 
-                                       this.connect(cellNode, "ondijitclick", "_onCellClick");
-                                       this._trackMouseState(cellNode, this.cellClass);
+               _getCaretPos: function(/*DomNode*/ element){
+                       // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
+                       var pos = 0;
+                       if(typeof(element.selectionStart) == "number"){
+                               // FIXME: this is totally borked on Moz < 1.3. Any recourse?
+                               pos = element.selectionStart;
+                       }else if(has("ie")){
+                               // in the case of a mouse click in a popup being handled,
+                               // then the win.doc.selection is not the textarea, but the popup
+                               // var r = win.doc.selection.createRange();
+                               // hack to get IE 6 to play nice. What a POS browser.
+                               var tr = win.doc.selection.createRange().duplicate();
+                               var ntr = element.createTextRange();
+                               tr.move("character",0);
+                               ntr.move("character",0);
+                               try{
+                                       // If control doesn't have focus, you get an exception.
+                                       // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
+                                       // There appears to be no workaround for this - googled for quite a while.
+                                       ntr.setEndPoint("EndToEnd", tr);
+                                       pos = String(ntr.text).replace(/\r/g,"").length;
+                               }catch(e){
+                                       // If focus has shifted, 0 is fine for caret pos.
+                               }
+                       }
+                       return pos;
+               },
 
-                                       dojo.place(cellNode, rowNode);
+               _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
+                       location = parseInt(location);
+                       _TextBoxMixin.selectInputText(element, location, location);
+               },
 
-                                       cellNode.index = this._cells.length;
+               _setDisabledAttr: function(/*Boolean*/ value){
+                       // Additional code to set disabled state of ComboBox node.
+                       // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr().
+                       this.inherited(arguments);
+                       this.domNode.setAttribute("aria-disabled", value);
+               },
 
-                                       // save cell info into _cells
-                                       this._cells.push({node:cellNode, dye:cellObject});
+               _abortQuery: function(){
+                       // stop in-progress query
+                       if(this.searchTimer){
+                               clearTimeout(this.searchTimer);
+                               this.searchTimer = null;
+                       }
+                       if(this._fetchHandle){
+                               if(this._fetchHandle.cancel){
+                                       this._cancelingQuery = true;
+                                       this._fetchHandle.cancel();
+                                       this._cancelingQuery = false;
                                }
+                               this._fetchHandle = null;
                        }
-               }
-               this._xDim = choices[0].length;
-               this._yDim = choices.length;
-
-               // Now set all events
-               // The palette itself is navigated to with the tab key on the keyboard
-               // Keyboard navigation within the Palette is with the arrow keys
-               // Spacebar selects the cell.
-               // For the up key the index is changed by negative the x dimension.
+               },
 
-               var keyIncrementMap = {
-                       UP_ARROW: -this._xDim,
-                       // The down key the index is increase by the x dimension.
-                       DOWN_ARROW: this._xDim,
-                       // Right and left move the index by 1.
-                       RIGHT_ARROW: this.isLeftToRight() ? 1 : -1,
-                       LEFT_ARROW: this.isLeftToRight() ? -1 : 1
-               };
-               for(var key in keyIncrementMap){
-                       this._connects.push(
-                               dijit.typematic.addKeyListener(
-                                       this.domNode,
-                                       {charOrCode:dojo.keys[key], ctrlKey:false, altKey:false, shiftKey:false},
-                                       this,
-                                       function(){
-                                               var increment = keyIncrementMap[key];
-                                               return function(count){ this._navigateByKey(increment, count); };
-                                       }(),
-                                       this.timeoutChangeRate,
-                                       this.defaultTimeout
-                               )
-                       );
-               }
-       },
+               _onInput: function(/*Event*/ evt){
+                       // summary:
+                       //              Handles paste events
+                       this.inherited(arguments);
+                       if(evt.charOrCode == 229){ // IME or cut/paste event
+                               this._onKey(evt);
+                       }
+               },
 
-       postCreate: function(){
-               this.inherited(arguments);
+               _onKey: function(/*Event*/ evt){
+                       // summary:
+                       //              Handles keyboard events
 
-               // Set initial navigable node.
-               this._setCurrent(this._cells[0].node);
-       },
+                       if(this.disabled || this.readOnly){ return; }
+                       var key = evt.charOrCode;
 
-       focus: function(){
-               // summary:
-               //              Focus this widget.  Puts focus on the most recently focused cell.
+                       // except for cutting/pasting case - ctrl + x/v
+                       if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 'x' && key != 'v')) || key == keys.SHIFT){
+                               return; // throw out weird key combinations and spurious events
+                       }
 
-               // The cell already has tabIndex set, just need to set CSS and focus it
-               dijit.focus(this._currentFocus);
-       },
+                       var doSearch = false;
+                       var pw = this.dropDown;
+                       var highlighted = null;
+                       this._prev_key_backspace = false;
+                       this._abortQuery();
 
-       _onCellClick: function(/*Event*/ evt){
-               // summary:
-               //              Handler for click, enter key & space key. Selects the cell.
-               // evt:
-               //              The event.
-               // tags:
-               //              private
+                       // _HasDropDown will do some of the work:
+                       //              1. when drop down is not yet shown:
+                       //                      - if user presses the down arrow key, call loadDropDown()
+                       //              2. when drop down is already displayed:
+                       //                      - on ESC key, call closeDropDown()
+                       //                      - otherwise, call dropDown.handleKey() to process the keystroke
+                       this.inherited(arguments);
 
-               var target = evt.currentTarget, 
-                       value = this._getDye(target).getValue();
+                       if(this._opened){
+                               highlighted = pw.getHighlightedOption();
+                       }
+                       switch(key){
+                               case keys.PAGE_DOWN:
+                               case keys.DOWN_ARROW:
+                               case keys.PAGE_UP:
+                               case keys.UP_ARROW:
+                                       // Keystroke caused ComboBox_menu to move to a different item.
+                                       // Copy new item to <input> box.
+                                       if(this._opened){
+                                               this._announceOption(highlighted);
+                                       }
+                                       event.stop(evt);
+                                       break;
 
-               // First focus the clicked cell, and then send onChange() notification.
-               // onChange() (via _setValueAttr) must be after the focus call, because
-               // it may trigger a refocus to somewhere else (like the Editor content area), and that
-               // second focus should win.
-               // Use setTimeout because IE doesn't like changing focus inside of an event handler.
-               this._setCurrent(target);
-               setTimeout(dojo.hitch(this, function(){
-                       dijit.focus(target);            
-                       this._setValueAttr(value, true);                
-               }));
-
-               // workaround bug where hover class is not removed on popup because the popup is
-               // closed and then there's no onblur event on the cell
-               dojo.removeClass(target, "dijitPaletteCellHover");
+                               case keys.ENTER:
+                                       // prevent submitting form if user presses enter. Also
+                                       // prevent accepting the value if either Next or Previous
+                                       // are selected
+                                       if(highlighted){
+                                               // only stop event on prev/next
+                                               if(highlighted == pw.nextButton){
+                                                       this._nextSearch(1);
+                                                       event.stop(evt);
+                                                       break;
+                                               }else if(highlighted == pw.previousButton){
+                                                       this._nextSearch(-1);
+                                                       event.stop(evt);
+                                                       break;
+                                               }
+                                       }else{
+                                               // Update 'value' (ex: KY) according to currently displayed text
+                                               this._setBlurValue(); // set value if needed
+                                               this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
+                                       }
+                                       // default case:
+                                       // if enter pressed while drop down is open, or for FilteringSelect,
+                                       // if we are in the middle of a query to convert a directly typed in value to an item,
+                                       // prevent submit
+                                       if(this._opened || this._fetchHandle){
+                                               event.stop(evt);
+                                       }
+                                       // fall through
 
-               dojo.stopEvent(evt);
-       },
+                               case keys.TAB:
+                                       var newvalue = this.get('displayedValue');
+                                       //      if the user had More Choices selected fall into the
+                                       //      _onBlur handler
+                                       if(pw && (
+                                               newvalue == pw._messages["previousMessage"] ||
+                                               newvalue == pw._messages["nextMessage"])
+                                       ){
+                                               break;
+                                       }
+                                       if(highlighted){
+                                               this._selectOption(highlighted);
+                                       }
+                                       // fall through
 
-       _setCurrent: function(/*DomNode*/ node){
-               // summary:
-               //              Sets which node is the focused cell.
-               // description:
-               //              At any point in time there's exactly one
-               //              cell with tabIndex != -1.   If focus is inside the palette then
-               //              focus is on that cell.
-               //
-               //              After calling this method, arrow key handlers and mouse click handlers
-               //              should focus the cell in a setTimeout().
-               // tags:
-               //              protected
-               if("_currentFocus" in this){
-                       // Remove tabIndex on old cell
-                       dojo.attr(this._currentFocus, "tabIndex", "-1");
-               }
+                               case keys.ESCAPE:
+                                       if(this._opened){
+                                               this._lastQuery = null; // in case results come back later
+                                               this.closeDropDown();
+                                       }
+                                       break;
 
-               // Set tabIndex of new cell
-               this._currentFocus = node;
-               if(node){
-                       dojo.attr(node, "tabIndex", this.tabIndex);
-               }
-       },
+                               case ' ':
+                                       if(highlighted){
+                                               // user is effectively clicking a choice in the drop down menu
+                                               event.stop(evt);
+                                               this._selectOption(highlighted);
+                                               this.closeDropDown();
+                                       }else{
+                                               // user typed a space into the input box, treat as normal character
+                                               doSearch = true;
+                                       }
+                                       break;
 
-       _setValueAttr: function(value, priorityChange){
-               // summary:
-               //              This selects a cell. It triggers the onChange event.
-               // value: String value of the cell to select
-               // tags:
-               //              protected
-               // priorityChange:
-               //              Optional parameter used to tell the select whether or not to fire
-               //              onChange event.
-               
-               // clear old value and selected cell
-               this.value = null;
-               if(this._selectedCell >= 0){
-                       dojo.removeClass(this._cells[this._selectedCell].node, "dijitPaletteCellSelected");
-               }
-               this._selectedCell = -1;
+                               case keys.DELETE:
+                               case keys.BACKSPACE:
+                                       this._prev_key_backspace = true;
+                                       doSearch = true;
+                                       break;
 
-               // search for cell matching specified value
-               if(value){
-                       for(var i = 0; i < this._cells.length; i++){
-                               if(value == this._cells[i].dye.getValue()){
-                                       this._selectedCell = i;
-                                       this.value = value;
+                               default:
+                                       // Non char keys (F1-F12 etc..)  shouldn't open list.
+                                       // Ascii characters and IME input (Chinese, Japanese etc.) should.
+                                       //IME input produces keycode == 229.
+                                       doSearch = typeof key == 'string' || key == 229;
+                       }
+                       if(doSearch){
+                               // need to wait a tad before start search so that the event
+                               // bubbles through DOM and we have value visible
+                               this.item = undefined; // undefined means item needs to be set
+                               this.searchTimer = setTimeout(lang.hitch(this, "_startSearchFromInput"),1);
+                       }
+               },
 
-                                       dojo.addClass(this._cells[i].node, "dijitPaletteCellSelected");
+               _autoCompleteText: function(/*String*/ text){
+                       // summary:
+                       //              Fill in the textbox with the first item from the drop down
+                       //              list, and highlight the characters that were
+                       //              auto-completed. For example, if user typed "CA" and the
+                       //              drop down list appeared, the textbox would be changed to
+                       //              "California" and "ifornia" would be highlighted.
 
-                                       if(priorityChange || priorityChange === undefined){
-                                               this.onChange(value);
-                                       }
+                       var fn = this.focusNode;
 
-                                       break;
+                       // IE7: clear selection so next highlight works all the time
+                       _TextBoxMixin.selectInputText(fn, fn.value.length);
+                       // does text autoComplete the value in the textbox?
+                       var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr';
+                       if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){
+                               var cpos = this.autoComplete ? this._getCaretPos(fn) : fn.value.length;
+                               // only try to extend if we added the last character at the end of the input
+                               if((cpos+1) > fn.value.length){
+                                       // only add to input node as we would overwrite Capitalisation of chars
+                                       // actually, that is ok
+                                       fn.value = text;//.substr(cpos);
+                                       // visually highlight the autocompleted characters
+                                       _TextBoxMixin.selectInputText(fn, cpos);
                                }
+                       }else{
+                               // text does not autoComplete; replace the whole value and highlight
+                               fn.value = text;
+                               _TextBoxMixin.selectInputText(fn);
                        }
-               }
-       },
+               },
 
-       onChange: function(value){
-               // summary:
-               //              Callback when a cell is selected.
-               // value: String
-               //              Value corresponding to cell.
-       },
+               _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){
+                       // summary:
+                       //              Callback when a search completes.
+                       // description:
+                       //              1. generates drop-down list and calls _showResultList() to display it
+                       //              2. if this result list is from user pressing "more choices"/"previous choices"
+                       //                      then tell screen reader to announce new option
+                       this._fetchHandle = null;
+                       if(     this.disabled ||
+                               this.readOnly ||
+                               (query[this.searchAttr] !== this._lastQuery)    // TODO: better way to avoid getting unwanted notify
+                       ){
+                               return;
+                       }
+                       var wasSelected = this.dropDown.getHighlightedOption();
+                       this.dropDown.clearResultList();
+                       if(!results.length && options.start == 0){ // if no results and not just the previous choices button
+                               this.closeDropDown();
+                               return;
+                       }
 
-       _navigateByKey: function(increment, typeCount){
-               // summary:
-               //              This is the callback for typematic.
-               //              It changes the focus and the highlighed cell.
-               // increment:
-               //              How much the key is navigated.
-               // typeCount:
-               //              How many times typematic has fired.
-               // tags:
-               //              private
+                       // Fill in the textbox with the first item from the drop down list,
+                       // and highlight the characters that were auto-completed. For
+                       // example, if user typed "CA" and the drop down list appeared, the
+                       // textbox would be changed to "California" and "ifornia" would be
+                       // highlighted.
 
-               // typecount == -1 means the key is released.
-               if(typeCount == -1){ return; }
+                       var nodes = this.dropDown.createOptions(
+                               results,
+                               options,
+                               lang.hitch(this, "_getMenuLabelFromItem")
+                       );
 
-               var newFocusIndex = this._currentFocus.index + increment;
-               if(newFocusIndex < this._cells.length && newFocusIndex > -1){
-                       var focusNode = this._cells[newFocusIndex].node;
-                       this._setCurrent(focusNode);
+                       // show our list (only if we have content, else nothing)
+                       this._showResultList();
 
-                       // Actually focus the node, for the benefit of screen readers.
-                       // Use setTimeout because IE doesn't like changing focus inside of an event handler
-                       setTimeout(dojo.hitch(dijit, "focus", focusNode), 0);
-               }
-       },
+                       // #4091:
+                       //              tell the screen reader that the paging callback finished by
+                       //              shouting the next choice
+                       if(options.direction){
+                               if(1 == options.direction){
+                                       this.dropDown.highlightFirstOption();
+                               }else if(-1 == options.direction){
+                                       this.dropDown.highlightLastOption();
+                               }
+                               if(wasSelected){
+                                       this._announceOption(this.dropDown.getHighlightedOption());
+                               }
+                       }else if(this.autoComplete && !this._prev_key_backspace
+                               // when the user clicks the arrow button to show the full list,
+                               // startSearch looks for "*".
+                               // it does not make sense to autocomplete
+                               // if they are just previewing the options available.
+                               && !/^[*]+$/.test(query[this.searchAttr].toString())){
+                                       this._announceOption(nodes[1]); // 1st real item
+                       }
+               },
 
-       _getDye: function(/*DomNode*/ cell){
-               // summary:
-               //              Get JS object for given cell DOMNode
+               _showResultList: function(){
+                       // summary:
+                       //              Display the drop down if not already displayed, or if it is displayed, then
+                       //              reposition it if necessary (reposition may be necessary if drop down's height changed).
+                       this.closeDropDown(true);
+                       this.openDropDown();
+                       this.domNode.setAttribute("aria-expanded", "true");
+               },
 
-               return this._cells[cell.index].dye;
-       }
-});
+               loadDropDown: function(/*Function*/ /*===== callback =====*/){
+                       // Overrides _HasDropDown.loadDropDown().
+                       // This is called when user has pressed button icon or pressed the down arrow key
+                       // to open the drop down.
 
-/*=====
-dojo.declare("dijit.Dye",
-       null,
-       {
-               // summary:
-               //              Interface for the JS Object associated with a palette cell (i.e. DOMNode)
+                       this._startSearchAll();
+               },
 
-               constructor: function(alias){
-                       // summary:
-                       //              Initialize according to value or alias like "white"
-                       // alias: String
+               isLoaded: function(){
+                       // signal to _HasDropDown that it needs to call loadDropDown() to load the
+                       // drop down asynchronously before displaying it
+                       return false;
                },
 
-               getValue: function(){
+               closeDropDown: function(){
+                       // Overrides _HasDropDown.closeDropDown().  Closes the drop down (assuming that it's open).
+                       // This method is the callback when the user types ESC or clicking
+                       // the button icon while the drop down is open.  It's also called by other code.
+                       this._abortQuery();
+                       if(this._opened){
+                               this.inherited(arguments);
+                               this.domNode.setAttribute("aria-expanded", "false");
+                               this.focusNode.removeAttribute("aria-activedescendant");
+                       }
+               },
+
+               _setBlurValue: function(){
+                       // if the user clicks away from the textbox OR tabs away, set the
+                       // value to the textbox value
+                       // #4617:
+                       //              if value is now more choices or previous choices, revert
+                       //              the value
+                       var newvalue = this.get('displayedValue');
+                       var pw = this.dropDown;
+                       if(pw && (
+                               newvalue == pw._messages["previousMessage"] ||
+                               newvalue == pw._messages["nextMessage"]
+                               )
+                       ){
+                               this._setValueAttr(this._lastValueReported, true);
+                       }else if(typeof this.item == "undefined"){
+                               // Update 'value' (ex: KY) according to currently displayed text
+                               this.item = null;
+                               this.set('displayedValue', newvalue);
+                       }else{
+                               if(this.value != this._lastValueReported){
+                                       this._handleOnChange(this.value, true);
+                               }
+                               this._refreshState();
+                       }
+               },
+
+               _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
                        // summary:
-                       //              Return "value" of cell; meaning of "value" varies by subclass.
+                       //              Set the displayed valued in the input box, and the hidden value
+                       //              that gets submitted, based on a dojo.data store item.
                        // description:
-                       //              For example color hex value, emoticon ascii value etc, entity hex value.
+                       //              Users shouldn't call this function; they should be calling
+                       //              set('item', value)
+                       // tags:
+                       //              private
+                       var value = '';
+                       if(item){
+                               if(!displayedValue){
+                                       displayedValue = this.store._oldAPI ?   // remove getValue() for 2.0 (old dojo.data API)
+                                               this.store.getValue(item, this.searchAttr) : item[this.searchAttr];
+                               }
+                               value = this._getValueField() != this.searchAttr ? this.store.getIdentity(item) : displayedValue;
+                       }
+                       this.set('value', value, priorityChange, displayedValue, item);
                },
 
-               fillCell: function(cell, blankGif){
+               _announceOption: function(/*Node*/ node){
                        // summary:
-                       //              Add cell DOMNode inner structure
-                       //      cell: DomNode
-                       //              The surrounding cell
-                       //      blankGif: String
-                       //              URL for blank cell image
-               }
-       }
-);
-=====*/
+                       //              a11y code that puts the highlighted option in the textbox.
+                       //              This way screen readers will know what is happening in the
+                       //              menu.
 
-}
-
-if(!dojo._hasResource["dijit.ColorPalette"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.ColorPalette"] = true;
-dojo.provide("dijit.ColorPalette");
+                       if(!node){
+                               return;
+                       }
+                       // pull the text value from the item attached to the DOM node
+                       var newValue;
+                       if(node == this.dropDown.nextButton ||
+                               node == this.dropDown.previousButton){
+                               newValue = node.innerHTML;
+                               this.item = undefined;
+                               this.value = '';
+                       }else{
+                               newValue = (this.store._oldAPI ?        // remove getValue() for 2.0 (old dojo.data API)
+                                       this.store.getValue(node.item, this.searchAttr) : node.item[this.searchAttr]).toString();
+                               this.set('item', node.item, false, newValue);
+                       }
+                       // get the text that the user manually entered (cut off autocompleted text)
+                       this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
+                       // set up ARIA activedescendant
+                       this.focusNode.setAttribute("aria-activedescendant", domAttr.get(node, "id"));
+                       // autocomplete the rest of the option to announce change
+                       this._autoCompleteText(newValue);
+               },
 
+               _selectOption: function(/*DomNode*/ target){
+                       // summary:
+                       //              Menu callback function, called when an item in the menu is selected.
+                       this.closeDropDown();
+                       if(target){
+                               this._announceOption(target);
+                       }
+                       this._setCaretPos(this.focusNode, this.focusNode.value.length);
+                       this._handleOnChange(this.value, true);
+               },
 
+               _startSearchAll: function(){
+                       this._startSearch('');
+               },
 
+               _startSearchFromInput: function(){
+                       this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1"));
+               },
 
+               _getQueryString: function(/*String*/ text){
+                       return string.substitute(this.queryExpr, [text]);
+               },
 
+               _startSearch: function(/*String*/ key){
+                       // summary:
+                       //              Starts a search for elements matching key (key=="" means to return all items),
+                       //              and calls _openResultList() when the search completes, to display the results.
+                       if(!this.dropDown){
+                               var popupId = this.id + "_popup",
+                                       dropDownConstructor = lang.isString(this.dropDownClass) ?
+                                               lang.getObject(this.dropDownClass, false) : this.dropDownClass;
+                               this.dropDown = new dropDownConstructor({
+                                       onChange: lang.hitch(this, this._selectOption),
+                                       id: popupId,
+                                       dir: this.dir,
+                                       textDir: this.textDir
+                               });
+                               this.focusNode.removeAttribute("aria-activedescendant");
+                               this.textbox.setAttribute("aria-owns",popupId); // associate popup with textbox
+                       }
+                       this._lastInput = key; // Store exactly what was entered by the user.
 
+                       // Setup parameters to be passed to store.query().
+                       // Create a new query to prevent accidentally querying for a hidden
+                       // value from FilteringSelect's keyField
+                       var query = lang.clone(this.query); // #5970
+                       var options = {
+                               start: 0,
+                               count: this.pageSize,
+                               queryOptions: {         // remove for 2.0
+                                       ignoreCase: this.ignoreCase,
+                                       deep: true
+                               }
+                       };
+                       lang.mixin(options, this.fetchProperties);
 
+                       // Generate query
+                       var qs = this._getQueryString(key), q;
+                       if(this.store._oldAPI){
+                               // remove this branch for 2.0
+                               q = qs;
+                       }else{
+                               // Query on searchAttr is a regex for benefit of dojo.store.Memory,
+                               // but with a toString() method to help dojo.store.JsonRest.
+                               // Search string like "Co*" converted to regex like /^Co.*$/i.
+                               q = filter.patternToRegExp(qs, this.ignoreCase);
+                               q.toString = function(){ return qs; };
+                       }
+                       this._lastQuery = query[this.searchAttr] = q;
+
+                       // Function to run the query, wait for the results, and then call _openResultList()
+                       var _this = this,
+                               startQuery = function(){
+                                       var resPromise = _this._fetchHandle = _this.store.query(query, options);
+                                       Deferred.when(resPromise, function(res){
+                                               _this._fetchHandle = null;
+                                               res.total = resPromise.total;
+                                               _this._openResultList(res, query, options);
+                                       }, function(err){
+                                               _this._fetchHandle = null;
+                                               if(!_this._cancelingQuery){     // don't treat canceled query as an error
+                                                       console.error(_this.declaredClass + ' ' + err.toString());
+                                                       _this.closeDropDown();
+                                               }
+                                       });
+                               };
 
+                       // #5970: set _lastQuery, *then* start the timeout
+                       // otherwise, if the user types and the last query returns before the timeout,
+                       // _lastQuery won't be set and their input gets rewritten
 
+                       this.searchTimer = setTimeout(lang.hitch(this, function(query, _this){
+                               this.searchTimer = null;
 
-dojo.declare("dijit.ColorPalette",
-       [dijit._Widget, dijit._Templated, dijit._PaletteMixin],
-       {
-       // summary:
-       //              A keyboard accessible color-picking widget
-       // description:
-       //              Grid showing various colors, so the user can pick a certain color.
-       //              Can be used standalone, or as a popup.
-       //
-       // example:
-       // |    <div dojoType="dijit.ColorPalette"></div>
-       //
-       // example:
-       // |    var picker = new dijit.ColorPalette({ },srcNode);
-       // |    picker.startup();
+                               startQuery();
 
+                               // Setup method to handle clicking next/previous buttons to page through results
+                               this._nextSearch = this.dropDown.onPage = function(direction){
+                                       options.start += options.count * direction;
+                                       //      tell callback the direction of the paging so the screen
+                                       //      reader knows which menu option to shout
+                                       options.direction = direction;
+                                       startQuery();
+                                       _this.focus();
+                               };
+                       }, query, this), this.searchDelay);
+               },
 
-       // palette: String
-       //              Size of grid, either "7x10" or "3x4".
-       palette: "7x10",
+               _getValueField: function(){
+                       // summary:
+                       //              Helper for postMixInProperties() to set this.value based on data inlined into the markup.
+                       //              Returns the attribute name in the item (in dijit.form._ComboBoxDataStore) to use as the value.
+                       return this.searchAttr;
+               },
 
-       // _palettes: [protected] Map
-       //              This represents the value of the colors.
-       //              The first level is a hashmap of the different palettes available.
-       //              The next two dimensions represent the columns and rows of colors.
-       _palettes: {
-               "7x10": [["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan",     "lavender", "plum"],
-                               ["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],
-                               ["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise",      "skyblue", "mediumslateblue","orchid"],
-                               ["gray", "red", "orangered", "darkorange", "yellow", "limegreen",       "darkseagreen", "royalblue", "slateblue", "mediumorchid"],
-                               ["dimgray", "crimson",  "chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],
-                               ["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],
-                               ["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo",        "purple"]],
+               //////////// INITIALIZATION METHODS ///////////////////////////////////////
 
-               "3x4": [["white", "lime", "green", "blue"],
-                       ["silver", "yellow", "fuchsia", "navy"],
-                       ["gray", "red", "purple", "black"]]
-       },
+               constructor: function(){
+                       this.query={};
+                       this.fetchProperties={};
+               },
 
-       // _imagePaths: [protected] Map
-       //              This is stores the path to the palette images
-       _imagePaths: {
-               "7x10": dojo.moduleUrl("dijit.themes", "a11y/colors7x10.png"),
-               "3x4": dojo.moduleUrl("dijit.themes", "a11y/colors3x4.png"),
-               "7x10-rtl": dojo.moduleUrl("dijit.themes", "a11y/colors7x10-rtl.png"),
-               "3x4-rtl": dojo.moduleUrl("dijit.themes", "a11y/colors3x4-rtl.png")
-       },
+               postMixInProperties: function(){
+                       if(!this.store){
+                               var srcNodeRef = this.srcNodeRef;
+                               var list = this.list;
+                               if(list){
+                                       this.store = registry.byId(list);
+                               }else{
+                                       // if user didn't specify store, then assume there are option tags
+                                       this.store = new DataList({}, srcNodeRef);
+                               }
 
-       // templateString: String
-       //              The template of this widget.
-       templateString: dojo.cache("dijit", "templates/ColorPalette.html", "<div class=\"dijitInline dijitColorPalette\">\n\t<img class=\"dijitColorPaletteUnder\" dojoAttachPoint=\"imageNode\" waiRole=\"presentation\" alt=\"\"/>\n\t<table class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\">\n\t\t<tbody dojoAttachPoint=\"gridNode\"></tbody>\n\t</table>\n</div>\n"),
+                               // if there is no value set and there is an option list, set
+                               // the value to the first value to be consistent with native Select
+                               // Firefox and Safari set value
+                               // IE6 and Opera set selectedIndex, which is automatically set
+                               // by the selected attribute of an option tag
+                               // IE6 does not set value, Opera sets value = selectedIndex
+                               if(!("value" in this.params)){
+                                       var item = (this.item = this.store.fetchSelectedItem());
+                                       if(item){
+                                               var valueField = this._getValueField();
+                                               // remove getValue() for 2.0 (old dojo.data API)
+                                               this.value = this.store._oldAPI ? this.store.getValue(item, valueField) : item[valueField];
+                                       }
+                               }
+                       }
 
-       baseClass: "dijitColorPalette",
+                       this.inherited(arguments);
+               },
 
-       dyeClass: 'dijit._Color',
+               postCreate: function(){
+                       // summary:
+                       //              Subclasses must call this method from their postCreate() methods
+                       // tags:
+                       //              protected
 
-       buildRendering: function(){
-               // Instantiate the template, which makes a skeleton into which we'll insert a bunch of
-               // <img> nodes
+                       // find any associated label element and add to ComboBox node.
+                       var label=query('label[for="'+this.id+'"]');
+                       if(label.length){
+                               label[0].id = (this.id+"_label");
+                               this.domNode.setAttribute("aria-labelledby", label[0].id);
 
-               this.inherited(arguments);
+                       }
+                       this.inherited(arguments);
+               },
 
-               this.imageNode.setAttribute("src", this._imagePaths[this.palette + (this.isLeftToRight() ? "" : "-rtl")].toString());
+               _getMenuLabelFromItem: function(/*Item*/ item){
+                       var label = this.labelFunc(item, this.store),
+                               labelType = this.labelType;
+                       // If labelType is not "text" we don't want to screw any markup ot whatever.
+                       if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){
+                               label = this.doHighlight(label, this._escapeHtml(this._lastInput));
+                               labelType = "html";
+                       }
+                       return {html: labelType == "html", label: label};
+               },
 
-               var i18nColorNames = dojo.i18n.getLocalization("dojo", "colors", this.lang);
-               this._preparePalette(
-                       this._palettes[this.palette],
-                       i18nColorNames
-               );
-       }
-});
+               doHighlight: function(/*String*/ label, /*String*/ find){
+                       // summary:
+                       //              Highlights the string entered by the user in the menu.  By default this
+                       //              highlights the first occurrence found. Override this method
+                       //              to implement your custom highlighting.
+                       // tags:
+                       //              protected
 
-dojo.declare("dijit._Color", dojo.Color,
-       // summary:
-       //              Object associated with each cell in a ColorPalette palette.
-       //              Implements dijit.Dye.
-       {
-               constructor: function(/*String*/alias){
-                       this._alias = alias;
-                       this.setColor(dojo.Color.named[alias]);
+                       var
+                               // Add (g)lobal modifier when this.highlightMatch == "all" and (i)gnorecase when this.ignoreCase == true
+                               modifiers = (this.ignoreCase ? "i" : "") + (this.highlightMatch == "all" ? "g" : ""),
+                               i = this.queryExpr.indexOf("${0}");
+                       find = regexp.escapeString(find); // escape regexp special chars
+                       return this._escapeHtml(label).replace(
+                               // prepend ^ when this.queryExpr == "${0}*" and append $ when this.queryExpr == "*${0}"
+                               new RegExp((i == 0 ? "^" : "") + "("+ find +")" + (i == (this.queryExpr.length - 4) ? "$" : ""), modifiers),
+                               '<span class="dijitComboBoxHighlightMatch">$1</span>'
+                       ); // returns String, (almost) valid HTML (entities encoded)
                },
 
-               getValue: function(){
+               _escapeHtml: function(/*String*/ str){
+                       // TODO Should become dojo.html.entities(), when exists use instead
                        // summary:
-                       //              Note that although dijit._Color is initialized with a value like "white" getValue() always
-                       //              returns a hex value
-                       return this.toHex();
+                       //              Adds escape sequences for special characters in XML: &<>"'
+                       str = String(str).replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
+                               .replace(/>/gm, "&gt;").replace(/"/gm, "&quot;"); //balance"
+                       return str; // string
                },
 
-               fillCell: function(/*DOMNode*/ cell, /*String*/ blankGif){
-                       dojo.create("img", {
-                               src: blankGif,
-                               "class": "dijitPaletteImg",
-                               alt: this._alias
-                       }, cell);
-               }
-       }
-);
+               reset: function(){
+                       // Overrides the _FormWidget.reset().
+                       // Additionally reset the .item (to clean up).
+                       this.item = null;
+                       this.inherited(arguments);
+               },
 
-}
+               labelFunc: function(/*item*/ item, /*dojo.store.api.Store*/ store){
+                       // summary:
+                       //              Computes the label to display based on the dojo.data store item.
+                       // returns:
+                       //              The label that the ComboBox should display
+                       // tags:
+                       //              private
 
-if(!dojo._hasResource["dojo.dnd.common"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.common"] = true;
-dojo.provide("dojo.dnd.common");
+                       // Use toString() because XMLStore returns an XMLItem whereas this
+                       // method is expected to return a String (#9354).
+                       // Remove getValue() for 2.0 (old dojo.data API)
+                       return (store._oldAPI ? store.getValue(item, this.labelAttr || this.searchAttr) :
+                               item[this.labelAttr || this.searchAttr]).toString(); // String
+               },
 
-dojo.dnd.getCopyKeyState = dojo.isCopyKey;
+               _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){
+                       // summary:
+                       //              Hook so set('value', value) works.
+                       // description:
+                       //              Sets the value of the select.
+                       this._set("item", item||null); // value not looked up in store
+                       if(!value){ value = ''; } // null translates to blank
+                       this.inherited(arguments);
+               },
+               _setTextDirAttr: function(/*String*/ textDir){
+                       // summary:
+                       //              Setter for textDir, needed for the dropDown's textDir update.
+                       // description:
+                       //              Users shouldn't call this function; they should be calling
+                       //              set('textDir', value)
+                       // tags:
+                       //              private
+                       this.inherited(arguments);
+                       // update the drop down also (_ComboBoxMenuMixin)
+                       if(this.dropDown){
+                               this.dropDown._set("textDir", textDir);
+                       }
+               }
+       });
+});
 
-dojo.dnd._uniqueId = 0;
-dojo.dnd.getUniqueId = function(){
-       // summary:
-       //              returns a unique string for use with any DOM element
-       var id;
-       do{
-               id = dojo._scopeName + "Unique" + (++dojo.dnd._uniqueId);
-       }while(dojo.byId(id));
-       return id;
-};
+},
+'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n",
+'url:dijit/layout/templates/_ScrollingTabControllerButton.html':"<div data-dojo-attach-event=\"onclick:_onClick\">\n\t<div role=\"presentation\" class=\"dijitTabInnerDiv\" data-dojo-attach-point=\"innerDiv,focusNode\">\n\t\t<div role=\"presentation\" class=\"dijitTabContent dijitButtonContents\" data-dojo-attach-point=\"tabContent\">\n\t\t\t<img role=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t\t\t<span data-dojo-attach-point=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n\t\t</div>\n\t</div>\n</div>",
+'dijit/form/MappedTextBox':function(){
+define("dijit/form/MappedTextBox", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-construct", // domConstruct.place
+       "./ValidationTextBox"
+], function(declare, domConstruct, ValidationTextBox){
 
-dojo.dnd._empty = {};
+/*=====
+       var ValidationTextBox = dijit.form.ValidationTextBox;
+=====*/
 
-dojo.dnd.isFormElement = function(/*Event*/ e){
+       // module:
+       //              dijit/form/MappedTextBox
        // summary:
-       //              returns true if user clicked on a form element
-       var t = e.target;
-       if(t.nodeType == 3 /*TEXT_NODE*/){
-               t = t.parentNode;
-       }
-       return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0;       // Boolean
-};
+       //              A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
+       //              a visible formatted display value, and a serializable
+       //              value in a hidden input field which is actually sent to the server.
 
-}
-
-if(!dojo._hasResource["dojo.dnd.autoscroll"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.autoscroll"] = true;
-dojo.provide("dojo.dnd.autoscroll");
+       return declare("dijit.form.MappedTextBox", ValidationTextBox, {
+               // summary:
+               //              A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
+               //              a visible formatted display value, and a serializable
+               //              value in a hidden input field which is actually sent to the server.
+               // description:
+               //              The visible display may
+               //              be locale-dependent and interactive.  The value sent to the server is stored in a hidden
+               //              input field which uses the `name` attribute declared by the original widget.  That value sent
+               //              to the server is defined by the dijit.form.MappedTextBox.serialize method and is typically
+               //              locale-neutral.
+               // tags:
+               //              protected
 
-dojo.dnd.getViewport = function(){
-       // summary:
-       //              Returns a viewport size (visible part of the window)
-
-       // TODO: remove this when getViewport() moved to dojo core, see #7028
-
-       // FIXME: need more docs!!
-       var d = dojo.doc, dd = d.documentElement, w = window, b = dojo.body();
-       if(dojo.isMozilla){
-               return {w: dd.clientWidth, h: w.innerHeight};   // Object
-       }else if(!dojo.isOpera && w.innerWidth){
-               return {w: w.innerWidth, h: w.innerHeight};             // Object
-       }else if (!dojo.isOpera && dd && dd.clientWidth){
-               return {w: dd.clientWidth, h: dd.clientHeight}; // Object
-       }else if (b.clientWidth){
-               return {w: b.clientWidth, h: b.clientHeight};   // Object
-       }
-       return null;    // Object
-};
+               postMixInProperties: function(){
+                       this.inherited(arguments);
 
-dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;
-dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;
+                       // we want the name attribute to go to the hidden <input>, not the displayed <input>,
+                       // so override _FormWidget.postMixInProperties() setting of nameAttrSetting
+                       this.nameAttrSetting = "";
+               },
 
-dojo.dnd.V_AUTOSCROLL_VALUE = 16;
-dojo.dnd.H_AUTOSCROLL_VALUE = 16;
+               // Override default behavior to assign name to focusNode
+               _setNameAttr: null,
 
-dojo.dnd.autoScroll = function(e){
-       // summary:
-       //              a handler for onmousemove event, which scrolls the window, if
-       //              necesary
-       // e: Event
-       //              onmousemove event
+               serialize: function(val /*=====, options =====*/){
+                       // summary:
+                       //              Overridable function used to convert the get('value') result to a canonical
+                       //              (non-localized) string.  For example, will print dates in ISO format, and
+                       //              numbers the same way as they are represented in javascript.
+                       // val: anything
+                       // options: Object?
+                       // tags:
+                       //              protected extension
+                       return val.toString ? val.toString() : ""; // String
+               },
 
-       // FIXME: needs more docs!
-       var v = dojo.dnd.getViewport(), dx = 0, dy = 0;
-       if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){
-               dx = -dojo.dnd.H_AUTOSCROLL_VALUE;
-       }else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){
-               dx = dojo.dnd.H_AUTOSCROLL_VALUE;
-       }
-       if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){
-               dy = -dojo.dnd.V_AUTOSCROLL_VALUE;
-       }else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){
-               dy = dojo.dnd.V_AUTOSCROLL_VALUE;
-       }
-       window.scrollBy(dx, dy);
-};
+               toString: function(){
+                       // summary:
+                       //              Returns widget as a printable string using the widget's value
+                       // tags:
+                       //              protected
+                       var val = this.filter(this.get('value')); // call filter in case value is nonstring and filter has been customized
+                       return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String
+               },
 
-dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};
-dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};
+               validate: function(){
+                       // Overrides `dijit.form.TextBox.validate`
+                       this.valueNode.value = this.toString();
+                       return this.inherited(arguments);
+               },
 
-dojo.dnd.autoScrollNodes = function(e){
+               buildRendering: function(){
+                       // Overrides `dijit._TemplatedMixin.buildRendering`
+
+                       this.inherited(arguments);
+
+                       // Create a hidden <input> node with the serialized value used for submit
+                       // (as opposed to the displayed value).
+                       // Passing in name as markup rather than calling domConstruct.create() with an attrs argument
+                       // to make query(input[name=...]) work on IE. (see #8660)
+                       this.valueNode = domConstruct.place("<input type='hidden'" + (this.name ? " name='" + this.name.replace(/'/g, "&quot;") + "'" : "") + "/>", this.textbox, "after");
+               },
+
+               reset: function(){
+                       // Overrides `dijit.form.ValidationTextBox.reset` to
+                       // reset the hidden textbox value to ''
+                       this.valueNode.value = '';
+                       this.inherited(arguments);
+               }
+       });
+});
+
+},
+'dijit/form/ComboBoxMixin':function(){
+require({cache:{
+'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"&#9660; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&#935; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n"}});
+define("dijit/form/ComboBoxMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred",
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.mixin
+       "dojo/store/util/QueryResults", // dojo.store.util.QueryResults
+       "./_AutoCompleterMixin",
+       "./_ComboBoxMenu",
+       "../_HasDropDown",
+       "dojo/text!./templates/DropDownBox.html"
+], function(declare, Deferred, kernel, lang, QueryResults, _AutoCompleterMixin, _ComboBoxMenu, _HasDropDown, template){
+
+/*=====
+       var _AutoCompleterMixin = dijit.form._AutoCompleterMixin;
+       var _ComboBoxMenu = dijit.form._ComboBoxMenu;
+       var _HasDropDown = dijit._HasDropDown;
+=====*/
+
+       // module:
+       //              dijit/form/ComboBoxMixin
        // summary:
-       //              a handler for onmousemove event, which scrolls the first avaialble
-       //              Dom element, it falls back to dojo.dnd.autoScroll()
-       // e: Event
-       //              onmousemove event
+       //              Provides main functionality of ComboBox widget
 
-       // FIXME: needs more docs!
-       for(var n = e.target; n;){
-               if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){
-                       var s = dojo.getComputedStyle(n);
-                       if(s.overflow.toLowerCase() in dojo.dnd._validOverflow){
-                               var b = dojo._getContentBox(n, s), t = dojo.position(n, true);
-                               //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
-                               var w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2), 
-                                       h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2),
-                                       rx = e.pageX - t.x, ry = e.pageY - t.y, dx = 0, dy = 0;
-                               if(dojo.isWebKit || dojo.isOpera){
-                                       // FIXME: this code should not be here, it should be taken into account 
-                                       // either by the event fixing code, or the dojo.position()
-                                       // FIXME: this code doesn't work on Opera 9.5 Beta
-                                       rx += dojo.body().scrollLeft, ry += dojo.body().scrollTop;
-                               }
-                               if(rx > 0 && rx < b.w){
-                                       if(rx < w){
-                                               dx = -w;
-                                       }else if(rx > b.w - w){
-                                               dx = w;
+       return declare("dijit.form.ComboBoxMixin", [_HasDropDown, _AutoCompleterMixin], {
+               // summary:
+               //              Provides main functionality of ComboBox widget
+
+               // dropDownClass: [protected extension] Function String
+               //              Dropdown widget class used to select a date/time.
+               //              Subclasses should specify this.
+               dropDownClass: _ComboBoxMenu,
+
+               // hasDownArrow: Boolean
+               //              Set this textbox to have a down arrow button, to display the drop down list.
+               //              Defaults to true.
+               hasDownArrow: true,
+
+               templateString: template,
+
+               baseClass: "dijitTextBox dijitComboBox",
+
+               /*=====
+               // store: [const] dojo.store.api.Store || dojo.data.api.Read
+               //              Reference to data provider object used by this ComboBox.
+               //
+               //              Should be dojo.store.api.Store, but dojo.data.api.Read supported
+               //              for backwards compatibility.
+               store: null,
+               =====*/
+
+               // Set classes like dijitDownArrowButtonHover depending on
+               // mouse action over button node
+               cssStateNodes: {
+                       "_buttonNode": "dijitDownArrowButton"
+               },
+
+               _setHasDownArrowAttr: function(/*Boolean*/ val){
+                       this._set("hasDownArrow", val);
+                       this._buttonNode.style.display = val ? "" : "none";
+               },
+
+               _showResultList: function(){
+                       // hide the tooltip
+                       this.displayMessage("");
+                       this.inherited(arguments);
+               },
+
+               _setStoreAttr: function(store){
+                       // For backwards-compatibility, accept dojo.data store in addition to dojo.store.store.  Remove in 2.0.
+                       if(!store.get){
+                               lang.mixin(store, {
+                                       _oldAPI: true,
+                                       get: function(id){
+                                               // summary:
+                                               //              Retrieves an object by it's identity. This will trigger a fetchItemByIdentity.
+                                               //              Like dojo.store.DataStore.get() except returns native item.
+                                               var deferred = new Deferred();
+                                               this.fetchItemByIdentity({
+                                                       identity: id,
+                                                       onItem: function(object){
+                                                               deferred.resolve(object);
+                                                       },
+                                                       onError: function(error){
+                                                               deferred.reject(error);
+                                                       }
+                                               });
+                                               return deferred.promise;
+                                       },
+                                       query: function(query, options){
+                                               // summary:
+                                               //              Queries the store for objects.   Like dojo.store.DataStore.query()
+                                               //              except returned Deferred contains array of native items.
+                                               var deferred = new Deferred(function(){ fetchHandle.abort && fetchHandle.abort(); });
+                                               var fetchHandle = this.fetch(lang.mixin({
+                                                       query: query,
+                                                       onBegin: function(count){
+                                                               deferred.total = count;
+                                                       },
+                                                       onComplete: function(results){
+                                                               deferred.resolve(results);
+                                                       },
+                                                       onError: function(error){
+                                                               deferred.reject(error);
+                                                       }
+                                               }, options));
+                                               return QueryResults(deferred);
                                        }
-                               }
-                               //console.log("ry =", ry, "b.h =", b.h, "h =", h);
-                               if(ry > 0 && ry < b.h){
-                                       if(ry < h){
-                                               dy = -h;
-                                       }else if(ry > b.h - h){
-                                               dy = h;
+                               });
+                       }
+                       this._set("store", store);
+               },
+
+               postMixInProperties: function(){
+                       // Since _setValueAttr() depends on this.store, _setStoreAttr() needs to execute first.
+                       // Unfortunately, without special code, it ends up executing second.
+                       if(this.params.store){
+                               this._setStoreAttr(this.params.store);
+                       }
+
+                       this.inherited(arguments);
+
+                       // User may try to access this.store.getValue() etc.  in a custom labelFunc() function.
+                       // It's not available with the new data store for handling inline <option> tags, so add it.
+                       if(!this.params.store){
+                               var clazz = this.declaredClass;
+                               lang.mixin(this.store, {
+                                       getValue: function(item, attr){
+                                               kernel.deprecated(clazz + ".store.getValue(item, attr) is deprecated for builtin store.  Use item.attr directly", "", "2.0");
+                                               return item[attr];
+                                       },
+                                       getLabel: function(item){
+                                               kernel.deprecated(clazz + ".store.getLabel(item) is deprecated for builtin store.  Use item.label directly", "", "2.0");
+                                               return item.name;
+                                       },
+                                       fetch: function(args){
+                                               kernel.deprecated(clazz + ".store.fetch() is deprecated for builtin store.", "Use store.query()", "2.0");
+                                               var shim = ["dojo/data/ObjectStore"];   // indirection so it doesn't get rolled into a build
+                                               require(shim, lang.hitch(this, function(ObjectStore){
+                                                       new ObjectStore({objectStore: this}).fetch(args);
+                                               }));
                                        }
-                               }
-                               var oldLeft = n.scrollLeft, oldTop = n.scrollTop;
-                               n.scrollLeft = n.scrollLeft + dx;
-                               n.scrollTop  = n.scrollTop  + dy;
-                               if(oldLeft != n.scrollLeft || oldTop != n.scrollTop){ return; }
+                               });
                        }
                }
-               try{
-                       n = n.parentNode;
-               }catch(x){
-                       n = null;
-               }
-       }
-       dojo.dnd.autoScroll(e);
-};
+       });
+});
 
-}
+},
+'dijit/form/_TextBoxMixin':function(){
+define("dijit/form/_TextBoxMixin", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.byId
+       "dojo/_base/event", // event.stop
+       "dojo/keys", // keys.ALT keys.CAPS_LOCK keys.CTRL keys.META keys.SHIFT
+       "dojo/_base/lang", // lang.mixin
+       ".."    // for exporting dijit._setSelectionRange, dijit.selectInputText
+], function(array, declare, dom, event, keys, lang, dijit){
+
+// module:
+//             dijit/form/_TextBoxMixin
+// summary:
+//             A mixin for textbox form input widgets
+
+var _TextBoxMixin = declare("dijit.form._TextBoxMixin", null, {
+       // summary:
+       //              A mixin for textbox form input widgets
 
-if(!dojo._hasResource["dojo.dnd.Mover"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Mover"] = true;
-dojo.provide("dojo.dnd.Mover");
+       // trim: Boolean
+       //              Removes leading and trailing whitespace if true.  Default is false.
+       trim: false,
 
+       // uppercase: Boolean
+       //              Converts all characters to uppercase if true.  Default is false.
+       uppercase: false,
 
+       // lowercase: Boolean
+       //              Converts all characters to lowercase if true.  Default is false.
+       lowercase: false,
 
+       // propercase: Boolean
+       //              Converts the first character of each word to uppercase if true.
+       propercase: false,
 
-dojo.declare("dojo.dnd.Mover", null, {
-       constructor: function(node, e, host){
+       // maxLength: String
+       //              HTML INPUT tag maxLength declaration.
+       maxLength: "",
+
+       // selectOnClick: [const] Boolean
+       //              If true, all text will be selected when focused with mouse
+       selectOnClick: false,
+
+       // placeHolder: String
+       //              Defines a hint to help users fill out the input field (as defined in HTML 5).
+       //              This should only contain plain text (no html markup).
+       placeHolder: "",
+
+       _getValueAttr: function(){
                // summary:
-               //              an object, which makes a node follow the mouse. 
-               //              Used as a default mover, and as a base class for custom movers.
-               // node: Node
-               //              a node (or node's id) to be moved
-               // e: Event
-               //              a mouse event, which started the move;
-               //              only pageX and pageY properties are used
-               // host: Object?
-               //              object which implements the functionality of the move,
-               //              and defines proper events (onMoveStart and onMoveStop)
-               this.node = dojo.byId(node);
-               this.marginBox = {l: e.pageX, t: e.pageY};
-               this.mouseButton = e.button;
-               var h = this.host = host, d = node.ownerDocument, 
-                       firstEvent = dojo.connect(d, "onmousemove", this, "onFirstMove");
-               this.events = [
-                       dojo.connect(d, "onmousemove", this, "onMouseMove"),
-                       dojo.connect(d, "onmouseup",   this, "onMouseUp"),
-                       // cancel text selection and text dragging
-                       dojo.connect(d, "ondragstart",   dojo.stopEvent),
-                       dojo.connect(d.body, "onselectstart", dojo.stopEvent),
-                       firstEvent
-               ];
-               // notify that the move has started
-               if(h && h.onMoveStart){
-                       h.onMoveStart(this);
-               }
+               //              Hook so get('value') works as we like.
+               // description:
+               //              For `dijit.form.TextBox` this basically returns the value of the <input>.
+               //
+               //              For `dijit.form.MappedTextBox` subclasses, which have both
+               //              a "displayed value" and a separate "submit value",
+               //              This treats the "displayed value" as the master value, computing the
+               //              submit value from it via this.parse().
+               return this.parse(this.get('displayedValue'), this.constraints);
        },
-       // mouse event processors
-       onMouseMove: function(e){
+
+       _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
                // summary:
-               //              event processor for onmousemove
-               // e: Event
-               //              mouse event
-               dojo.dnd.autoScroll(e);
-               var m = this.marginBox;
-               this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
-               dojo.stopEvent(e);
-       },
-       onMouseUp: function(e){
-               if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ? 
-                               e.button == 0 : this.mouseButton == e.button){
-                       this.destroy();
+               //              Hook so set('value', ...) works.
+               //
+               // description:
+               //              Sets the value of the widget to "value" which can be of
+               //              any type as determined by the widget.
+               //
+               // value:
+               //              The visual element value is also set to a corresponding,
+               //              but not necessarily the same, value.
+               //
+               // formattedValue:
+               //              If specified, used to set the visual element value,
+               //              otherwise a computed visual value is used.
+               //
+               // priorityChange:
+               //              If true, an onChange event is fired immediately instead of
+               //              waiting for the next blur event.
+
+               var filteredValue;
+               if(value !== undefined){
+                       // TODO: this is calling filter() on both the display value and the actual value.
+                       // I added a comment to the filter() definition about this, but it should be changed.
+                       filteredValue = this.filter(value);
+                       if(typeof formattedValue != "string"){
+                               if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){
+                                       formattedValue = this.filter(this.format(filteredValue, this.constraints));
+                               }else{ formattedValue = ''; }
+                       }
                }
-               dojo.stopEvent(e);
-       },
-       // utilities
-       onFirstMove: function(e){
-               // summary:
-               //              makes the node absolute; it is meant to be called only once. 
-               //              relative and absolutely positioned nodes are assumed to use pixel units
-               var s = this.node.style, l, t, h = this.host;
-               switch(s.position){
-                       case "relative":
-                       case "absolute":
-                               // assume that left and top values are in pixels already
-                               l = Math.round(parseFloat(s.left)) || 0;
-                               t = Math.round(parseFloat(s.top)) || 0;
-                               break;
-                       default:
-                               s.position = "absolute";        // enforcing the absolute mode
-                               var m = dojo.marginBox(this.node);
-                               // event.pageX/pageY (which we used to generate the initial
-                               // margin box) includes padding and margin set on the body.
-                               // However, setting the node's position to absolute and then
-                               // doing dojo.marginBox on it *doesn't* take that additional
-                               // space into account - so we need to subtract the combined
-                               // padding and margin.  We use getComputedStyle and
-                               // _getMarginBox/_getContentBox to avoid the extra lookup of
-                               // the computed style. 
-                               var b = dojo.doc.body;
-                               var bs = dojo.getComputedStyle(b);
-                               var bm = dojo._getMarginBox(b, bs);
-                               var bc = dojo._getContentBox(b, bs);
-                               l = m.l - (bc.l - bm.l);
-                               t = m.t - (bc.t - bm.t);
-                               break;
+               if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){
+                       this.textbox.value = formattedValue;
+                       this._set("displayedValue", this.get("displayedValue"));
                }
-               this.marginBox.l = l - this.marginBox.l;
-               this.marginBox.t = t - this.marginBox.t;
-               if(h && h.onFirstMove){
-                       h.onFirstMove(this, e);
+
+               if(this.textDir == "auto"){
+                       this.applyTextDir(this.focusNode, formattedValue);
                }
-               dojo.disconnect(this.events.pop());
+
+               this.inherited(arguments, [filteredValue, priorityChange]);
        },
-       destroy: function(){
+
+       // displayedValue: String
+       //              For subclasses like ComboBox where the displayed value
+       //              (ex: Kentucky) and the serialized value (ex: KY) are different,
+       //              this represents the displayed value.
+       //
+       //              Setting 'displayedValue' through set('displayedValue', ...)
+       //              updates 'value', and vice-versa.  Otherwise 'value' is updated
+       //              from 'displayedValue' periodically, like onBlur etc.
+       //
+       //              TODO: move declaration to MappedTextBox?
+       //              Problem is that ComboBox references displayedValue,
+       //              for benefit of FilteringSelect.
+       displayedValue: "",
+
+       _getDisplayedValueAttr: function(){
                // summary:
-               //              stops the move, deletes all references, so the object can be garbage-collected
-               dojo.forEach(this.events, dojo.disconnect);
-               // undo global settings
-               var h = this.host;
-               if(h && h.onMoveStop){
-                       h.onMoveStop(this);
-               }
-               // destroy objects
-               this.events = this.node = this.host = null;
-       }
-});
+               //              Hook so get('displayedValue') works.
+               // description:
+               //              Returns the displayed value (what the user sees on the screen),
+               //              after filtering (ie, trimming spaces etc.).
+               //
+               //              For some subclasses of TextBox (like ComboBox), the displayed value
+               //              is different from the serialized value that's actually
+               //              sent to the server (see dijit.form.ValidationTextBox.serialize)
 
-}
+               // TODO: maybe we should update this.displayedValue on every keystroke so that we don't need
+               // this method
+               // TODO: this isn't really the displayed value when the user is typing
+               return this.filter(this.textbox.value);
+       },
 
-if(!dojo._hasResource["dojo.dnd.Moveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Moveable"] = true;
-dojo.provide("dojo.dnd.Moveable");
+       _setDisplayedValueAttr: function(/*String*/ value){
+               // summary:
+               //              Hook so set('displayedValue', ...) works.
+               // description:
+               //              Sets the value of the visual element to the string "value".
+               //              The widget value is also set to a corresponding,
+               //              but not necessarily the same, value.
 
+               if(value === null || value === undefined){ value = '' }
+               else if(typeof value != "string"){ value = String(value) }
 
+               this.textbox.value = value;
 
-/*=====
-dojo.declare("dojo.dnd.__MoveableArgs", [], {
-       // handle: Node||String
-       //              A node (or node's id), which is used as a mouse handle.
-       //              If omitted, the node itself is used as a handle.
-       handle: null,
+               // sets the serialized value to something corresponding to specified displayedValue
+               // (if possible), and also updates the textbox.value, for example converting "123"
+               // to "123.00"
+               this._setValueAttr(this.get('value'), undefined);
 
-       // delay: Number
-       //              delay move by this number of pixels
-       delay: 0,
+               this._set("displayedValue", this.get('displayedValue'));
 
-       // skip: Boolean
-       //              skip move of form elements
-       skip: false,
-
-       // mover: Object
-       //              a constructor of custom Mover
-       mover: dojo.dnd.Mover
-});
-=====*/
+               // textDir support
+               if(this.textDir == "auto"){
+                       this.applyTextDir(this.focusNode, value);
+               }
+       },
 
-dojo.declare("dojo.dnd.Moveable", null, {
-       // object attributes (for markup)
-       handle: "",
-       delay: 0,
-       skip: false,
-       
-       constructor: function(node, params){
+       format: function(value /*=====, constraints =====*/){
                // summary:
-               //              an object, which makes a node moveable
-               // node: Node
-               //              a node (or node's id) to be moved
-               // params: dojo.dnd.__MoveableArgs?
-               //              optional parameters
-               this.node = dojo.byId(node);
-               if(!params){ params = {}; }
-               this.handle = params.handle ? dojo.byId(params.handle) : null;
-               if(!this.handle){ this.handle = this.node; }
-               this.delay = params.delay > 0 ? params.delay : 0;
-               this.skip  = params.skip;
-               this.mover = params.mover ? params.mover : dojo.dnd.Mover;
-               this.events = [
-                       dojo.connect(this.handle, "onmousedown", this, "onMouseDown"),
-                       // cancel text selection and text dragging
-                       dojo.connect(this.handle, "ondragstart",   this, "onSelectStart"),
-                       dojo.connect(this.handle, "onselectstart", this, "onSelectStart")
-               ];
+               //              Replaceable function to convert a value to a properly formatted string.
+               // value: String
+               // constraints: Object
+               // tags:
+               //              protected extension
+               return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
        },
 
-       // markup methods
-       markupFactory: function(params, node){
-               return new dojo.dnd.Moveable(node, params);
+       parse: function(value /*=====, constraints =====*/){
+               // summary:
+               //              Replaceable function to convert a formatted string to a value
+               // value: String
+               // constraints: Object
+               // tags:
+               //              protected extension
+
+               return value;   // String
        },
 
-       // methods
-       destroy: function(){
+       _refreshState: function(){
                // summary:
-               //              stops watching for possible move, deletes all references, so the object can be garbage-collected
-               dojo.forEach(this.events, dojo.disconnect);
-               this.events = this.node = this.handle = null;
+               //              After the user types some characters, etc., this method is
+               //              called to check the field for validity etc.  The base method
+               //              in `dijit.form.TextBox` does nothing, but subclasses override.
+               // tags:
+               //              protected
        },
-       
-       // mouse event processors
-       onMouseDown: function(e){
+
+       /*=====
+       onInput: function(event){
                // summary:
-               //              event processor for onmousedown, creates a Mover for the node
-               // e: Event
-               //              mouse event
-               if(this.skip && dojo.dnd.isFormElement(e)){ return; }
-               if(this.delay){
-                       this.events.push(
-                               dojo.connect(this.handle, "onmousemove", this, "onMouseMove"),
-                               dojo.connect(this.handle, "onmouseup", this, "onMouseUp")
-                       );
-                       this._lastX = e.pageX;
-                       this._lastY = e.pageY;
-               }else{
-                       this.onDragDetected(e);
-               }
-               dojo.stopEvent(e);
+               //              Connect to this function to receive notifications of various user data-input events.
+               //              Return false to cancel the event and prevent it from being processed.
+               // event:
+               //              keydown | keypress | cut | paste | input
+               // tags:
+               //              callback
        },
-       onMouseMove: function(e){
+       =====*/
+       onInput: function(){},
+
+       __skipInputEvent: false,
+       _onInput: function(){
                // summary:
-               //              event processor for onmousemove, used only for delayed drags
-               // e: Event
-               //              mouse event
-               if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){
-                       this.onMouseUp(e);
-                       this.onDragDetected(e);
+               //              Called AFTER the input event has happened
+               // set text direction according to textDir that was defined in creation
+               if(this.textDir == "auto"){
+                       this.applyTextDir(this.focusNode, this.focusNode.value);
                }
-               dojo.stopEvent(e);
+
+               this._refreshState();
+
+               // In case someone is watch()'ing for changes to displayedValue
+               this._set("displayedValue", this.get("displayedValue"));
        },
-       onMouseUp: function(e){
-               // summary:
-               //              event processor for onmouseup, used only for delayed drags
-               // e: Event
-               //              mouse event
-               for(var i = 0; i < 2; ++i){
-                       dojo.disconnect(this.events.pop());
-               }
-               dojo.stopEvent(e);
+
+       postCreate: function(){
+               // setting the value here is needed since value="" in the template causes "undefined"
+               // and setting in the DOM (instead of the JS object) helps with form reset actions
+               this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values should be the same
+
+               this.inherited(arguments);
+
+               // normalize input events to reduce spurious event processing
+               //      onkeydown: do not forward modifier keys
+               //                 set charOrCode to numeric keycode
+               //      onkeypress: do not forward numeric charOrCode keys (already sent through onkeydown)
+               //      onpaste & oncut: set charOrCode to 229 (IME)
+               //      oninput: if primary event not already processed, set charOrCode to 229 (IME), else do not forward
+               var handleEvent = function(e){
+                       var charCode = e.charOrCode || e.keyCode || 229;
+                       if(e.type == "keydown"){
+                               switch(charCode){ // ignore "state" keys
+                                       case keys.SHIFT:
+                                       case keys.ALT:
+                                       case keys.CTRL:
+                                       case keys.META:
+                                       case keys.CAPS_LOCK:
+                                               return;
+                                       default:
+                                               if(charCode >= 65 && charCode <= 90){ return; } // keydown for A-Z can be processed with keypress
+                               }
+                       }
+                       if(e.type == "keypress" && typeof charCode != "string"){ return; }
+                       if(e.type == "input"){
+                               if(this.__skipInputEvent){ // duplicate event
+                                       this.__skipInputEvent = false;
+                                       return;
+                               }
+                       }else{
+                               this.__skipInputEvent = true;
+                       }
+                       // create fake event to set charOrCode and to know if preventDefault() was called
+                       var faux = lang.mixin({}, e, {
+                               charOrCode: charCode,
+                               wasConsumed: false,
+                               preventDefault: function(){
+                                       faux.wasConsumed = true;
+                                       e.preventDefault();
+                               },
+                               stopPropagation: function(){ e.stopPropagation(); }
+                       });
+                       // give web page author a chance to consume the event
+                       if(this.onInput(faux) === false){
+                               event.stop(faux); // return false means stop
+                       }
+                       if(faux.wasConsumed){ return; } // if preventDefault was called
+                       setTimeout(lang.hitch(this, "_onInput", faux), 0); // widget notification after key has posted
+               };
+               array.forEach([ "onkeydown", "onkeypress", "onpaste", "oncut", "oninput", "oncompositionend" ], function(event){
+                       this.connect(this.textbox, event, handleEvent);
+               }, this);
        },
-       onSelectStart: function(e){
+
+       _blankValue: '', // if the textbox is blank, what value should be reported
+       filter: function(val){
                // summary:
-               //              event processor for onselectevent and ondragevent
-               // e: Event
-               //              mouse event
-               if(!this.skip || !dojo.dnd.isFormElement(e)){
-                       dojo.stopEvent(e);
+               //              Auto-corrections (such as trimming) that are applied to textbox
+               //              value on blur or form submit.
+               // description:
+               //              For MappedTextBox subclasses, this is called twice
+               //                      - once with the display value
+               //                      - once the value as set/returned by set('value', ...)
+               //              and get('value'), ex: a Number for NumberTextBox.
+               //
+               //              In the latter case it does corrections like converting null to NaN.  In
+               //              the former case the NumberTextBox.filter() method calls this.inherited()
+               //              to execute standard trimming code in TextBox.filter().
+               //
+               //              TODO: break this into two methods in 2.0
+               //
+               // tags:
+               //              protected extension
+               if(val === null){ return this._blankValue; }
+               if(typeof val != "string"){ return val; }
+               if(this.trim){
+                       val = lang.trim(val);
                }
+               if(this.uppercase){
+                       val = val.toUpperCase();
+               }
+               if(this.lowercase){
+                       val = val.toLowerCase();
+               }
+               if(this.propercase){
+                       val = val.replace(/[^\s]+/g, function(word){
+                               return word.substring(0,1).toUpperCase() + word.substring(1);
+                       });
+               }
+               return val;
        },
-       
-       // local events
-       onDragDetected: function(/* Event */ e){
-               // summary:
-               //              called when the drag is detected;
-               //              responsible for creation of the mover
-               new this.mover(this.node, e, this);
-       },
-       onMoveStart: function(/* dojo.dnd.Mover */ mover){
-               // summary:
-               //              called before every move operation
-               dojo.publish("/dnd/move/start", [mover]);
-               dojo.addClass(dojo.body(), "dojoMove"); 
-               dojo.addClass(this.node, "dojoMoveItem"); 
-       },
-       onMoveStop: function(/* dojo.dnd.Mover */ mover){
-               // summary:
-               //              called after every move operation
-               dojo.publish("/dnd/move/stop", [mover]);
-               dojo.removeClass(dojo.body(), "dojoMove");
-               dojo.removeClass(this.node, "dojoMoveItem");
-       },
-       onFirstMove: function(/* dojo.dnd.Mover */ mover, /* Event */ e){
-               // summary:
-               //              called during the very first move notification;
-               //              can be used to initialize coordinates, can be overwritten.
-               
-               // default implementation does nothing
-       },
-       onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop, /* Event */ e){
-               // summary:
-               //              called during every move notification;
-               //              should actually move the node; can be overwritten.
-               this.onMoving(mover, leftTop);
-               var s = mover.node.style;
-               s.left = leftTop.l + "px";
-               s.top  = leftTop.t + "px";
-               this.onMoved(mover, leftTop);
-       },
-       onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
-               // summary:
-               //              called before every incremental move; can be overwritten.
-               
-               // default implementation does nothing
-       },
-       onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
-               // summary:
-               //              called after every incremental move; can be overwritten.
-               
-               // default implementation does nothing
-       }
-});
 
-}
+       _setBlurValue: function(){
+               this._setValueAttr(this.get('value'), true);
+       },
 
-if(!dojo._hasResource["dojo.dnd.move"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.move"] = true;
-dojo.provide("dojo.dnd.move");
+       _onBlur: function(e){
+               if(this.disabled){ return; }
+               this._setBlurValue();
+               this.inherited(arguments);
 
+               if(this._selectOnClickHandle){
+                       this.disconnect(this._selectOnClickHandle);
+               }
+       },
 
+       _isTextSelected: function(){
+               return this.textbox.selectionStart == this.textbox.selectionEnd;
+       },
 
+       _onFocus: function(/*String*/ by){
+               if(this.disabled || this.readOnly){ return; }
 
-/*=====
-dojo.declare("dojo.dnd.move.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
-       // constraints: Function
-       //              Calculates a constraint box.
-       //              It is called in a context of the moveable object.
-       constraints: function(){},
+               // Select all text on focus via click if nothing already selected.
+               // Since mouse-up will clear the selection need to defer selection until after mouse-up.
+               // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
+               if(this.selectOnClick && by == "mouse"){
+                       this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
+                               // Only select all text on first click; otherwise users would have no way to clear
+                               // the selection.
+                               this.disconnect(this._selectOnClickHandle);
 
-       // within: Boolean
-       //              restrict move within boundaries.
-       within: false
-});
-=====*/
+                               // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
+                               // and if not, then select all the text
+                               if(this._isTextSelected()){
+                                       _TextBoxMixin.selectInputText(this.textbox);
+                               }
+                       });
+               }
+               // call this.inherited() before refreshState(), since this.inherited() will possibly scroll the viewport
+               // (to scroll the TextBox into view), which will affect how _refreshState() positions the tooltip
+               this.inherited(arguments);
 
-dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {
-       // object attributes (for markup)
-       constraints: function(){},
-       within: false,
-       
-       // markup methods
-       markupFactory: function(params, node){
-               return new dojo.dnd.move.constrainedMoveable(node, params);
+               this._refreshState();
        },
 
-       constructor: function(node, params){
-               // summary:
-               //              an object that makes a node moveable
-               // node: Node
-               //              a node (or node's id) to be moved
-               // params: dojo.dnd.move.__constrainedMoveableArgs?
-               //              an optional object with additional parameters;
-               //              the rest is passed to the base class
-               if(!params){ params = {}; }
-               this.constraints = params.constraints;
-               this.within = params.within;
+       reset: function(){
+               // Overrides dijit._FormWidget.reset().
+               // Additionally resets the displayed textbox value to ''
+               this.textbox.value = '';
+               this.inherited(arguments);
        },
-       onFirstMove: function(/* dojo.dnd.Mover */ mover){
+       _setTextDirAttr: function(/*String*/ textDir){
                // summary:
-               //              called during the very first move notification;
-               //              can be used to initialize coordinates, can be overwritten.
-               var c = this.constraintBox = this.constraints.call(this, mover);
-               c.r = c.l + c.w;
-               c.b = c.t + c.h;
-               if(this.within){
-                       var mb = dojo.marginBox(mover.node);
-                       c.r -= mb.w;
-                       c.b -= mb.h;
+               //              Setter for textDir.
+               // description:
+               //              Users shouldn't call this function; they should be calling
+               //              set('textDir', value)
+               // tags:
+               //              private
+
+               // only if new textDir is different from the old one
+               // and on widgets creation.
+               if(!this._created
+                       || this.textDir != textDir){
+                               this._set("textDir", textDir);
+                               // so the change of the textDir will take place immediately.
+                               this.applyTextDir(this.focusNode, this.focusNode.value);
                }
-       },
-       onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
-               // summary:
-               //              called during every move notification;
-               //              should actually move the node; can be overwritten.
-               var c = this.constraintBox, s = mover.node.style;
-               s.left = (leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l) + "px";
-               s.top  = (leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t) + "px";
        }
 });
 
-/*=====
-dojo.declare("dojo.dnd.move.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
-       // box: Object
-       //              a constraint box
-       box: {}
+
+_TextBoxMixin._setSelectionRange = dijit._setSelectionRange = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
+       if(element.setSelectionRange){
+               element.setSelectionRange(start, stop);
+       }
+};
+
+_TextBoxMixin.selectInputText = dijit.selectInputText = function(/*DomNode*/ element, /*Number?*/ start, /*Number?*/ stop){
+       // summary:
+       //              Select text in the input element argument, from start (default 0), to stop (default end).
+
+       // TODO: use functions in _editor/selection.js?
+       element = dom.byId(element);
+       if(isNaN(start)){ start = 0; }
+       if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
+       try{
+               element.focus();
+               _TextBoxMixin._setSelectionRange(element, start, stop);
+       }catch(e){ /* squelch random errors (esp. on IE) from unexpected focus changes or DOM nodes being hidden */ }
+};
+
+return _TextBoxMixin;
 });
+
+},
+'dijit/form/SimpleTextarea':function(){
+define("dijit/form/SimpleTextarea", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add
+       "dojo/_base/sniff", // has("ie") has("opera")
+       "dojo/_base/window", // win.doc.selection win.doc.selection.createRange
+       "./TextBox"
+], function(declare, domClass, has, win, TextBox){
+
+/*=====
+       var TextBox = dijit.form.TextBox;
 =====*/
 
-dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
-       // box:
-       //              object attributes (for markup)
-       box: {},
-       
-       // markup methods
-       markupFactory: function(params, node){
-               return new dojo.dnd.move.boxConstrainedMoveable(node, params);
-       },
+// module:
+//             dijit/form/SimpleTextarea
+// summary:
+//             A simple textarea that degrades, and responds to
+//             minimal LayoutContainer usage, and works with dijit.form.Form.
+//             Doesn't automatically size according to input, like Textarea.
 
-       constructor: function(node, params){
-               // summary:
-               //              an object, which makes a node moveable
-               // node: Node
-               //              a node (or node's id) to be moved
-               // params: dojo.dnd.move.__boxConstrainedMoveableArgs?
-               //              an optional object with parameters
-               var box = params && params.box;
-               this.constraints = function(){ return box; };
-       }
-});
+return declare("dijit.form.SimpleTextarea", TextBox, {
+       // summary:
+       //              A simple textarea that degrades, and responds to
+       //              minimal LayoutContainer usage, and works with dijit.form.Form.
+       //              Doesn't automatically size according to input, like Textarea.
+       //
+       // example:
+       //      |       <textarea data-dojo-type="dijit.form.SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea>
+       //
+       // example:
+       //      |       new dijit.form.SimpleTextarea({ rows:20, cols:30 }, "foo");
 
-/*=====
-dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
-       // area: String
-       //              A parent's area to restrict the move.
-       //              Can be "margin", "border", "padding", or "content".
-       area: ""
-});
-=====*/
+       baseClass: "dijitTextBox dijitTextArea",
 
-dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
-       // area:
-       //              object attributes (for markup)
-       area: "content",
+       // rows: Number
+       //              The number of rows of text.
+       rows: "3",
 
-       // markup methods
-       markupFactory: function(params, node){
-               return new dojo.dnd.move.parentConstrainedMoveable(node, params);
+       // rows: Number
+       //              The number of characters per line.
+       cols: "20",
+
+       templateString: "<textarea ${!nameAttrSetting} data-dojo-attach-point='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
+
+       postMixInProperties: function(){
+               // Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef)
+               // TODO: parser will handle this in 2.0
+               if(!this.value && this.srcNodeRef){
+                       this.value = this.srcNodeRef.value;
+               }
+               this.inherited(arguments);
        },
 
-       constructor: function(node, params){
-               // summary:
-               //              an object, which makes a node moveable
-               // node: Node
-               //              a node (or node's id) to be moved
-               // params: dojo.dnd.move.__parentConstrainedMoveableArgs?
-               //              an optional object with parameters
-               var area = params && params.area;
-               this.constraints = function(){
-                       var n = this.node.parentNode, 
-                               s = dojo.getComputedStyle(n), 
-                               mb = dojo._getMarginBox(n, s);
-                       if(area == "margin"){
-                               return mb;      // Object
-                       }
-                       var t = dojo._getMarginExtents(n, s);
-                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-                       if(area == "border"){
-                               return mb;      // Object
-                       }
-                       t = dojo._getBorderExtents(n, s);
-                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-                       if(area == "padding"){
-                               return mb;      // Object
+       buildRendering: function(){
+               this.inherited(arguments);
+               if(has("ie") && this.cols){ // attribute selectors is not supported in IE6
+                       domClass.add(this.textbox, "dijitTextAreaCols");
+               }
+       },
+
+       filter: function(/*String*/ value){
+               // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
+               // as \r\n instead of just \n
+               if(value){
+                       value = value.replace(/\r/g,"");
+               }
+               return this.inherited(arguments);
+       },
+
+       _onInput: function(/*Event?*/ e){
+               // Override TextBox._onInput() to enforce maxLength restriction
+               if(this.maxLength){
+                       var maxLength = parseInt(this.maxLength);
+                       var value = this.textbox.value.replace(/\r/g,'');
+                       var overflow = value.length - maxLength;
+                       if(overflow > 0){
+                               var textarea = this.textbox;
+                               if(textarea.selectionStart){
+                                       var pos = textarea.selectionStart;
+                                       var cr = 0;
+                                       if(has("opera")){
+                                               cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
+                                       }
+                                       this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
+                                       textarea.setSelectionRange(pos-overflow, pos-overflow);
+                               }else if(win.doc.selection){ //IE
+                                       textarea.focus();
+                                       var range = win.doc.selection.createRange();
+                                       // delete overflow characters
+                                       range.moveStart("character", -overflow);
+                                       range.text = '';
+                                       // show cursor
+                                       range.select();
+                               }
                        }
-                       t = dojo._getPadExtents(n, s);
-                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-                       return mb;      // Object
-               };
+               }
+               this.inherited(arguments);
        }
 });
 
-// WARNING: below are obsolete objects, instead of custom movers use custom moveables (above)
+});
 
-dojo.dnd.move.constrainedMover = function(fun, within){
+},
+'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode\" data-dojo-attach-event='onclick:onClick'>\n    <div role=\"presentation\" class='dijitTabInnerDiv' data-dojo-attach-point='innerDiv'>\n        <div role=\"presentation\" class='dijitTabContent' data-dojo-attach-point='tabContent'>\n        \t<div role=\"presentation\" data-dojo-attach-point='focusNode'>\n\t\t        <img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode' />\n\t\t        <span data-dojo-attach-point='containerNode' class='tabLabel'></span>\n\t\t        <span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t        \t\tdata-dojo-attach-event='onclick: onClickCloseButton' role=\"presentation\">\n\t\t            <span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t        ></span>\n\t\t\t</div>\n        </div>\n    </div>\n</div>\n",
+'dijit/_base/window':function(){
+define("dijit/_base/window", [
+       "dojo/window", // windowUtils.get
+       ".."    // export symbol to dijit
+], function(windowUtils, dijit){
+       // module:
+       //              dijit/_base/window
        // summary:
-       //              returns a constrained version of dojo.dnd.Mover
-       // description:
-       //              this function produces n object, which will put a constraint on 
-       //              the margin box of dragged object in absolute coordinates
-       // fun: Function
-       //              called on drag, and returns a constraint box
-       // within: Boolean
-       //              if true, constraints the whole dragged object withtin the rectangle, 
-       //              otherwise the constraint is applied to the left-top corner
+       //              Back compatibility module, new code should use windowUtils directly instead of using this module.
 
-       dojo.deprecated("dojo.dnd.move.constrainedMover, use dojo.dnd.move.constrainedMoveable instead");
-       var mover = function(node, e, notifier){
-               dojo.dnd.Mover.call(this, node, e, notifier);
+       dijit.getDocumentWindow = function(doc){
+               return windowUtils.get(doc);
        };
-       dojo.extend(mover, dojo.dnd.Mover.prototype);
-       dojo.extend(mover, {
-               onMouseMove: function(e){
-                       // summary: event processor for onmousemove
-                       // e: Event: mouse event
-                       dojo.dnd.autoScroll(e);
-                       var m = this.marginBox, c = this.constraintBox,
-                               l = m.l + e.pageX, t = m.t + e.pageY;
-                       l = l < c.l ? c.l : c.r < l ? c.r : l;
-                       t = t < c.t ? c.t : c.b < t ? c.b : t;
-                       this.host.onMove(this, {l: l, t: t});
-               },
-               onFirstMove: function(){
-                       // summary: called once to initialize things; it is meant to be called only once
-                       dojo.dnd.Mover.prototype.onFirstMove.call(this);
-                       var c = this.constraintBox = fun.call(this);
-                       c.r = c.l + c.w;
-                       c.b = c.t + c.h;
-                       if(within){
-                               var mb = dojo.marginBox(this.node);
-                               c.r -= mb.w;
-                               c.b -= mb.h;
-                       }
-               }
-       });
-       return mover;   // Object
-};
+});
 
-dojo.dnd.move.boxConstrainedMover = function(box, within){
-       // summary:
-       //              a specialization of dojo.dnd.constrainedMover, which constrains to the specified box
-       // box: Object
-       //              a constraint box (l, t, w, h)
-       // within: Boolean
-       //              if true, constraints the whole dragged object withtin the rectangle, 
-       //              otherwise the constraint is applied to the left-top corner
+},
+'dijit/form/RadioButton':function(){
+define("dijit/form/RadioButton", [
+       "dojo/_base/declare", // declare
+       "./CheckBox",
+       "./_RadioButtonMixin"
+], function(declare, CheckBox, _RadioButtonMixin){
 
-       dojo.deprecated("dojo.dnd.move.boxConstrainedMover, use dojo.dnd.move.boxConstrainedMoveable instead");
-       return dojo.dnd.move.constrainedMover(function(){ return box; }, within);       // Object
-};
+/*=====
+       var CheckBox = dijit.form.CheckBox;
+       var _RadioButtonMixin = dijit.form._RadioButtonMixin;
+=====*/
 
-dojo.dnd.move.parentConstrainedMover = function(area, within){
+       // module:
+       //              dijit/form/RadioButton
        // summary:
-       //              a specialization of dojo.dnd.constrainedMover, which constrains to the parent node
-       // area: String
-       //              "margin" to constrain within the parent's margin box, "border" for the border box,
-       //              "padding" for the padding box, and "content" for the content box; "content" is the default value.
-       // within: Boolean
-       //              if true, constraints the whole dragged object within the rectangle, 
-       //              otherwise the constraint is applied to the left-top corner
-
-       dojo.deprecated("dojo.dnd.move.parentConstrainedMover, use dojo.dnd.move.parentConstrainedMoveable instead");
-       var fun = function(){
-               var n = this.node.parentNode, 
-                       s = dojo.getComputedStyle(n), 
-                       mb = dojo._getMarginBox(n, s);
-               if(area == "margin"){
-                       return mb;      // Object
-               }
-               var t = dojo._getMarginExtents(n, s);
-               mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-               if(area == "border"){
-                       return mb;      // Object
-               }
-               t = dojo._getBorderExtents(n, s);
-               mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-               if(area == "padding"){
-                       return mb;      // Object
-               }
-               t = dojo._getPadExtents(n, s);
-               mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
-               return mb;      // Object
-       };
-       return dojo.dnd.move.constrainedMover(fun, within);     // Object
-};
+       //              Radio button widget
 
-// patching functions one level up for compatibility
+       return declare("dijit.form.RadioButton", [CheckBox, _RadioButtonMixin], {
+               // summary:
+               //              Same as an HTML radio, but with fancy styling.
 
-dojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;
-dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;
-dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;
+               baseClass: "dijitRadio"
+       });
+});
 
-}
+},
+'dijit/main':function(){
+define("dijit/main", [
+       "dojo/_base/kernel"
+], function(dojo){
+       // module:
+       //              dijit
+       // summary:
+       //              The dijit package main module
+
+       return dojo.dijit;
+});
+
+},
+'dijit/_OnDijitClickMixin':function(){
+define("dijit/_OnDijitClickMixin", [
+       "dojo/on",
+       "dojo/_base/array", // array.forEach
+       "dojo/keys", // keys.ENTER keys.SPACE
+       "dojo/_base/declare", // declare
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/unload", // unload.addOnWindowUnload
+       "dojo/_base/window" // win.doc.addEventListener win.doc.attachEvent win.doc.detachEvent
+], function(on, array, keys, declare, has, unload, win){
+
+       // module:
+       //              dijit/_OnDijitClickMixin
+       // summary:
+       //              Mixin so you can pass "ondijitclick" to this.connect() method,
+       //              as a way to handle clicks by mouse, or by keyboard (SPACE/ENTER key)
+
+
+       // Keep track of where the last keydown event was, to help avoid generating
+       // spurious ondijitclick events when:
+       // 1. focus is on a <button> or <a>
+       // 2. user presses then releases the ENTER key
+       // 3. onclick handler fires and shifts focus to another node, with an ondijitclick handler
+       // 4. onkeyup event fires, causing the ondijitclick handler to fire
+       var lastKeyDownNode = null;
+       if(has("ie")){
+               (function(){
+                       var keydownCallback = function(evt){
+                               lastKeyDownNode = evt.srcElement;
+                       };
+                       win.doc.attachEvent('onkeydown', keydownCallback);
+                       unload.addOnWindowUnload(function(){
+                               win.doc.detachEvent('onkeydown', keydownCallback);
+                       });
+               })();
+       }else{
+               win.doc.addEventListener('keydown', function(evt){
+                       lastKeyDownNode = evt.target;
+               }, true);
+       }
 
-if(!dojo._hasResource["dojo.dnd.TimedMoveable"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.TimedMoveable"] = true;
-dojo.provide("dojo.dnd.TimedMoveable");
+       // Custom a11yclick (a.k.a. ondijitclick) event
+       var a11yclick = function(node, listener){
+               if(/input|button/i.test(node.nodeName)){
+                       // pass through, the browser already generates click event on SPACE/ENTER key
+                       return on(node, "click", listener);
+               }else{
+                       // Don't fire the click event unless both the keydown and keyup occur on this node.
+                       // Avoids problems where focus shifted to this node or away from the node on keydown,
+                       // either causing this node to process a stray keyup event, or causing another node
+                       // to get a stray keyup event.
+
+                       function clickKey(/*Event*/ e){
+                               return (e.keyCode == keys.ENTER || e.keyCode == keys.SPACE) &&
+                                               !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey;
+                       }
+                       var handles = [
+                               on(node, "keypress", function(e){
+                                       //console.log(this.id + ": onkeydown, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
+                                       if(clickKey(e)){
+                                               // needed on IE for when focus changes between keydown and keyup - otherwise dropdown menus do not work
+                                               lastKeyDownNode = e.target;
+
+                                               // Prevent viewport scrolling on space key in IE<9.
+                                               // (Reproducible on test_Button.html on any of the first dijit.form.Button examples)
+                                               // Do this onkeypress rather than onkeydown because onkeydown.preventDefault() will
+                                               // suppress the onkeypress event, breaking _HasDropDown
+                                               e.preventDefault();
+                                       }
+                               }),
 
+                               on(node, "keyup", function(e){
+                                       //console.log(this.id + ": onkeyup, e.target = ", e.target, ", lastKeyDownNode was ", lastKeyDownNode, ", equality is ", (e.target === lastKeyDownNode));
+                                       if(clickKey(e) && e.target == lastKeyDownNode){ // === breaks greasemonkey
+                                               //need reset here or have problems in FF when focus returns to trigger element after closing popup/alert
+                                               lastKeyDownNode = null;
+                                               listener.call(this, e);
+                                       }
+                               }),
 
+                               on(node, "click", function(e){
+                                       // and connect for mouse clicks too (or touch-clicks on mobile)
+                                       listener.call(this, e);
+                               })
+                       ];
 
-/*=====
-dojo.declare("dojo.dnd.__TimedMoveableArgs", [dojo.dnd.__MoveableArgs], {
-       // timeout: Number
-       //              delay move by this number of ms,
-       //              accumulating position changes during the timeout
-       timeout: 0
-});
-=====*/
+                       return {
+                               remove: function(){
+                                       array.forEach(handles, function(h){ h.remove(); });
+                               }
+                       };
+               }
+       };
 
-(function(){
-       // precalculate long expressions
-       var oldOnMove = dojo.dnd.Moveable.prototype.onMove;
-               
-       dojo.declare("dojo.dnd.TimedMoveable", dojo.dnd.Moveable, {
-               // summary:
-               //              A specialized version of Moveable to support an FPS throttling.
-               //              This class puts an upper restriction on FPS, which may reduce 
-               //              the CPU load. The additional parameter "timeout" regulates
-               //              the delay before actually moving the moveable object.
-               
-               // object attributes (for markup)
-               timeout: 40,    // in ms, 40ms corresponds to 25 fps
-       
-               constructor: function(node, params){
+       return declare("dijit._OnDijitClickMixin", null, {
+               connect: function(
+                               /*Object|null*/ obj,
+                               /*String|Function*/ event,
+                               /*String|Function*/ method){
                        // summary:
-                       //              an object that makes a node moveable with a timer
-                       // node: Node||String
-                       //              a node (or node's id) to be moved
-                       // params: dojo.dnd.__TimedMoveableArgs
-                       //              object with additional parameters.
-                       
-                       // sanitize parameters
-                       if(!params){ params = {}; }
-                       if(params.timeout && typeof params.timeout == "number" && params.timeout >= 0){
-                               this.timeout = params.timeout;
-                       }
-               },
-       
-               // markup methods
-               markupFactory: function(params, node){
-                       return new dojo.dnd.TimedMoveable(node, params);
-               },
-       
-               onMoveStop: function(/* dojo.dnd.Mover */ mover){
-                       if(mover._timer){
-                               // stop timer
-                               clearTimeout(mover._timer)
-                               // reflect the last received position
-                               oldOnMove.call(this, mover, mover._leftTop)
-                       }
-                       dojo.dnd.Moveable.prototype.onMoveStop.apply(this, arguments);
-               },
-               onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
-                       mover._leftTop = leftTop;
-                       if(!mover._timer){
-                               var _t = this;  // to avoid using dojo.hitch()
-                               mover._timer = setTimeout(function(){
-                                       // we don't have any pending requests
-                                       mover._timer = null;
-                                       // reflect the last received position
-                                       oldOnMove.call(_t, mover, mover._leftTop);
-                               }, this.timeout);
-                       }
+                       //              Connects specified obj/event to specified method of this object
+                       //              and registers for disconnect() on widget destroy.
+                       // description:
+                       //              Provide widget-specific analog to connect.connect, except with the
+                       //              implicit use of this widget as the target object.
+                       //              This version of connect also provides a special "ondijitclick"
+                       //              event which triggers on a click or space or enter keyup.
+                       //              Events connected with `this.connect` are disconnected upon
+                       //              destruction.
+                       // returns:
+                       //              A handle that can be passed to `disconnect` in order to disconnect before
+                       //              the widget is destroyed.
+                       // example:
+                       //      |       var btn = new dijit.form.Button();
+                       //      |       // when foo.bar() is called, call the listener we're going to
+                       //      |       // provide in the scope of btn
+                       //      |       btn.connect(foo, "bar", function(){
+                       //      |               console.debug(this.toString());
+                       //      |       });
+                       // tags:
+                       //              protected
+
+                       return this.inherited(arguments, [obj, event == "ondijitclick" ? a11yclick : event, method]);
                }
        });
-})();
-
-}
+});
 
-if(!dojo._hasResource["dijit.form._FormMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form._FormMixin"] = true;
-dojo.provide("dijit.form._FormMixin");
+},
+'dijit/InlineEditBox':function(){
+require({cache:{
+'url:dijit/templates/InlineEditBox.html':"<span data-dojo-attach-point=\"editNode\" role=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdata-dojo-attach-event=\"onkeypress: _onKeyPress\"\n\t><span data-dojo-attach-point=\"editorPlaceholder\"></span\n\t><span data-dojo-attach-point=\"buttonContainer\"\n\t\t><button data-dojo-type=\"dijit.form.Button\" data-dojo-props=\"label: '${buttonSave}', 'class': 'saveButton'\"\n\t\t\tdata-dojo-attach-point=\"saveButton\" data-dojo-attach-event=\"onClick:save\"></button\n\t\t><button data-dojo-type=\"dijit.form.Button\"  data-dojo-props=\"label: '${buttonCancel}', 'class': 'cancelButton'\"\n\t\t\tdata-dojo-attach-point=\"cancelButton\" data-dojo-attach-event=\"onClick:cancel\"></button\n\t></span\n></span>\n"}});
+define("dijit/InlineEditBox", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set domAttr.get
+       "dojo/dom-class", // domClass.add domClass.remove domClass.toggle
+       "dojo/dom-construct", // domConstruct.create domConstruct.destroy
+       "dojo/dom-style", // domStyle.getComputedStyle domStyle.set domStyle.get
+       "dojo/_base/event", // event.stop
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/keys", // keys.ENTER keys.ESCAPE
+       "dojo/_base/lang", // lang.getObject
+       "dojo/_base/sniff", // has("ie")
+       "./focus",
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_WidgetsInTemplateMixin",
+       "./_Container",
+       "./form/Button",
+       "./form/_TextBoxMixin",
+       "./form/TextBox",
+       "dojo/text!./templates/InlineEditBox.html",
+       "dojo/i18n!./nls/common"
+], function(array, declare, domAttr, domClass, domConstruct, domStyle, event, i18n, kernel, keys, lang, has,
+                       fm, _Widget, _TemplatedMixin, _WidgetsInTemplateMixin, _Container, Button, _TextBoxMixin, TextBox, template){
 
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _WidgetsInTemplateMixin = dijit._WidgetsInTemplateMixin;
+       var _Container = dijit._Container;
+       var Button = dijit.form.Button;
+       var TextBox = dijit.form.TextBox;
+=====*/
 
+// module:
+//             dijit/InlineEditBox
+// summary:
+//             An element with in-line edit capabilities
 
-dojo.declare("dijit.form._FormMixin", null,
-       {
+var InlineEditor = declare("dijit._InlineEditor", [_Widget, _TemplatedMixin, _WidgetsInTemplateMixin], {
        // summary:
-       //              Mixin for containers of form widgets (i.e. widgets that represent a single value
-       //              and can be children of a <form> node or dijit.form.Form widget)
-       // description:
-       //              Can extract all the form widgets
-       //              values and combine them into a single javascript object, or alternately
-       //              take such an object and set the values for all the contained
-       //              form widgets
-
-/*=====
-    // value: Object
-       //              Name/value hash for each child widget with a name and value.
-       //              Child widgets without names are not part of the hash.
-       // 
-       //              If there are multiple child widgets w/the same name, value is an array,
-       //              unless they are radio buttons in which case value is a scalar (since only
-       //              one radio button can be checked at a time).
-       //
-       //              If a child widget's name is a dot separated list (like a.b.c.d), it's a nested structure.
+       //              Internal widget used by InlineEditBox, displayed when in editing mode
+       //              to display the editor and maybe save/cancel buttons.  Calling code should
+       //              connect to save/cancel methods to detect when editing is finished
        //
-       //              Example:
-       //      |       { name: "John Smith", interests: ["sports", "movies"] }
-=====*/
-
-       //      TODO:
-       //      * Repeater
-       //      * better handling for arrays.  Often form elements have names with [] like
-       //      * people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
+       //              Has mainly the same parameters as InlineEditBox, plus these values:
        //
+       // style: Object
+       //              Set of CSS attributes of display node, to replicate in editor
        //
+       // value: String
+       //              Value as an HTML string or plain text string, depending on renderAsHTML flag
 
-               reset: function(){
-                       dojo.forEach(this.getDescendants(), function(widget){
-                               if(widget.reset){
-                                       widget.reset();
-                               }
-                       });
-               },
-
-               validate: function(){
-                       // summary:
-                       //              returns if the form is valid - same as isValid - but
-                       //                      provides a few additional (ui-specific) features.
-                       //                      1 - it will highlight any sub-widgets that are not
-                       //                              valid
-                       //                      2 - it will call focus() on the first invalid
-                       //                              sub-widget
-                       var didFocus = false;
-                       return dojo.every(dojo.map(this.getDescendants(), function(widget){
-                               // Need to set this so that "required" widgets get their
-                               // state set.
-                               widget._hasBeenBlurred = true;
-                               var valid = widget.disabled || !widget.validate || widget.validate();
-                               if(!valid && !didFocus){
-                                       // Set focus of the first non-valid widget
-                                       dojo.window.scrollIntoView(widget.containerNode || widget.domNode);
-                                       widget.focus();
-                                       didFocus = true;
-                               }
-                               return valid;
-                       }), function(item){ return item; });
-               },
+       templateString: template,
 
-               setValues: function(val){
-                       dojo.deprecated(this.declaredClass+"::setValues() is deprecated. Use set('value', val) instead.", "", "2.0");
-                       return this.set('value', val);
-               },
-               _setValueAttr: function(/*object*/obj){
-                       // summary:
-                       //              Fill in form values from according to an Object (in the format returned by attr('value'))
+       postMixInProperties: function(){
+               this.inherited(arguments);
+               this.messages = i18n.getLocalization("dijit", "common", this.lang);
+               array.forEach(["buttonSave", "buttonCancel"], function(prop){
+                       if(!this[prop]){ this[prop] = this.messages[prop]; }
+               }, this);
+       },
 
-                       // generate map from name --> [list of widgets with that name]
-                       var map = { };
-                       dojo.forEach(this.getDescendants(), function(widget){
-                               if(!widget.name){ return; }
-                               var entry = map[widget.name] || (map[widget.name] = [] );
-                               entry.push(widget);
-                       });
+       buildRendering: function(){
+               this.inherited(arguments);
 
-                       for(var name in map){
-                               if(!map.hasOwnProperty(name)){
-                                       continue;
-                               }
-                               var widgets = map[name],                                                // array of widgets w/this name
-                                       values = dojo.getObject(name, false, obj);      // list of values for those widgets
+               // Create edit widget in place in the template
+               var cls = typeof this.editor == "string" ? lang.getObject(this.editor) : this.editor;
 
-                               if(values === undefined){
-                                       continue;
-                               }
-                               if(!dojo.isArray(values)){
-                                       values = [ values ];
-                               }
-                               if(typeof widgets[0].checked == 'boolean'){
-                                       // for checkbox/radio, values is a list of which widgets should be checked
-                                       dojo.forEach(widgets, function(w, i){
-                                               w.set('value', dojo.indexOf(values, w.value) != -1);
-                                       });
-                               }else if(widgets[0].multiple){
-                                       // it takes an array (e.g. multi-select)
-                                       widgets[0].set('value', values);
-                               }else{
-                                       // otherwise, values is a list of values to be assigned sequentially to each widget
-                                       dojo.forEach(widgets, function(w, i){
-                                               w.set('value', values[i]);
-                                       });
-                               }
+               // Copy the style from the source
+               // Don't copy ALL properties though, just the necessary/applicable ones.
+               // wrapperStyle/destStyle code is to workaround IE bug where getComputedStyle().fontSize
+               // is a relative value like 200%, rather than an absolute value like 24px, and
+               // the 200% can refer *either* to a setting on the node or it's ancestor (see #11175)
+               var srcStyle = this.sourceStyle,
+                       editStyle = "line-height:" + srcStyle.lineHeight + ";",
+                       destStyle = domStyle.getComputedStyle(this.domNode);
+               array.forEach(["Weight","Family","Size","Style"], function(prop){
+                       var textStyle = srcStyle["font"+prop],
+                               wrapperStyle = destStyle["font"+prop];
+                       if(wrapperStyle != textStyle){
+                               editStyle += "font-"+prop+":"+srcStyle["font"+prop]+";";
                        }
+               }, this);
+               array.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){
+                       this.domNode.style[prop] = srcStyle[prop];
+               }, this);
+               var width = this.inlineEditBox.width;
+               if(width == "100%"){
+                       // block mode
+                       editStyle += "width:100%;";
+                       this.domNode.style.display = "block";
+               }else{
+                       // inline-block mode
+                       editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";";
+               }
+               var editorParams = lang.delegate(this.inlineEditBox.editorParams, {
+                       style: editStyle,
+                       dir: this.dir,
+                       lang: this.lang,
+                       textDir: this.textDir
+               });
+               editorParams[ "displayedValue" in cls.prototype ? "displayedValue" : "value"] = this.value;
+               this.editWidget = new cls(editorParams, this.editorPlaceholder);
 
-                       /***
-                        *      TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
+               if(this.inlineEditBox.autoSave){
+                       // Remove the save/cancel buttons since saving is done by simply tabbing away or
+                       // selecting a value from the drop down list
+                       domConstruct.destroy(this.buttonContainer);
+               }
+       },
 
-                       dojo.forEach(this.containerNode.elements, function(element){
-                               if(element.name == ''){return}; // like "continue"
-                               var namePath = element.name.split(".");
-                               var myObj=obj;
-                               var name=namePath[namePath.length-1];
-                               for(var j=1,len2=namePath.length;j<len2;++j){
-                                       var p=namePath[j - 1];
-                                       // repeater support block
-                                       var nameA=p.split("[");
-                                       if(nameA.length > 1){
-                                               if(typeof(myObj[nameA[0]]) == "undefined"){
-                                                       myObj[nameA[0]]=[ ];
-                                               } // if
+       postCreate: function(){
+               this.inherited(arguments);
 
-                                               nameIndex=parseInt(nameA[1]);
-                                               if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
-                                                       myObj[nameA[0]][nameIndex] = { };
-                                               }
-                                               myObj=myObj[nameA[0]][nameIndex];
-                                               continue;
-                                       } // repeater support ends
+               var ew = this.editWidget;
 
-                                       if(typeof(myObj[p]) == "undefined"){
-                                               myObj=undefined;
-                                               break;
-                                       };
-                                       myObj=myObj[p];
-                               }
+               if(this.inlineEditBox.autoSave){
+                       // Selecting a value from a drop down list causes an onChange event and then we save
+                       this.connect(ew, "onChange", "_onChange");
 
-                               if(typeof(myObj) == "undefined"){
-                                       return;         // like "continue"
-                               }
-                               if(typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
-                                       return;         // like "continue"
-                               }
+                       // ESC and TAB should cancel and save.  Note that edit widgets do a stopEvent() on ESC key (to
+                       // prevent Dialog from closing when the user just wants to revert the value in the edit widget),
+                       // so this is the only way we can see the key press event.
+                       this.connect(ew, "onKeyPress", "_onKeyPress");
+               }else{
+                       // If possible, enable/disable save button based on whether the user has changed the value
+                       if("intermediateChanges" in ew){
+                               ew.set("intermediateChanges", true);
+                               this.connect(ew, "onChange", "_onIntermediateChange");
+                               this.saveButton.set("disabled", true);
+                       }
+               }
+       },
 
-                               // TODO: widget values (just call attr('value', ...) on the widget)
+       _onIntermediateChange: function(/*===== val =====*/){
+               // summary:
+               //              Called for editor widgets that support the intermediateChanges=true flag as a way
+               //              to detect when to enable/disabled the save button
+               this.saveButton.set("disabled", (this.getValue() == this._resetValue) || !this.enableSave());
+       },
 
-                               // TODO: maybe should call dojo.getNodeProp() instead
-                               switch(element.type){
-                                       case "checkbox":
-                                               element.checked = (name in myObj) &&
-                                                       dojo.some(myObj[name], function(val){ return val == element.value; });
-                                               break;
-                                       case "radio":
-                                               element.checked = (name in myObj) && myObj[name] == element.value;
-                                               break;
-                                       case "select-multiple":
-                                               element.selectedIndex=-1;
-                                               dojo.forEach(element.options, function(option){
-                                                       option.selected = dojo.some(myObj[name], function(val){ return option.value == val; });
-                                               });
-                                               break;
-                                       case "select-one":
-                                               element.selectedIndex="0";
-                                               dojo.forEach(element.options, function(option){
-                                                       option.selected = option.value == myObj[name];
-                                               });
-                                               break;
-                                       case "hidden":
-                                       case "text":
-                                       case "textarea":
-                                       case "password":
-                                               element.value = myObj[name] || "";
-                                               break;
-                               }
-                       });
-                       */
-               },
+       destroy: function(){
+               this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM
+               this.inherited(arguments);
+       },
 
-               getValues: function(){
-                       dojo.deprecated(this.declaredClass+"::getValues() is deprecated. Use get('value') instead.", "", "2.0");
-                       return this.get('value');
-               },
-               _getValueAttr: function(){
-                       // summary:
-                       //              Returns Object representing form values.
-                       // description:
-                       //              Returns name/value hash for each form element.
-                       //              If there are multiple elements w/the same name, value is an array,
-                       //              unless they are radio buttons in which case value is a scalar since only
-                       //              one can be checked at a time.
-                       //
-                       //              If the name is a dot separated list (like a.b.c.d), creates a nested structure.
-                       //              Only works on widget form elements.
-                       // example:
-                       //              | { name: "John Smith", interests: ["sports", "movies"] }
+       getValue: function(){
+               // summary:
+               //              Return the [display] value of the edit widget
+               var ew = this.editWidget;
+               return String(ew.get("displayedValue" in ew ? "displayedValue" : "value"));
+       },
 
-                       // get widget values
-                       var obj = { };
-                       dojo.forEach(this.getDescendants(), function(widget){
-                               var name = widget.name;
-                               if(!name || widget.disabled){ return; }
+       _onKeyPress: function(e){
+               // summary:
+               //              Handler for keypress in the edit box in autoSave mode.
+               // description:
+               //              For autoSave widgets, if Esc/Enter, call cancel/save.
+               // tags:
+               //              private
 
-                               // Single value widget (checkbox, radio, or plain <input> type widget
-                               var value = widget.get('value');
+               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
+                       if(e.altKey || e.ctrlKey){ return; }
+                       // If Enter/Esc pressed, treat as save/cancel.
+                       if(e.charOrCode == keys.ESCAPE){
+                               event.stop(e);
+                               this.cancel(true); // sets editing=false which short-circuits _onBlur processing
+                       }else if(e.charOrCode == keys.ENTER && e.target.tagName == "INPUT"){
+                               event.stop(e);
+                               this._onChange(); // fire _onBlur and then save
+                       }
 
-                               // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
-                               if(typeof widget.checked == 'boolean'){
-                                       if(/Radio/.test(widget.declaredClass)){
-                                               // radio button
-                                               if(value !== false){
-                                                       dojo.setObject(name, value, obj);
-                                               }else{
-                                                       // give radio widgets a default of null
-                                                       value = dojo.getObject(name, false, obj);
-                                                       if(value === undefined){
-                                                               dojo.setObject(name, null, obj);
-                                                       }
-                                               }
-                                       }else{
-                                               // checkbox/toggle button
-                                               var ary=dojo.getObject(name, false, obj);
-                                               if(!ary){
-                                                       ary=[];
-                                                       dojo.setObject(name, ary, obj);
-                                               }
-                                               if(value !== false){
-                                                       ary.push(value);
-                                               }
-                                       }
-                               }else{
-                                       var prev=dojo.getObject(name, false, obj);
-                                       if(typeof prev != "undefined"){
-                                               if(dojo.isArray(prev)){
-                                                       prev.push(value);
-                                               }else{
-                                                       dojo.setObject(name, [prev, value], obj);
-                                               }
-                                       }else{
-                                               // unique name
-                                               dojo.setObject(name, value, obj);
-                                       }
-                               }
-                       });
+                       // _onBlur will handle TAB automatically by allowing
+                       // the TAB to change focus before we mess with the DOM: #6227
+                       // Expounding by request:
+                       //      The current focus is on the edit widget input field.
+                       //      save() will hide and destroy this widget.
+                       //      We want the focus to jump from the currently hidden
+                       //      displayNode, but since it's hidden, it's impossible to
+                       //      unhide it, focus it, and then have the browser focus
+                       //      away from it to the next focusable element since each
+                       //      of these events is asynchronous and the focus-to-next-element
+                       //      is already queued.
+                       //      So we allow the browser time to unqueue the move-focus event
+                       //      before we do all the hide/show stuff.
+               }
+       },
 
-                       /***
-                        * code for plain input boxes (see also dojo.formToObject, can we use that instead of this code?
-                        * but it doesn't understand [] notation, presumably)
-                       var obj = { };
-                       dojo.forEach(this.containerNode.elements, function(elm){
-                               if(!elm.name)   {
-                                       return;         // like "continue"
-                               }
-                               var namePath = elm.name.split(".");
-                               var myObj=obj;
-                               var name=namePath[namePath.length-1];
-                               for(var j=1,len2=namePath.length;j<len2;++j){
-                                       var nameIndex = null;
-                                       var p=namePath[j - 1];
-                                       var nameA=p.split("[");
-                                       if(nameA.length > 1){
-                                               if(typeof(myObj[nameA[0]]) == "undefined"){
-                                                       myObj[nameA[0]]=[ ];
-                                               } // if
-                                               nameIndex=parseInt(nameA[1]);
-                                               if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
-                                                       myObj[nameA[0]][nameIndex] = { };
-                                               }
-                                       } else if(typeof(myObj[nameA[0]]) == "undefined"){
-                                               myObj[nameA[0]] = { }
-                                       } // if
-
-                                       if(nameA.length == 1){
-                                               myObj=myObj[nameA[0]];
-                                       } else{
-                                               myObj=myObj[nameA[0]][nameIndex];
-                                       } // if
-                               } // for
-
-                               if((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type == "radio" && elm.checked)){
-                                       if(name == name.split("[")[0]){
-                                               myObj[name]=elm.value;
-                                       } else{
-                                               // can not set value when there is no name
-                                       }
-                               } else if(elm.type == "checkbox" && elm.checked){
-                                       if(typeof(myObj[name]) == 'undefined'){
-                                               myObj[name]=[ ];
-                                       }
-                                       myObj[name].push(elm.value);
-                               } else if(elm.type == "select-multiple"){
-                                       if(typeof(myObj[name]) == 'undefined'){
-                                               myObj[name]=[ ];
-                                       }
-                                       for(var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
-                                               if(elm.options[jdx].selected){
-                                                       myObj[name].push(elm.options[jdx].value);
-                                               }
-                                       }
-                               } // if
-                               name=undefined;
-                       }); // forEach
-                       ***/
-                       return obj;
-               },
+       _onBlur: function(){
+               // summary:
+               //              Called when focus moves outside the editor
+               // tags:
+               //              private
 
-               // TODO: ComboBox might need time to process a recently input value.  This should be async?
-               isValid: function(){
-                       // summary:
-                       //              Returns true if all of the widgets are valid
+               this.inherited(arguments);
+               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
+                       if(this.getValue() == this._resetValue){
+                               this.cancel(false);
+                       }else if(this.enableSave()){
+                               this.save(false);
+                       }
+               }
+       },
 
-                       // This also populate this._invalidWidgets[] array with list of invalid widgets...
-                       // TODO: put that into separate function?   It's confusing to have that as a side effect
-                       // of a method named isValid().
+       _onChange: function(){
+               // summary:
+               //              Called when the underlying widget fires an onChange event,
+               //              such as when the user selects a value from the drop down list of a ComboBox,
+               //              which means that the user has finished entering the value and we should save.
+               // tags:
+               //              private
 
-                       this._invalidWidgets = dojo.filter(this.getDescendants(), function(widget){
-                               return !widget.disabled && widget.isValid && !widget.isValid();
-                       });
-                       return !this._invalidWidgets.length;
-               },
+               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){
+                       fm.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value
+               }
+       },
 
+       enableSave: function(){
+               // summary:
+               //              User overridable function returning a Boolean to indicate
+               //              if the Save button should be enabled or not - usually due to invalid conditions
+               // tags:
+               //              extension
+               return (
+                       this.editWidget.isValid
+                       ? this.editWidget.isValid()
+                       : true
+               );
+       },
 
-               onValidStateChange: function(isValid){
-                       // summary:
-                       //              Stub function to connect to if you want to do something
-                       //              (like disable/enable a submit button) when the valid
-                       //              state changes on the form as a whole.
-               },
+       focus: function(){
+               // summary:
+               //              Focus the edit widget.
+               // tags:
+               //              protected
 
-               _widgetChange: function(widget){
-                       // summary:
-                       //              Connected to a widget's onChange function - update our
-                       //              valid state, if needed.
-                       var isValid = this._lastValidState;
-                       if(!widget || this._lastValidState === undefined){
-                               // We have passed a null widget, or we haven't been validated
-                               // yet - let's re-check all our children
-                               // This happens when we connect (or reconnect) our children
-                               isValid = this.isValid();
-                               if(this._lastValidState === undefined){
-                                       // Set this so that we don't fire an onValidStateChange
-                                       // the first time
-                                       this._lastValidState = isValid;
-                               }
-                       }else if(widget.isValid){
-                               this._invalidWidgets = dojo.filter(this._invalidWidgets || [], function(w){
-                                       return (w != widget);
-                               }, this);
-                               if(!widget.isValid() && !widget.get("disabled")){
-                                       this._invalidWidgets.push(widget);
-                               }
-                               isValid = (this._invalidWidgets.length === 0);
-                       }
-                       if(isValid !== this._lastValidState){
-                               this._lastValidState = isValid;
-                               this.onValidStateChange(isValid);
+               this.editWidget.focus();
+               setTimeout(lang.hitch(this, function(){
+                       if(this.editWidget.focusNode && this.editWidget.focusNode.tagName == "INPUT"){
+                               _TextBoxMixin.selectInputText(this.editWidget.focusNode);
                        }
-               },
-
-               connectChildren: function(){
-                       // summary:
-                       //              Connects to the onChange function of all children to
-                       //              track valid state changes.  You can call this function
-                       //              directly, ex. in the event that you programmatically
-                       //              add a widget to the form *after* the form has been
-                       //              initialized.
-                       dojo.forEach(this._changeConnections, dojo.hitch(this, "disconnect"));
-                       var _this = this;
-
-                       // we connect to validate - so that it better reflects the states
-                       // of the widgets - also, we only connect if it has a validate
-                       // function (to avoid too many unneeded connections)
-                       var conns = (this._changeConnections = []);
-                       dojo.forEach(dojo.filter(this.getDescendants(),
-                               function(item){ return item.validate; }
-                       ),
-                       function(widget){
-                               // We are interested in whenever the widget is validated - or
-                               // whenever the disabled attribute on that widget is changed
-                               conns.push(_this.connect(widget, "validate",
-                                                                       dojo.hitch(_this, "_widgetChange", widget)));
-                               conns.push(_this.connect(widget, "_setDisabledAttr",
-                                                                       dojo.hitch(_this, "_widgetChange", widget)));
-                       });
-
-                       // Call the widget change function to update the valid state, in
-                       // case something is different now.
-                       this._widgetChange(null);
-               },
-
-               startup: function(){
-                       this.inherited(arguments);
-                       // Initialize our valid state tracking.  Needs to be done in startup
-                       // because it's not guaranteed that our children are initialized
-                       // yet.
-                       this._changeConnections = [];
-                       this.connectChildren();
-               }
-       });
+               }), 0);
+       }
+});
 
-}
 
-if(!dojo._hasResource["dijit._DialogMixin"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._DialogMixin"] = true;
-dojo.provide("dijit._DialogMixin");
+var InlineEditBox = declare("dijit.InlineEditBox", _Widget, {
+       // summary:
+       //              An element with in-line edit capabilities
+       //
+       // description:
+       //              Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that
+       //              when you click it, an editor shows up in place of the original
+       //              text.  Optionally, Save and Cancel button are displayed below the edit widget.
+       //              When Save is clicked, the text is pulled from the edit
+       //              widget and redisplayed and the edit widget is again hidden.
+       //              By default a plain Textarea widget is used as the editor (or for
+       //              inline values a TextBox), but you can specify an editor such as
+       //              dijit.Editor (for editing HTML) or a Slider (for adjusting a number).
+       //              An edit widget must support the following API to be used:
+       //                      - displayedValue or value as initialization parameter,
+       //                      and available through set('displayedValue') / set('value')
+       //                      - void focus()
+       //                      - DOM-node focusNode = node containing editable text
 
+       // editing: [readonly] Boolean
+       //              Is the node currently in edit mode?
+       editing: false,
 
+       // autoSave: Boolean
+       //              Changing the value automatically saves it; don't have to push save button
+       //              (and save button isn't even displayed)
+       autoSave: true,
 
-dojo.declare("dijit._DialogMixin", null,
-       {
-               // summary:
-               //              This provides functions useful to Dialog and TooltipDialog
+       // buttonSave: String
+       //              Save button label
+       buttonSave: "",
 
-               attributeMap: dijit._Widget.prototype.attributeMap,
+       // buttonCancel: String
+       //              Cancel button label
+       buttonCancel: "",
 
-               execute: function(/*Object*/ formContents){
-                       // summary:
-                       //              Callback when the user hits the submit button.
-                       //              Override this method to handle Dialog execution.
-                       // description:
-                       //              After the user has pressed the submit button, the Dialog
-                       //              first calls onExecute() to notify the container to hide the
-                       //              dialog and restore focus to wherever it used to be.
-                       //
-                       //              *Then* this method is called.
-                       // type:
-                       //              callback
-               },
+       // renderAsHtml: Boolean
+       //              Set this to true if the specified Editor's value should be interpreted as HTML
+       //              rather than plain text (ex: `dijit.Editor`)
+       renderAsHtml: false,
 
-               onCancel: function(){
-                       // summary:
-                       //          Called when user has pressed the Dialog's cancel button, to notify container.
-                       // description:
-                       //          Developer shouldn't override or connect to this method;
-                       //              it's a private communication device between the TooltipDialog
-                       //              and the thing that opened it (ex: `dijit.form.DropDownButton`)
-                       // type:
-                       //              protected
-               },
+       // editor: String|Function
+       //              Class name (or reference to the Class) for Editor widget
+       editor: TextBox,
 
-               onExecute: function(){
-                       // summary:
-                       //          Called when user has pressed the dialog's OK button, to notify container.
-                       // description:
-                       //          Developer shouldn't override or connect to this method;
-                       //              it's a private communication device between the TooltipDialog
-                       //              and the thing that opened it (ex: `dijit.form.DropDownButton`)
-                       // type:
-                       //              protected
-               },
+       // editorWrapper: String|Function
+       //              Class name (or reference to the Class) for widget that wraps the editor widget, displaying save/cancel
+       //              buttons.
+       editorWrapper: InlineEditor,
 
-               _onSubmit: function(){
-                       // summary:
-                       //              Callback when user hits submit button
-                       // type:
-                       //              protected
-                       this.onExecute();       // notify container that we are about to execute
-                       this.execute(this.get('value'));
-               },
+       // editorParams: Object
+       //              Set of parameters for editor, like {required: true}
+       editorParams: {},
 
-               _getFocusItems: function(/*Node*/ dialogNode){
-                       // summary:
-                       //              Find focusable Items each time a dialog is opened,
-                       //              setting _firstFocusItem and _lastFocusItem
-                       // tags:
-                       //              protected
+       // disabled: Boolean
+       //              If true, clicking the InlineEditBox to edit it will have no effect.
+       disabled: false,
 
-                       var elems = dijit._getTabNavigable(dojo.byId(dialogNode));
-                       this._firstFocusItem = elems.lowest || elems.first || dialogNode;
-                       this._lastFocusItem = elems.last || elems.highest || this._firstFocusItem;
-                       if(dojo.isMoz && this._firstFocusItem.tagName.toLowerCase() == "input" &&
-                                       dojo.getNodeProp(this._firstFocusItem, "type").toLowerCase() == "file"){
-                               // FF doesn't behave well when first element is input type=file, set first focusable to dialog container
-                               dojo.attr(dialogNode, "tabIndex", "0");
-                               this._firstFocusItem = dialogNode;
-                       }
-               }
-       }
-);
+       onChange: function(/*===== value =====*/){
+               // summary:
+               //              Set this handler to be notified of changes to value.
+               // tags:
+               //              callback
+       },
 
-}
+       onCancel: function(){
+               // summary:
+               //              Set this handler to be notified when editing is cancelled.
+               // tags:
+               //              callback
+       },
 
-if(!dojo._hasResource["dijit.DialogUnderlay"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.DialogUnderlay"] = true;
-dojo.provide("dijit.DialogUnderlay");
+       // width: String
+       //              Width of editor.  By default it's width=100% (ie, block mode).
+       width: "100%",
 
+       // value: String
+       //              The display value of the widget in read-only mode
+       value: "",
 
+       // noValueIndicator: [const] String
+       //              The text that gets displayed when there is no value (so that the user has a place to click to edit)
+       noValueIndicator: has("ie") <= 6 ?      // font-family needed on IE6 but it messes up IE8
+               "<span style='font-family: wingdings; text-decoration: underline;'>&#160;&#160;&#160;&#160;&#x270d;&#160;&#160;&#160;&#160;</span>" :
+               "<span style='text-decoration: underline;'>&#160;&#160;&#160;&#160;&#x270d;&#160;&#160;&#160;&#160;</span>",    //      // &#160; == &nbsp;
 
+       constructor: function(){
+               // summary:
+               //              Sets up private arrays etc.
+               // tags:
+               //              private
+               this.editorParams = {};
+       },
 
+       postMixInProperties: function(){
+               this.inherited(arguments);
 
+               // save pointer to original source node, since Widget nulls-out srcNodeRef
+               this.displayNode = this.srcNodeRef;
 
-dojo.declare(
-       "dijit.DialogUnderlay",
-       [dijit._Widget, dijit._Templated],
-       {
-               // summary:
-               //              The component that blocks the screen behind a `dijit.Dialog`
-               //
-               // description:
-               //              A component used to block input behind a `dijit.Dialog`. Only a single
-               //              instance of this widget is created by `dijit.Dialog`, and saved as
-               //              a reference to be shared between all Dialogs as `dijit._underlay`
-               //
-               //              The underlay itself can be styled based on and id:
-               //      |       #myDialog_underlay { background-color:red; }
-               //
-               //              In the case of `dijit.Dialog`, this id is based on the id of the Dialog,
-               //              suffixed with _underlay.
-
-               // Template has two divs; outer div is used for fade-in/fade-out, and also to hold background iframe.
-               // Inner div has opacity specified in CSS file.
-               templateString: "<div class='dijitDialogUnderlayWrapper'><div class='dijitDialogUnderlay' dojoAttachPoint='node'></div></div>",
-
-               // Parameters on creation or updatable later
+               // connect handlers to the display node
+               var events = {
+                       ondijitclick: "_onClick",
+                       onmouseover: "_onMouseOver",
+                       onmouseout: "_onMouseOut",
+                       onfocus: "_onMouseOver",
+                       onblur: "_onMouseOut"
+               };
+               for(var name in events){
+                       this.connect(this.displayNode, name, events[name]);
+               }
+               this.displayNode.setAttribute("role", "button");
+               if(!this.displayNode.getAttribute("tabIndex")){
+                       this.displayNode.setAttribute("tabIndex", 0);
+               }
 
-               // dialogId: String
-               //              Id of the dialog.... DialogUnderlay's id is based on this id
-               dialogId: "",
+               if(!this.value && !("value" in this.params)){ // "" is a good value if specified directly so check params){
+                       this.value = lang.trim(this.renderAsHtml ? this.displayNode.innerHTML :
+                               (this.displayNode.innerText||this.displayNode.textContent||""));
+               }
+               if(!this.value){
+                       this.displayNode.innerHTML = this.noValueIndicator;
+               }
 
-               // class: String
-               //              This class name is used on the DialogUnderlay node, in addition to dijitDialogUnderlay
-               "class": "",
+               domClass.add(this.displayNode, 'dijitInlineEditBoxDisplayMode');
+       },
 
-               attributeMap: { id: "domNode" },
+       setDisabled: function(/*Boolean*/ disabled){
+               // summary:
+               //              Deprecated.   Use set('disabled', ...) instead.
+               // tags:
+               //              deprecated
+               kernel.deprecated("dijit.InlineEditBox.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
+               this.set('disabled', disabled);
+       },
 
-               _setDialogIdAttr: function(id){
-                       dojo.attr(this.node, "id", id + "_underlay");
-               },
+       _setDisabledAttr: function(/*Boolean*/ disabled){
+               // summary:
+               //              Hook to make set("disabled", ...) work.
+               //              Set disabled state of widget.
+               this.domNode.setAttribute("aria-disabled", disabled);
+               if(disabled){
+                       this.displayNode.removeAttribute("tabIndex");
+               }else{
+                       this.displayNode.setAttribute("tabIndex", 0);
+               }
+               domClass.toggle(this.displayNode, "dijitInlineEditBoxDisplayModeDisabled", disabled);
+               this._set("disabled", disabled);
+       },
 
-               _setClassAttr: function(clazz){
-                       this.node.className = "dijitDialogUnderlay " + clazz;
-               },
+       _onMouseOver: function(){
+               // summary:
+               //              Handler for onmouseover and onfocus event.
+               // tags:
+               //              private
+               if(!this.disabled){
+                       domClass.add(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
+               }
+       },
 
-               postCreate: function(){
-                       // summary:
-                       //              Append the underlay to the body
-                       dojo.body().appendChild(this.domNode);
-               },
+       _onMouseOut: function(){
+               // summary:
+               //              Handler for onmouseout and onblur event.
+               // tags:
+               //              private
+               domClass.remove(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
+       },
 
-               layout: function(){
-                       // summary:
-                       //              Sets the background to the size of the viewport
-                       //
-                       // description:
-                       //              Sets the background to the size of the viewport (rather than the size
-                       //              of the document) since we need to cover the whole browser window, even
-                       //              if the document is only a few lines long.
-                       // tags:
-                       //              private
+       _onClick: function(/*Event*/ e){
+               // summary:
+               //              Handler for onclick event.
+               // tags:
+               //              private
+               if(this.disabled){ return; }
+               if(e){ event.stop(e); }
+               this._onMouseOut();
 
-                       var is = this.node.style,
-                               os = this.domNode.style;
+               // Since FF gets upset if you move a node while in an event handler for that node...
+               setTimeout(lang.hitch(this, "edit"), 0);
+       },
 
-                       // hide the background temporarily, so that the background itself isn't
-                       // causing scrollbars to appear (might happen when user shrinks browser
-                       // window and then we are called to resize)
-                       os.display = "none";
+       edit: function(){
+               // summary:
+               //              Display the editor widget in place of the original (read only) markup.
+               // tags:
+               //              private
 
-                       // then resize and show
-                       var viewport = dojo.window.getBox();
-                       os.top = viewport.t + "px";
-                       os.left = viewport.l + "px";
-                       is.width = viewport.w + "px";
-                       is.height = viewport.h + "px";
-                       os.display = "block";
-               },
+               if(this.disabled || this.editing){ return; }
+               this._set('editing', true);
 
-               show: function(){
-                       // summary:
-                       //              Show the dialog underlay
-                       this.domNode.style.display = "block";
-                       this.layout();
-                       this.bgIframe = new dijit.BackgroundIframe(this.domNode);
-               },
+               // save some display node values that can be restored later
+               this._savedPosition = domStyle.get(this.displayNode, "position") || "static";
+               this._savedOpacity = domStyle.get(this.displayNode, "opacity") || "1";
+               this._savedTabIndex = domAttr.get(this.displayNode, "tabIndex") || "0";
 
-               hide: function(){
-                       // summary:
-                       //              Hides the dialog underlay
-                       this.bgIframe.destroy();
-                       this.domNode.style.display = "none";
-               },
+               if(this.wrapperWidget){
+                       var ew = this.wrapperWidget.editWidget;
+                       ew.set("displayedValue" in ew ? "displayedValue" : "value", this.value);
+               }else{
+                       // Placeholder for edit widget
+                       // Put place holder (and eventually editWidget) before the display node so that it's positioned correctly
+                       // when Calendar dropdown appears, which happens automatically on focus.
+                       var placeholder = domConstruct.create("span", null, this.domNode, "before");
 
-               uninitialize: function(){
-                       if(this.bgIframe){
-                               this.bgIframe.destroy();
+                       // Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons)
+                       var ewc = typeof this.editorWrapper == "string" ? lang.getObject(this.editorWrapper) : this.editorWrapper;
+                       this.wrapperWidget = new ewc({
+                               value: this.value,
+                               buttonSave: this.buttonSave,
+                               buttonCancel: this.buttonCancel,
+                               dir: this.dir,
+                               lang: this.lang,
+                               tabIndex: this._savedTabIndex,
+                               editor: this.editor,
+                               inlineEditBox: this,
+                               sourceStyle: domStyle.getComputedStyle(this.displayNode),
+                               save: lang.hitch(this, "save"),
+                               cancel: lang.hitch(this, "cancel"),
+                               textDir: this.textDir
+                       }, placeholder);
+                       if(!this._started){
+                               this.startup();
                        }
-                       this.inherited(arguments);
                }
-       }
-);
-
-}
+               var ww = this.wrapperWidget;
 
-if(!dojo._hasResource["dojo.html"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.html"] = true;
-dojo.provide("dojo.html");
+               // to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,
+               // and then when it's finished rendering, we switch from display mode to editor
+               // position:absolute releases screen space allocated to the display node
+               // opacity:0 is the same as visibility:hidden but is still focusable
+               // visiblity:hidden removes focus outline
 
-// the parser might be needed..
+               domStyle.set(this.displayNode, { position: "absolute", opacity: "0" }); // makes display node invisible, display style used for focus-ability
+               domStyle.set(ww.domNode, { position: this._savedPosition, visibility: "visible", opacity: "1" });
+               domAttr.set(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode
 
-(function(){ // private scope, sort of a namespace
+               // Replace the display widget with edit widget, leaving them both displayed for a brief time so that
+               // focus can be shifted without incident.  (browser may needs some time to render the editor.)
+               setTimeout(lang.hitch(ww, function(){
+                       this.focus(); // both nodes are showing, so we can switch focus safely
+                       this._resetValue = this.getValue();
+               }), 0);
+       },
 
-       // idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
-       var idCounter = 0, 
-               d = dojo;
-       
-       dojo.html._secureForInnerHtml = function(/*String*/ cont){
+       _onBlur: function(){
                // summary:
-               //              removes !DOCTYPE and title elements from the html string.
-               // 
-               //              khtml is picky about dom faults, you can't attach a style or <title> node as child of body
-               //              must go into head, so we need to cut out those tags
-               //      cont:
-               //              An html string for insertion into the dom
-               //      
-               return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
-       };
+               //              Called when focus moves outside the InlineEditBox.
+               //              Performs garbage collection.
+               // tags:
+               //              private
 
-/*====
-       dojo.html._emptyNode = function(node){
-               // summary:
-               //              removes all child nodes from the given node
-               //      node: DOMNode
-               //              the parent element
-       };
-=====*/
-       dojo.html._emptyNode = dojo.empty;
+               this.inherited(arguments);
+               if(!this.editing){
+                       /* causes IE focus problems, see TooltipDialog_a11y.html...
+                       setTimeout(lang.hitch(this, function(){
+                               if(this.wrapperWidget){
+                                       this.wrapperWidget.destroy();
+                                       delete this.wrapperWidget;
+                               }
+                       }), 0);
+                       */
+               }
+       },
 
-       dojo.html._setNodeContent = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont){
+       destroy: function(){
+               if(this.wrapperWidget && !this.wrapperWidget._destroyed){
+                       this.wrapperWidget.destroy();
+                       delete this.wrapperWidget;
+               }
+               this.inherited(arguments);
+       },
+
+       _showText: function(/*Boolean*/ focus){
                // summary:
-               //              inserts the given content into the given node
-               //      node:
-               //              the parent element
-               //      content:
-               //              the content to be set on the parent element. 
-               //              This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
-               
-               // always empty
-               d.empty(node);
+               //              Revert to display mode, and optionally focus on display node
+               // tags:
+               //              private
 
-               if(cont) {
-                       if(typeof cont == "string") {
-                               cont = d._toDom(cont, node.ownerDocument);
-                       }
-                       if(!cont.nodeType && d.isArrayLike(cont)) {
-                               // handle as enumerable, but it may shrink as we enumerate it
-                               for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
-                                       d.place( cont[i], node, "last");
-                               }
-                       } else {
-                               // pass nodes, documentFragments and unknowns through to dojo.place
-                               d.place(cont, node, "last");
-                       }
+               var ww = this.wrapperWidget;
+               domStyle.set(ww.domNode, { position: "absolute", visibility: "hidden", opacity: "0" }); // hide the editor from mouse/keyboard events
+               domStyle.set(this.displayNode, { position: this._savedPosition, opacity: this._savedOpacity }); // make the original text visible
+               domAttr.set(this.displayNode, "tabIndex", this._savedTabIndex);
+               if(focus){
+                       fm.focus(this.displayNode);
                }
+       },
 
-               // return DomNode
-               return node;
-       };
+       save: function(/*Boolean*/ focus){
+               // summary:
+               //              Save the contents of the editor and revert to display mode.
+               // focus: Boolean
+               //              Focus on the display mode text
+               // tags:
+               //              private
 
-       // we wrap up the content-setting operation in a object
-       dojo.declare("dojo.html._ContentSetter", null, 
-               {
-                       // node: DomNode|String
-                       //              An node which will be the parent element that we set content into
-                       node: "",
+               if(this.disabled || !this.editing){ return; }
+               this._set('editing', false);
 
-                       // content: String|DomNode|DomNode[]
-                       //              The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
-                       content: "",
-                       
-                       // id: String?
-                       //              Usually only used internally, and auto-generated with each instance 
-                       id: "",
+               var ww = this.wrapperWidget;
+               var value = ww.getValue();
+               this.set('value', value); // display changed, formatted value
 
-                       // cleanContent: Boolean
-                       //              Should the content be treated as a full html document, 
-                       //              and the real content stripped of <html>, <body> wrapper before injection
-                       cleanContent: false,
-                       
-                       // extractContent: Boolean
-                       //              Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
-                       extractContent: false,
+               this._showText(focus); // set focus as needed
+       },
 
-                       // parseContent: Boolean
-                       //              Should the node by passed to the parser after the new content is set
-                       parseContent: false,
-                       
-                       // lifecyle methods
-                       constructor: function(/* Object */params, /* String|DomNode */node){
-                               //      summary:
-                               //              Provides a configurable, extensible object to wrap the setting on content on a node
-                               //              call the set() method to actually set the content..
-                               // the original params are mixed directly into the instance "this"
-                               dojo.mixin(this, params || {});
+       setValue: function(/*String*/ val){
+               // summary:
+               //              Deprecated.   Use set('value', ...) instead.
+               // tags:
+               //              deprecated
+               kernel.deprecated("dijit.InlineEditBox.setValue() is deprecated.  Use set('value', ...) instead.", "", "2.0");
+               return this.set("value", val);
+       },
 
-                               // give precedence to params.node vs. the node argument
-                               // and ensure its a node, not an id string
-                               node = this.node = dojo.byId( this.node || node );
-       
-                               if(!this.id){
-                                       this.id = [
-                                               "Setter",
-                                               (node) ? node.id || node.tagName : "", 
-                                               idCounter++
-                                       ].join("_");
-                               }
-                       },
-                       set: function(/* String|DomNode|NodeList? */ cont, /* Object? */ params){
-                               // summary:
-                               //              front-end to the set-content sequence 
-                               //      cont:
-                               //              An html string, node or enumerable list of nodes for insertion into the dom
-                               //              If not provided, the object's content property will be used
-                               if(undefined !== cont){
-                                       this.content = cont;
-                               }
-                               // in the re-use scenario, set needs to be able to mixin new configuration
-                               if(params){
-                                       this._mixin(params);
-                               }
+       _setValueAttr: function(/*String*/ val){
+               // summary:
+               //              Hook to make set("value", ...) work.
+               //              Inserts specified HTML value into this node, or an "input needed" character if node is blank.
 
-                               this.onBegin();
-                               this.setContent();
-                               this.onEnd();
+               val = lang.trim(val);
+               var renderVal = this.renderAsHtml ? val : val.replace(/&/gm, "&amp;").replace(/</gm, "&lt;").replace(/>/gm, "&gt;").replace(/"/gm, "&quot;").replace(/\n/g, "<br>");
+               this.displayNode.innerHTML = renderVal || this.noValueIndicator;
+               this._set("value", val);
 
-                               return this.node;
-                       },
-                       setContent: function(){
-                               // summary:
-                               //              sets the content on the node 
+               if(this._started){
+                       // tell the world that we have changed
+                       setTimeout(lang.hitch(this, "onChange", val), 0); // setTimeout prevents browser freeze for long-running event handlers
+               }
+               // contextual (auto) text direction depends on the text value
+               if(this.textDir == "auto"){
+                       this.applyTextDir(this.displayNode, this.displayNode.innerText);
+               }
+       },
 
-                               var node = this.node; 
-                               if(!node) {
-                                   // can't proceed
-                                       throw new Error(this.declaredClass + ": setContent given no node");
-                               }
-                               try{
-                                       node = dojo.html._setNodeContent(node, this.content);
-                               }catch(e){
-                                       // check if a domfault occurs when we are appending this.errorMessage
-                                       // like for instance if domNode is a UL and we try append a DIV
-       
-                                       // FIXME: need to allow the user to provide a content error message string
-                                       var errMess = this.onContentError(e); 
-                                       try{
-                                               node.innerHTML = errMess;
-                                       }catch(e){
-                                               console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e);
-                                       }
-                               }
-                               // always put back the node for the next method
-                               this.node = node; // DomNode
-                       },
-                       
-                       empty: function() {
-                               // summary
-                               //      cleanly empty out existing content
+       getValue: function(){
+               // summary:
+               //              Deprecated.   Use get('value') instead.
+               // tags:
+               //              deprecated
+               kernel.deprecated("dijit.InlineEditBox.getValue() is deprecated.  Use get('value') instead.", "", "2.0");
+               return this.get("value");
+       },
 
-                               // destroy any widgets from a previous run
-                               // NOTE: if you dont want this you'll need to empty 
-                               // the parseResults array property yourself to avoid bad things happenning
-                               if(this.parseResults && this.parseResults.length) {
-                                       dojo.forEach(this.parseResults, function(w) {
-                                               if(w.destroy){
-                                                       w.destroy();
-                                               }
-                                       });
-                                       delete this.parseResults;
-                               }
-                               // this is fast, but if you know its already empty or safe, you could 
-                               // override empty to skip this step
-                               dojo.html._emptyNode(this.node);
-                       },
-       
-                       onBegin: function(){
-                               // summary
-                               //              Called after instantiation, but before set(); 
-                               //              It allows modification of any of the object properties 
-                               //              - including the node and content provided - before the set operation actually takes place
-                               //              This default implementation checks for cleanContent and extractContent flags to 
-                               //              optionally pre-process html string content
-                               var cont = this.content;
-       
-                               if(dojo.isString(cont)){
-                                       if(this.cleanContent){
-                                               cont = dojo.html._secureForInnerHtml(cont);
-                                       }
-  
-                                       if(this.extractContent){
-                                               var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
-                                               if(match){ cont = match[1]; }
-                                       }
-                               }
+       cancel: function(/*Boolean*/ focus){
+               // summary:
+               //              Revert to display mode, discarding any changes made in the editor
+               // tags:
+               //              private
 
-                               // clean out the node and any cruft associated with it - like widgets
-                               this.empty();
-                               
-                               this.content = cont;
-                               return this.node; /* DomNode */
-                       },
-       
-                       onEnd: function(){
-                               // summary
-                               //              Called after set(), when the new content has been pushed into the node
-                               //              It provides an opportunity for post-processing before handing back the node to the caller
-                               //              This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
-                               if(this.parseContent){
-                                       // populates this.parseResults if you need those..
-                                       this._parse();
-                               }
-                               return this.node; /* DomNode */
-                       },
-       
-                       tearDown: function(){
-                               // summary
-                               //              manually reset the Setter instance if its being re-used for example for another set()
-                               // description
-                               //              tearDown() is not called automatically. 
-                               //              In normal use, the Setter instance properties are simply allowed to fall out of scope
-                               //              but the tearDown method can be called to explicitly reset this instance.
-                               delete this.parseResults; 
-                               delete this.node; 
-                               delete this.content; 
-                       },
-  
-                       onContentError: function(err){
-                               return "Error occured setting content: " + err; 
-                       },
-                       
-                       _mixin: function(params){
-                               // mix properties/methods into the instance
-                               // TODO: the intention with tearDown is to put the Setter's state 
-                               // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
-                               // so we could do something here to move the original properties aside for later restoration
-                               var empty = {}, key;
-                               for(key in params){
-                                       if(key in empty){ continue; }
-                                       // TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
-                                       // .. but history shows we'll almost always guess wrong
-                                       this[key] = params[key]; 
-                               }
-                       },
-                       _parse: function(){
-                               // summary: 
-                               //              runs the dojo parser over the node contents, storing any results in this.parseResults
-                               //              Any errors resulting from parsing are passed to _onError for handling
+               if(this.disabled || !this.editing){ return; }
+               this._set('editing', false);
 
-                               var rootNode = this.node;
-                               try{
-                                       // store the results (widgets, whatever) for potential retrieval
-                                       this.parseResults = dojo.parser.parse({
-                                               rootNode: rootNode,
-                                               dir: this.dir,
-                                               lang: this.lang
-                                       });
-                               }catch(e){
-                                       this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id);
-                               }
-                       },
-  
-                       _onError: function(type, err, consoleText){
-                               // summary:
-                               //              shows user the string that is returned by on[type]Error
-                               //              overide/implement on[type]Error and return your own string to customize
-                               var errText = this['on' + type + 'Error'].call(this, err);
-                               if(consoleText){
-                                       console.error(consoleText, err);
-                               }else if(errText){ // a empty string won't change current content
-                                       dojo.html._setNodeContent(this.node, errText, true);
-                               }
-                       }
-       }); // end dojo.declare()
+               // tell the world that we have no changes
+               setTimeout(lang.hitch(this, "onCancel"), 0); // setTimeout prevents browser freeze for long-running event handlers
 
-       dojo.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
-                       // summary:
-                       //              inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
-                       //              may be a better choice for simple HTML insertion.
-                       // description:
-                       //              Unless you need to use the params capabilities of this method, you should use
-                       //              dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
-                       //              an HTML string into the DOM, but it only handles inserting an HTML string as DOM
-                       //              elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
-                       //              or the other capabilities as defined by the params object for this method.
-                       //      node:
-                       //              the parent element that will receive the content
-                       //      cont:
-                       //              the content to be set on the parent element. 
-                       //              This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
-                       //      params: 
-                       //              Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
-                       //      example:
-                       //              A safe string/node/nodelist content replacement/injection with hooks for extension
-                       //              Example Usage: 
-                       //              dojo.html.set(node, "some string"); 
-                       //              dojo.html.set(node, contentNode, {options}); 
-                       //              dojo.html.set(node, myNode.childNodes, {options}); 
-               if(undefined == cont){
-                       console.warn("dojo.html.set: no cont argument provided, using empty string");
-                       cont = "";
-               }       
-               if(!params){
-                       // simple and fast
-                       return dojo.html._setNodeContent(node, cont, true);
-               }else{ 
-                       // more options but slower
-                       // note the arguments are reversed in order, to match the convention for instantiation via the parser
-                       var op = new dojo.html._ContentSetter(dojo.mixin( 
-                                       params, 
-                                       { content: cont, node: node } 
-                       ));
-                       return op.set();
+               this._showText(focus);
+       },
+       _setTextDirAttr: function(/*String*/ textDir){
+               // summary:
+               //              Setter for textDir.
+               // description:
+               //              Users shouldn't call this function; they should be calling
+               //              set('textDir', value)
+               // tags:
+               //              private
+               if(!this._created || this.textDir != textDir){
+                       this._set("textDir", textDir);
+                       this.applyTextDir(this.displayNode, this.displayNode.innerText);
+                       this.displayNode.align = this.dir == "rtl" ? "right" : "left"; //fix the text alignment
                }
-       };
-})();
+   }
+});
 
-}
+InlineEditBox._InlineEditor = InlineEditor;    // for monkey patching
 
-if(!dojo._hasResource["dijit.layout.ContentPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.ContentPane"] = true;
-dojo.provide("dijit.layout.ContentPane");
+return InlineEditBox;
+});
+},
+'dojo/selector/acme':function(){
+define("dojo/selector/acme", ["../_base/kernel", "../has", "../dom", "../_base/sniff", "../_base/array", "../_base/lang", "../_base/window"], function(dojo, has, dom){
+  //  module:
+  //    dojo/selector/acme
+  //  summary:
+  //    This module defines the Acme selector engine
 
+/*
+       acme architectural overview:
+
+               acme is a relatively full-featured CSS3 query library. It is
+               designed to take any valid CSS3 selector and return the nodes matching
+               the selector. To do this quickly, it processes queries in several
+               steps, applying caching where profitable.
+
+               The steps (roughly in reverse order of the way they appear in the code):
+                       1.) check to see if we already have a "query dispatcher"
+                               - if so, use that with the given parameterization. Skip to step 4.
+                       2.) attempt to determine which branch to dispatch the query to:
+                               - JS (optimized DOM iteration)
+                               - native (FF3.1+, Safari 3.1+, IE 8+)
+                       3.) tokenize and convert to executable "query dispatcher"
+                               - this is where the lion's share of the complexity in the
+                                       system lies. In the DOM version, the query dispatcher is
+                                       assembled as a chain of "yes/no" test functions pertaining to
+                                       a section of a simple query statement (".blah:nth-child(odd)"
+                                       but not "div div", which is 2 simple statements). Individual
+                                       statement dispatchers are cached (to prevent re-definition)
+                                       as are entire dispatch chains (to make re-execution of the
+                                       same query fast)
+                       4.) the resulting query dispatcher is called in the passed scope
+                                       (by default the top-level document)
+                               - for DOM queries, this results in a recursive, top-down
+                                       evaluation of nodes based on each simple query section
+                               - for native implementations, this may mean working around spec
+                                       bugs. So be it.
+                       5.) matched nodes are pruned to ensure they are unique (if necessary)
+*/
 
 
-       // for dijit.layout.marginBox2contentBox()
+       ////////////////////////////////////////////////////////////////////////
+       // Toolkit aliases
+       ////////////////////////////////////////////////////////////////////////
 
+       // if you are extracting acme for use in your own system, you will
+       // need to provide these methods and properties. No other porting should be
+       // necessary, save for configuring the system to use a class other than
+       // dojo.NodeList as the return instance instantiator
+       var trim =                      dojo.trim;
+       var each =                      dojo.forEach;
+       //                                      d.isIE; // float
+       //                                      d.isSafari; // float
+       //                                      d.isOpera; // float
+       //                                      d.isWebKit; // float
+       //                                      d.doc ; // document element
 
+       var getDoc = function(){ return dojo.doc; };
+       // NOTE(alex): the spec is idiotic. CSS queries should ALWAYS be case-sensitive, but nooooooo
+       var cssCaseBug = ((dojo.isWebKit||dojo.isMozilla) && ((getDoc().compatMode) == "BackCompat"));
 
+       ////////////////////////////////////////////////////////////////////////
+       // Global utilities
+       ////////////////////////////////////////////////////////////////////////
 
 
+       var specials = ">~+";
 
-dojo.declare(
-       "dijit.layout.ContentPane", dijit._Widget,
-{
-       // summary:
-       //              A widget that acts as a container for mixed HTML and widgets, and includes an Ajax interface
-       // description:
-       //              A widget that can be used as a stand alone widget
-       //              or as a base class for other widgets.
-       //
-       //              Handles replacement of document fragment using either external uri or javascript
-       //              generated markup or DOM content, instantiating widgets within that content.
-       //              Don't confuse it with an iframe, it only needs/wants document fragments.
-       //              It's useful as a child of LayoutContainer, SplitContainer, or TabContainer.
-       //              But note that those classes can contain any widget as a child.
-       // example:
-       //              Some quick samples:
-       //              To change the innerHTML use .set('content', '<b>new content</b>')
-       //
-       //              Or you can send it a NodeList, .set('content', dojo.query('div [class=selected]', userSelection))
-       //              please note that the nodes in NodeList will copied, not moved
-       //
-       //              To do a ajax update use .set('href', url)
+       // global thunk to determine whether we should treat the current query as
+       // case sensitive or not. This switch is flipped by the query evaluator
+       // based on the document passed as the context to search.
+       var caseSensitive = false;
 
-       // href: String
-       //              The href of the content that displays now.
-       //              Set this at construction if you want to load data externally when the
-       //              pane is shown.  (Set preload=true to load it immediately.)
-       //              Changing href after creation doesn't have any effect; Use set('href', ...);
-       href: "",
+       // how high?
+       var yesman = function(){ return true; };
 
-/*=====
-       // content: String || DomNode || NodeList || dijit._Widget
-       //              The innerHTML of the ContentPane.
-       //              Note that the initialization parameter / argument to attr("content", ...)
-       //              can be a String, DomNode, Nodelist, or _Widget.
-       content: "",
-=====*/
+       ////////////////////////////////////////////////////////////////////////
+       // Tokenizer
+       ////////////////////////////////////////////////////////////////////////
 
-       // extractContent: Boolean
-       //              Extract visible content from inside of <body> .... </body>.
-       //              I.e., strip <html> and <head> (and it's contents) from the href
-       extractContent: false,
+       var getQueryParts = function(query){
+               //      summary:
+               //              state machine for query tokenization
+               //      description:
+               //              instead of using a brittle and slow regex-based CSS parser,
+               //              acme implements an AST-style query representation. This
+               //              representation is only generated once per query. For example,
+               //              the same query run multiple times or under different root nodes
+               //              does not re-parse the selector expression but instead uses the
+               //              cached data structure. The state machine implemented here
+               //              terminates on the last " " (space) character and returns an
+               //              ordered array of query component structures (or "parts"). Each
+               //              part represents an operator or a simple CSS filtering
+               //              expression. The structure for parts is documented in the code
+               //              below.
+
+
+               // NOTE:
+               //              this code is designed to run fast and compress well. Sacrifices
+               //              to readability and maintainability have been made.  Your best
+               //              bet when hacking the tokenizer is to put The Donnas on *really*
+               //              loud (may we recommend their "Spend The Night" release?) and
+               //              just assume you're gonna make mistakes. Keep the unit tests
+               //              open and run them frequently. Knowing is half the battle ;-)
+               if(specials.indexOf(query.slice(-1)) >= 0){
+                       // if we end with a ">", "+", or "~", that means we're implicitly
+                       // searching all children, so make it explicit
+                       query += " * "
+               }else{
+                       // if you have not provided a terminator, one will be provided for
+                       // you...
+                       query += " ";
+               }
 
-       // parseOnLoad: Boolean
-       //              Parse content and create the widgets, if any.
-       parseOnLoad: true,
+               var ts = function(/*Integer*/ s, /*Integer*/ e){
+                       // trim and slice.
 
-       // preventCache: Boolean
-       //              Prevent caching of data from href's by appending a timestamp to the href.
-       preventCache: false,
+                       // take an index to start a string slice from and an end position
+                       // and return a trimmed copy of that sub-string
+                       return trim(query.slice(s, e));
+               };
 
-       // preload: Boolean
-       //              Force load of data on initialization even if pane is hidden.
-       preload: false,
+               // the overall data graph of the full query, as represented by queryPart objects
+               var queryParts = [];
+
+
+               // state keeping vars
+               var inBrackets = -1, inParens = -1, inMatchFor = -1,
+                       inPseudo = -1, inClass = -1, inId = -1, inTag = -1,
+                       lc = "", cc = "", pStart;
+
+               // iteration vars
+               var x = 0, // index in the query
+                       ql = query.length,
+                       currentPart = null, // data structure representing the entire clause
+                       _cp = null; // the current pseudo or attr matcher
+
+               // several temporary variables are assigned to this structure during a
+               // potential sub-expression match:
+               //              attr:
+               //                      a string representing the current full attribute match in a
+               //                      bracket expression
+               //              type:
+               //                      if there's an operator in a bracket expression, this is
+               //                      used to keep track of it
+               //              value:
+               //                      the internals of parenthetical expression for a pseudo. for
+               //                      :nth-child(2n+1), value might be "2n+1"
+
+               var endTag = function(){
+                       // called when the tokenizer hits the end of a particular tag name.
+                       // Re-sets state variables for tag matching and sets up the matcher
+                       // to handle the next type of token (tag or operator).
+                       if(inTag >= 0){
+                               var tv = (inTag == x) ? null : ts(inTag, x); // .toLowerCase();
+                               currentPart[ (specials.indexOf(tv) < 0) ? "tag" : "oper" ] = tv;
+                               inTag = -1;
+                       }
+               };
 
-       // refreshOnShow: Boolean
-       //              Refresh (re-download) content when pane goes from hidden to shown
-       refreshOnShow: false,
+               var endId = function(){
+                       // called when the tokenizer might be at the end of an ID portion of a match
+                       if(inId >= 0){
+                               currentPart.id = ts(inId, x).replace(/\\/g, "");
+                               inId = -1;
+                       }
+               };
 
-       // loadingMessage: String
-       //              Message that shows while downloading
-       loadingMessage: "<span class='dijitContentPaneLoading'>${loadingState}</span>",
+               var endClass = function(){
+                       // called when the tokenizer might be at the end of a class name
+                       // match. CSS allows for multiple classes, so we augment the
+                       // current item with another class in its list
+                       if(inClass >= 0){
+                               currentPart.classes.push(ts(inClass + 1, x).replace(/\\/g, ""));
+                               inClass = -1;
+                       }
+               };
 
-       // errorMessage: String
-       //              Message that shows if an error occurs
-       errorMessage: "<span class='dijitContentPaneError'>${errorState}</span>",
+               var endAll = function(){
+                       // at the end of a simple fragment, so wall off the matches
+                       endId();
+                       endTag();
+                       endClass();
+               };
 
-       // isLoaded: [readonly] Boolean
-       //              True if the ContentPane has data in it, either specified
-       //              during initialization (via href or inline content), or set
-       //              via attr('content', ...) / attr('href', ...)
-       //
-       //              False if it doesn't have any content, or if ContentPane is
-       //              still in the process of downloading href.
-       isLoaded: false,
+               var endPart = function(){
+                       endAll();
+                       if(inPseudo >= 0){
+                               currentPart.pseudos.push({ name: ts(inPseudo + 1, x) });
+                       }
+                       // hint to the selector engine to tell it whether or not it
+                       // needs to do any iteration. Many simple selectors don't, and
+                       // we can avoid significant construction-time work by advising
+                       // the system to skip them
+                       currentPart.loops = (
+                                       currentPart.pseudos.length ||
+                                       currentPart.attrs.length ||
+                                       currentPart.classes.length      );
+
+                       currentPart.oquery = currentPart.query = ts(pStart, x); // save the full expression as a string
+
+
+                       // otag/tag are hints to suggest to the system whether or not
+                       // it's an operator or a tag. We save a copy of otag since the
+                       // tag name is cast to upper-case in regular HTML matches. The
+                       // system has a global switch to figure out if the current
+                       // expression needs to be case sensitive or not and it will use
+                       // otag or tag accordingly
+                       currentPart.otag = currentPart.tag = (currentPart["oper"]) ? null : (currentPart.tag || "*");
+
+                       if(currentPart.tag){
+                               // if we're in a case-insensitive HTML doc, we likely want
+                               // the toUpperCase when matching on element.tagName. If we
+                               // do it here, we can skip the string op per node
+                               // comparison
+                               currentPart.tag = currentPart.tag.toUpperCase();
+                       }
+
+                       // add the part to the list
+                       if(queryParts.length && (queryParts[queryParts.length-1].oper)){
+                               // operators are always infix, so we remove them from the
+                               // list and attach them to the next match. The evaluator is
+                               // responsible for sorting out how to handle them.
+                               currentPart.infixOper = queryParts.pop();
+                               currentPart.query = currentPart.infixOper.query + " " + currentPart.query;
+                               /*
+                               console.debug(  "swapping out the infix",
+                                                               currentPart.infixOper,
+                                                               "and attaching it to",
+                                                               currentPart);
+                               */
+                       }
+                       queryParts.push(currentPart);
+
+                       currentPart = null;
+               };
 
-       baseClass: "dijitContentPane",
+               // iterate over the query, character by character, building up a
+               // list of query part objects
+               for(; lc=cc, cc=query.charAt(x), x < ql; x++){
+                       //              cc: the current character in the match
+                       //              lc: the last character (if any)
+
+                       // someone is trying to escape something, so don't try to match any
+                       // fragments. We assume we're inside a literal.
+                       if(lc == "\\"){ continue; }
+                       if(!currentPart){ // a part was just ended or none has yet been created
+                               // NOTE: I hate all this alloc, but it's shorter than writing tons of if's
+                               pStart = x;
+                               //      rules describe full CSS sub-expressions, like:
+                               //              #someId
+                               //              .className:first-child
+                               //      but not:
+                               //              thinger > div.howdy[type=thinger]
+                               //      the indidual components of the previous query would be
+                               //      split into 3 parts that would be represented a structure
+                               //      like:
+                               //              [
+                               //                      {
+                               //                              query: "thinger",
+                               //                              tag: "thinger",
+                               //                      },
+                               //                      {
+                               //                              query: "div.howdy[type=thinger]",
+                               //                              classes: ["howdy"],
+                               //                              infixOper: {
+                               //                                      query: ">",
+                               //                                      oper: ">",
+                               //                              }
+                               //                      },
+                               //              ]
+                               currentPart = {
+                                       query: null, // the full text of the part's rule
+                                       pseudos: [], // CSS supports multiple pseud-class matches in a single rule
+                                       attrs: [],      // CSS supports multi-attribute match, so we need an array
+                                       classes: [], // class matches may be additive, e.g.: .thinger.blah.howdy
+                                       tag: null,      // only one tag...
+                                       oper: null, // ...or operator per component. Note that these wind up being exclusive.
+                                       id: null,       // the id component of a rule
+                                       getTag: function(){
+                                               return (caseSensitive) ? this.otag : this.tag;
+                                       }
+                               };
 
-       // doLayout: Boolean
-       //              - false - don't adjust size of children
-       //              - true - if there is a single visible child widget, set it's size to
-       //                              however big the ContentPane is
-       doLayout: true,
+                               // if we don't have a part, we assume we're going to start at
+                               // the beginning of a match, which should be a tag name. This
+                               // might fault a little later on, but we detect that and this
+                               // iteration will still be fine.
+                               inTag = x;
+                       }
+
+                       if(inBrackets >= 0){
+                               // look for a the close first
+                               if(cc == "]"){ // if we're in a [...] clause and we end, do assignment
+                                       if(!_cp.attr){
+                                               // no attribute match was previously begun, so we
+                                               // assume this is an attribute existence match in the
+                                               // form of [someAttributeName]
+                                               _cp.attr = ts(inBrackets+1, x);
+                                       }else{
+                                               // we had an attribute already, so we know that we're
+                                               // matching some sort of value, as in [attrName=howdy]
+                                               _cp.matchFor = ts((inMatchFor||inBrackets+1), x);
+                                       }
+                                       var cmf = _cp.matchFor;
+                                       if(cmf){
+                                               // try to strip quotes from the matchFor value. We want
+                                               // [attrName=howdy] to match the same
+                                               //      as [attrName = 'howdy' ]
+                                               if(     (cmf.charAt(0) == '"') || (cmf.charAt(0) == "'") ){
+                                                       _cp.matchFor = cmf.slice(1, -1);
+                                               }
+                                       }
+                                       // end the attribute by adding it to the list of attributes.
+                                       currentPart.attrs.push(_cp);
+                                       _cp = null; // necessary?
+                                       inBrackets = inMatchFor = -1;
+                               }else if(cc == "="){
+                                       // if the last char was an operator prefix, make sure we
+                                       // record it along with the "=" operator.
+                                       var addToCc = ("|~^$*".indexOf(lc) >=0 ) ? lc : "";
+                                       _cp.type = addToCc+cc;
+                                       _cp.attr = ts(inBrackets+1, x-addToCc.length);
+                                       inMatchFor = x+1;
+                               }
+                               // now look for other clause parts
+                       }else if(inParens >= 0){
+                               // if we're in a parenthetical expression, we need to figure
+                               // out if it's attached to a pseudo-selector rule like
+                               // :nth-child(1)
+                               if(cc == ")"){
+                                       if(inPseudo >= 0){
+                                               _cp.value = ts(inParens+1, x);
+                                       }
+                                       inPseudo = inParens = -1;
+                               }
+                       }else if(cc == "#"){
+                               // start of an ID match
+                               endAll();
+                               inId = x+1;
+                       }else if(cc == "."){
+                               // start of a class match
+                               endAll();
+                               inClass = x;
+                       }else if(cc == ":"){
+                               // start of a pseudo-selector match
+                               endAll();
+                               inPseudo = x;
+                       }else if(cc == "["){
+                               // start of an attribute match.
+                               endAll();
+                               inBrackets = x;
+                               // provide a new structure for the attribute match to fill-in
+                               _cp = {
+                                       /*=====
+                                       attr: null, type: null, matchFor: null
+                                       =====*/
+                               };
+                       }else if(cc == "("){
+                               // we really only care if we've entered a parenthetical
+                               // expression if we're already inside a pseudo-selector match
+                               if(inPseudo >= 0){
+                                       // provide a new structure for the pseudo match to fill-in
+                                       _cp = {
+                                               name: ts(inPseudo+1, x),
+                                               value: null
+                                       };
+                                       currentPart.pseudos.push(_cp);
+                               }
+                               inParens = x;
+                       }else if(
+                               (cc == " ") &&
+                               // if it's a space char and the last char is too, consume the
+                               // current one without doing more work
+                               (lc != cc)
+                       ){
+                               endPart();
+                       }
+               }
+               return queryParts;
+       };
 
-       // ioArgs: Object
-       //              Parameters to pass to xhrGet() request, for example:
-       // |    <div dojoType="dijit.layout.ContentPane" href="./bar" ioArgs="{timeout: 500}">
-       ioArgs: {},
 
-       // isContainer: [protected] Boolean
-       //              Indicates that this widget acts as a "parent" to the descendant widgets.
-       //              When the parent is started it will call startup() on the child widgets.
-       //              See also `isLayoutContainer`.
-       isContainer: true,
+       ////////////////////////////////////////////////////////////////////////
+       // DOM query infrastructure
+       ////////////////////////////////////////////////////////////////////////
 
-       // isLayoutContainer: [protected] Boolean
-       //              Indicates that this widget will call resize() on it's child widgets
-       //              when they become visible.
-       isLayoutContainer: true,
+       var agree = function(first, second){
+               // the basic building block of the yes/no chaining system. agree(f1,
+               // f2) generates a new function which returns the boolean results of
+               // both of the passed functions to a single logical-anded result. If
+               // either are not passed, the other is used exclusively.
+               if(!first){ return second; }
+               if(!second){ return first; }
 
-       // onLoadDeferred: [readonly] dojo.Deferred
-       //              This is the `dojo.Deferred` returned by attr('href', ...) and refresh().
-       //              Calling onLoadDeferred.addCallback() or addErrback() registers your
-       //              callback to be called only once, when the prior attr('href', ...) call or
-       //              the initial href parameter to the constructor finishes loading.
-       //
-       //              This is different than an onLoad() handler which gets called any time any href is loaded.
-       onLoadDeferred: null,
+               return function(){
+                       return first.apply(window, arguments) && second.apply(window, arguments);
+               }
+       };
 
-       // Override _Widget's attributeMap because we don't want the title attribute (used to specify
-       // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
-       // entire pane.
-       attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-               title: []
-       }),
+       var getArr = function(i, arr){
+               // helps us avoid array alloc when we don't need it
+               var r = arr||[]; // FIXME: should this be 'new d._NodeListCtor()' ?
+               if(i){ r.push(i); }
+               return r;
+       };
 
-       postMixInProperties: function(){
-               this.inherited(arguments);
-               var messages = dojo.i18n.getLocalization("dijit", "loading", this.lang);
-               this.loadingMessage = dojo.string.substitute(this.loadingMessage, messages);
-               this.errorMessage = dojo.string.substitute(this.errorMessage, messages);
+       var _isElement = function(n){ return (1 == n.nodeType); };
 
-               // Detect if we were initialized with data
-               if(!this.href && this.srcNodeRef && this.srcNodeRef.innerHTML){
-                       this.isLoaded = true;
+       // FIXME: need to coalesce _getAttr with defaultGetter
+       var blank = "";
+       var _getAttr = function(elem, attr){
+               if(!elem){ return blank; }
+               if(attr == "class"){
+                       return elem.className || blank;
                }
-       },
-
-       buildRendering: function(){
-               // Overrides Widget.buildRendering().
-               // Since we have no template we need to set this.containerNode ourselves.
-               // For subclasses of ContentPane do have a template, does nothing.
-               this.inherited(arguments);
-               if(!this.containerNode){
-                       // make getDescendants() work
-                       this.containerNode = this.domNode;
+               if(attr == "for"){
+                       return elem.htmlFor || blank;
                }
-       },
-
-       postCreate: function(){
-               // remove the title attribute so it doesn't show up when hovering
-               // over a node
-               this.domNode.title = "";
-
-               if(!dojo.attr(this.domNode,"role")){
-                       dijit.setWaiRole(this.domNode, "group");
+               if(attr == "style"){
+                       return elem.style.cssText || blank;
                }
+               return (caseSensitive ? elem.getAttribute(attr) : elem.getAttribute(attr, 2)) || blank;
+       };
 
-               dojo.addClass(this.domNode, this.baseClass);
-       },
-
-       startup: function(){
-               // summary:
-               //              See `dijit.layout._LayoutWidget.startup` for description.
-               //              Although ContentPane doesn't extend _LayoutWidget, it does implement
-               //              the same API.
-               if(this._started){ return; }
-
-               var parent = dijit._Contained.prototype.getParent.call(this);
-               this._childOfLayoutWidget = parent && parent.isLayoutContainer;
+       var attrs = {
+               "*=": function(attr, value){
+                       return function(elem){
+                               // E[foo*="bar"]
+                               //              an E element whose "foo" attribute value contains
+                               //              the substring "bar"
+                               return (_getAttr(elem, attr).indexOf(value)>=0);
+                       }
+               },
+               "^=": function(attr, value){
+                       // E[foo^="bar"]
+                       //              an E element whose "foo" attribute value begins exactly
+                       //              with the string "bar"
+                       return function(elem){
+                               return (_getAttr(elem, attr).indexOf(value)==0);
+                       }
+               },
+               "$=": function(attr, value){
+                       // E[foo$="bar"]
+                       //              an E element whose "foo" attribute value ends exactly
+                       //              with the string "bar"
+                       return function(elem){
+                               var ea = " "+_getAttr(elem, attr);
+                               return (ea.lastIndexOf(value)==(ea.length-value.length));
+                       }
+               },
+               "~=": function(attr, value){
+                       // E[foo~="bar"]
+                       //              an E element whose "foo" attribute value is a list of
+                       //              space-separated values, one of which is exactly equal
+                       //              to "bar"
+
+                       // return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]";
+                       var tval = " "+value+" ";
+                       return function(elem){
+                               var ea = " "+_getAttr(elem, attr)+" ";
+                               return (ea.indexOf(tval)>=0);
+                       }
+               },
+               "|=": function(attr, value){
+                       // E[hreflang|="en"]
+                       //              an E element whose "hreflang" attribute has a
+                       //              hyphen-separated list of values beginning (from the
+                       //              left) with "en"
+                       var valueDash = value+"-";
+                       return function(elem){
+                               var ea = _getAttr(elem, attr);
+                               return (
+                                       (ea == value) ||
+                                       (ea.indexOf(valueDash)==0)
+                               );
+                       }
+               },
+               "=": function(attr, value){
+                       return function(elem){
+                               return (_getAttr(elem, attr) == value);
+                       }
+               }
+       };
 
-               // I need to call resize() on my child/children (when I become visible), unless
-               // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
-               this._needLayout = !this._childOfLayoutWidget;
+       // avoid testing for node type if we can. Defining this in the negative
+       // here to avoid negation in the fast path.
+       var _noNES = (typeof getDoc().firstChild.nextElementSibling == "undefined");
+       var _ns = !_noNES ? "nextElementSibling" : "nextSibling";
+       var _ps = !_noNES ? "previousElementSibling" : "previousSibling";
+       var _simpleNodeTest = (_noNES ? _isElement : yesman);
 
-               if(this.isLoaded){
-                       dojo.forEach(this.getChildren(), function(child){
-                               child.startup();
-                       });
+       var _lookLeft = function(node){
+               // look left
+               while(node = node[_ps]){
+                       if(_simpleNodeTest(node)){ return false; }
                }
+               return true;
+       };
 
-               if(this._isShown() || this.preload){
-                       this._onShow();
+       var _lookRight = function(node){
+               // look right
+               while(node = node[_ns]){
+                       if(_simpleNodeTest(node)){ return false; }
                }
+               return true;
+       };
 
-               this.inherited(arguments);
-       },
-
-       _checkIfSingleChild: function(){
-               // summary:
-               //              Test if we have exactly one visible widget as a child,
-               //              and if so assume that we are a container for that widget,
-               //              and should propogate startup() and resize() calls to it.
-               //              Skips over things like data stores since they aren't visible.
+       var getNodeIndex = function(node){
+               var root = node.parentNode;
+               var i = 0,
+                       tret = root.children || root.childNodes,
+                       ci = (node["_i"]||-1),
+                       cl = (root["_l"]||-1);
+
+               if(!tret){ return -1; }
+               var l = tret.length;
+
+               // we calculate the parent length as a cheap way to invalidate the
+               // cache. It's not 100% accurate, but it's much more honest than what
+               // other libraries do
+               if( cl == l && ci >= 0 && cl >= 0 ){
+                       // if it's legit, tag and release
+                       return ci;
+               }
+
+               // else re-key things
+               root["_l"] = l;
+               ci = -1;
+               for(var te = root["firstElementChild"]||root["firstChild"]; te; te = te[_ns]){
+                       if(_simpleNodeTest(te)){
+                               te["_i"] = ++i;
+                               if(node === te){
+                                       // NOTE:
+                                       //      shortcutting the return at this step in indexing works
+                                       //      very well for benchmarking but we avoid it here since
+                                       //      it leads to potential O(n^2) behavior in sequential
+                                       //      getNodexIndex operations on a previously un-indexed
+                                       //      parent. We may revisit this at a later time, but for
+                                       //      now we just want to get the right answer more often
+                                       //      than not.
+                                       ci = i;
+                               }
+                       }
+               }
+               return ci;
+       };
 
-               var childNodes = dojo.query("> *", this.containerNode).filter(function(node){
-                               return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
-                       }),
-                       childWidgetNodes = childNodes.filter(function(node){
-                               return dojo.hasAttr(node, "dojoType") || dojo.hasAttr(node, "widgetId");
-                       }),
-                       candidateWidgets = dojo.filter(childWidgetNodes.map(dijit.byNode), function(widget){
-                               return widget && widget.domNode && widget.resize;
-                       });
+       var isEven = function(elem){
+               return !((getNodeIndex(elem)) % 2);
+       };
 
-               if(
-                       // all child nodes are widgets
-                       childNodes.length == childWidgetNodes.length &&
+       var isOdd = function(elem){
+               return ((getNodeIndex(elem)) % 2);
+       };
 
-                       // all but one are invisible (like dojo.data)
-                       candidateWidgets.length == 1
-               ){
-                       this._singleChild = candidateWidgets[0];
-               }else{
-                       delete this._singleChild;
+       var pseudos = {
+               "checked": function(name, condition){
+                       return function(elem){
+                               return !!("checked" in elem ? elem.checked : elem.selected);
+                       }
+               },
+               "first-child": function(){ return _lookLeft; },
+               "last-child": function(){ return _lookRight; },
+               "only-child": function(name, condition){
+                       return function(node){
+                               return _lookLeft(node) && _lookRight(node);
+                       };
+               },
+               "empty": function(name, condition){
+                       return function(elem){
+                               // DomQuery and jQuery get this wrong, oddly enough.
+                               // The CSS 3 selectors spec is pretty explicit about it, too.
+                               var cn = elem.childNodes;
+                               var cnl = elem.childNodes.length;
+                               // if(!cnl){ return true; }
+                               for(var x=cnl-1; x >= 0; x--){
+                                       var nt = cn[x].nodeType;
+                                       if((nt === 1)||(nt == 3)){ return false; }
+                               }
+                               return true;
+                       }
+               },
+               "contains": function(name, condition){
+                       var cz = condition.charAt(0);
+                       if( cz == '"' || cz == "'" ){ //remove quote
+                               condition = condition.slice(1, -1);
+                       }
+                       return function(elem){
+                               return (elem.innerHTML.indexOf(condition) >= 0);
+                       }
+               },
+               "not": function(name, condition){
+                       var p = getQueryParts(condition)[0];
+                       var ignores = { el: 1 };
+                       if(p.tag != "*"){
+                               ignores.tag = 1;
+                       }
+                       if(!p.classes.length){
+                               ignores.classes = 1;
+                       }
+                       var ntf = getSimpleFilterFunc(p, ignores);
+                       return function(elem){
+                               return (!ntf(elem));
+                       }
+               },
+               "nth-child": function(name, condition){
+                       var pi = parseInt;
+                       // avoid re-defining function objects if we can
+                       if(condition == "odd"){
+                               return isOdd;
+                       }else if(condition == "even"){
+                               return isEven;
+                       }
+                       // FIXME: can we shorten this?
+                       if(condition.indexOf("n") != -1){
+                               var tparts = condition.split("n", 2);
+                               var pred = tparts[0] ? ((tparts[0] == '-') ? -1 : pi(tparts[0])) : 1;
+                               var idx = tparts[1] ? pi(tparts[1]) : 0;
+                               var lb = 0, ub = -1;
+                               if(pred > 0){
+                                       if(idx < 0){
+                                               idx = (idx % pred) && (pred + (idx % pred));
+                                       }else if(idx>0){
+                                               if(idx >= pred){
+                                                       lb = idx - idx % pred;
+                                               }
+                                               idx = idx % pred;
+                                       }
+                               }else if(pred<0){
+                                       pred *= -1;
+                                       // idx has to be greater than 0 when pred is negative;
+                                       // shall we throw an error here?
+                                       if(idx > 0){
+                                               ub = idx;
+                                               idx = idx % pred;
+                                       }
+                               }
+                               if(pred > 0){
+                                       return function(elem){
+                                               var i = getNodeIndex(elem);
+                                               return (i>=lb) && (ub<0 || i<=ub) && ((i % pred) == idx);
+                                       }
+                               }else{
+                                       condition = idx;
+                               }
+                       }
+                       var ncount = pi(condition);
+                       return function(elem){
+                               return (getNodeIndex(elem) == ncount);
+                       }
                }
+       };
 
-               // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
-               dojo.toggleClass(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
-       },
+       var defaultGetter = (dojo.isIE && (dojo.isIE < 9 || dojo.isQuirks)) ? function(cond){
+               var clc = cond.toLowerCase();
+               if(clc == "class"){ cond = "className"; }
+               return function(elem){
+                       return (caseSensitive ? elem.getAttribute(cond) : elem[cond]||elem[clc]);
+               }
+       } : function(cond){
+               return function(elem){
+                       return (elem && elem.getAttribute && elem.hasAttribute(cond));
+               }
+       };
 
-       setHref: function(/*String|Uri*/ href){
-               // summary:
-               //              Deprecated.   Use set('href', ...) instead.
-               dojo.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0");
-               return this.set("href", href);
-       },
-       _setHrefAttr: function(/*String|Uri*/ href){
-               // summary:
-               //              Hook so attr("href", ...) works.
-               // description:
-               //              Reset the (external defined) content of this pane and replace with new url
-               //              Note: It delays the download until widget is shown if preload is false.
-               //      href:
-               //              url to the page you want to get, must be within the same domain as your mainpage
+       var getSimpleFilterFunc = function(query, ignores){
+               // generates a node tester function based on the passed query part. The
+               // query part is one of the structures generated by the query parser
+               // when it creates the query AST. The "ignores" object specifies which
+               // (if any) tests to skip, allowing the system to avoid duplicating
+               // work where it may have already been taken into account by other
+               // factors such as how the nodes to test were fetched in the first
+               // place
+               if(!query){ return yesman; }
+               ignores = ignores||{};
 
-               // Cancel any in-flight requests (an attr('href') will cancel any in-flight attr('href', ...))
-               this.cancel();
+               var ff = null;
 
-               this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
+               if(!("el" in ignores)){
+                       ff = agree(ff, _isElement);
+               }
 
-               this.href = href;
+               if(!("tag" in ignores)){
+                       if(query.tag != "*"){
+                               ff = agree(ff, function(elem){
+                                       return (elem && (elem.tagName == query.getTag()));
+                               });
+                       }
+               }
 
-               // _setHrefAttr() is called during creation and by the user, after creation.
-               // only in the second case do we actually load the URL; otherwise it's done in startup()
-               if(this._created && (this.preload || this._isShown())){
-                       this._load();
-               }else{
-                       // Set flag to indicate that href needs to be loaded the next time the
-                       // ContentPane is made visible
-                       this._hrefChanged = true;
+               if(!("classes" in ignores)){
+                       each(query.classes, function(cname, idx, arr){
+                               // get the class name
+                               /*
+                               var isWildcard = cname.charAt(cname.length-1) == "*";
+                               if(isWildcard){
+                                       cname = cname.substr(0, cname.length-1);
+                               }
+                               // I dislike the regex thing, even if memoized in a cache, but it's VERY short
+                               var re = new RegExp("(?:^|\\s)" + cname + (isWildcard ? ".*" : "") + "(?:\\s|$)");
+                               */
+                               var re = new RegExp("(?:^|\\s)" + cname + "(?:\\s|$)");
+                               ff = agree(ff, function(elem){
+                                       return re.test(elem.className);
+                               });
+                               ff.count = idx;
+                       });
                }
 
-               return this.onLoadDeferred;             // dojo.Deferred
-       },
+               if(!("pseudos" in ignores)){
+                       each(query.pseudos, function(pseudo){
+                               var pn = pseudo.name;
+                               if(pseudos[pn]){
+                                       ff = agree(ff, pseudos[pn](pn, pseudo.value));
+                               }
+                       });
+               }
 
-       setContent: function(/*String|DomNode|Nodelist*/data){
-               // summary:
-               //              Deprecated.   Use set('content', ...) instead.
-               dojo.deprecated("dijit.layout.ContentPane.setContent() is deprecated.  Use set('content', ...) instead.", "", "2.0");
-               this.set("content", data);
-       },
-       _setContentAttr: function(/*String|DomNode|Nodelist*/data){
-               // summary:
-               //              Hook to make attr("content", ...) work.
-               //              Replaces old content with data content, include style classes from old content
-               //      data:
-               //              the new Content may be String, DomNode or NodeList
-               //
-               //              if data is a NodeList (or an array of nodes) nodes are copied
-               //              so you can import nodes from another document implicitly
+               if(!("attrs" in ignores)){
+                       each(query.attrs, function(attr){
+                               var matcher;
+                               var a = attr.attr;
+                               // type, attr, matchFor
+                               if(attr.type && attrs[attr.type]){
+                                       matcher = attrs[attr.type](a, attr.matchFor);
+                               }else if(a.length){
+                                       matcher = defaultGetter(a);
+                               }
+                               if(matcher){
+                                       ff = agree(ff, matcher);
+                               }
+                       });
+               }
 
-               // clear href so we can't run refresh and clear content
-               // refresh should only work if we downloaded the content
-               this.href = "";
+               if(!("id" in ignores)){
+                       if(query.id){
+                               ff = agree(ff, function(elem){
+                                       return (!!elem && (elem.id == query.id));
+                               });
+                       }
+               }
 
-               // Cancel any in-flight requests (an attr('content') will cancel any in-flight attr('href', ...))
-               this.cancel();
+               if(!ff){
+                       if(!("default" in ignores)){
+                               ff = yesman;
+                       }
+               }
+               return ff;
+       };
 
-               // Even though user is just setting content directly, still need to define an onLoadDeferred
-               // because the _onLoadHandler() handler is still getting called from setContent()
-               this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
+       var _nextSibling = function(filterFunc){
+               return function(node, ret, bag){
+                       while(node = node[_ns]){
+                               if(_noNES && (!_isElement(node))){ continue; }
+                               if(
+                                       (!bag || _isUnique(node, bag)) &&
+                                       filterFunc(node)
+                               ){
+                                       ret.push(node);
+                               }
+                               break;
+                       }
+                       return ret;
+               }
+       };
 
-               this._setContent(data || "");
+       var _nextSiblings = function(filterFunc){
+               return function(root, ret, bag){
+                       var te = root[_ns];
+                       while(te){
+                               if(_simpleNodeTest(te)){
+                                       if(bag && !_isUnique(te, bag)){
+                                               break;
+                                       }
+                                       if(filterFunc(te)){
+                                               ret.push(te);
+                                       }
+                               }
+                               te = te[_ns];
+                       }
+                       return ret;
+               }
+       };
 
-               this._isDownloaded = false; // mark that content is from a attr('content') not an attr('href')
+       // get an array of child *elements*, skipping text and comment nodes
+       var _childElements = function(filterFunc){
+               filterFunc = filterFunc||yesman;
+               return function(root, ret, bag){
+                       // get an array of child elements, skipping text and comment nodes
+                       var te, x = 0, tret = root.children || root.childNodes;
+                       while(te = tret[x++]){
+                               if(
+                                       _simpleNodeTest(te) &&
+                                       (!bag || _isUnique(te, bag)) &&
+                                       (filterFunc(te, x))
+                               ){
+                                       ret.push(te);
+                               }
+                       }
+                       return ret;
+               };
+       };
 
-               return this.onLoadDeferred;     // dojo.Deferred
-       },
-       _getContentAttr: function(){
-               // summary:
-               //              Hook to make attr("content") work
-               return this.containerNode.innerHTML;
-       },
+       /*
+       // thanks, Dean!
+       var itemIsAfterRoot = d.isIE ? function(item, root){
+               return (item.sourceIndex > root.sourceIndex);
+       } : function(item, root){
+               return (item.compareDocumentPosition(root) == 2);
+       };
+       */
 
-       cancel: function(){
-               // summary:
-               //              Cancels an in-flight download of content
-               if(this._xhrDfd && (this._xhrDfd.fired == -1)){
-                       this._xhrDfd.cancel();
+       // test to see if node is below root
+       var _isDescendant = function(node, root){
+               var pn = node.parentNode;
+               while(pn){
+                       if(pn == root){
+                               break;
+                       }
+                       pn = pn.parentNode;
                }
-               delete this._xhrDfd; // garbage collect
+               return !!pn;
+       };
 
-               this.onLoadDeferred = null;
-       },
-
-       uninitialize: function(){
-               if(this._beingDestroyed){
-                       this.cancel();
-               }
-               this.inherited(arguments);
-       },
+       var _getElementsFuncCache = {};
+
+       var getElementsFunc = function(query){
+               var retFunc = _getElementsFuncCache[query.query];
+               // if we've got a cached dispatcher, just use that
+               if(retFunc){ return retFunc; }
+               // else, generate a new on
+
+               // NOTE:
+               //              this function returns a function that searches for nodes and
+               //              filters them.  The search may be specialized by infix operators
+               //              (">", "~", or "+") else it will default to searching all
+               //              descendants (the " " selector). Once a group of children is
+               //              found, a test function is applied to weed out the ones we
+               //              don't want. Many common cases can be fast-pathed. We spend a
+               //              lot of cycles to create a dispatcher that doesn't do more work
+               //              than necessary at any point since, unlike this function, the
+               //              dispatchers will be called every time. The logic of generating
+               //              efficient dispatchers looks like this in pseudo code:
+               //
+               //              # if it's a purely descendant query (no ">", "+", or "~" modifiers)
+               //              if infixOperator == " ":
+               //                      if only(id):
+               //                              return def(root):
+               //                                      return d.byId(id, root);
+               //
+               //                      elif id:
+               //                              return def(root):
+               //                                      return filter(d.byId(id, root));
+               //
+               //                      elif cssClass && getElementsByClassName:
+               //                              return def(root):
+               //                                      return filter(root.getElementsByClassName(cssClass));
+               //
+               //                      elif only(tag):
+               //                              return def(root):
+               //                                      return root.getElementsByTagName(tagName);
+               //
+               //                      else:
+               //                              # search by tag name, then filter
+               //                              return def(root):
+               //                                      return filter(root.getElementsByTagName(tagName||"*"));
+               //
+               //              elif infixOperator == ">":
+               //                      # search direct children
+               //                      return def(root):
+               //                              return filter(root.children);
+               //
+               //              elif infixOperator == "+":
+               //                      # search next sibling
+               //                      return def(root):
+               //                              return filter(root.nextElementSibling);
+               //
+               //              elif infixOperator == "~":
+               //                      # search rightward siblings
+               //                      return def(root):
+               //                              return filter(nextSiblings(root));
+
+               var io = query.infixOper;
+               var oper = (io ? io.oper : "");
+               // the default filter func which tests for all conditions in the query
+               // part. This is potentially inefficient, so some optimized paths may
+               // re-define it to test fewer things.
+               var filterFunc = getSimpleFilterFunc(query, { el: 1 });
+               var qt = query.tag;
+               var wildcardTag = ("*" == qt);
+               var ecs = getDoc()["getElementsByClassName"];
+
+               if(!oper){
+                       // if there's no infix operator, then it's a descendant query. ID
+                       // and "elements by class name" variants can be accelerated so we
+                       // call them out explicitly:
+                       if(query.id){
+                               // testing shows that the overhead of yesman() is acceptable
+                               // and can save us some bytes vs. re-defining the function
+                               // everywhere.
+                               filterFunc = (!query.loops && wildcardTag) ?
+                                       yesman :
+                                       getSimpleFilterFunc(query, { el: 1, id: 1 });
+
+                               retFunc = function(root, arr){
+                                       var te = dom.byId(query.id, (root.ownerDocument||root));
+                                       if(!te || !filterFunc(te)){ return; }
+                                       if(9 == root.nodeType){ // if root's a doc, we just return directly
+                                               return getArr(te, arr);
+                                       }else{ // otherwise check ancestry
+                                               if(_isDescendant(te, root)){
+                                                       return getArr(te, arr);
+                                               }
+                                       }
+                               }
+                       }else if(
+                               ecs &&
+                               // isAlien check. Workaround for Prototype.js being totally evil/dumb.
+                               /\{\s*\[native code\]\s*\}/.test(String(ecs)) &&
+                               query.classes.length &&
+                               !cssCaseBug
+                       ){
+                               // it's a class-based query and we've got a fast way to run it.
+
+                               // ignore class and ID filters since we will have handled both
+                               filterFunc = getSimpleFilterFunc(query, { el: 1, classes: 1, id: 1 });
+                               var classesString = query.classes.join(" ");
+                               retFunc = function(root, arr, bag){
+                                       var ret = getArr(0, arr), te, x=0;
+                                       var tret = root.getElementsByClassName(classesString);
+                                       while((te = tret[x++])){
+                                               if(filterFunc(te, root) && _isUnique(te, bag)){
+                                                       ret.push(te);
+                                               }
+                                       }
+                                       return ret;
+                               };
 
-       destroyRecursive: function(/*Boolean*/ preserveDom){
-               // summary:
-               //              Destroy the ContentPane and its contents
+                       }else if(!wildcardTag && !query.loops){
+                               // it's tag only. Fast-path it.
+                               retFunc = function(root, arr, bag){
+                                       var ret = getArr(0, arr), te, x=0;
+                                       var tret = root.getElementsByTagName(query.getTag());
+                                       while((te = tret[x++])){
+                                               if(_isUnique(te, bag)){
+                                                       ret.push(te);
+                                               }
+                                       }
+                                       return ret;
+                               };
+                       }else{
+                               // the common case:
+                               //              a descendant selector without a fast path. By now it's got
+                               //              to have a tag selector, even if it's just "*" so we query
+                               //              by that and filter
+                               filterFunc = getSimpleFilterFunc(query, { el: 1, tag: 1, id: 1 });
+                               retFunc = function(root, arr, bag){
+                                       var ret = getArr(0, arr), te, x=0;
+                                       // we use getTag() to avoid case sensitivity issues
+                                       var tret = root.getElementsByTagName(query.getTag());
+                                       while((te = tret[x++])){
+                                               if(filterFunc(te, root) && _isUnique(te, bag)){
+                                                       ret.push(te);
+                                               }
+                                       }
+                                       return ret;
+                               };
+                       }
+               }else{
+                       // the query is scoped in some way. Instead of querying by tag we
+                       // use some other collection to find candidate nodes
+                       var skipFilters = { el: 1 };
+                       if(wildcardTag){
+                               skipFilters.tag = 1;
+                       }
+                       filterFunc = getSimpleFilterFunc(query, skipFilters);
+                       if("+" == oper){
+                               retFunc = _nextSibling(filterFunc);
+                       }else if("~" == oper){
+                               retFunc = _nextSiblings(filterFunc);
+                       }else if(">" == oper){
+                               retFunc = _childElements(filterFunc);
+                       }
+               }
+               // cache it and return
+               return _getElementsFuncCache[query.query] = retFunc;
+       };
 
-               // if we have multiple controllers destroying us, bail after the first
-               if(this._beingDestroyed){
-                       return;
+       var filterDown = function(root, queryParts){
+               // NOTE:
+               //              this is the guts of the DOM query system. It takes a list of
+               //              parsed query parts and a root and finds children which match
+               //              the selector represented by the parts
+               var candidates = getArr(root), qp, x, te, qpl = queryParts.length, bag, ret;
+
+               for(var i = 0; i < qpl; i++){
+                       ret = [];
+                       qp = queryParts[i];
+                       x = candidates.length - 1;
+                       if(x > 0){
+                               // if we have more than one root at this level, provide a new
+                               // hash to use for checking group membership but tell the
+                               // system not to post-filter us since we will already have been
+                               // gauranteed to be unique
+                               bag = {};
+                               ret.nozip = true;
+                       }
+                       var gef = getElementsFunc(qp);
+                       for(var j = 0; (te = candidates[j]); j++){
+                               // for every root, get the elements that match the descendant
+                               // selector, adding them to the "ret" array and filtering them
+                               // via membership in this level's bag. If there are more query
+                               // parts, then this level's return will be used as the next
+                               // level's candidates
+                               gef(te, ret, bag);
+                       }
+                       if(!ret.length){ break; }
+                       candidates = ret;
                }
-               this.inherited(arguments);
-       },
+               return ret;
+       };
 
-       resize: function(changeSize, resultSize){
-               // summary:
-               //              See `dijit.layout._LayoutWidget.resize` for description.
-               //              Although ContentPane doesn't extend _LayoutWidget, it does implement
-               //              the same API.
+       ////////////////////////////////////////////////////////////////////////
+       // the query runner
+       ////////////////////////////////////////////////////////////////////////
 
-               // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
-               // never called, so resize() is our trigger to do the initial href download.
-               if(!this._wasShown){
-                       this._onShow();
-               }
+       // these are the primary caches for full-query results. The query
+       // dispatcher functions are generated then stored here for hash lookup in
+       // the future
+       var _queryFuncCacheDOM = {},
+               _queryFuncCacheQSA = {};
 
-               this._resizeCalled = true;
+       // this is the second level of spliting, from full-length queries (e.g.,
+       // "div.foo .bar") into simple query expressions (e.g., ["div.foo",
+       // ".bar"])
+       var getStepQueryFunc = function(query){
+               var qparts = getQueryParts(trim(query));
 
-               // Set margin box size, unless it wasn't specified, in which case use current size.
-               if(changeSize){
-                       dojo.marginBox(this.domNode, changeSize);
+               // if it's trivial, avoid iteration and zipping costs
+               if(qparts.length == 1){
+                       // we optimize this case here to prevent dispatch further down the
+                       // chain, potentially slowing things down. We could more elegantly
+                       // handle this in filterDown(), but it's slower for simple things
+                       // that need to be fast (e.g., "#someId").
+                       var tef = getElementsFunc(qparts[0]);
+                       return function(root){
+                               var r = tef(root, []);
+                               if(r){ r.nozip = true; }
+                               return r;
+                       }
                }
 
-               // Compute content box size of containerNode in case we [later] need to size our single child.
-               var cn = this.containerNode;
-               if(cn === this.domNode){
-                       // If changeSize or resultSize was passed to this method and this.containerNode ==
-                       // this.domNode then we can compute the content-box size without querying the node,
-                       // which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
-                       var mb = resultSize || {};
-                       dojo.mixin(mb, changeSize || {}); // changeSize overrides resultSize
-                       if(!("h" in mb) || !("w" in mb)){
-                               mb = dojo.mixin(dojo.marginBox(cn), mb); // just use dojo.marginBox() to fill in missing values
-                       }
-                       this._contentBox = dijit.layout.marginBox2contentBox(cn, mb);
-               }else{
-                       this._contentBox = dojo.contentBox(cn);
+               // otherwise, break it up and return a runner that iterates over the parts recursively
+               return function(root){
+                       return filterDown(root, qparts);
                }
+       };
 
-               // Make my children layout, or size my single child widget
-               this._layoutChildren();
-       },
+       // NOTES:
+       //      * we can't trust QSA for anything but document-rooted queries, so
+       //        caching is split into DOM query evaluators and QSA query evaluators
+       //      * caching query results is dirty and leak-prone (or, at a minimum,
+       //        prone to unbounded growth). Other toolkits may go this route, but
+       //        they totally destroy their own ability to manage their memory
+       //        footprint. If we implement it, it should only ever be with a fixed
+       //        total element reference # limit and an LRU-style algorithm since JS
+       //        has no weakref support. Caching compiled query evaluators is also
+       //        potentially problematic, but even on large documents the size of the
+       //        query evaluators is often < 100 function objects per evaluator (and
+       //        LRU can be applied if it's ever shown to be an issue).
+       //      * since IE's QSA support is currently only for HTML documents and even
+       //        then only in IE 8's "standards mode", we have to detect our dispatch
+       //        route at query time and keep 2 separate caches. Ugg.
+
+       // we need to determine if we think we can run a given query via
+       // querySelectorAll or if we'll need to fall back on DOM queries to get
+       // there. We need a lot of information about the environment and the query
+       // to make the determiniation (e.g. does it support QSA, does the query in
+       // question work in the native QSA impl, etc.).
+       var nua = navigator.userAgent;
+       // some versions of Safari provided QSA, but it was buggy and crash-prone.
+       // We need te detect the right "internal" webkit version to make this work.
+       var wk = "WebKit/";
+       var is525 = (
+               dojo.isWebKit &&
+               (nua.indexOf(wk) > 0) &&
+               (parseFloat(nua.split(wk)[1]) > 528)
+       );
 
-       _isShown: function(){
-               // summary:
-               //              Returns true if the content is currently shown.
-               // description:
-               //              If I am a child of a layout widget then it actually returns true if I've ever been visible,
-               //              not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
-               //              tree every call, and at least solves the performance problem on page load by deferring loading
-               //              hidden ContentPanes until they are first shown
+       // IE QSA queries may incorrectly include comment nodes, so we throw the
+       // zipping function into "remove" comments mode instead of the normal "skip
+       // it" which every other QSA-clued browser enjoys
+       var noZip = dojo.isIE ? "commentStrip" : "nozip";
 
-               if(this._childOfLayoutWidget){
-                       // If we are TitlePane, etc - we return that only *IF* we've been resized
-                       if(this._resizeCalled && "open" in this){
-                               return this.open;
-                       }
-                       return this._resizeCalled;
-               }else if("open" in this){
-                       return this.open;               // for TitlePane, etc.
-               }else{
-                       // TODO: with _childOfLayoutWidget check maybe this branch no longer necessary?
-                       var node = this.domNode;
-                       return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !dojo.hasClass(node, "dijitHidden");
-               }
-       },
+       var qsa = "querySelectorAll";
+       var qsaAvail = (
+               !!getDoc()[qsa] &&
+               // see #5832
+               (!dojo.isSafari || (dojo.isSafari > 3.1) || is525 )
+       );
 
-       _onShow: function(){
-               // summary:
-               //              Called when the ContentPane is made visible
-               // description:
-               //              For a plain ContentPane, this is called on initialization, from startup().
-               //              If the ContentPane is a hidden pane of a TabContainer etc., then it's
-               //              called whenever the pane is made visible.
-               //
-               //              Does necessary processing, including href download and layout/resize of
-               //              child widget(s)
+       //Don't bother with n+3 type of matches, IE complains if we modify those.
+       var infixSpaceRe = /n\+\d|([^ ])?([>~+])([^ =])?/g;
+       var infixSpaceFunc = function(match, pre, ch, post){
+               return ch ? (pre ? pre + " " : "") + ch + (post ? " " + post : "") : /*n+3*/ match;
+       };
 
-               if(this.href){
-                       if(!this._xhrDfd && // if there's an href that isn't already being loaded
-                               (!this.isLoaded || this._hrefChanged || this.refreshOnShow)
-                       ){
-                               this.refresh();
-                       }
-               }else{
-                       // If we are the child of a layout widget then the layout widget will call resize() on
-                       // us, and then we will size our child/children.   Otherwise, we need to do it now.
-                       if(!this._childOfLayoutWidget && this._needLayout){
-                               // If a layout has been scheduled for when we become visible, do it now
-                               this._layoutChildren();
-                       }
+       var getQueryFunc = function(query, forceDOM){
+               //Normalize query. The CSS3 selectors spec allows for omitting spaces around
+               //infix operators, >, ~ and +
+               //Do the work here since detection for spaces is used as a simple "not use QSA"
+               //test below.
+               query = query.replace(infixSpaceRe, infixSpaceFunc);
+
+               if(qsaAvail){
+                       // if we've got a cached variant and we think we can do it, run it!
+                       var qsaCached = _queryFuncCacheQSA[query];
+                       if(qsaCached && !forceDOM){ return qsaCached; }
                }
 
-               this.inherited(arguments);
+               // else if we've got a DOM cached variant, assume that we already know
+               // all we need to and use it
+               var domCached = _queryFuncCacheDOM[query];
+               if(domCached){ return domCached; }
 
-               // Need to keep track of whether ContentPane has been shown (which is different than
-               // whether or not it's currently visible).
-               this._wasShown = true;
-       },
+               // TODO:
+               //              today we're caching DOM and QSA branches separately so we
+               //              recalc useQSA every time. If we had a way to tag root+query
+               //              efficiently, we'd be in good shape to do a global cache.
+
+               var qcz = query.charAt(0);
+               var nospace = (-1 == query.indexOf(" "));
+
+               // byId searches are wicked fast compared to QSA, even when filtering
+               // is required
+               if( (query.indexOf("#") >= 0) && (nospace) ){
+                       forceDOM = true;
+               }
+
+               var useQSA = (
+                       qsaAvail && (!forceDOM) &&
+                       // as per CSS 3, we can't currently start w/ combinator:
+                       //              http://www.w3.org/TR/css3-selectors/#w3cselgrammar
+                       (specials.indexOf(qcz) == -1) &&
+                       // IE's QSA impl sucks on pseudos
+                       (!dojo.isIE || (query.indexOf(":") == -1)) &&
+
+                       (!(cssCaseBug && (query.indexOf(".") >= 0))) &&
+
+                       // FIXME:
+                       //              need to tighten up browser rules on ":contains" and "|=" to
+                       //              figure out which aren't good
+                       //              Latest webkit (around 531.21.8) does not seem to do well with :checked on option
+                       //              elements, even though according to spec, selected options should
+                       //              match :checked. So go nonQSA for it:
+                       //              http://bugs.dojotoolkit.org/ticket/5179
+                       (query.indexOf(":contains") == -1) && (query.indexOf(":checked") == -1) &&
+                       (query.indexOf("|=") == -1) // some browsers don't grok it
+               );
 
-       refresh: function(){
-               // summary:
-               //              [Re]download contents of href and display
-               // description:
-               //              1. cancels any currently in-flight requests
-               //              2. posts "loading..." message
-               //              3. sends XHR to download new data
+               // TODO:
+               //              if we've got a descendant query (e.g., "> .thinger" instead of
+               //              just ".thinger") in a QSA-able doc, but are passed a child as a
+               //              root, it should be possible to give the item a synthetic ID and
+               //              trivially rewrite the query to the form "#synid > .thinger" to
+               //              use the QSA branch
 
-               // Cancel possible prior in-flight request
-               this.cancel();
 
-               this.onLoadDeferred = new dojo.Deferred(dojo.hitch(this, "cancel"));
-               this._load();
-               return this.onLoadDeferred;
-       },
+               if(useQSA){
+                       var tq = (specials.indexOf(query.charAt(query.length-1)) >= 0) ?
+                                               (query + " *") : query;
+                       return _queryFuncCacheQSA[query] = function(root){
+                               try{
+                                       // the QSA system contains an egregious spec bug which
+                                       // limits us, effectively, to only running QSA queries over
+                                       // entire documents.  See:
+                                       //              http://ejohn.org/blog/thoughts-on-queryselectorall/
+                                       //      despite this, we can also handle QSA runs on simple
+                                       //      selectors, but we don't want detection to be expensive
+                                       //      so we're just checking for the presence of a space char
+                                       //      right now. Not elegant, but it's cheaper than running
+                                       //      the query parser when we might not need to
+                                       if(!((9 == root.nodeType) || nospace)){ throw ""; }
+                                       var r = root[qsa](tq);
+                                       // skip expensive duplication checks and just wrap in a NodeList
+                                       r[noZip] = true;
+                                       return r;
+                               }catch(e){
+                                       // else run the DOM branch on this query, ensuring that we
+                                       // default that way in the future
+                                       return getQueryFunc(query, true)(root);
+                               }
+                       }
+               }else{
+                       // DOM branch
+                       var parts = query.split(/\s*,\s*/);
+                       return _queryFuncCacheDOM[query] = ((parts.length < 2) ?
+                               // if not a compound query (e.g., ".foo, .bar"), cache and return a dispatcher
+                               getStepQueryFunc(query) :
+                               // if it *is* a complex query, break it up into its
+                               // constituent parts and return a dispatcher that will
+                               // merge the parts when run
+                               function(root){
+                                       var pindex = 0, // avoid array alloc for every invocation
+                                               ret = [],
+                                               tp;
+                                       while((tp = parts[pindex++])){
+                                               ret = ret.concat(getStepQueryFunc(tp)(root));
+                                       }
+                                       return ret;
+                               }
+                       );
+               }
+       };
 
-       _load: function(){
-               // summary:
-               //              Load/reload the href specified in this.href
+       var _zipIdx = 0;
 
-               // display loading message
-               this._setContent(this.onDownloadStart(), true);
+       // NOTE:
+       //              this function is Moo inspired, but our own impl to deal correctly
+       //              with XML in IE
+       var _nodeUID = dojo.isIE ? function(node){
+               if(caseSensitive){
+                       // XML docs don't have uniqueID on their nodes
+                       return (node.getAttribute("_uid") || node.setAttribute("_uid", ++_zipIdx) || _zipIdx);
 
-               var self = this;
-               var getArgs = {
-                       preventCache: (this.preventCache || this.refreshOnShow),
-                       url: this.href,
-                       handleAs: "text"
-               };
-               if(dojo.isObject(this.ioArgs)){
-                       dojo.mixin(getArgs, this.ioArgs);
+               }else{
+                       return node.uniqueID;
                }
+       } :
+       function(node){
+               return (node._uid || (node._uid = ++_zipIdx));
+       };
 
-               var hand = (this._xhrDfd = (this.ioMethod || dojo.xhrGet)(getArgs));
+       // determine if a node in is unique in a "bag". In this case we don't want
+       // to flatten a list of unique items, but rather just tell if the item in
+       // question is already in the bag. Normally we'd just use hash lookup to do
+       // this for us but IE's DOM is busted so we can't really count on that. On
+       // the upside, it gives us a built in unique ID function.
+       var _isUnique = function(node, bag){
+               if(!bag){ return 1; }
+               var id = _nodeUID(node);
+               if(!bag[id]){ return bag[id] = 1; }
+               return 0;
+       };
 
-               hand.addCallback(function(html){
+       // attempt to efficiently determine if an item in a list is a dupe,
+       // returning a list of "uniques", hopefully in doucment order
+       var _zipIdxName = "_zipIdx";
+       var _zip = function(arr){
+               if(arr && arr.nozip){
+                       return arr;
+               }
+               var ret = [];
+               if(!arr || !arr.length){ return ret; }
+               if(arr[0]){
+                       ret.push(arr[0]);
+               }
+               if(arr.length < 2){ return ret; }
+
+               _zipIdx++;
+
+               // we have to fork here for IE and XML docs because we can't set
+               // expandos on their nodes (apparently). *sigh*
+               if(dojo.isIE && caseSensitive){
+                       var szidx = _zipIdx+"";
+                       arr[0].setAttribute(_zipIdxName, szidx);
+                       for(var x = 1, te; te = arr[x]; x++){
+                               if(arr[x].getAttribute(_zipIdxName) != szidx){
+                                       ret.push(te);
+                               }
+                               te.setAttribute(_zipIdxName, szidx);
+                       }
+               }else if(dojo.isIE && arr.commentStrip){
                        try{
-                               self._isDownloaded = true;
-                               self._setContent(html, false);
-                               self.onDownloadEnd();
-                       }catch(err){
-                               self._onError('Content', err); // onContentError
+                               for(var x = 1, te; te = arr[x]; x++){
+                                       if(_isElement(te)){
+                                               ret.push(te);
+                                       }
+                               }
+                       }catch(e){ /* squelch */ }
+               }else{
+                       if(arr[0]){ arr[0][_zipIdxName] = _zipIdx; }
+                       for(var x = 1, te; te = arr[x]; x++){
+                               if(arr[x][_zipIdxName] != _zipIdx){
+                                       ret.push(te);
+                               }
+                               te[_zipIdxName] = _zipIdx;
                        }
-                       delete self._xhrDfd;
-                       return html;
-               });
+               }
+               return ret;
+       };
 
-               hand.addErrback(function(err){
-                       if(!hand.canceled){
-                               // show error message in the pane
-                               self._onError('Download', err); // onDownloadError
-                       }
-                       delete self._xhrDfd;
-                       return err;
-               });
+       // the main executor
+       var query = function(/*String*/ query, /*String|DOMNode?*/ root){
+               //      summary:
+               //              Returns nodes which match the given CSS3 selector, searching the
+               //              entire document by default but optionally taking a node to scope
+               //              the search by. Returns an array.
+               //      description:
+               //              dojo.query() is the swiss army knife of DOM node manipulation in
+               //              Dojo. Much like Prototype's "$$" (bling-bling) function or JQuery's
+               //              "$" function, dojo.query provides robust, high-performance
+               //              CSS-based node selector support with the option of scoping searches
+               //              to a particular sub-tree of a document.
+               //
+               //              Supported Selectors:
+               //              --------------------
+               //
+               //              acme supports a rich set of CSS3 selectors, including:
+               //
+               //                      * class selectors (e.g., `.foo`)
+               //                      * node type selectors like `span`
+               //                      * ` ` descendant selectors
+               //                      * `>` child element selectors
+               //                      * `#foo` style ID selectors
+               //                      * `*` universal selector
+               //                      * `~`, the preceded-by sibling selector
+               //                      * `+`, the immediately preceded-by sibling selector
+               //                      * attribute queries:
+               //                      |       * `[foo]` attribute presence selector
+               //                      |       * `[foo='bar']` attribute value exact match
+               //                      |       * `[foo~='bar']` attribute value list item match
+               //                      |       * `[foo^='bar']` attribute start match
+               //                      |       * `[foo$='bar']` attribute end match
+               //                      |       * `[foo*='bar']` attribute substring match
+               //                      * `:first-child`, `:last-child`, and `:only-child` positional selectors
+               //                      * `:empty` content emtpy selector
+               //                      * `:checked` pseudo selector
+               //                      * `:nth-child(n)`, `:nth-child(2n+1)` style positional calculations
+               //                      * `:nth-child(even)`, `:nth-child(odd)` positional selectors
+               //                      * `:not(...)` negation pseudo selectors
+               //
+               //              Any legal combination of these selectors will work with
+               //              `dojo.query()`, including compound selectors ("," delimited).
+               //              Very complex and useful searches can be constructed with this
+               //              palette of selectors and when combined with functions for
+               //              manipulation presented by dojo.NodeList, many types of DOM
+               //              manipulation operations become very straightforward.
+               //
+               //              Unsupported Selectors:
+               //              ----------------------
+               //
+               //              While dojo.query handles many CSS3 selectors, some fall outside of
+               //              what's reasonable for a programmatic node querying engine to
+               //              handle. Currently unsupported selectors include:
+               //
+               //                      * namespace-differentiated selectors of any form
+               //                      * all `::` pseduo-element selectors
+               //                      * certain pseduo-selectors which don't get a lot of day-to-day use:
+               //                      |       * `:root`, `:lang()`, `:target`, `:focus`
+               //                      * all visual and state selectors:
+               //                      |       * `:root`, `:active`, `:hover`, `:visisted`, `:link`,
+               //                                `:enabled`, `:disabled`
+               //                      * `:*-of-type` pseudo selectors
+               //
+               //              dojo.query and XML Documents:
+               //              -----------------------------
+               //
+               //              `dojo.query` (as of dojo 1.2) supports searching XML documents
+               //              in a case-sensitive manner. If an HTML document is served with
+               //              a doctype that forces case-sensitivity (e.g., XHTML 1.1
+               //              Strict), dojo.query() will detect this and "do the right
+               //              thing". Case sensitivity is dependent upon the document being
+               //              searched and not the query used. It is therefore possible to
+               //              use case-sensitive queries on strict sub-documents (iframes,
+               //              etc.) or XML documents while still assuming case-insensitivity
+               //              for a host/root document.
+               //
+               //              Non-selector Queries:
+               //              ---------------------
+               //
+               //              If something other than a String is passed for the query,
+               //              `dojo.query` will return a new `dojo.NodeList` instance
+               //              constructed from that parameter alone and all further
+               //              processing will stop. This means that if you have a reference
+               //              to a node or NodeList, you can quickly construct a new NodeList
+               //              from the original by calling `dojo.query(node)` or
+               //              `dojo.query(list)`.
+               //
+               //      query:
+               //              The CSS3 expression to match against. For details on the syntax of
+               //              CSS3 selectors, see <http://www.w3.org/TR/css3-selectors/#selectors>
+               //      root:
+               //              A DOMNode (or node id) to scope the search from. Optional.
+               //      returns: Array
+               //      example:
+               //              search the entire document for elements with the class "foo":
+               //      |       dojo.query(".foo");
+               //              these elements will match:
+               //      |       <span class="foo"></span>
+               //      |       <span class="foo bar"></span>
+               //      |       <p class="thud foo"></p>
+               //      example:
+               //              search the entire document for elements with the classes "foo" *and* "bar":
+               //      |       dojo.query(".foo.bar");
+               //              these elements will match:
+               //      |       <span class="foo bar"></span>
+               //              while these will not:
+               //      |       <span class="foo"></span>
+               //      |       <p class="thud foo"></p>
+               //      example:
+               //              find `<span>` elements which are descendants of paragraphs and
+               //              which have a "highlighted" class:
+               //      |       dojo.query("p span.highlighted");
+               //              the innermost span in this fragment matches:
+               //      |       <p class="foo">
+               //      |               <span>...
+               //      |                       <span class="highlighted foo bar">...</span>
+               //      |               </span>
+               //      |       </p>
+               //      example:
+               //              set an "odd" class on all odd table rows inside of the table
+               //              `#tabular_data`, using the `>` (direct child) selector to avoid
+               //              affecting any nested tables:
+               //      |       dojo.query("#tabular_data > tbody > tr:nth-child(odd)").addClass("odd");
+               //      example:
+               //              remove all elements with the class "error" from the document
+               //              and store them in a list:
+               //      |       var errors = dojo.query(".error").orphan();
+               //      example:
+               //              add an onclick handler to every submit button in the document
+               //              which causes the form to be sent via Ajax instead:
+               //      |       dojo.query("input[type='submit']").onclick(function(e){
+               //      |               dojo.stopEvent(e); // prevent sending the form
+               //      |               var btn = e.target;
+               //      |               dojo.xhrPost({
+               //      |                       form: btn.form,
+               //      |                       load: function(data){
+               //      |                               // replace the form with the response
+               //      |                               var div = dojo.doc.createElement("div");
+               //      |                               dojo.place(div, btn.form, "after");
+               //      |                               div.innerHTML = data;
+               //      |                               dojo.style(btn.form, "display", "none");
+               //      |                       }
+               //      |               });
+               //      |       });
 
-               // Remove flag saying that a load is needed
-               delete this._hrefChanged;
-       },
+               root = root||getDoc();
+               var od = root.ownerDocument||root.documentElement;
 
-       _onLoadHandler: function(data){
-               // summary:
-               //              This is called whenever new content is being loaded
-               this.isLoaded = true;
-               try{
-                       this.onLoadDeferred.callback(data);
-                       this.onLoad(data);
-               }catch(e){
-                       console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message);
-               }
-       },
+               // throw the big case sensitivity switch
 
-       _onUnloadHandler: function(){
-               // summary:
-               //              This is called whenever the content is being unloaded
-               this.isLoaded = false;
-               try{
-                       this.onUnload();
-               }catch(e){
-                       console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message);
-               }
-       },
+               // NOTE:
+               //              Opera in XHTML mode doesn't detect case-sensitivity correctly
+               //              and it's not clear that there's any way to test for it
+               caseSensitive = (root.contentType && root.contentType=="application/xml") ||
+                                               (dojo.isOpera && (root.doctype || od.toString() == "[object XMLDocument]")) ||
+                                               (!!od) &&
+                               (dojo.isIE ? od.xml : (root.xmlVersion || od.xmlVersion));
 
-       destroyDescendants: function(){
-               // summary:
-               //              Destroy all the widgets inside the ContentPane and empty containerNode
+               // NOTE:
+               //              adding "true" as the 2nd argument to getQueryFunc is useful for
+               //              testing the DOM branch without worrying about the
+               //              behavior/performance of the QSA branch.
+               var r = getQueryFunc(query)(root);
 
-               // Make sure we call onUnload (but only when the ContentPane has real content)
-               if(this.isLoaded){
-                       this._onUnloadHandler();
+               // FIXME:
+               //              need to investigate this branch WRT #8074 and #8075
+               if(r && r.nozip){
+                       return r;
                }
-
-               // Even if this.isLoaded == false there might still be a "Loading..." message
-               // to erase, so continue...
-
-               // For historical reasons we need to delete all widgets under this.containerNode,
-               // even ones that the user has created manually.
-               var setter = this._contentSetter;
-               dojo.forEach(this.getChildren(), function(widget){
-                       if(widget.destroyRecursive){
-                               widget.destroyRecursive();
-                       }
-               });
-               if(setter){
-                       // Most of the widgets in setter.parseResults have already been destroyed, but
-                       // things like Menu that have been moved to <body> haven't yet
-                       dojo.forEach(setter.parseResults, function(widget){
-                               if(widget.destroyRecursive && widget.domNode && widget.domNode.parentNode == dojo.body()){
-                                       widget.destroyRecursive();
-                               }
-                       });
-                       delete setter.parseResults;
+               return _zip(r); // dojo.NodeList
+       };
+       query.filter = function(/*Node[]*/ nodeList, /*String*/ filter, /*String|DOMNode?*/ root){
+               // summary:
+               //              function for filtering a NodeList based on a selector, optimized for simple selectors
+               var tmpNodeList = [],
+                       parts = getQueryParts(filter),
+                       filterFunc =
+                               (parts.length == 1 && !/[^\w#\.]/.test(filter)) ?
+                               getSimpleFilterFunc(parts[0]) :
+                               function(node){
+                                       return dojo.query(filter, root).indexOf(node) != -1;
+                               };
+               for(var x = 0, te; te = nodeList[x]; x++){
+                       if(filterFunc(te)){ tmpNodeList.push(te); }
                }
+               return tmpNodeList;
+       };
+       return query;
+});//end defineQuery
 
-               // And then clear away all the DOM nodes
-               dojo.html._emptyNode(this.containerNode);
+},
+'dojo/dnd/autoscroll':function(){
+define("dojo/dnd/autoscroll", ["../main", "../window"], function(dojo) {
+       // module:
+       //              dojo/dnd/autoscroll
+       // summary:
+       //              TODOC
 
-               // Delete any state information we have about current contents
-               delete this._singleChild;
-       },
+dojo.getObject("dnd", true, dojo);
 
-       _setContent: function(cont, isFakeContent){
-               // summary:
-               //              Insert the content into the container node
+dojo.dnd.getViewport = dojo.window.getBox;
 
-               // first get rid of child widgets
-               this.destroyDescendants();
+dojo.dnd.V_TRIGGER_AUTOSCROLL = 32;
+dojo.dnd.H_TRIGGER_AUTOSCROLL = 32;
 
-               // dojo.html.set will take care of the rest of the details
-               // we provide an override for the error handling to ensure the widget gets the errors
-               // configure the setter instance with only the relevant widget instance properties
-               // NOTE: unless we hook into attr, or provide property setters for each property,
-               // we need to re-configure the ContentSetter with each use
-               var setter = this._contentSetter;
-               if(! (setter && setter instanceof dojo.html._ContentSetter)){
-                       setter = this._contentSetter = new dojo.html._ContentSetter({
-                               node: this.containerNode,
-                               _onError: dojo.hitch(this, this._onError),
-                               onContentError: dojo.hitch(this, function(e){
-                                       // fires if a domfault occurs when we are appending this.errorMessage
-                                       // like for instance if domNode is a UL and we try append a DIV
-                                       var errMess = this.onContentError(e);
-                                       try{
-                                               this.containerNode.innerHTML = errMess;
-                                       }catch(e){
-                                               console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
-                                       }
-                               })/*,
-                               _onError */
-                       });
-               };
+dojo.dnd.V_AUTOSCROLL_VALUE = 16;
+dojo.dnd.H_AUTOSCROLL_VALUE = 16;
 
-               var setterParams = dojo.mixin({
-                       cleanContent: this.cleanContent,
-                       extractContent: this.extractContent,
-                       parseContent: this.parseOnLoad,
-                       dir: this.dir,
-                       lang: this.lang
-               }, this._contentSetterParams || {});
+dojo.dnd.autoScroll = function(e){
+       // summary:
+       //              a handler for onmousemove event, which scrolls the window, if
+       //              necesary
+       // e: Event
+       //              onmousemove event
 
-               dojo.mixin(setter, setterParams);
+       // FIXME: needs more docs!
+       var v = dojo.window.getBox(), dx = 0, dy = 0;
+       if(e.clientX < dojo.dnd.H_TRIGGER_AUTOSCROLL){
+               dx = -dojo.dnd.H_AUTOSCROLL_VALUE;
+       }else if(e.clientX > v.w - dojo.dnd.H_TRIGGER_AUTOSCROLL){
+               dx = dojo.dnd.H_AUTOSCROLL_VALUE;
+       }
+       if(e.clientY < dojo.dnd.V_TRIGGER_AUTOSCROLL){
+               dy = -dojo.dnd.V_AUTOSCROLL_VALUE;
+       }else if(e.clientY > v.h - dojo.dnd.V_TRIGGER_AUTOSCROLL){
+               dy = dojo.dnd.V_AUTOSCROLL_VALUE;
+       }
+       window.scrollBy(dx, dy);
+};
 
-               setter.set( (dojo.isObject(cont) && cont.domNode) ? cont.domNode : cont );
+dojo.dnd._validNodes = {"div": 1, "p": 1, "td": 1};
+dojo.dnd._validOverflow = {"auto": 1, "scroll": 1};
 
-               // setter params must be pulled afresh from the ContentPane each time
-               delete this._contentSetterParams;
+dojo.dnd.autoScrollNodes = function(e){
+       // summary:
+       //              a handler for onmousemove event, which scrolls the first avaialble
+       //              Dom element, it falls back to dojo.dnd.autoScroll()
+       // e: Event
+       //              onmousemove event
 
-               if(!isFakeContent){
-                       // Startup each top level child widget (and they will start their children, recursively)
-                       dojo.forEach(this.getChildren(), function(child){
-                               // The parser has already called startup on all widgets *without* a getParent() method
-                               if(!this.parseOnLoad || child.getParent){
-                                       child.startup();
-                               }
-                       }, this);
+       // FIXME: needs more docs!
 
-                       // Call resize() on each of my child layout widgets,
-                       // or resize() on my single child layout widget...
-                       // either now (if I'm currently visible)
-                       // or when I become visible
-                       this._scheduleLayout();
+       var b, t, w, h, rx, ry, dx = 0, dy = 0, oldLeft, oldTop;
 
-                       this._onLoadHandler(cont);
+       for(var n = e.target; n;){
+               if(n.nodeType == 1 && (n.tagName.toLowerCase() in dojo.dnd._validNodes)){
+                       var s = dojo.getComputedStyle(n),
+                               overflow = (s.overflow.toLowerCase() in dojo.dnd._validOverflow),
+                               overflowX = (s.overflowX.toLowerCase() in dojo.dnd._validOverflow),
+                               overflowY = (s.overflowY.toLowerCase() in dojo.dnd._validOverflow);
+                       if(overflow || overflowX || overflowY){
+                               b = dojo._getContentBox(n, s);
+                               t = dojo.position(n, true);
+                       }
+                       // overflow-x
+                       if(overflow || overflowX){
+                               w = Math.min(dojo.dnd.H_TRIGGER_AUTOSCROLL, b.w / 2);
+                               rx = e.pageX - t.x;
+                               if(dojo.isWebKit || dojo.isOpera){
+                                       // FIXME: this code should not be here, it should be taken into account
+                                       // either by the event fixing code, or the dojo.position()
+                                       // FIXME: this code doesn't work on Opera 9.5 Beta
+                                       rx += dojo.body().scrollLeft;
+                               }
+                               dx = 0;
+                               if(rx > 0 && rx < b.w){
+                                       if(rx < w){
+                                               dx = -w;
+                                       }else if(rx > b.w - w){
+                                               dx = w;
+                                       }
+                                       oldLeft = n.scrollLeft;
+                                       n.scrollLeft = n.scrollLeft + dx;
+                               }
+                       }
+                       // overflow-y
+                       if(overflow || overflowY){
+                               //console.log(b.l, b.t, t.x, t.y, n.scrollLeft, n.scrollTop);
+                               h = Math.min(dojo.dnd.V_TRIGGER_AUTOSCROLL, b.h / 2);
+                               ry = e.pageY - t.y;
+                               if(dojo.isWebKit || dojo.isOpera){
+                                       // FIXME: this code should not be here, it should be taken into account
+                                       // either by the event fixing code, or the dojo.position()
+                                       // FIXME: this code doesn't work on Opera 9.5 Beta
+                                       ry += dojo.body().scrollTop;
+                               }
+                               dy = 0;
+                               if(ry > 0 && ry < b.h){
+                                       if(ry < h){
+                                               dy = -h;
+                                       }else if(ry > b.h - h){
+                                               dy = h;
+                                       }
+                                       oldTop = n.scrollTop;
+                                       n.scrollTop  = n.scrollTop  + dy;
+                               }
+                       }
+                       if(dx || dy){ return; }
                }
-       },
-
-       _onError: function(type, err, consoleText){
-               this.onLoadDeferred.errback(err);
-
-               // shows user the string that is returned by on[type]Error
-               // overide on[type]Error and return your own string to customize
-               var errText = this['on' + type + 'Error'].call(this, err);
-               if(consoleText){
-                       console.error(consoleText, err);
-               }else if(errText){// a empty string won't change current content
-                       this._setContent(errText, true);
+               try{
+                       n = n.parentNode;
+               }catch(x){
+                       n = null;
                }
-       },
+       }
+       dojo.dnd.autoScroll(e);
+};
 
-       _scheduleLayout: function(){
-               // summary:
-               //              Call resize() on each of my child layout widgets, either now
-               //              (if I'm currently visible) or when I become visible
-               if(this._isShown()){
-                       this._layoutChildren();
-               }else{
-                       this._needLayout = true;
-               }
-       },
+       return dojo.dnd;
+});
 
-       _layoutChildren: function(){
-               // summary:
-               //              Since I am a Container widget, each of my children expects me to
-               //              call resize() or layout() on them.
-               // description:
-               //              Should be called on initialization and also whenever we get new content
-               //              (from an href, or from attr('content', ...))... but deferred until
-               //              the ContentPane is visible
+},
+'dojo/data/ItemFileWriteStore':function(){
+define("dojo/data/ItemFileWriteStore", ["../_base/lang", "../_base/declare", "../_base/array", "../_base/json", "../_base/window", 
+       "./ItemFileReadStore", "../date/stamp"
+], function(lang, declare, arrayUtil, jsonUtil, window, ItemFileReadStore, dateStamp) {
+       // module:
+       //              dojo/data/ItemFileWriteStore
+       // summary:
+       //              TODOC
 
-               if(this.doLayout){
-                       this._checkIfSingleChild();
-               }
+/*===== var ItemFileReadStore = dojo.data.ItemFileReadStore; =====*/
+return declare("dojo.data.ItemFileWriteStore", ItemFileReadStore, {
+       constructor: function(/* object */ keywordParameters){
+               //      keywordParameters: {typeMap: object)
+               //              The structure of the typeMap object is as follows:
+               //              {
+               //                      type0: function || object,
+               //                      type1: function || object,
+               //                      ...
+               //                      typeN: function || object
+               //              }
+               //              Where if it is a function, it is assumed to be an object constructor that takes the
+               //              value of _value as the initialization parameters.  It is serialized assuming object.toString()
+               //              serialization.  If it is an object, then it is assumed
+               //              to be an object of general form:
+               //              {
+               //                      type: function, //constructor.
+               //                      deserialize:    function(value) //The function that parses the value and constructs the object defined by type appropriately.
+               //                      serialize:      function(object) //The function that converts the object back into the proper file format form.
+               //              }
 
-               if(this._singleChild && this._singleChild.resize){
-                       var cb = this._contentBox || dojo.contentBox(this.containerNode);
+               // ItemFileWriteStore extends ItemFileReadStore to implement these additional dojo.data APIs
+               this._features['dojo.data.api.Write'] = true;
+               this._features['dojo.data.api.Notification'] = true;
 
-                       // note: if widget has padding this._contentBox will have l and t set,
-                       // but don't pass them to resize() or it will doubly-offset the child
-                       this._singleChild.resize({w: cb.w, h: cb.h});
-               }else{
-                       // All my child widgets are independently sized (rather than matching my size),
-                       // but I still need to call resize() on each child to make it layout.
-                       dojo.forEach(this.getChildren(), function(widget){
-                               if(widget.resize){
-                                       widget.resize();
-                               }
-                       });
+               // For keeping track of changes so that we can implement isDirty and revert
+               this._pending = {
+                       _newItems:{},
+                       _modifiedItems:{},
+                       _deletedItems:{}
+               };
+
+               if(!this._datatypeMap['Date'].serialize){
+                       this._datatypeMap['Date'].serialize = function(obj){
+                               return dateStamp.toISOString(obj, {zulu:true});
+                       };
+               }
+               //Disable only if explicitly set to false.
+               if(keywordParameters && (keywordParameters.referenceIntegrity === false)){
+                       this.referenceIntegrity = false;
                }
-               delete this._needLayout;
-       },
 
-       // EVENT's, should be overide-able
-       onLoad: function(data){
-               // summary:
-               //              Event hook, is called after everything is loaded and widgetified
-               // tags:
-               //              callback
+               // this._saveInProgress is set to true, briefly, from when save() is first called to when it completes
+               this._saveInProgress = false;
        },
 
-       onUnload: function(){
-               // summary:
-               //              Event hook, is called before old content is cleared
-               // tags:
-               //              callback
-       },
+       referenceIntegrity: true, //Flag that defaultly enabled reference integrity tracking.  This way it can also be disabled pogrammatially or declaratively.
 
-       onDownloadStart: function(){
-               // summary:
-               //              Called before download starts.
-               // description:
-               //              The string returned by this function will be the html
-               //              that tells the user we are loading something.
-               //              Override with your own function if you want to change text.
-               // tags:
-               //              extension
-               return this.loadingMessage;
+       _assert: function(/* boolean */ condition){
+               if(!condition){
+                       throw new Error("assertion failed in ItemFileWriteStore");
+               }
        },
 
-       onContentError: function(/*Error*/ error){
-               // summary:
-               //              Called on DOM faults, require faults etc. in content.
-               //
-               //              In order to display an error message in the pane, return
-               //              the error message from this method, as an HTML string.
-               //
-               //              By default (if this method is not overriden), it returns
-               //              nothing, so the error message is just printed to the console.
-               // tags:
-               //              extension
+       _getIdentifierAttribute: function(){
+               // this._assert((identifierAttribute === Number) || (dojo.isString(identifierAttribute)));
+               return this.getFeatures()['dojo.data.api.Identity'];
        },
 
-       onDownloadError: function(/*Error*/ error){
-               // summary:
-               //              Called when download error occurs.
-               //
-               //              In order to display an error message in the pane, return
-               //              the error message from this method, as an HTML string.
-               //
-               //              Default behavior (if this method is not overriden) is to display
-               //              the error message inside the pane.
-               // tags:
-               //              extension
-               return this.errorMessage;
-       },
 
-       onDownloadEnd: function(){
-               // summary:
-               //              Called when download is finished.
-               // tags:
-               //              callback
-       }
-});
+/* dojo.data.api.Write */
 
-}
+       newItem: function(/* Object? */ keywordArgs, /* Object? */ parentInfo){
+               // summary: See dojo.data.api.Write.newItem()
 
-if(!dojo._hasResource["dijit.TooltipDialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.TooltipDialog"] = true;
-dojo.provide("dijit.TooltipDialog");
+               this._assert(!this._saveInProgress);
 
+               if(!this._loadFinished){
+                       // We need to do this here so that we'll be able to find out what
+                       // identifierAttribute was specified in the data file.
+                       this._forceLoad();
+               }
 
+               if(typeof keywordArgs != "object" && typeof keywordArgs != "undefined"){
+                       throw new Error("newItem() was passed something other than an object");
+               }
+               var newIdentity = null;
+               var identifierAttribute = this._getIdentifierAttribute();
+               if(identifierAttribute === Number){
+                       newIdentity = this._arrayOfAllItems.length;
+               }else{
+                       newIdentity = keywordArgs[identifierAttribute];
+                       if(typeof newIdentity === "undefined"){
+                               throw new Error("newItem() was not passed an identity for the new item");
+                       }
+                       if(lang.isArray(newIdentity)){
+                               throw new Error("newItem() was not passed an single-valued identity");
+                       }
+               }
 
+               // make sure this identity is not already in use by another item, if identifiers were
+               // defined in the file.  Otherwise it would be the item count,
+               // which should always be unique in this case.
+               if(this._itemsByIdentity){
+                       this._assert(typeof this._itemsByIdentity[newIdentity] === "undefined");
+               }
+               this._assert(typeof this._pending._newItems[newIdentity] === "undefined");
+               this._assert(typeof this._pending._deletedItems[newIdentity] === "undefined");
 
+               var newItem = {};
+               newItem[this._storeRefPropName] = this;
+               newItem[this._itemNumPropName] = this._arrayOfAllItems.length;
+               if(this._itemsByIdentity){
+                       this._itemsByIdentity[newIdentity] = newItem;
+                       //We have to set the identifier now, otherwise we can't look it
+                       //up at calls to setValueorValues in parentInfo handling.
+                       newItem[identifierAttribute] = [newIdentity];
+               }
+               this._arrayOfAllItems.push(newItem);
 
+               //We need to construct some data for the onNew call too...
+               var pInfo = null;
 
-dojo.declare(
-               "dijit.TooltipDialog",
-               [dijit.layout.ContentPane, dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin],
-               {
-                       // summary:
-                       //              Pops up a dialog that appears like a Tooltip
-
-                       // title: String
-                       //              Description of tooltip dialog (required for a11y)
-                       title: "",
-
-                       // doLayout: [protected] Boolean
-                       //              Don't change this parameter from the default value.
-                       //              This ContentPane parameter doesn't make sense for TooltipDialog, since TooltipDialog
-                       //              is never a child of a layout container, nor can you specify the size of
-                       //              TooltipDialog in order to control the size of an inner widget.
-                       doLayout: false,
-
-                       // autofocus: Boolean
-                       //              A Toggle to modify the default focus behavior of a Dialog, which
-                       //              is to focus on the first dialog element after opening the dialog.
-                       //              False will disable autofocusing. Default: true
-                       autofocus: true,
-
-                       // baseClass: [protected] String
-                       //              The root className to use for the various states of this widget
-                       baseClass: "dijitTooltipDialog",
+               // Now we need to check to see where we want to assign this thingm if any.
+               if(parentInfo && parentInfo.parent && parentInfo.attribute){
+                       pInfo = {
+                               item: parentInfo.parent,
+                               attribute: parentInfo.attribute,
+                               oldValue: undefined
+                       };
 
-                       // _firstFocusItem: [private] [readonly] DomNode
-                       //              The pointer to the first focusable node in the dialog.
-                       //              Set by `dijit._DialogMixin._getFocusItems`.
-                       _firstFocusItem: null,
+                       //See if it is multi-valued or not and handle appropriately
+                       //Generally, all attributes are multi-valued for this store
+                       //So, we only need to append if there are already values present.
+                       var values = this.getValues(parentInfo.parent, parentInfo.attribute);
+                       if(values && values.length > 0){
+                               var tempValues = values.slice(0, values.length);
+                               if(values.length === 1){
+                                       pInfo.oldValue = values[0];
+                               }else{
+                                       pInfo.oldValue = values.slice(0, values.length);
+                               }
+                               tempValues.push(newItem);
+                               this._setValueOrValues(parentInfo.parent, parentInfo.attribute, tempValues, false);
+                               pInfo.newValue = this.getValues(parentInfo.parent, parentInfo.attribute);
+                       }else{
+                               this._setValueOrValues(parentInfo.parent, parentInfo.attribute, newItem, false);
+                               pInfo.newValue = newItem;
+                       }
+               }else{
+                       //Toplevel item, add to both top list as well as all list.
+                       newItem[this._rootItemPropName]=true;
+                       this._arrayOfTopLevelItems.push(newItem);
+               }
 
-                       // _lastFocusItem: [private] [readonly] DomNode
-                       //              The pointer to which node has focus prior to our dialog.
-                       //              Set by `dijit._DialogMixin._getFocusItems`.
-                       _lastFocusItem: null,
+               this._pending._newItems[newIdentity] = newItem;
 
-                       templateString: dojo.cache("dijit", "templates/TooltipDialog.html", "<div waiRole=\"presentation\">\n\t<div class=\"dijitTooltipContainer\" waiRole=\"presentation\">\n\t\t<div class =\"dijitTooltipContents dijitTooltipFocusNode\" dojoAttachPoint=\"containerNode\" tabindex=\"-1\" waiRole=\"dialog\"></div>\n\t</div>\n\t<div class=\"dijitTooltipConnector\" waiRole=\"presentation\"></div>\n</div>\n"),
+               //Clone over the properties to the new item
+               for(var key in keywordArgs){
+                       if(key === this._storeRefPropName || key === this._itemNumPropName){
+                               // Bummer, the user is trying to do something like
+                               // newItem({_S:"foo"}).  Unfortunately, our superclass,
+                               // ItemFileReadStore, is already using _S in each of our items
+                               // to hold private info.  To avoid a naming collision, we
+                               // need to move all our private info to some other property
+                               // of all the items/objects.  So, we need to iterate over all
+                               // the items and do something like:
+                               //    item.__S = item._S;
+                               //    item._S = undefined;
+                               // But first we have to make sure the new "__S" variable is
+                               // not in use, which means we have to iterate over all the
+                               // items checking for that.
+                               throw new Error("encountered bug in ItemFileWriteStore.newItem");
+                       }
+                       var value = keywordArgs[key];
+                       if(!lang.isArray(value)){
+                               value = [value];
+                       }
+                       newItem[key] = value;
+                       if(this.referenceIntegrity){
+                               for(var i = 0; i < value.length; i++){
+                                       var val = value[i];
+                                       if(this.isItem(val)){
+                                               this._addReferenceToMap(val, newItem, key);
+                                       }
+                               }
+                       }
+               }
+               this.onNew(newItem, pInfo); // dojo.data.api.Notification call
+               return newItem; // item
+       },
 
-                       postCreate: function(){
-                               this.inherited(arguments);
-                               this.connect(this.containerNode, "onkeypress", "_onKey");
-                               this.containerNode.title = this.title;
-                       },
+       _removeArrayElement: function(/* Array */ array, /* anything */ element){
+               var index = arrayUtil.indexOf(array, element);
+               if(index != -1){
+                       array.splice(index, 1);
+                       return true;
+               }
+               return false;
+       },
 
-                       orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ corner){
-                               // summary:
-                               //              Configure widget to be displayed in given position relative to the button.
-                               //              This is called from the dijit.popup code, and should not be called
-                               //              directly.
-                               // tags:
-                               //              protected
-                               var c = this._currentOrientClass;
-                               if(c){
-                                       dojo.removeClass(this.domNode, c);
-                               }
-                               c = "dijitTooltipAB"+(corner.charAt(1) == 'L'?"Left":"Right")+" dijitTooltip"+(corner.charAt(0) == 'T' ? "Below" : "Above");
-                               dojo.addClass(this.domNode, c);
-                               this._currentOrientClass = c;
-                       },
+       deleteItem: function(/* item */ item){
+               // summary: See dojo.data.api.Write.deleteItem()
+               this._assert(!this._saveInProgress);
+               this._assertIsItem(item);
 
-                       onOpen: function(/*Object*/ pos){
-                               // summary:
-                               //              Called when dialog is displayed.
-                               //              This is called from the dijit.popup code, and should not be called directly.
-                               // tags:
-                               //              protected
+               // Remove this item from the _arrayOfAllItems, but leave a null value in place
+               // of the item, so as not to change the length of the array, so that in newItem()
+               // we can still safely do: newIdentity = this._arrayOfAllItems.length;
+               var indexInArrayOfAllItems = item[this._itemNumPropName];
+               var identity = this.getIdentity(item);
 
-                               this.orient(this.domNode,pos.aroundCorner, pos.corner);
-                               this._onShow(); // lazy load trigger
+               //If we have reference integrity on, we need to do reference cleanup for the deleted item
+               if(this.referenceIntegrity){
+                       //First scan all the attributes of this items for references and clean them up in the map
+                       //As this item is going away, no need to track its references anymore.
 
-                               if(this.autofocus){
-                                       this._getFocusItems(this.containerNode);
-                                       dijit.focus(this._firstFocusItem);
-                               }
-                       },
+                       //Get the attributes list before we generate the backup so it
+                       //doesn't pollute the attributes list.
+                       var attributes = this.getAttributes(item);
 
-                       onClose: function(){
-                               // summary:
-                               //              Called when dialog is hidden.
-                               //              This is called from the dijit.popup code, and should not be called directly.
-                               // tags:
-                               //              protected
-                               this.onHide();
-                       },
+                       //Backup the map, we'll have to restore it potentially, in a revert.
+                       if(item[this._reverseRefMap]){
+                               item["backup_" + this._reverseRefMap] = lang.clone(item[this._reverseRefMap]);
+                       }
 
-                       _onKey: function(/*Event*/ evt){
-                               // summary:
-                               //              Handler for keyboard events
-                               // description:
-                               //              Keep keyboard focus in dialog; close dialog on escape key
-                               // tags:
-                               //              private
+                       //TODO:  This causes a reversion problem.  This list won't be restored on revert since it is
+                       //attached to the 'value'. item, not ours.  Need to back tese up somehow too.
+                       //Maybe build a map of the backup of the entries and attach it to the deleted item to be restored
+                       //later.  Or just record them and call _addReferenceToMap on them in revert.
+                       arrayUtil.forEach(attributes, function(attribute){
+                               arrayUtil.forEach(this.getValues(item, attribute), function(value){
+                                       if(this.isItem(value)){
+                                               //We have to back up all the references we had to others so they can be restored on a revert.
+                                               if(!item["backupRefs_" + this._reverseRefMap]){
+                                                       item["backupRefs_" + this._reverseRefMap] = [];
+                                               }
+                                               item["backupRefs_" + this._reverseRefMap].push({id: this.getIdentity(value), attr: attribute});
+                                               this._removeReferenceFromMap(value, item, attribute);
+                                       }
+                               }, this);
+                       }, this);
 
-                               var node = evt.target;
-                               var dk = dojo.keys;
-                               if(evt.charOrCode === dk.TAB){
-                                       this._getFocusItems(this.containerNode);
-                               }
-                               var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
-                               if(evt.charOrCode == dk.ESCAPE){
-                                       // Use setTimeout to avoid crash on IE, see #10396.
-                                       setTimeout(dojo.hitch(this, "onCancel"), 0);
-                                       dojo.stopEvent(evt);
-                               }else if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === dk.TAB){
-                                       if(!singleFocusItem){
-                                               dijit.focus(this._lastFocusItem); // send focus to last item in dialog
+                       //Next, see if we have references to this item, if we do, we have to clean them up too.
+                       var references = item[this._reverseRefMap];
+                       if(references){
+                               //Look through all the items noted as references to clean them up.
+                               for(var itemId in references){
+                                       var containingItem = null;
+                                       if(this._itemsByIdentity){
+                                               containingItem = this._itemsByIdentity[itemId];
+                                       }else{
+                                               containingItem = this._arrayOfAllItems[itemId];
                                        }
-                                       dojo.stopEvent(evt);
-                               }else if(node == this._lastFocusItem && evt.charOrCode === dk.TAB && !evt.shiftKey){
-                                       if(!singleFocusItem){
-                                               dijit.focus(this._firstFocusItem); // send focus to first item in dialog
+                                       //We have a reference to a containing item, now we have to process the
+                                       //attributes and clear all references to the item being deleted.
+                                       if(containingItem){
+                                               for(var attribute in references[itemId]){
+                                                       var oldValues = this.getValues(containingItem, attribute) || [];
+                                                       var newValues = arrayUtil.filter(oldValues, function(possibleItem){
+                                                               return !(this.isItem(possibleItem) && this.getIdentity(possibleItem) == identity);
+                                                       }, this);
+                                                       //Remove the note of the reference to the item and set the values on the modified attribute.
+                                                       this._removeReferenceFromMap(item, containingItem, attribute);
+                                                       if(newValues.length < oldValues.length){
+                                                               this._setValueOrValues(containingItem, attribute, newValues, true);
+                                                       }
+                                               }
                                        }
-                                       dojo.stopEvent(evt);
-                               }else if(evt.charOrCode === dk.TAB){
-                                       // we want the browser's default tab handling to move focus
-                                       // but we don't want the tab to propagate upwards
-                                       evt.stopPropagation();
                                }
                        }
                }
-       );
-
-}
-
-if(!dojo._hasResource["dijit.Dialog"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Dialog"] = true;
-dojo.provide("dijit.Dialog");
 
+               this._arrayOfAllItems[indexInArrayOfAllItems] = null;
 
+               item[this._storeRefPropName] = null;
+               if(this._itemsByIdentity){
+                       delete this._itemsByIdentity[identity];
+               }
+               this._pending._deletedItems[identity] = item;
 
+               //Remove from the toplevel items, if necessary...
+               if(item[this._rootItemPropName]){
+                       this._removeArrayElement(this._arrayOfTopLevelItems, item);
+               }
+               this.onDelete(item); // dojo.data.api.Notification call
+               return true;
+       },
 
+       setValue: function(/* item */ item, /* attribute-name-string */ attribute, /* almost anything */ value){
+               // summary: See dojo.data.api.Write.set()
+               return this._setValueOrValues(item, attribute, value, true); // boolean
+       },
 
+       setValues: function(/* item */ item, /* attribute-name-string */ attribute, /* array */ values){
+               // summary: See dojo.data.api.Write.setValues()
+               return this._setValueOrValues(item, attribute, values, true); // boolean
+       },
 
+       unsetAttribute: function(/* item */ item, /* attribute-name-string */ attribute){
+               // summary: See dojo.data.api.Write.unsetAttribute()
+               return this._setValueOrValues(item, attribute, [], true);
+       },
 
+       _setValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ newValueOrValues, /*boolean?*/ callOnSet){
+               this._assert(!this._saveInProgress);
 
+               // Check for valid arguments
+               this._assertIsItem(item);
+               this._assert(lang.isString(attribute));
+               this._assert(typeof newValueOrValues !== "undefined");
 
+               // Make sure the user isn't trying to change the item's identity
+               var identifierAttribute = this._getIdentifierAttribute();
+               if(attribute == identifierAttribute){
+                       throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
+               }
 
+               // To implement the Notification API, we need to make a note of what
+               // the old attribute value was, so that we can pass that info when
+               // we call the onSet method.
+               var oldValueOrValues = this._getValueOrValues(item, attribute);
 
+               var identity = this.getIdentity(item);
+               if(!this._pending._modifiedItems[identity]){
+                       // Before we actually change the item, we make a copy of it to
+                       // record the original state, so that we'll be able to revert if
+                       // the revert method gets called.  If the item has already been
+                       // modified then there's no need to do this now, since we already
+                       // have a record of the original state.
+                       var copyOfItemState = {};
+                       for(var key in item){
+                               if((key === this._storeRefPropName) || (key === this._itemNumPropName) || (key === this._rootItemPropName)){
+                                       copyOfItemState[key] = item[key];
+                               }else if(key === this._reverseRefMap){
+                                       copyOfItemState[key] = lang.clone(item[key]);
+                               }else{
+                                       copyOfItemState[key] = item[key].slice(0, item[key].length);
+                               }
+                       }
+                       // Now mark the item as dirty, and save the copy of the original state
+                       this._pending._modifiedItems[identity] = copyOfItemState;
+               }
 
+               // Okay, now we can actually change this attribute on the item
+               var success = false;
 
+               if(lang.isArray(newValueOrValues) && newValueOrValues.length === 0){
 
+                       // If we were passed an empty array as the value, that counts
+                       // as "unsetting" the attribute, so we need to remove this
+                       // attribute from the item.
+                       success = delete item[attribute];
+                       newValueOrValues = undefined; // used in the onSet Notification call below
 
-/*=====
-dijit._underlay = function(kwArgs){
-       // summary:
-       //              A shared instance of a `dijit.DialogUnderlay`
-       //
-       // description:
-       //              A shared instance of a `dijit.DialogUnderlay` created and
-       //              used by `dijit.Dialog`, though never created until some Dialog
-       //              or subclass thereof is shown.
-};
-=====*/
+                       if(this.referenceIntegrity && oldValueOrValues){
+                               var oldValues = oldValueOrValues;
+                               if(!lang.isArray(oldValues)){
+                                       oldValues = [oldValues];
+                               }
+                               for(var i = 0; i < oldValues.length; i++){
+                                       var value = oldValues[i];
+                                       if(this.isItem(value)){
+                                               this._removeReferenceFromMap(value, item, attribute);
+                                       }
+                               }
+                       }
+               }else{
+                       var newValueArray;
+                       if(lang.isArray(newValueOrValues)){
+                               // Unfortunately, it's not safe to just do this:
+                               //    newValueArray = newValueOrValues;
+                               // Instead, we need to copy the array, which slice() does very nicely.
+                               // This is so that our internal data structure won't
+                               // get corrupted if the user mucks with the values array *after*
+                               // calling setValues().
+                               newValueArray = newValueOrValues.slice(0, newValueOrValues.length);
+                       }else{
+                               newValueArray = [newValueOrValues];
+                       }
 
-dojo.declare(
-       "dijit._DialogBase",
-       [dijit._Templated, dijit.form._FormMixin, dijit._DialogMixin, dijit._CssStateMixin],
-       {
-               // summary:
-               //              A modal dialog Widget
-               //
-               // description:
-               //              Pops up a modal dialog window, blocking access to the screen
-               //              and also graying out the screen Dialog is extended from
-               //              ContentPane so it supports all the same parameters (href, etc.)
-               //
-               // example:
-               // |    <div dojoType="dijit.Dialog" href="test.html"></div>
-               //
-               // example:
-               // |    var foo = new dijit.Dialog({ title: "test dialog", content: "test content" };
-               // |    dojo.body().appendChild(foo.domNode);
-               // |    foo.startup();
-
-               templateString: dojo.cache("dijit", "templates/Dialog.html", "<div class=\"dijitDialog\" tabindex=\"-1\" waiRole=\"dialog\" waiState=\"labelledby-${id}_title\">\n\t<div dojoAttachPoint=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span dojoAttachPoint=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span dojoAttachPoint=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" dojoAttachEvent=\"onclick: onCancel\" title=\"${buttonCancel}\">\n\t\t<span dojoAttachPoint=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div dojoAttachPoint=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n"),
-               
-               baseClass: "dijitDialog",
-               
-               cssStateNodes: {
-                       closeButtonNode: "dijitDialogCloseIcon"
-               },
-
-               attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-                       title: [
-                               { node: "titleNode", type: "innerHTML" },
-                               { node: "titleBar", type: "attribute" }
-                       ],
-                       "aria-describedby":""
-               }),
-
-               // open: Boolean
-               //              True if Dialog is currently displayed on screen.
-               open: false,
-
-               // duration: Integer
-               //              The time in milliseconds it takes the dialog to fade in and out
-               duration: dijit.defaultDuration,
-
-               // refocus: Boolean
-               //              A Toggle to modify the default focus behavior of a Dialog, which
-               //              is to re-focus the element which had focus before being opened.
-               //              False will disable refocusing. Default: true
-               refocus: true,
-
-               // autofocus: Boolean
-               //              A Toggle to modify the default focus behavior of a Dialog, which
-               //              is to focus on the first dialog element after opening the dialog.
-               //              False will disable autofocusing. Default: true
-               autofocus: true,
-
-               // _firstFocusItem: [private] [readonly] DomNode
-               //              The pointer to the first focusable node in the dialog.
-               //              Set by `dijit._DialogMixin._getFocusItems`.
-               _firstFocusItem: null,
-
-               // _lastFocusItem: [private] [readonly] DomNode
-               //              The pointer to which node has focus prior to our dialog.
-               //              Set by `dijit._DialogMixin._getFocusItems`.
-               _lastFocusItem: null,
-
-               // doLayout: [protected] Boolean
-               //              Don't change this parameter from the default value.
-               //              This ContentPane parameter doesn't make sense for Dialog, since Dialog
-               //              is never a child of a layout container, nor can you specify the size of
-               //              Dialog in order to control the size of an inner widget.
-               doLayout: false,
-
-               // draggable: Boolean
-               //              Toggles the moveable aspect of the Dialog. If true, Dialog
-               //              can be dragged by it's title. If false it will remain centered
-               //              in the viewport.
-               draggable: true,
-
-               //aria-describedby: String
-               //              Allows the user to add an aria-describedby attribute onto the dialog.   The value should
-               //              be the id of the container element of text that describes the dialog purpose (usually
-               //              the first text in the dialog).
-               //              <div dojoType="dijit.Dialog" aria-describedby="intro" .....>
-               //                      <div id="intro">Introductory text</div>
-               //                      <div>rest of dialog contents</div>
-               //              </div>
-               "aria-describedby":"",
-
-               postMixInProperties: function(){
-                       var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-                       dojo.mixin(this, _nlsResources);
-                       this.inherited(arguments);
-               },
-
-               postCreate: function(){
-                       dojo.style(this.domNode, {
-                               display: "none",
-                               position:"absolute"
-                       });
-                       dojo.body().appendChild(this.domNode);
-
-                       this.inherited(arguments);
-
-                       this.connect(this, "onExecute", "hide");
-                       this.connect(this, "onCancel", "hide");
-                       this._modalconnects = [];
-               },
-
-               onLoad: function(){
-                       // summary:
-                       //              Called when data has been loaded from an href.
-                       //              Unlike most other callbacks, this function can be connected to (via `dojo.connect`)
-                       //              but should *not* be overriden.
-                       // tags:
-                       //              callback
-
-                       // when href is specified we need to reposition the dialog after the data is loaded
-                       // and find the focusable elements
-                       this._position();
-                       if(this.autofocus){
-                               this._getFocusItems(this.domNode);
-                               dijit.focus(this._firstFocusItem);
-                       }
-                       this.inherited(arguments);
-               },
-
-               _endDrag: function(e){
-                       // summary:
-                       //              Called after dragging the Dialog. Saves the position of the dialog in the viewport.
-                       // tags:
-                       //              private
-                       if(e && e.node && e.node === this.domNode){
-                               this._relativePosition = dojo.position(e.node);
-                       }
-               },
-
-               _setup: function(){
-                       // summary:
-                       //              Stuff we need to do before showing the Dialog for the first
-                       //              time (but we defer it until right beforehand, for
-                       //              performance reasons).
-                       // tags:
-                       //              private
-
-                       var node = this.domNode;
-
-                       if(this.titleBar && this.draggable){
-                               this._moveable = (dojo.isIE == 6) ?
-                                       new dojo.dnd.TimedMoveable(node, { handle: this.titleBar }) :   // prevent overload, see #5285
-                                       new dojo.dnd.Moveable(node, { handle: this.titleBar, timeout: 0 });
-                               dojo.subscribe("/dnd/move/stop",this,"_endDrag");
-                       }else{
-                               dojo.addClass(node,"dijitDialogFixed");
-                       }
-
-                       this.underlayAttrs = {
-                               dialogId: this.id,
-                               "class": dojo.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
-                       };
-
-                       this._fadeIn = dojo.fadeIn({
-                               node: node,
-                               duration: this.duration,
-                               beforeBegin: dojo.hitch(this, function(){
-                                       var underlay = dijit._underlay;
-                                       if(!underlay){
-                                               underlay = dijit._underlay = new dijit.DialogUnderlay(this.underlayAttrs);
-                                       }else{
-                                               underlay.set(this.underlayAttrs);
+                       //We need to handle reference integrity if this is on.
+                       //In the case of set, we need to see if references were added or removed
+                       //and update the reference tracking map accordingly.
+                       if(this.referenceIntegrity){
+                               if(oldValueOrValues){
+                                       var oldValues = oldValueOrValues;
+                                       if(!lang.isArray(oldValues)){
+                                               oldValues = [oldValues];
                                        }
-
-                                       var ds = dijit._dialogStack,
-                                               zIndex = 948 + ds.length*2;
-                                       if(ds.length == 1){     // first dialog
-                                               underlay.show();
+                                       //Use an associative map to determine what was added/removed from the list.
+                                       //Should be O(n) performant.  First look at all the old values and make a list of them
+                                       //Then for any item not in the old list, we add it.  If it was already present, we remove it.
+                                       //Then we pass over the map and any references left it it need to be removed (IE, no match in
+                                       //the new values list).
+                                       var map = {};
+                                       arrayUtil.forEach(oldValues, function(possibleItem){
+                                               if(this.isItem(possibleItem)){
+                                                       var id = this.getIdentity(possibleItem);
+                                                       map[id.toString()] = true;
+                                               }
+                                       }, this);
+                                       arrayUtil.forEach(newValueArray, function(possibleItem){
+                                               if(this.isItem(possibleItem)){
+                                                       var id = this.getIdentity(possibleItem);
+                                                       if(map[id.toString()]){
+                                                               delete map[id.toString()];
+                                                       }else{
+                                                               this._addReferenceToMap(possibleItem, item, attribute);
+                                                       }
+                                               }
+                                       }, this);
+                                       for(var rId in map){
+                                               var removedItem;
+                                               if(this._itemsByIdentity){
+                                                       removedItem = this._itemsByIdentity[rId];
+                                               }else{
+                                                       removedItem = this._arrayOfAllItems[rId];
+                                               }
+                                               this._removeReferenceFromMap(removedItem, item, attribute);
                                        }
-                                       dojo.style(dijit._underlay.domNode, 'zIndex', zIndex);
-                                       dojo.style(this.domNode, 'zIndex', zIndex + 1);
-                               }),
-                               onEnd: dojo.hitch(this, function(){
-                                       if(this.autofocus){
-                                               // find focusable Items each time dialog is shown since if dialog contains a widget the
-                                               // first focusable items can change
-                                               this._getFocusItems(this.domNode);
-                                               dijit.focus(this._firstFocusItem);
+                               }else{
+                                       //Everything is new (no old values) so we have to just
+                                       //insert all the references, if any.
+                                       for(var i = 0; i < newValueArray.length; i++){
+                                               var value = newValueArray[i];
+                                               if(this.isItem(value)){
+                                                       this._addReferenceToMap(value, item, attribute);
+                                               }
                                        }
-                               })
-                        });
+                               }
+                       }
+                       item[attribute] = newValueArray;
+                       success = true;
+               }
 
-                       this._fadeOut = dojo.fadeOut({
-                               node: node,
-                               duration: this.duration,
-                               onEnd: dojo.hitch(this, function(){
-                                       node.style.display = "none";
+               // Now we make the dojo.data.api.Notification call
+               if(callOnSet){
+                       this.onSet(item, attribute, oldValueOrValues, newValueOrValues);
+               }
+               return success; // boolean
+       },
 
-                                       // Restore the previous dialog in the stack, or if this is the only dialog
-                                       // then restore to original page
-                                       var ds = dijit._dialogStack;
-                                       if(ds.length == 0){
-                                               dijit._underlay.hide();
-                                       }else{
-                                               dojo.style(dijit._underlay.domNode, 'zIndex', 948 + ds.length*2);
-                                               dijit._underlay.set(ds[ds.length-1].underlayAttrs);
-                                       }
+       _addReferenceToMap: function(/* item */ refItem, /* item */ parentItem, /* string */ attribute){
+               //      summary:
+               //              Method to add an reference map entry for an item and attribute.
+               //      description:
+               //              Method to add an reference map entry for an item and attribute.                  //
+               //      refItem:
+               //              The item that is referenced.
+               //      parentItem:
+               //              The item that holds the new reference to refItem.
+               //      attribute:
+               //              The attribute on parentItem that contains the new reference.
 
-                                       // Restore focus to wherever it was before this dialog was displayed
-                                       if(this.refocus){
-                                               var focus = this._savedFocus;
-
-                                               // If we are returning control to a previous dialog but for some reason
-                                               // that dialog didn't have a focused field, set focus to first focusable item.
-                                               // This situation could happen if two dialogs appeared at nearly the same time,
-                                               // since a dialog doesn't set it's focus until the fade-in is finished.
-                                               if(ds.length > 0){
-                                                       var pd = ds[ds.length-1];
-                                                       if(!dojo.isDescendant(focus.node, pd.domNode)){
-                                                               pd._getFocusItems(pd.domNode);
-                                                               focus = pd._firstFocusItem;
-                                                       }
-                                               }
+               var parentId = this.getIdentity(parentItem);
+               var references = refItem[this._reverseRefMap];
 
-                                               dijit.focus(focus);
-                                       }
-                               })
-                        });
-               },
+               if(!references){
+                       references = refItem[this._reverseRefMap] = {};
+               }
+               var itemRef = references[parentId];
+               if(!itemRef){
+                       itemRef = references[parentId] = {};
+               }
+               itemRef[attribute] = true;
+       },
 
-               uninitialize: function(){
-                       var wasPlaying = false;
-                       if(this._fadeIn && this._fadeIn.status() == "playing"){
-                               wasPlaying = true;
-                               this._fadeIn.stop();
-                       }
-                       if(this._fadeOut && this._fadeOut.status() == "playing"){
-                               wasPlaying = true;
-                               this._fadeOut.stop();
+       _removeReferenceFromMap: function(/* item */ refItem, /* item */ parentItem, /* string */ attribute){
+               //      summary:
+               //              Method to remove an reference map entry for an item and attribute.
+               //      description:
+               //              Method to remove an reference map entry for an item and attribute.  This will
+               //              also perform cleanup on the map such that if there are no more references at all to
+               //              the item, its reference object and entry are removed.
+               //
+               //      refItem:
+               //              The item that is referenced.
+               //      parentItem:
+               //              The item holding a reference to refItem.
+               //      attribute:
+               //              The attribute on parentItem that contains the reference.
+               var identity = this.getIdentity(parentItem);
+               var references = refItem[this._reverseRefMap];
+               var itemId;
+               if(references){
+                       for(itemId in references){
+                               if(itemId == identity){
+                                       delete references[itemId][attribute];
+                                       if(this._isEmpty(references[itemId])){
+                                               delete references[itemId];
+                                       }
+                               }
                        }
-                       
-                       // Hide the underlay, unless the underlay widget has already been destroyed
-                       // because we are being called during page unload (when all widgets are destroyed)
-                       if((this.open || wasPlaying) && !dijit._underlay._destroyed){
-                               dijit._underlay.hide();
+                       if(this._isEmpty(references)){
+                               delete refItem[this._reverseRefMap];
                        }
+               }
+       },
 
-                       if(this._moveable){
-                               this._moveable.destroy();
+       _dumpReferenceMap: function(){
+               //      summary:
+               //              Function to dump the reverse reference map of all items in the store for debug purposes.
+               //      description:
+               //              Function to dump the reverse reference map of all items in the store for debug purposes.
+               var i;
+               for(i = 0; i < this._arrayOfAllItems.length; i++){
+                       var item = this._arrayOfAllItems[i];
+                       if(item && item[this._reverseRefMap]){
+                               console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + jsonUtil.toJson(item[this._reverseRefMap]));
                        }
-                       this.inherited(arguments);
-               },
+               }
+       },
 
-               _size: function(){
-                       // summary:
-                       //              If necessary, shrink dialog contents so dialog fits in viewport
-                       // tags:
-                       //              private
-
-                       this._checkIfSingleChild();
-
-                       // If we resized the dialog contents earlier, reset them back to original size, so
-                       // that if the user later increases the viewport size, the dialog can display w/out a scrollbar.
-                       // Need to do this before the dojo.marginBox(this.domNode) call below.
-                       if(this._singleChild){
-                               if(this._singleChildOriginalStyle){
-                                       this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
-                               }
-                               delete this._singleChildOriginalStyle;
+       _getValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute){
+               var valueOrValues = undefined;
+               if(this.hasAttribute(item, attribute)){
+                       var valueArray = this.getValues(item, attribute);
+                       if(valueArray.length == 1){
+                               valueOrValues = valueArray[0];
                        }else{
-                               dojo.style(this.containerNode, {
-                                       width:"auto",
-                                       height:"auto"
-                               });
+                               valueOrValues = valueArray;
                        }
+               }
+               return valueOrValues;
+       },
 
-                       var mb = dojo.marginBox(this.domNode);
-                       var viewport = dojo.window.getBox();
-                       if(mb.w >= viewport.w || mb.h >= viewport.h){
-                               // Reduce size of dialog contents so that dialog fits in viewport
-
-                               var w = Math.min(mb.w, Math.floor(viewport.w * 0.75)),
-                                       h = Math.min(mb.h, Math.floor(viewport.h * 0.75));
-
-                               if(this._singleChild && this._singleChild.resize){
-                                       this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText;
-                                       this._singleChild.resize({w: w, h: h});
-                               }else{
-                                       dojo.style(this.containerNode, {
-                                               width: w + "px",
-                                               height: h + "px",
-                                               overflow: "auto",
-                                               position: "relative"    // workaround IE bug moving scrollbar or dragging dialog
-                                       });
-                               }
-                       }else{
-                               if(this._singleChild && this._singleChild.resize){
-                                       this._singleChild.resize();
+       _flatten: function(/* anything */ value){
+               if(this.isItem(value)){
+                       // Given an item, return an serializable object that provides a
+                       // reference to the item.
+                       // For example, given kermit:
+                       //    var kermit = store.newItem({id:2, name:"Kermit"});
+                       // we want to return
+                       //    {_reference:2}
+                       return {_reference: this.getIdentity(value)};
+               }else{
+                       if(typeof value === "object"){
+                               for(var type in this._datatypeMap){
+                                       var typeMap = this._datatypeMap[type];
+                                       if(lang.isObject(typeMap) && !lang.isFunction(typeMap)){
+                                               if(value instanceof typeMap.type){
+                                                       if(!typeMap.serialize){
+                                                               throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: [" + type + "]");
+                                                       }
+                                                       return {_type: type, _value: typeMap.serialize(value)};
+                                               }
+                                       } else if(value instanceof typeMap){
+                                               //SImple mapping, therefore, return as a toString serialization.
+                                               return {_type: type, _value: value.toString()};
+                                       }
                                }
                        }
-               },
-
-               _position: function(){
-                       // summary:
-                       //              Position modal dialog in the viewport. If no relative offset
-                       //              in the viewport has been determined (by dragging, for instance),
-                       //              center the node. Otherwise, use the Dialog's stored relative offset,
-                       //              and position the node to top: left: values based on the viewport.
-                       // tags:
-                       //              private
-                       if(!dojo.hasClass(dojo.body(),"dojoMove")){
-                               var node = this.domNode,
-                                       viewport = dojo.window.getBox(),
-                                       p = this._relativePosition,
-                                       bb = p ? null : dojo._getBorderBox(node),
-                                       l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)),
-                                       t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2))
-                               ;
-                               dojo.style(node,{
-                                       left: l + "px",
-                                       top: t + "px"
-                               });
-                       }
-               },
-
-               _onKey: function(/*Event*/ evt){
-                       // summary:
-                       //              Handles the keyboard events for accessibility reasons
-                       // tags:
-                       //              private
+                       return value;
+               }
+       },
 
-                       var ds = dijit._dialogStack;
-                       if(ds[ds.length-1] != this){
-                               // console.debug(this.id + ': skipping because', this, 'is not the active dialog');
-                               return;
-                       }
+       _getNewFileContentString: function(){
+               // summary:
+               //              Generate a string that can be saved to a file.
+               //              The result should look similar to:
+               //              http://trac.dojotoolkit.org/browser/dojo/trunk/tests/data/countries.json
+               var serializableStructure = {};
 
-                       if(evt.charOrCode){
-                               var dk = dojo.keys;
-                               var node = evt.target;
-                               if(evt.charOrCode === dk.TAB){
-                                       this._getFocusItems(this.domNode);
-                               }
-                               var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
-                               // see if we are shift-tabbing from first focusable item on dialog
-                               if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === dk.TAB){
-                                       if(!singleFocusItem){
-                                               dijit.focus(this._lastFocusItem); // send focus to last item in dialog
-                                       }
-                                       dojo.stopEvent(evt);
-                               }else if(node == this._lastFocusItem && evt.charOrCode === dk.TAB && !evt.shiftKey){
-                                       if(!singleFocusItem){
-                                               dijit.focus(this._firstFocusItem); // send focus to first item in dialog
-                                       }
-                                       dojo.stopEvent(evt);
-                               }else{
-                                       // see if the key is for the dialog
-                                       while(node){
-                                               if(node == this.domNode || dojo.hasClass(node, "dijitPopup")){
-                                                       if(evt.charOrCode == dk.ESCAPE){
-                                                               this.onCancel();
-                                                       }else{
-                                                               return; // just let it go
+               var identifierAttribute = this._getIdentifierAttribute();
+               if(identifierAttribute !== Number){
+                       serializableStructure.identifier = identifierAttribute;
+               }
+               if(this._labelAttr){
+                       serializableStructure.label = this._labelAttr;
+               }
+               serializableStructure.items = [];
+               for(var i = 0; i < this._arrayOfAllItems.length; ++i){
+                       var item = this._arrayOfAllItems[i];
+                       if(item !== null){
+                               var serializableItem = {};
+                               for(var key in item){
+                                       if(key !== this._storeRefPropName && key !== this._itemNumPropName && key !== this._reverseRefMap && key !== this._rootItemPropName){
+                                               var valueArray = this.getValues(item, key);
+                                               if(valueArray.length == 1){
+                                                       serializableItem[key] = this._flatten(valueArray[0]);
+                                               }else{
+                                                       var serializableArray = [];
+                                                       for(var j = 0; j < valueArray.length; ++j){
+                                                               serializableArray.push(this._flatten(valueArray[j]));
+                                                               serializableItem[key] = serializableArray;
                                                        }
                                                }
-                                               node = node.parentNode;
-                                       }
-                                       // this key is for the disabled document window
-                                       if(evt.charOrCode !== dk.TAB){ // allow tabbing into the dialog for a11y
-                                               dojo.stopEvent(evt);
-                                       // opera won't tab to a div
-                                       }else if(!dojo.isOpera){
-                                               try{
-                                                       this._firstFocusItem.focus();
-                                               }catch(e){ /*squelch*/ }
                                        }
                                }
+                               serializableStructure.items.push(serializableItem);
                        }
-               },
-
-               show: function(){
-                       // summary:
-                       //              Display the dialog
-                       if(this.open){ return; }
+               }
+               var prettyPrint = true;
+               return jsonUtil.toJson(serializableStructure, prettyPrint);
+       },
 
-                       // first time we show the dialog, there's some initialization stuff to do
-                       if(!this._alreadyInitialized){
-                               this._setup();
-                               this._alreadyInitialized=true;
+       _isEmpty: function(something){
+               //      summary:
+               //              Function to determine if an array or object has no properties or values.
+               //      something:
+               //              The array or object to examine.
+               var empty = true;
+               if(lang.isObject(something)){
+                       var i;
+                       for(i in something){
+                               empty = false;
+                               break;
                        }
-
-                       if(this._fadeOut.status() == "playing"){
-                               this._fadeOut.stop();
+               }else if(lang.isArray(something)){
+                       if(something.length > 0){
+                               empty = false;
                        }
+               }
+               return empty; //boolean
+       },
 
-                       this._modalconnects.push(dojo.connect(window, "onscroll", this, "layout"));
-                       this._modalconnects.push(dojo.connect(window, "onresize", this, function(){
-                               // IE gives spurious resize events and can actually get stuck
-                               // in an infinite loop if we don't ignore them
-                               var viewport = dojo.window.getBox();
-                               if(!this._oldViewport ||
-                                               viewport.h != this._oldViewport.h ||
-                                               viewport.w != this._oldViewport.w){
-                                       this.layout();
-                                       this._oldViewport = viewport;
-                               }
-                       }));
-                       this._modalconnects.push(dojo.connect(dojo.doc.documentElement, "onkeypress", this, "_onKey"));
-
-                       dojo.style(this.domNode, {
-                               opacity:0,
-                               display:""
-                       });
-
-                       this.open = true;
-                       this._onShow(); // lazy load trigger
-
-                       this._size();
-                       this._position();
-                       dijit._dialogStack.push(this);
-                       this._fadeIn.play();
+       save: function(/* object */ keywordArgs){
+               // summary: See dojo.data.api.Write.save()
+               this._assert(!this._saveInProgress);
 
-                       this._savedFocus = dijit.getFocus(this);
-               },
+               // this._saveInProgress is set to true, briefly, from when save is first called to when it completes
+               this._saveInProgress = true;
 
-               hide: function(){
-                       // summary:
-                       //              Hide the dialog
+               var self = this;
+               var saveCompleteCallback = function(){
+                       self._pending = {
+                               _newItems:{},
+                               _modifiedItems:{},
+                               _deletedItems:{}
+                       };
 
-                       // if we haven't been initialized yet then we aren't showing and we can just return
-                       // or if we aren't the active dialog, don't allow us to close yet
-                       var ds = dijit._dialogStack;
-                       if(!this._alreadyInitialized || this != ds[ds.length-1]){
-                               return;
+                       self._saveInProgress = false; // must come after this._pending is cleared, but before any callbacks
+                       if(keywordArgs && keywordArgs.onComplete){
+                               var scope = keywordArgs.scope || window.global;
+                               keywordArgs.onComplete.call(scope);
                        }
-
-                       if(this._fadeIn.status() == "playing"){
-                               this._fadeIn.stop();
+               };
+               var saveFailedCallback = function(err){
+                       self._saveInProgress = false;
+                       if(keywordArgs && keywordArgs.onError){
+                               var scope = keywordArgs.scope || window.global;
+                               keywordArgs.onError.call(scope, err);
                        }
+               };
 
-                       // throw away current active dialog from stack -- making the previous dialog or the node on the original page active
-                       ds.pop();
+               if(this._saveEverything){
+                       var newFileContentString = this._getNewFileContentString();
+                       this._saveEverything(saveCompleteCallback, saveFailedCallback, newFileContentString);
+               }
+               if(this._saveCustom){
+                       this._saveCustom(saveCompleteCallback, saveFailedCallback);
+               }
+               if(!this._saveEverything && !this._saveCustom){
+                       // Looks like there is no user-defined save-handler function.
+                       // That's fine, it just means the datastore is acting as a "mock-write"
+                       // store -- changes get saved in memory but don't get saved to disk.
+                       saveCompleteCallback();
+               }
+       },
 
-                       this._fadeOut.play();
+       revert: function(){
+               // summary: See dojo.data.api.Write.revert()
+               this._assert(!this._saveInProgress);
 
-                       if(this._scrollConnected){
-                               this._scrollConnected = false;
+               var identity;
+               for(identity in this._pending._modifiedItems){
+                       // find the original item and the modified item that replaced it
+                       var copyOfItemState = this._pending._modifiedItems[identity];
+                       var modifiedItem = null;
+                       if(this._itemsByIdentity){
+                               modifiedItem = this._itemsByIdentity[identity];
+                       }else{
+                               modifiedItem = this._arrayOfAllItems[identity];
                        }
-                       dojo.forEach(this._modalconnects, dojo.disconnect);
-                       this._modalconnects = [];
 
-                       if(this._relativePosition){
-                               delete this._relativePosition;
+                       // Restore the original item into a full-fledged item again, we want to try to
+                       // keep the same object instance as if we don't it, causes bugs like #9022.
+                       copyOfItemState[this._storeRefPropName] = this;
+                       for(var key in modifiedItem){
+                               delete modifiedItem[key];
                        }
-                       this.open = false;
-
-                       this.onHide();
-               },
-
-               layout: function(){
-                       // summary:
-                       //              Position the Dialog and the underlay
-                       // tags:
-                       //              private
-                       if(this.domNode.style.display != "none"){
-                               if(dijit._underlay){    // avoid race condition during show()
-                                       dijit._underlay.layout();
-                               }
-                               this._position();
-                       }
-               },
+                       lang.mixin(modifiedItem, copyOfItemState);
+               }
+               var deletedItem;
+               for(identity in this._pending._deletedItems){
+                       deletedItem = this._pending._deletedItems[identity];
+                       deletedItem[this._storeRefPropName] = this;
+                       var index = deletedItem[this._itemNumPropName];
 
-               destroy: function(){
-                       dojo.forEach(this._modalconnects, dojo.disconnect);
-                       if(this.refocus && this.open){
-                               setTimeout(dojo.hitch(dijit,"focus",this._savedFocus), 25);
+                       //Restore the reverse refererence map, if any.
+                       if(deletedItem["backup_" + this._reverseRefMap]){
+                               deletedItem[this._reverseRefMap] = deletedItem["backup_" + this._reverseRefMap];
+                               delete deletedItem["backup_" + this._reverseRefMap];
+                       }
+                       this._arrayOfAllItems[index] = deletedItem;
+                       if(this._itemsByIdentity){
+                               this._itemsByIdentity[identity] = deletedItem;
+                       }
+                       if(deletedItem[this._rootItemPropName]){
+                               this._arrayOfTopLevelItems.push(deletedItem);
+                       }
+               }
+               //We have to pass through it again and restore the reference maps after all the
+               //undeletes have occurred.
+               for(identity in this._pending._deletedItems){
+                       deletedItem = this._pending._deletedItems[identity];
+                       if(deletedItem["backupRefs_" + this._reverseRefMap]){
+                               arrayUtil.forEach(deletedItem["backupRefs_" + this._reverseRefMap], function(reference){
+                                       var refItem;
+                                       if(this._itemsByIdentity){
+                                               refItem = this._itemsByIdentity[reference.id];
+                                       }else{
+                                               refItem = this._arrayOfAllItems[reference.id];
+                                       }
+                                       this._addReferenceToMap(refItem, deletedItem, reference.attr);
+                               }, this);
+                               delete deletedItem["backupRefs_" + this._reverseRefMap];
                        }
-                       this.inherited(arguments);
                }
-       }
-);
 
-dojo.declare(
-       "dijit.Dialog",
-       [dijit.layout.ContentPane, dijit._DialogBase],
-       {}
-);
+               for(identity in this._pending._newItems){
+                       var newItem = this._pending._newItems[identity];
+                       newItem[this._storeRefPropName] = null;
+                       // null out the new item, but don't change the array index so
+                       // so we can keep using _arrayOfAllItems.length.
+                       this._arrayOfAllItems[newItem[this._itemNumPropName]] = null;
+                       if(newItem[this._rootItemPropName]){
+                               this._removeArrayElement(this._arrayOfTopLevelItems, newItem);
+                       }
+                       if(this._itemsByIdentity){
+                               delete this._itemsByIdentity[identity];
+                       }
+               }
 
-// Stack of currenctly displayed dialogs, layered on top of each other
-dijit._dialogStack = [];
+               this._pending = {
+                       _newItems:{},
+                       _modifiedItems:{},
+                       _deletedItems:{}
+               };
+               return true; // boolean
+       },
 
-// For back-compat.  TODO: remove in 2.0
+       isDirty: function(/* item? */ item){
+               // summary: See dojo.data.api.Write.isDirty()
+               if(item){
+                       // return true if the item is dirty
+                       var identity = this.getIdentity(item);
+                       return new Boolean(this._pending._newItems[identity] ||
+                               this._pending._modifiedItems[identity] ||
+                               this._pending._deletedItems[identity]).valueOf(); // boolean
+               }else{
+                       // return true if the store is dirty -- which means return true
+                       // if there are any new items, dirty items, or modified items
+                       return !this._isEmpty(this._pending._newItems) ||
+                               !this._isEmpty(this._pending._modifiedItems) ||
+                               !this._isEmpty(this._pending._deletedItems); // boolean
+               }
+       },
 
+/* dojo.data.api.Notification */
 
-}
+       onSet: function(/* item */ item,
+                                       /*attribute-name-string*/ attribute,
+                                       /*object|array*/ oldValue,
+                                       /*object|array*/ newValue){
+               // summary: See dojo.data.api.Notification.onSet()
 
-if(!dojo._hasResource["dijit._HasDropDown"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._HasDropDown"] = true;
-dojo.provide("dijit._HasDropDown");
+               // No need to do anything. This method is here just so that the
+               // client code can connect observers to it.
+       },
 
+       onNew: function(/* item */ newItem, /*object?*/ parentInfo){
+               // summary: See dojo.data.api.Notification.onNew()
 
+               // No need to do anything. This method is here just so that the
+               // client code can connect observers to it.
+       },
 
+       onDelete: function(/* item */ deletedItem){
+               // summary: See dojo.data.api.Notification.onDelete()
 
-dojo.declare("dijit._HasDropDown",
-       null,
-       {
-               // summary:
-               //              Mixin for widgets that need drop down ability.
+               // No need to do anything. This method is here just so that the
+               // client code can connect observers to it.
+       },
 
-               // _buttonNode: [protected] DomNode
-               //              The button/icon/node to click to display the drop down.
-               //              Can be set via a dojoAttachPoint assignment.
-               //              If missing, then either focusNode or domNode (if focusNode is also missing) will be used.
-               _buttonNode: null,
+       close: function(/* object? */ request){
+                // summary:
+                //             Over-ride of base close function of ItemFileReadStore to add in check for store state.
+                // description:
+                //             Over-ride of base close function of ItemFileReadStore to add in check for store state.
+                //             If the store is still dirty (unsaved changes), then an error will be thrown instead of
+                //             clearing the internal state for reload from the url.
 
-               // _arrowWrapperNode: [protected] DomNode
-               //              Will set CSS class dijitUpArrow, dijitDownArrow, dijitRightArrow etc. on this node depending
-               //              on where the drop down is set to be positioned.
-               //              Can be set via a dojoAttachPoint assignment.
-               //              If missing, then _buttonNode will be used.
-               _arrowWrapperNode: null,
+                //Clear if not dirty ... or throw an error
+                if(this.clearOnClose){
+                        if(!this.isDirty()){
+                                this.inherited(arguments);
+                        }else{
+                                //Only throw an error if the store was dirty and we were loading from a url (cannot reload from url until state is saved).
+                                throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
+                        }
+                }
+       }
+});
 
-               // _popupStateNode: [protected] DomNode
-               //              The node to set the popupActive class on.
-               //              Can be set via a dojoAttachPoint assignment.
-               //              If missing, then focusNode or _buttonNode (if focusNode is missing) will be used.
-               _popupStateNode: null,
+});
 
-               // _aroundNode: [protected] DomNode
-               //              The node to display the popup around.
-               //              Can be set via a dojoAttachPoint assignment.
-               //              If missing, then domNode will be used.
-               _aroundNode: null,
+},
+'dijit/form/_RadioButtonMixin':function(){
+define("dijit/form/_RadioButtonMixin", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/event", // event.stop
+       "dojo/_base/lang", // lang.hitch
+       "dojo/query", // query
+       "dojo/_base/window", // win.doc
+       "../registry"   // registry.getEnclosingWidget
+], function(array, declare, domAttr, event, lang, query, win, registry){
+
+       // module:
+       //              dijit/form/_RadioButtonMixin
+       // summary:
+       //              Mixin to provide widget functionality for an HTML radio button
 
-               // dropDown: [protected] Widget
-               //              The widget to display as a popup.  This widget *must* be
-               //              defined before the startup function is called.
-               dropDown: null,
+       return declare("dijit.form._RadioButtonMixin", null, {
+               // summary:
+               //              Mixin to provide widget functionality for an HTML radio button
 
-               // autoWidth: [protected] Boolean
-               //              Set to true to make the drop down at least as wide as this
-               //              widget.  Set to false if the drop down should just be its
-               //              default width
-               autoWidth: true,
+               // type: [private] String
+               //              type attribute on <input> node.
+               //              Users should not change this value.
+               type: "radio",
 
-               // forceWidth: [protected] Boolean
-               //              Set to true to make the drop down exactly as wide as this
-               //              widget.  Overrides autoWidth.
-               forceWidth: false,
+               _getRelatedWidgets: function(){
+                       // Private function needed to help iterate over all radio buttons in a group.
+                       var ary = [];
+                       query("input[type=radio]", this.focusNode.form || win.doc).forEach( // can't use name= since query doesn't support [] in the name
+                               lang.hitch(this, function(inputNode){
+                                       if(inputNode.name == this.name && inputNode.form == this.focusNode.form){
+                                               var widget = registry.getEnclosingWidget(inputNode);
+                                               if(widget){
+                                                       ary.push(widget);
+                                               }
+                                       }
+                               })
+                       );
+                       return ary;
+               },
 
-               // maxHeight: [protected] Integer
-               //              The max height for our dropdown.  Set to 0 for no max height.
-               //              any dropdown taller than this will have scrollbars
-               maxHeight: 0,
+               _setCheckedAttr: function(/*Boolean*/ value){
+                       // If I am being checked then have to deselect currently checked radio button
+                       this.inherited(arguments);
+                       if(!this._created){ return; }
+                       if(value){
+                               array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){
+                                       if(widget != this && widget.checked){
+                                               widget.set('checked', false);
+                                       }
+                               }));
+                       }
+               },
 
-               // dropDownPosition: [const] String[]
-               //              This variable controls the position of the drop down.
-               //              It's an array of strings with the following values:
-               //
-               //                      * before: places drop down to the left of the target node/widget, or to the right in
-               //                        the case of RTL scripts like Hebrew and Arabic
-               //                      * after: places drop down to the right of the target node/widget, or to the left in
-               //                        the case of RTL scripts like Hebrew and Arabic
-               //                      * above: drop down goes above target node
-               //                      * below: drop down goes below target node
-               //
-               //              The list is positions is tried, in order, until a position is found where the drop down fits
-               //              within the viewport.
-               //
-               dropDownPosition: ["below","above"],
+               _onClick: function(/*Event*/ e){
+                       if(this.checked || this.disabled){ // nothing to do
+                               event.stop(e);
+                               return false;
+                       }
+                       if(this.readOnly){ // ignored by some browsers so we have to resync the DOM elements with widget values
+                               event.stop(e);
+                               array.forEach(this._getRelatedWidgets(), lang.hitch(this, function(widget){
+                                       domAttr.set(this.focusNode || this.domNode, 'checked', widget.checked);
+                               }));
+                               return false;
+                       }
+                       return this.inherited(arguments);
+               }
+       });
+});
 
-               // _stopClickEvents: Boolean
-               //              When set to false, the click events will not be stopped, in
-               //              case you want to use them in your subwidget
-               _stopClickEvents: true,
+},
+'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow\" role=\"presentation\" data-dojo-attach-event=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\" data-dojo-attach-event=\"onfocus:_onLabelFocus\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n",
+'dojo/dnd/TimedMoveable':function(){
+define("dojo/dnd/TimedMoveable", ["../main", "./Moveable"], function(dojo) {
+       // module:
+       //              dojo/dnd/TimedMoveable
+       // summary:
+       //              TODOC
 
-               _onDropDownMouseDown: function(/*Event*/ e){
-                       // summary:
-                       //              Callback when the user mousedown's on the arrow icon
+       /*=====
+       dojo.declare("dojo.dnd.__TimedMoveableArgs", [dojo.dnd.__MoveableArgs], {
+               // timeout: Number
+               //              delay move by this number of ms,
+               //              accumulating position changes during the timeout
+               timeout: 0
+       });
+       =====*/
 
-                       if(this.disabled || this.readOnly){ return; }
+       // precalculate long expressions
+       var oldOnMove = dojo.dnd.Moveable.prototype.onMove;
 
-                       this._docHandler = this.connect(dojo.doc, "onmouseup", "_onDropDownMouseUp");
+       dojo.declare("dojo.dnd.TimedMoveable", dojo.dnd.Moveable, {
+               // summary:
+               //              A specialized version of Moveable to support an FPS throttling.
+               //              This class puts an upper restriction on FPS, which may reduce
+               //              the CPU load. The additional parameter "timeout" regulates
+               //              the delay before actually moving the moveable object.
 
-                       this.toggleDropDown();
-               },
+               // object attributes (for markup)
+               timeout: 40,    // in ms, 40ms corresponds to 25 fps
 
-               _onDropDownMouseUp: function(/*Event?*/ e){
+               constructor: function(node, params){
                        // summary:
-                       //              Callback when the user lifts their mouse after mouse down on the arrow icon.
-                       //              If the drop is a simple menu and the mouse is over the menu, we execute it, otherwise, we focus our
-                       //              dropDown node.  If the event is missing, then we are not
-                       //              a mouseup event.
-                       //
-                       //              This is useful for the common mouse movement pattern
-                       //              with native browser <select> nodes:
-                       //                      1. mouse down on the select node (probably on the arrow)
-                       //                      2. move mouse to a menu item while holding down the mouse button
-                       //                      3. mouse up.  this selects the menu item as though the user had clicked it.
-                       if(e && this._docHandler){
-                               this.disconnect(this._docHandler);
+                       //              an object that makes a node moveable with a timer
+                       // node: Node||String
+                       //              a node (or node's id) to be moved
+                       // params: dojo.dnd.__TimedMoveableArgs
+                       //              object with additional parameters.
+
+                       // sanitize parameters
+                       if(!params){ params = {}; }
+                       if(params.timeout && typeof params.timeout == "number" && params.timeout >= 0){
+                               this.timeout = params.timeout;
                        }
-                       var dropDown = this.dropDown, overMenu = false;
+               },
 
-                       if(e && this._opened){
-                               // This code deals with the corner-case when the drop down covers the original widget,
-                               // because it's so large.  In that case mouse-up shouldn't select a value from the menu.
-                               // Find out if our target is somewhere in our dropdown widget,
-                               // but not over our _buttonNode (the clickable node)
-                               var c = dojo.position(this._buttonNode, true);
-                               if(!(e.pageX >= c.x && e.pageX <= c.x + c.w) ||
-                                       !(e.pageY >= c.y && e.pageY <= c.y + c.h)){
-                                       var t = e.target;
-                                       while(t && !overMenu){
-                                               if(dojo.hasClass(t, "dijitPopup")){
-                                                       overMenu = true;
-                                               }else{
-                                                       t = t.parentNode;
-                                               }
-                                       }
-                                       if(overMenu){
-                                               t = e.target;
-                                               if(dropDown.onItemClick){
-                                                       var menuItem;
-                                                       while(t && !(menuItem = dijit.byNode(t))){
-                                                               t = t.parentNode;
-                                                       }
-                                                       if(menuItem && menuItem.onClick && menuItem.getParent){
-                                                               menuItem.getParent().onItemClick(menuItem, e);
-                                                       }
-                                               }
-                                               return;
-                                       }
-                               }
-                       }
-                       if(this._opened && dropDown.focus){
-                               // Focus the dropdown widget - do it on a delay so that we
-                               // don't steal our own focus.
-                               window.setTimeout(dojo.hitch(dropDown, "focus"), 1);
+               onMoveStop: function(/* dojo.dnd.Mover */ mover){
+                       if(mover._timer){
+                               // stop timer
+                               clearTimeout(mover._timer);
+                               // reflect the last received position
+                               oldOnMove.call(this, mover, mover._leftTop)
                        }
+                       dojo.dnd.Moveable.prototype.onMoveStop.apply(this, arguments);
                },
-
-               _onDropDownClick: function(/*Event*/ e){
-                       // the drop down was already opened on mousedown/keydown; just need to call stopEvent()
-                       if(this._stopClickEvents){
-                               dojo.stopEvent(e);
-                       }                       
-               },
-
-               _setupDropdown: function(){
-                       // summary:
-                       //              set up nodes and connect our mouse and keypress events
-                       this._buttonNode = this._buttonNode || this.focusNode || this.domNode;
-                       this._popupStateNode = this._popupStateNode || this.focusNode || this._buttonNode;
-                       this._aroundNode = this._aroundNode || this.domNode;
-                       this.connect(this._buttonNode, "onmousedown", "_onDropDownMouseDown");
-                       this.connect(this._buttonNode, "onclick", "_onDropDownClick");
-                       this.connect(this._buttonNode, "onkeydown", "_onDropDownKeydown");
-                       this.connect(this._buttonNode, "onkeyup", "_onKey");
-
-                       // If we have a _setStateClass function (which happens when
-                       // we are a form widget), then we need to connect our open/close
-                       // functions to it
-                       if(this._setStateClass){
-                               this.connect(this, "openDropDown", "_setStateClass");
-                               this.connect(this, "closeDropDown", "_setStateClass");
+               onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+                       mover._leftTop = leftTop;
+                       if(!mover._timer){
+                               var _t = this;  // to avoid using dojo.hitch()
+                               mover._timer = setTimeout(function(){
+                                       // we don't have any pending requests
+                                       mover._timer = null;
+                                       // reflect the last received position
+                                       oldOnMove.call(_t, mover, mover._leftTop);
+                               }, this.timeout);
                        }
+               }
+       });
 
-                       // Add a class to the "dijitDownArrowButton" type class to _buttonNode so theme can set direction of arrow
-                       // based on where drop down will normally appear
-                       var defaultPos = {
-                                       "after" : this.isLeftToRight() ? "Right" : "Left",
-                                       "before" : this.isLeftToRight() ? "Left" : "Right",
-                                       "above" : "Up",
-                                       "below" : "Down",
-                                       "left" : "Left",
-                                       "right" : "Right"
-                       }[this.dropDownPosition[0]] || this.dropDownPosition[0] || "Down";
-                       dojo.addClass(this._arrowWrapperNode || this._buttonNode, "dijit" + defaultPos + "ArrowButton");
-               },
-
-               postCreate: function(){
-                       this._setupDropdown();
-                       this.inherited(arguments);
-               },
+       return dojo.dnd.TimedMoveable;
+       
+});
 
-               destroyDescendants: function(){
-                       if(this.dropDown){
-                               // Destroy the drop down, unless it's already been destroyed.  This can happen because
-                               // the drop down is a direct child of <body> even though it's logically my child.
-                               if(!this.dropDown._destroyed){
-                                       this.dropDown.destroyRecursive();
-                               }
-                               delete this.dropDown;
-                       }
-                       this.inherited(arguments);
-               },
+},
+'dojo/NodeList-fx':function(){
+define("dojo/NodeList-fx", ["dojo/_base/NodeList", "./_base/lang", "./_base/connect", "./_base/fx", "./fx"], 
+  function(NodeList, lang, connectLib, baseFx, coreFx) {
+       // module:
+       //              dojo/NodeList-fx
+       // summary:
+       //              TODOC
 
-               _onDropDownKeydown: function(/*Event*/ e){
-                       if(e.keyCode == dojo.keys.DOWN_ARROW || e.keyCode == dojo.keys.ENTER || e.keyCode == dojo.keys.SPACE){
-                               e.preventDefault();     // stop IE screen jump
-                       }
-               },
+/*=====
+dojo["NodeList-fx"] = {
+       // summary: Adds dojo.fx animation support to dojo.query() by extending the NodeList class
+       //              with additional FX functions.  NodeList is the array-like object used to hold query results.
+};
 
-               _onKey: function(/*Event*/ e){
-                       // summary:
-                       //              Callback when the user presses a key while focused on the button node
+// doc alias helpers:
+NodeList = dojo.NodeList;
+=====*/
 
-                       if(this.disabled || this.readOnly){ return; }
-                       var d = this.dropDown;
-                       if(d && this._opened && d.handleKey){
-                               if(d.handleKey(e) === false){ return; }
-                       }
-                       if(d && this._opened && e.keyCode == dojo.keys.ESCAPE){
-                               this.toggleDropDown();
-                       }else if(d && !this._opened && 
-                                       (e.keyCode == dojo.keys.DOWN_ARROW || e.keyCode == dojo.keys.ENTER || e.keyCode == dojo.keys.SPACE)){
-                               this.toggleDropDown();
-                               if(d.focus){
-                                       setTimeout(dojo.hitch(d, "focus"), 1);
-                               }
-                       }
-               },
+lang.extend(NodeList, {
+       _anim: function(obj, method, args){
+               args = args||{};
+               var a = coreFx.combine(
+                       this.map(function(item){
+                               var tmpArgs = { node: item };
+                               lang.mixin(tmpArgs, args);
+                               return obj[method](tmpArgs);
+                       })
+               );
+               return args.auto ? a.play() && this : a; // dojo.Animation|dojo.NodeList
+       },
 
-               _onBlur: function(){
-                       // summary:
-                       //              Called magically when focus has shifted away from this widget and it's dropdown
+       wipeIn: function(args){
+               // summary:
+               //              wipe in all elements of this NodeList via `dojo.fx.wipeIn`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //              Fade in all tables with class "blah":
+               //              |       dojo.query("table.blah").wipeIn().play();
+               //
+               // example:
+               //              Utilizing `auto` to get the NodeList back:
+               //              |       dojo.query(".titles").wipeIn({ auto:true }).onclick(someFunction);
+               //
+               return this._anim(coreFx, "wipeIn", args); // dojo.Animation|dojo.NodeList
+       },
 
-                       this.closeDropDown();
-                       // don't focus on button.  the user has explicitly focused on something else.
-                       this.inherited(arguments);
-               },
+       wipeOut: function(args){
+               // summary:
+               //              wipe out all elements of this NodeList via `dojo.fx.wipeOut`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //              Wipe out all tables with class "blah":
+               //              |       dojo.query("table.blah").wipeOut().play();
+               return this._anim(coreFx, "wipeOut", args); // dojo.Animation|dojo.NodeList
+       },
 
-               isLoaded: function(){
-                       // summary:
-                       //              Returns whether or not the dropdown is loaded.  This can
-                       //              be overridden in order to force a call to loadDropDown().
-                       // tags:
-                       //              protected
+       slideTo: function(args){
+               // summary:
+               //              slide all elements of the node list to the specified place via `dojo.fx.slideTo`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //              |       Move all tables with class "blah" to 300/300:
+               //              |       dojo.query("table.blah").slideTo({
+               //              |               left: 40,
+               //              |               top: 50
+               //              |       }).play();
+               return this._anim(coreFx, "slideTo", args); // dojo.Animation|dojo.NodeList
+       },
 
-                       return true;
-               },
 
-               loadDropDown: function(/* Function */ loadCallback){
-                       // summary:
-                       //              Loads the data for the dropdown, and at some point, calls
-                       //              the given callback
-                       // tags:
-                       //              protected
+       fadeIn: function(args){
+               // summary:
+               //              fade in all elements of this NodeList via `dojo.fadeIn`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //              Fade in all tables with class "blah":
+               //              |       dojo.query("table.blah").fadeIn().play();
+               return this._anim(baseFx, "fadeIn", args); // dojo.Animation|dojo.NodeList
+       },
 
-                       loadCallback();
-               },
+       fadeOut: function(args){
+               // summary:
+               //              fade out all elements of this NodeList via `dojo.fadeOut`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //              Fade out all elements with class "zork":
+               //              |       dojo.query(".zork").fadeOut().play();
+               // example:
+               //              Fade them on a delay and do something at the end:
+               //              |       var fo = dojo.query(".zork").fadeOut();
+               //              |       dojo.connect(fo, "onEnd", function(){ /*...*/ });
+               //              |       fo.play();
+               // example:
+               //              Using `auto`:
+               //              |       dojo.query("li").fadeOut({ auto:true }).filter(filterFn).forEach(doit);
+               //
+               return this._anim(baseFx, "fadeOut", args); // dojo.Animation|dojo.NodeList
+       },
 
-               toggleDropDown: function(){
-                       // summary:
-                       //              Toggle the drop-down widget; if it is up, close it, if not, open it
-                       // tags:
-                       //              protected
+       animateProperty: function(args){
+               // summary:
+               //              Animate all elements of this NodeList across the properties specified.
+               //              syntax identical to `dojo.animateProperty`
+               //
+               // args: Object?
+               //              Additional dojo.Animation arguments to mix into this set with the addition of
+               //              an `auto` parameter.
+               //
+               // returns: dojo.Animation|dojo.NodeList
+               //              A special args member `auto` can be passed to automatically play the animation.
+               //              If args.auto is present, the original dojo.NodeList will be returned for further
+               //              chaining. Otherwise the dojo.Animation instance is returned and must be .play()'ed
+               //
+               // example:
+               //      |       dojo.query(".zork").animateProperty({
+               //      |               duration: 500,
+               //      |               properties: {
+               //      |                       color:          { start: "black", end: "white" },
+               //      |                       left:           { end: 300 }
+               //      |               }
+               //      |       }).play();
+               //
+               //      example:
+               //      |       dojo.query(".grue").animateProperty({
+               //      |               auto:true,
+               //      |               properties: {
+               //      |                       height:240
+               //      |               }
+               //      |       }).onclick(handler);
+               return this._anim(baseFx, "animateProperty", args); // dojo.Animation|dojo.NodeList
+       },
 
-                       if(this.disabled || this.readOnly){ return; }
-                       this.focus();
-                       var dropDown = this.dropDown;
-                       if(!dropDown){ return; }
-                       if(!this._opened){
-                               // If we aren't loaded, load it first so there isn't a flicker
-                               if(!this.isLoaded()){
-                                       this.loadDropDown(dojo.hitch(this, "openDropDown"));
-                                       return;
-                               }else{
-                                       this.openDropDown();
-                               }
-                       }else{
-                               this.closeDropDown();
-                       }
-               },
-
-               openDropDown: function(){
-                       // summary:
-                       //              Opens the dropdown for this widget - it returns the
-                       //              return value of dijit.popup.open
-                       // tags:
-                       //              protected
-
-                       var dropDown = this.dropDown;
-                       var ddNode = dropDown.domNode;
-                       var self = this;
-
-                       // Prepare our popup's height and honor maxHeight if it exists.
-
-                       // TODO: isn't maxHeight dependent on the return value from dijit.popup.open(),
-                       // ie, dependent on how much space is available (BK)
-
-                       if(!this._preparedNode){
-                               dijit.popup.moveOffScreen(ddNode);
-                               this._preparedNode = true;                      
-                               // Check if we have explicitly set width and height on the dropdown widget dom node
-                               if(ddNode.style.width){
-                                       this._explicitDDWidth = true;
-                               }
-                               if(ddNode.style.height){
-                                       this._explicitDDHeight = true;
-                               }
-                       }
-
-                       // Code for resizing dropdown (height limitation, or increasing width to match my width)
-                       if(this.maxHeight || this.forceWidth || this.autoWidth){
-                               var myStyle = {
-                                       display: "",
-                                       visibility: "hidden"
-                               };
-                               if(!this._explicitDDWidth){
-                                       myStyle.width = "";
-                               }
-                               if(!this._explicitDDHeight){
-                                       myStyle.height = "";
-                               }
-                               dojo.style(ddNode, myStyle);
-                               
-                               // Get size of drop down, and determine if vertical scroll bar needed
-                               var mb = dojo.marginBox(ddNode);
-                               var overHeight = (this.maxHeight && mb.h > this.maxHeight);
-                               dojo.style(ddNode, {
-                                       overflowX: "hidden",
-                                       overflowY: overHeight ? "auto" : "hidden"
+       anim: function( /*Object*/                      properties,
+                                       /*Integer?*/            duration,
+                                       /*Function?*/           easing,
+                                       /*Function?*/           onEnd,
+                                       /*Integer?*/            delay){
+               // summary:
+               //              Animate one or more CSS properties for all nodes in this list.
+               //              The returned animation object will already be playing when it
+               //              is returned. See the docs for `dojo.anim` for full details.
+               // properties: Object
+               //              the properties to animate. does NOT support the `auto` parameter like other
+               //              NodeList-fx methods.
+               // duration: Integer?
+               //              Optional. The time to run the animations for
+               // easing: Function?
+               //              Optional. The easing function to use.
+               // onEnd: Function?
+               //              A function to be called when the animation ends
+               // delay:
+               //              how long to delay playing the returned animation
+               // example:
+               //              Another way to fade out:
+               //      |       dojo.query(".thinger").anim({ opacity: 0 });
+               // example:
+               //              animate all elements with the "thigner" class to a width of 500
+               //              pixels over half a second
+               //      |       dojo.query(".thinger").anim({ width: 500 }, 700);
+               var canim = coreFx.combine(
+                       this.map(function(item){
+                               return baseFx.animateProperty({
+                                       node: item,
+                                       properties: properties,
+                                       duration: duration||350,
+                                       easing: easing
                                });
-                               if(overHeight){
-                                       mb.h = this.maxHeight;
-                                       if("w" in mb){
-                                               mb.w += 16;     // room for vertical scrollbar
-                                       }
-                               }else{
-                                       delete mb.h;
-                               }
-                               delete mb.t;
-                               delete mb.l;
-
-                               // Adjust dropdown width to match or be larger than my width
-                               if(this.forceWidth){
-                                       mb.w = this.domNode.offsetWidth;
-                               }else if(this.autoWidth){
-                                       mb.w = Math.max(mb.w, this.domNode.offsetWidth);
-                               }else{
-                                       delete mb.w;
-                               }
-                               
-                               // And finally, resize the dropdown to calculated height and width
-                               if(dojo.isFunction(dropDown.resize)){
-                                       dropDown.resize(mb);
-                               }else{
-                                       dojo.marginBox(ddNode, mb);
-                               }
-                       }
-
-                       var retVal = dijit.popup.open({
-                               parent: this,
-                               popup: dropDown,
-                               around: this._aroundNode,
-                               orient: dijit.getPopupAroundAlignment((this.dropDownPosition && this.dropDownPosition.length) ? this.dropDownPosition : ["below"],this.isLeftToRight()),
-                               onExecute: function(){
-                                       self.closeDropDown(true);
-                               },
-                               onCancel: function(){
-                                       self.closeDropDown(true);
-                               },
-                               onClose: function(){
-                                       dojo.attr(self._popupStateNode, "popupActive", false);
-                                       dojo.removeClass(self._popupStateNode, "dijitHasDropDownOpen");
-                                       self._opened = false;
-                                       self.state = "";
-                               }
-                       });
-                       dojo.attr(this._popupStateNode, "popupActive", "true");
-                       dojo.addClass(self._popupStateNode, "dijitHasDropDownOpen");
-                       this._opened=true;
-                       this.state="Opened";
-                       // TODO: set this.checked and call setStateClass(), to affect button look while drop down is shown
-                       return retVal;
-               },
-
-               closeDropDown: function(/*Boolean*/ focus){
-                       // summary:
-                       //              Closes the drop down on this widget
-                       // tags:
-                       //              protected
-
-                       if(this._opened){
-                               if(focus){ this.focus(); }
-                               dijit.popup.close(this.dropDown);
-                               this._opened = false;
-                               this.state = "";
-                       }
+                       })
+               );
+               if(onEnd){
+                       connectLib.connect(canim, "onEnd", onEnd);
                }
-
+               return canim.play(delay||0); // dojo.Animation
        }
-);
-
-}
-
-if(!dojo._hasResource["dijit.form.Button"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.Button"] = true;
-dojo.provide("dijit.form.Button");
+});
 
+return NodeList;
+});
 
+},
+'dijit/form/_ListMouseMixin':function(){
+define("dijit/form/_ListMouseMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/touch",
+       "./_ListBase"
+], function(declare, event, touch, _ListBase){
 
+/*=====
+var _ListBase = dijit.form._ListBase;
+=====*/
 
+// module:
+//             dijit/form/_ListMouseMixin
+// summary:
+//             a mixin to handle mouse or touch events for a focus-less menu
 
-dojo.declare("dijit.form.Button",
-       dijit.form._FormWidget,
-       {
+return declare( "dijit.form._ListMouseMixin", _ListBase, {
        // summary:
-       //              Basically the same thing as a normal HTML button, but with special styling.
-       // description:
-       //              Buttons can display a label, an icon, or both.
-       //              A label should always be specified (through innerHTML) or the label
-       //              attribute.  It can be hidden via showLabel=false.
-       // example:
-       // |    <button dojoType="dijit.form.Button" onClick="...">Hello world</button>
-       //
-       // example:
-       // |    var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
-       // |    dojo.body().appendChild(button1.domNode);
-
-       // label: HTML String
-       //              Text to display in button.
-       //              If the label is hidden (showLabel=false) then and no title has
-       //              been specified, then label is also set as title attribute of icon.
-       label: "",
-
-       // showLabel: Boolean
-       //              Set this to true to hide the label text and display only the icon.
-       //              (If showLabel=false then iconClass must be specified.)
-       //              Especially useful for toolbars.
-       //              If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
-       //
-       //              The exception case is for computers in high-contrast mode, where the label
-       //              will still be displayed, since the icon doesn't appear.
-       showLabel: true,
-
-       // iconClass: String
-       //              Class to apply to DOMNode in button to make it display an icon
-       iconClass: "",
-
-       // type: String
-       //              Defines the type of button.  "button", "submit", or "reset".
-       type: "button",
-
-       baseClass: "dijitButton",
-
-       templateString: dojo.cache("dijit.form", "templates/Button.html", "<span class=\"dijit dijitReset dijitInline\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdojoAttachPoint=\"titleNode,focusNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" dojoAttachPoint=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#x25CF;</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdojoAttachPoint=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\tdojoAttachPoint=\"valueNode\"\n/></span>\n"),
-
-       attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-               value: "valueNode",
-               iconClass: { node: "iconNode", type: "class" }
-       }),
-
-
-       _onClick: function(/*Event*/ e){
-               // summary:
-               //              Internal function to handle click actions
-               if(this.disabled){
-                       return false;
-               }
-               this._clicked(); // widget click actions
-               return this.onClick(e); // user click actions
-       },
-
-       _onButtonClick: function(/*Event*/ e){
-               // summary:
-               //              Handler when the user activates the button portion.
-               if(this._onClick(e) === false){ // returning nothing is same as true
-                       e.preventDefault(); // needed for checkbox
-               }else if(this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a nonform widget needs to be signalled
-                       for(var node=this.domNode; node.parentNode/*#5935*/; node=node.parentNode){
-                               var widget=dijit.byNode(node);
-                               if(widget && typeof widget._onSubmit == "function"){
-                                       widget._onSubmit(e);
-                                       break;
-                               }
-                       }
-               }else if(this.valueNode){
-                       this.valueNode.click();
-                       e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click
-               }
-       },
-
-       _fillContent: function(/*DomNode*/ source){
-               // Overrides _Templated._fillContent().
-               // If button label is specified as srcNodeRef.innerHTML rather than
-               // this.params.label, handle it here.
-               if(source && (!this.params || !("label" in this.params))){
-                       this.set('label', source.innerHTML);
-               }
-       },
+       //              a Mixin to handle mouse or touch events for a focus-less menu
+       //              Abstract methods that must be defined externally:
+       //                      onClick: item was chosen (mousedown somewhere on the menu and mouseup somewhere on the menu)
+       // tags:
+       //              private
 
        postCreate: function(){
-               dojo.setSelectable(this.focusNode, false);
                this.inherited(arguments);
+               this.connect(this.domNode, touch.press, "_onMouseDown");
+               this.connect(this.domNode, touch.release, "_onMouseUp");
+               this.connect(this.domNode, "onmouseover", "_onMouseOver");
+               this.connect(this.domNode, "onmouseout", "_onMouseOut");
        },
 
-       _setShowLabelAttr: function(val){
-               if(this.containerNode){
-                       dojo.toggleClass(this.containerNode, "dijitDisplayNone", !val);
+       _onMouseDown: function(/*Event*/ evt){
+               event.stop(evt);
+               if(this._hoveredNode){
+                       this.onUnhover(this._hoveredNode);
+                       this._hoveredNode = null;
                }
-               this.showLabel = val;
-       },
-
-       onClick: function(/*Event*/ e){
-               // summary:
-               //              Callback for when button is clicked.
-               //              If type="submit", return true to perform submit, or false to cancel it.
-               // type:
-               //              callback
-               return true;            // Boolean
+               this._isDragging = true;
+               this._setSelectedAttr(this._getTarget(evt));
        },
 
-       _clicked: function(/*Event*/ e){
-               // summary:
-               //              Internal overridable function for when the button is clicked
+       _onMouseUp: function(/*Event*/ evt){
+               event.stop(evt);
+               this._isDragging = false;
+               var selectedNode = this._getSelectedAttr();
+               var target = this._getTarget(evt);
+               var hoveredNode = this._hoveredNode;
+               if(selectedNode && target == selectedNode){
+                       this.onClick(selectedNode);
+               }else if(hoveredNode && target == hoveredNode){ // drag to select
+                       this._setSelectedAttr(hoveredNode);
+                       this.onClick(hoveredNode);
+               }
        },
 
-       setLabel: function(/*String*/ content){
-               // summary:
-               //              Deprecated.  Use set('label', ...) instead.
-               dojo.deprecated("dijit.form.Button.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
-               this.set("label", content);
+       _onMouseOut: function(/*Event*/ /*===== evt ====*/){
+               if(this._hoveredNode){
+                       this.onUnhover(this._hoveredNode);
+                       if(this._getSelectedAttr() == this._hoveredNode){
+                               this.onSelect(this._hoveredNode);
+                       }
+                       this._hoveredNode = null;
+               }
+               if(this._isDragging){
+                       this._cancelDrag = (new Date()).getTime() + 1000; // cancel in 1 second if no _onMouseOver fires
+               }
        },
 
-       _setLabelAttr: function(/*String*/ content){
-               // summary:
-               //              Hook for attr('label', ...) to work.
-               // description:
-               //              Set the label (text) of the button; takes an HTML string.
-               this.containerNode.innerHTML = this.label = content;
-               if(this.showLabel == false && !this.params.title){
-                       this.titleNode.title = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+       _onMouseOver: function(/*Event*/ evt){
+               if(this._cancelDrag){
+                       var time = (new Date()).getTime();
+                       if(time > this._cancelDrag){
+                               this._isDragging = false;
+                       }
+                       this._cancelDrag = null;
+               }
+               var node = this._getTarget(evt);
+               if(!node){ return; }
+               if(this._hoveredNode != node){
+                       if(this._hoveredNode){
+                               this._onMouseOut({ target: this._hoveredNode });
+                       }
+                       if(node && node.parentNode == this.containerNode){
+                               if(this._isDragging){
+                                       this._setSelectedAttr(node);
+                               }else{
+                                       this._hoveredNode = node;
+                                       this.onHover(node);
+                               }
+                       }
                }
        }
 });
 
+});
 
-dojo.declare("dijit.form.DropDownButton", [dijit.form.Button, dijit._Container, dijit._HasDropDown], {
+},
+'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\"\n\tdata-dojo-attach-event=\"onkeypress:_onKeyPress\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n",
+'dojo/cookie':function(){
+define("dojo/cookie", ["./_base/kernel", "./regexp"], function(dojo, regexp) {
+       // module:
+       //              dojo/cookie
        // summary:
-       //              A button with a drop down
-       //
-       // example:
-       // |    <button dojoType="dijit.form.DropDownButton" label="Hello world">
-       // |            <div dojotype="dijit.Menu">...</div>
-       // |    </button>
-       //
-       // example:
-       // |    var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
-       // |    dojo.body().appendChild(button1);
-       //
+       //              TODOC
 
-       baseClass : "dijitDropDownButton",
-
-       templateString: dojo.cache("dijit.form", "templates/DropDownButton.html", "<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdojoAttachEvent=\"ondijitclick:_onButtonClick\" dojoAttachPoint=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdojoAttachPoint=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true,labelledby-${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdojoAttachPoint=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdojoAttachPoint=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\tdojoAttachPoint=\"valueNode\"\n/></span>\n"),
 
-       _fillContent: function(){
-               // Overrides Button._fillContent().
-               //
-               // My inner HTML contains both the button contents and a drop down widget, like
-               // <DropDownButton>  <span>push me</span>  <Menu> ... </Menu> </DropDownButton>
-               // The first node is assumed to be the button content. The widget is the popup.
+/*=====
+dojo.__cookieProps = function(){
+       //      expires: Date|String|Number?
+       //              If a number, the number of days from today at which the cookie
+       //              will expire. If a date, the date past which the cookie will expire.
+       //              If expires is in the past, the cookie will be deleted.
+       //              If expires is omitted or is 0, the cookie will expire when the browser closes.
+       //      path: String?
+       //              The path to use for the cookie.
+       //      domain: String?
+       //              The domain to use for the cookie.
+       //      secure: Boolean?
+       //              Whether to only send the cookie on secure connections
+       this.expires = expires;
+       this.path = path;
+       this.domain = domain;
+       this.secure = secure;
+}
+=====*/
 
-               if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
-                       //FIXME: figure out how to filter out the widget and use all remaining nodes as button
-                       //      content, not just nodes[0]
-                       var nodes = dojo.query("*", this.srcNodeRef);
-                       dijit.form.DropDownButton.superclass._fillContent.call(this, nodes[0]);
 
-                       // save pointer to srcNode so we can grab the drop down widget after it's instantiated
-                       this.dropDownContainer = this.srcNodeRef;
-               }
-       },
-
-       startup: function(){
-               if(this._started){ return; }
-
-               // the child widget from srcNodeRef is the dropdown widget.  Insert it in the page DOM,
-               // make it invisible, and store a reference to pass to the popup code.
-               if(!this.dropDown){
-                       var dropDownNode = dojo.query("[widgetId]", this.dropDownContainer)[0];
-                       this.dropDown = dijit.byNode(dropDownNode);
-                       delete this.dropDownContainer;
+dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
+       //      summary:
+       //              Get or set a cookie.
+       //      description:
+       //              If one argument is passed, returns the value of the cookie
+       //              For two or more arguments, acts as a setter.
+       //      name:
+       //              Name of the cookie
+       //      value:
+       //              Value for the cookie
+       //      props:
+       //              Properties for the cookie
+       //      example:
+       //              set a cookie with the JSON-serialized contents of an object which
+       //              will expire 5 days from now:
+       //      |       dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
+       //
+       //      example:
+       //              de-serialize a cookie back into a JavaScript object:
+       //      |       var config = dojo.fromJson(dojo.cookie("configObj"));
+       //
+       //      example:
+       //              delete a cookie:
+       //      |       dojo.cookie("configObj", null, {expires: -1});
+       var c = document.cookie, ret;
+       if(arguments.length == 1){
+               var matches = c.match(new RegExp("(?:^|; )" + regexp.escapeString(name) + "=([^;]*)"));
+               ret = matches ? decodeURIComponent(matches[1]) : undefined; 
+       }else{
+               props = props || {};
+// FIXME: expires=0 seems to disappear right away, not on close? (FF3)  Change docs?
+               var exp = props.expires;
+               if(typeof exp == "number"){
+                       var d = new Date();
+                       d.setTime(d.getTime() + exp*24*60*60*1000);
+                       exp = props.expires = d;
                }
-               dijit.popup.moveOffScreen(this.dropDown.domNode);
+               if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
 
-               this.inherited(arguments);
-       },
+               value = encodeURIComponent(value);
+               var updatedCookie = name + "=" + value, propName;
+               for(propName in props){
+                       updatedCookie += "; " + propName;
+                       var propValue = props[propName];
+                       if(propValue !== true){ updatedCookie += "=" + propValue; }
+               }
+               document.cookie = updatedCookie;
+       }
+       return ret; // String|undefined
+};
 
-       isLoaded: function(){
-               // Returns whether or not we are loaded - if our dropdown has an href,
-               // then we want to check that.
-               var dropDown = this.dropDown;
-               return (!dropDown.href || dropDown.isLoaded);
-       },
+dojo.cookie.isSupported = function(){
+       //      summary:
+       //              Use to determine if the current browser supports cookies or not.
+       //
+       //              Returns true if user allows cookies.
+       //              Returns false if user doesn't allow cookies.
 
-       loadDropDown: function(){
-               // Loads our dropdown
-               var dropDown = this.dropDown;
-               if(!dropDown){ return; }
-               if(!this.isLoaded()){
-                       var handler = dojo.connect(dropDown, "onLoad", this, function(){
-                               dojo.disconnect(handler);
-                               this.openDropDown();
-                       });
-                       dropDown.refresh();
-               }else{
-                       this.openDropDown();
+       if(!("cookieEnabled" in navigator)){
+               this("__djCookieTest__", "CookiesAllowed");
+               navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
+               if(navigator.cookieEnabled){
+                       this("__djCookieTest__", "", {expires: -1});
                }
-       },
-
-       isFocusable: function(){
-               // Overridden so that focus is handled by the _HasDropDown mixin, not by
-               // the _FormWidget mixin.
-               return this.inherited(arguments) && !this._mouseDown;
        }
+       return navigator.cookieEnabled;
+};
+
+return dojo.cookie;
 });
 
-dojo.declare("dijit.form.ComboButton", dijit.form.DropDownButton, {
+},
+'dojo/cache':function(){
+define("dojo/cache", ["./_base/kernel", "./text"], function(dojo, text){
+       // module:
+       //              dojo/cache
        // summary:
-       //              A combination button and drop-down button.
-       //              Users can click one side to "press" the button, or click an arrow
-       //              icon to display the drop down.
-       //
-       // example:
-       // |    <button dojoType="dijit.form.ComboButton" onClick="...">
-       // |            <span>Hello world</span>
-       // |            <div dojoType="dijit.Menu">...</div>
-       // |    </button>
+       //              The module defines dojo.cache by loading dojo/text.
+
+       //dojo.cache is defined in dojo/text
+       return dojo.cache;
+});
+
+},
+'url:dijit/form/templates/DropDownBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\"\n\trole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdata-dojo-attach-point=\"_buttonNode, _popupStateNode\" role=\"presentation\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"&#9660; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&#935; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdata-dojo-attach-point=\"textbox,focusNode\" role=\"textbox\" aria-haspopup=\"true\"\n\t/></div\n></div>\n",
+'dijit/ProgressBar':function(){
+require({cache:{
+'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\n\t><div  data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\n\t\t><span style=\"visibility:hidden\">&#160;</span\n\t></div\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\n/></div>\n"}});
+define("dijit/ProgressBar", [
+       "require",                      // require.toUrl
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.toggle
+       "dojo/_base/lang", // lang.mixin
+       "dojo/number", // number.format
+       "./_Widget",
+       "./_TemplatedMixin",
+       "dojo/text!./templates/ProgressBar.html"
+], function(require, declare, domClass, lang, number, _Widget, _TemplatedMixin, template){
+
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+=====*/
+
+// module:
+//             dijit/ProgressBar
+// summary:
+//             A progress indication widget, showing the amount completed
+//             (often the percentage completed) of a task.
+
+
+return declare("dijit.ProgressBar", [_Widget, _TemplatedMixin], {
+       // summary:
+       //              A progress indication widget, showing the amount completed
+       //              (often the percentage completed) of a task.
        //
        // example:
-       // |    var button1 = new dijit.form.ComboButton({label: "hello world", onClick: foo, dropDown: "myMenu"});
-       // |    dojo.body().appendChild(button1.domNode);
-       //
+       // |    <div data-dojo-type="ProgressBar"
+       // |             places="0"
+       // |             value="..." maximum="...">
+       // |    </div>
 
-       templateString: dojo.cache("dijit.form", "templates/ComboButton.html", "<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tcellspacing='0' cellpadding='0' waiRole=\"presentation\"\n\t><tbody waiRole=\"presentation\"><tr waiRole=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonNode\" dojoAttachPoint=\"buttonNode\" dojoAttachEvent=\"ondijitclick:_onButtonClick,onkeypress:_onButtonKeyPress\"\n\t\t><div id=\"${id}_button\" class=\"dijitReset dijitButtonContents\"\n\t\t\tdojoAttachPoint=\"titleNode\"\n\t\t\twaiRole=\"button\" waiState=\"labelledby-${id}_label\"\n\t\t\t><div class=\"dijitReset dijitInline dijitIcon\" dojoAttachPoint=\"iconNode\" waiRole=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitInline dijitButtonText\" id=\"${id}_label\" dojoAttachPoint=\"containerNode\" waiRole=\"presentation\"></div\n\t\t></div\n\t\t></td\n\t\t><td id=\"${id}_arrow\" class='dijitReset dijitRight dijitButtonNode dijitArrowButton'\n\t\t\tdojoAttachPoint=\"_popupStateNode,focusNode,_buttonNode\"\n\t\t\tdojoAttachEvent=\"onkeypress:_onArrowKeyPress\"\n\t\t\ttitle=\"${optionsTitle}\"\n\t\t\twaiRole=\"button\" waiState=\"haspopup-true\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" waiRole=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" waiRole=\"presentation\">&#9660;</div\n\t\t></td\n\t\t><td style=\"display:none !important;\"\n\t\t\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" dojoAttachPoint=\"valueNode\"\n\t\t/></td></tr></tbody\n></table>\n"),
+       // progress: [const] String (Percentage or Number)
+       //              Number or percentage indicating amount of task completed.
+       //              Deprecated.   Use "value" instead.
+       progress: "0",
+
+       // value: String (Percentage or Number)
+       //              Number or percentage indicating amount of task completed.
+       //              With "%": percentage value, 0% <= progress <= 100%, or
+       //              without "%": absolute value, 0 <= progress <= maximum.
+       //              Infinity means that the progress bar is indeterminate.
+       value: "",
 
-       attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
-               id: "",
-               tabIndex: ["focusNode", "titleNode"],
-               title: "titleNode"
-       }),
+       // maximum: [const] Float
+       //              Max sample number
+       maximum: 100,
 
-       // optionsTitle: String
-       //              Text that describes the options menu (accessibility)
-       optionsTitle: "",
+       // places: [const] Number
+       //              Number of places to show in values; 0 by default
+       places: 0,
 
-       baseClass: "dijitComboButton",
+       // indeterminate: [const] Boolean
+       //              If false: show progress value (number or percentage).
+       //              If true: show that a process is underway but that the amount completed is unknown.
+       //              Deprecated.   Use "value" instead.
+       indeterminate: false,
 
-       // Set classes like dijitButtonContentsHover or dijitArrowButtonActive depending on
-       // mouse action over specified node
-       cssStateNodes: {
-               "buttonNode": "dijitButtonNode",
-               "titleNode": "dijitButtonContents",
-               "_popupStateNode": "dijitDownArrowButton"
-       },
+       // label: String?
+       //              Label on progress bar.   Defaults to percentage for determinate progress bar and
+       //              blank for indeterminate progress bar.
+       label:"",
 
-       _focusedNode: null,
+       // name: String
+       //              this is the field name (for a form) if set. This needs to be set if you want to use
+       //              this widget in a dijit.form.Form widget (such as dijit.Dialog)
+       name: '',
 
-       _onButtonKeyPress: function(/*Event*/ evt){
-               // summary:
-               //              Handler for right arrow key when focus is on left part of button
-               if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "RIGHT_ARROW" : "LEFT_ARROW"]){
-                       dijit.focus(this._popupStateNode);
-                       dojo.stopEvent(evt);
+       templateString: template,
+
+       // _indeterminateHighContrastImagePath: [private] URL
+       //              URL to image to use for indeterminate progress bar when display is in high contrast mode
+       _indeterminateHighContrastImagePath:
+               require.toUrl("./themes/a11y/indeterminate_progress.gif"),
+
+       postMixInProperties: function(){
+               this.inherited(arguments);
+               if(!("value" in this.params)){
+                       this.value = this.indeterminate ? Infinity : this.progress;
                }
        },
 
-       _onArrowKeyPress: function(/*Event*/ evt){
-               // summary:
-               //              Handler for left arrow key when focus is on right part of button
-               if(evt.charOrCode == dojo.keys[this.isLeftToRight() ? "LEFT_ARROW" : "RIGHT_ARROW"]){
-                       dijit.focus(this.titleNode);
-                       dojo.stopEvent(evt);
-               }
+       buildRendering: function(){
+               this.inherited(arguments);
+               this.indeterminateHighContrastImage.setAttribute("src",
+                       this._indeterminateHighContrastImagePath.toString());
+               this.update();
        },
-       
-       focus: function(/*String*/ position){
+
+       update: function(/*Object?*/attributes){
                // summary:
-               //              Focuses this widget to according to position, if specified,
-               //              otherwise on arrow node
-               // position:
-               //              "start" or "end"
-               
-               dijit.focus(position == "start" ? this.titleNode : this._popupStateNode);
-       }
-});
+               //              Internal method to change attributes of ProgressBar, similar to set(hash).  Users should call
+               //              set("value", ...) rather than calling this method directly.
+               // attributes:
+               //              May provide progress and/or maximum properties on this parameter;
+               //              see attribute specs for details.
+               // example:
+               //      |       myProgressBar.update({'indeterminate': true});
+               //      |       myProgressBar.update({'progress': 80});
+               //      |       myProgressBar.update({'indeterminate': true, label:"Loading ..." })
+               // tags:
+               //              private
 
-dojo.declare("dijit.form.ToggleButton", dijit.form.Button, {
-       // summary:
-       //              A button that can be in two states (checked or not).
-       //              Can be base class for things like tabs or checkbox or radio buttons
+               // TODO: deprecate this method and use set() instead
 
-       baseClass: "dijitToggleButton",
+               lang.mixin(this, attributes || {});
+               var tip = this.internalProgress, ap = this.domNode;
+               var percent = 1;
+               if(this.indeterminate){
+                       ap.removeAttribute("aria-valuenow");
+                       ap.removeAttribute("aria-valuemin");
+                       ap.removeAttribute("aria-valuemax");
+               }else{
+                       if(String(this.progress).indexOf("%") != -1){
+                               percent = Math.min(parseFloat(this.progress)/100, 1);
+                               this.progress = percent * this.maximum;
+                       }else{
+                               this.progress = Math.min(this.progress, this.maximum);
+                               percent = this.maximum ? this.progress / this.maximum : 0;
+                       }
 
-       // checked: Boolean
-       //              Corresponds to the native HTML <input> element's attribute.
-       //              In markup, specified as "checked='checked'" or just "checked".
-       //              True if the button is depressed, or the checkbox is checked,
-       //              or the radio button is selected, etc.
-       checked: false,
+                       ap.setAttribute("aria-describedby", this.labelNode.id);
+                       ap.setAttribute("aria-valuenow", this.progress);
+                       ap.setAttribute("aria-valuemin", 0);
+                       ap.setAttribute("aria-valuemax", this.maximum);
+               }
+               this.labelNode.innerHTML = this.report(percent);
 
-       attributeMap: dojo.mixin(dojo.clone(dijit.form.Button.prototype.attributeMap), {
-               checked:"focusNode"
-       }),
+               domClass.toggle(this.domNode, "dijitProgressBarIndeterminate", this.indeterminate);
+               tip.style.width = (percent * 100) + "%";
+               this.onChange();
+       },
 
-       _clicked: function(/*Event*/ evt){
-               this.set('checked', !this.checked);
+       _setValueAttr: function(v){
+               this._set("value", v);
+               if(v == Infinity){
+                       this.update({indeterminate:true});
+               }else{
+                       this.update({indeterminate:false, progress:v});
+               }
        },
 
-       _setCheckedAttr: function(/*Boolean*/ value, /* Boolean? */ priorityChange){
-               this.checked = value;
-               dojo.attr(this.focusNode || this.domNode, "checked", value);
-               dijit.setWaiState(this.focusNode || this.domNode, "pressed", value);
-               this._handleOnChange(value, priorityChange);
+       _setLabelAttr: function(label){
+               this._set("label", label);
+               this.update();
        },
 
-       setChecked: function(/*Boolean*/ checked){
-               // summary:
-               //              Deprecated.   Use set('checked', true/false) instead.
-               dojo.deprecated("setChecked("+checked+") is deprecated. Use set('checked',"+checked+") instead.", "", "2.0");
-               this.set('checked', checked);
+       _setIndeterminateAttr: function(indeterminate){
+               // Deprecated, use set("value", ...) instead
+               this.indeterminate = indeterminate;
+               this.update();
        },
 
-       reset: function(){
+       report: function(/*float*/percent){
                // summary:
-               //              Reset the widget's value to what it was at initialization time
+               //              Generates message to show inside progress bar (normally indicating amount of task completed).
+               //              May be overridden.
+               // tags:
+               //              extension
 
-               this._hasBeenBlurred = false;
+               return this.label ? this.label :
+                               (this.indeterminate ? "&#160;" : number.format(percent, { type: "percent", places: this.places, locale: this.lang }));
+       },
 
-               // set checked state to original setting
-               this.set('checked', this.params.checked || false);
+       onChange: function(){
+               // summary:
+               //              Callback fired when progress updates.
+               // tags:
+               //              extension
        }
 });
 
-}
+});
 
-if(!dojo._hasResource["dijit.form.ToggleButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.ToggleButton"] = true;
-dojo.provide("dijit.form.ToggleButton");
+},
+'dijit/_base/popup':function(){
+define("dijit/_base/popup", [
+       "dojo/dom-class", // domClass.contains
+       "../popup",
+       "../BackgroundIframe"   // just loading for back-compat, in case client code is referencing it
+], function(domClass, popup){
+
+// module:
+//             dijit/_base/popup
+// summary:
+//             Old module for popups, new code should use dijit/popup directly
+
+
+// Hack support for old API passing in node instead of a widget (to various methods)
+var origCreateWrapper = popup._createWrapper;
+popup._createWrapper = function(widget){
+       if(!widget.declaredClass){
+               // make fake widget to pass to new API
+               widget = {
+                       _popupWrapper: (widget.parentNode && domClass.contains(widget.parentNode, "dijitPopup")) ?
+                               widget.parentNode : null,
+                       domNode: widget,
+                       destroy: function(){}
+               };
+       }
+       return origCreateWrapper.call(this, widget);
+};
 
+// Support old format of orient parameter
+var origOpen = popup.open;
+popup.open = function(/*dijit.popup.__OpenArgs*/ args){
+       // Convert old hash structure (ex: {"BL": "TL", ...}) of orient to format compatible w/new popup.open() API.
+       // Don't do conversion for:
+       //              - null parameter (that means to use the default positioning)
+       //              - "R" or "L" strings used to indicate positioning for context menus (when there is no around node)
+       //              - new format, ex: ["below", "above"]
+       //              - return value from deprecated dijit.getPopupAroundAlignment() method,
+       //                      ex: ["below", "above"]
+       if(args.orient && typeof args.orient != "string" && !("length" in args.orient)){
+               var ary = [];
+               for(var key in args.orient){
+                       ary.push({aroundCorner: key, corner: args.orient[key]});
+               }
+               args.orient = ary;
+       }
 
-}
+       return origOpen.call(this, args);
+};
 
-if(!dojo._hasResource["dijit.form.CheckBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.CheckBox"] = true;
-dojo.provide("dijit.form.CheckBox");
+return popup;
+});
 
+},
+'dijit/ColorPalette':function(){
+require({cache:{
+'url:dijit/templates/ColorPalette.html':"<div class=\"dijitInline dijitColorPalette\">\n\t<table dojoAttachPoint=\"paletteTableNode\" class=\"dijitPaletteTable\" cellSpacing=\"0\" cellPadding=\"0\" role=\"grid\">\n\t\t<tbody data-dojo-attach-point=\"gridNode\"></tbody>\n\t</table>\n</div>\n"}});
+define("dijit/ColorPalette", [
+       "require",              // require.toUrl
+       "dojo/text!./templates/ColorPalette.html",
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_PaletteMixin",
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/Color", // dojo.Color dojo.Color.named
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.contains
+       "dojo/dom-construct", // domConstruct.place
+       "dojo/_base/window", // win.body
+       "dojo/string", // string.substitute
+       "dojo/i18n!dojo/nls/colors",    // translations
+       "dojo/colors"   // extend dojo.Color w/names of other colors
+], function(require, template, _Widget, _TemplatedMixin, _PaletteMixin, i18n, Color,
+       declare, domClass, domConstruct, win, string){
 
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _PaletteMixin = dijit._PaletteMixin;
+=====*/
 
-dojo.declare(
-       "dijit.form.CheckBox",
-       dijit.form.ToggleButton,
-       {
-               // summary:
-               //              Same as an HTML checkbox, but with fancy styling.
-               //
-               // description:
-               //              User interacts with real html inputs.
-               //              On onclick (which occurs by mouse click, space-bar, or
-               //              using the arrow keys to switch the selected radio button),
-               //              we update the state of the checkbox/radio.
-               //
-               //              There are two modes:
-               //                      1. High contrast mode
-               //                      2. Normal mode
-               //
-               //              In case 1, the regular html inputs are shown and used by the user.
-               //              In case 2, the regular html inputs are invisible but still used by
-               //              the user. They are turned quasi-invisible and overlay the background-image.
+// module:
+//             dijit/ColorPalette
+// summary:
+//             A keyboard accessible color-picking widget
 
-               templateString: dojo.cache("dijit.form", "templates/CheckBox.html", "<div class=\"dijit dijitReset dijitInline\" waiRole=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdojoAttachPoint=\"focusNode\"\n\t \tdojoAttachEvent=\"onclick:_onClick\"\n/></div>\n"),
+var ColorPalette = declare("dijit.ColorPalette", [_Widget, _TemplatedMixin, _PaletteMixin], {
+       // summary:
+       //              A keyboard accessible color-picking widget
+       // description:
+       //              Grid showing various colors, so the user can pick a certain color.
+       //              Can be used standalone, or as a popup.
+       //
+       // example:
+       // |    <div data-dojo-type="dijit.ColorPalette"></div>
+       //
+       // example:
+       // |    var picker = new dijit.ColorPalette({ },srcNode);
+       // |    picker.startup();
 
-               baseClass: "dijitCheckBox",
 
-               // type: [private] String
-               //              type attribute on <input> node.
-               //              Overrides `dijit.form.Button.type`.   Users should not change this value.
-               type: "checkbox",
+       // palette: [const] String
+       //              Size of grid, either "7x10" or "3x4".
+       palette: "7x10",
 
-               // value: String
-               //              As an initialization parameter, equivalent to value field on normal checkbox
-               //              (if checked, the value is passed as the value when form is submitted).
-               //
-               //              However, attr('value') will return either the string or false depending on
-               //              whether or not the checkbox is checked.
-               //
-               //              attr('value', string) will check the checkbox and change the value to the
-               //              specified string
-               //
-               //              attr('value', boolean) will change the checked state.
-               value: "on",
+       // _palettes: [protected] Map
+       //              This represents the value of the colors.
+       //              The first level is a hashmap of the different palettes available.
+       //              The next two dimensions represent the columns and rows of colors.
+       _palettes: {
+               "7x10": [["white", "seashell", "cornsilk", "lemonchiffon","lightyellow", "palegreen", "paleturquoise", "lightcyan",     "lavender", "plum"],
+                               ["lightgray", "pink", "bisque", "moccasin", "khaki", "lightgreen", "lightseagreen", "lightskyblue", "cornflowerblue", "violet"],
+                               ["silver", "lightcoral", "sandybrown", "orange", "palegoldenrod", "chartreuse", "mediumturquoise",      "skyblue", "mediumslateblue","orchid"],
+                               ["gray", "red", "orangered", "darkorange", "yellow", "limegreen",       "darkseagreen", "royalblue", "slateblue", "mediumorchid"],
+                               ["dimgray", "crimson",  "chocolate", "coral", "gold", "forestgreen", "seagreen", "blue", "blueviolet", "darkorchid"],
+                               ["darkslategray","firebrick","saddlebrown", "sienna", "olive", "green", "darkcyan", "mediumblue","darkslateblue", "darkmagenta" ],
+                               ["black", "darkred", "maroon", "brown", "darkolivegreen", "darkgreen", "midnightblue", "navy", "indigo",        "purple"]],
 
-               // readOnly: Boolean
-               //              Should this widget respond to user input?
-               //              In markup, this is specified as "readOnly".
-               //              Similar to disabled except readOnly form values are submitted.
-               readOnly: false,
-               
-               // the attributeMap should inherit from dijit.form._FormWidget.prototype.attributeMap 
-               // instead of ToggleButton as the icon mapping has no meaning for a CheckBox
-               attributeMap: dojo.delegate(dijit.form._FormWidget.prototype.attributeMap, {
-                       readOnly: "focusNode"
-               }),
+               "3x4": [["white", "lime", "green", "blue"],
+                       ["silver", "yellow", "fuchsia", "navy"],
+                       ["gray", "red", "purple", "black"]]
+       },
 
-               _setReadOnlyAttr: function(/*Boolean*/ value){
-                       this.readOnly = value;
-                       dojo.attr(this.focusNode, 'readOnly', value);
-                       dijit.setWaiState(this.focusNode, "readonly", value);
-               },
+       // templateString: String
+       //              The template of this widget.
+       templateString: template,
 
-               _setValueAttr: function(/*String or Boolean*/ newValue, /*Boolean*/ priorityChange){
-                       // summary:
-                       //              Handler for value= attribute to constructor, and also calls to
-                       //              attr('value', val).
-                       // description:
-                       //              During initialization, just saves as attribute to the <input type=checkbox>.
-                       //
-                       //              After initialization,
-                       //              when passed a boolean, controls whether or not the CheckBox is checked.
-                       //              If passed a string, changes the value attribute of the CheckBox (the one
-                       //              specified as "value" when the CheckBox was constructed (ex: <input
-                       //              dojoType="dijit.CheckBox" value="chicken">)
-                       if(typeof newValue == "string"){
-                               this.value = newValue;
-                               dojo.attr(this.focusNode, 'value', newValue);
-                               newValue = true;
-                       }
-                       if(this._created){
-                               this.set('checked', newValue, priorityChange);
-                       }
-               },
-               _getValueAttr: function(){
-                       // summary:
-                       //              Hook so attr('value') works.
-                       // description:
-                       //              If the CheckBox is checked, returns the value attribute.
-                       //              Otherwise returns false.
-                       return (this.checked ? this.value : false);
-               },
+       baseClass: "dijitColorPalette",
 
-               // Override dijit.form.Button._setLabelAttr() since we don't even have a containerNode.
-               // Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox.layout.TabContainer
-               _setLabelAttr: undefined,
+       _dyeFactory: function(value, row, col){
+               // Overrides _PaletteMixin._dyeFactory().
+               return new this._dyeClass(value, row, col);
+       },
 
-               postMixInProperties: function(){
-                       if(this.value == ""){
-                               this.value = "on";
-                       }
+       buildRendering: function(){
+               // Instantiate the template, which makes a skeleton into which we'll insert a bunch of
+               // <img> nodes
+               this.inherited(arguments);
 
-                       // Need to set initial checked state as part of template, so that form submit works.
-                       // dojo.attr(node, "checked", bool) doesn't work on IEuntil node has been attached
-                       // to <body>, see #8666
-                       this.checkedAttrSetting = this.checked ? "checked" : "";
+               //      Creates customized constructor for dye class (color of a single cell) for
+               //      specified palette and high-contrast vs. normal mode.   Used in _getDye().
+               this._dyeClass = declare(ColorPalette._Color, {
+                       hc: domClass.contains(win.body(), "dijit_a11y"),
+                       palette: this.palette
+               });
 
-                       this.inherited(arguments);
-               },
+               // Creates <img> nodes in each cell of the template.
+               this._preparePalette(
+                       this._palettes[this.palette],
+                       i18n.getLocalization("dojo", "colors", this.lang));
+       }
+});
 
-                _fillContent: function(/*DomNode*/ source){
-                       // Override Button::_fillContent() since it doesn't make sense for CheckBox,
-                       // since CheckBox doesn't even have a container
-               },
+ColorPalette._Color = declare("dijit._Color", Color, {
+       // summary:
+       //              Object associated with each cell in a ColorPalette palette.
+       //              Implements dijit.Dye.
 
-               reset: function(){
-                       // Override ToggleButton.reset()
+       // Template for each cell in normal (non-high-contrast mode).  Each cell contains a wrapper
+       // node for showing the border (called dijitPaletteImg for back-compat), and dijitColorPaletteSwatch
+       // for showing the color.
+       template:
+               "<span class='dijitInline dijitPaletteImg'>" +
+                       "<img src='${blankGif}' alt='${alt}' class='dijitColorPaletteSwatch' style='background-color: ${color}'/>" +
+               "</span>",
+
+       // Template for each cell in high contrast mode.  Each cell contains an image with the whole palette,
+       // but scrolled and clipped to show the correct color only
+       hcTemplate:
+               "<span class='dijitInline dijitPaletteImg' style='position: relative; overflow: hidden; height: 12px; width: 14px;'>" +
+                       "<img src='${image}' alt='${alt}' style='position: absolute; left: ${left}px; top: ${top}px; ${size}'/>" +
+               "</span>",
 
-                       this._hasBeenBlurred = false;
+       // _imagePaths: [protected] Map
+       //              This is stores the path to the palette images used for high-contrast mode display
+       _imagePaths: {
+               "7x10": require.toUrl("./themes/a11y/colors7x10.png"),
+               "3x4": require.toUrl("./themes/a11y/colors3x4.png")
+       },
 
-                       this.set('checked', this.params.checked || false);
+       constructor: function(/*String*/alias, /*Number*/ row, /*Number*/ col){
+               this._alias = alias;
+               this._row = row;
+               this._col = col;
+               this.setColor(Color.named[alias]);
+       },
 
-                       // Handle unlikely event that the <input type=checkbox> value attribute has changed
-                       this.value = this.params.value || "on";
-                       dojo.attr(this.focusNode, 'value', this.value);
-               },
+       getValue: function(){
+               // summary:
+               //              Note that although dijit._Color is initialized with a value like "white" getValue() always
+               //              returns a hex value
+               return this.toHex();
+       },
 
-               _onFocus: function(){
-                       if(this.id){
-                               dojo.query("label[for='"+this.id+"']").addClass("dijitFocusedLabel");
-                       }
-                       this.inherited(arguments);
-               },
+       fillCell: function(/*DOMNode*/ cell, /*String*/ blankGif){
+               var html = string.substitute(this.hc ? this.hcTemplate : this.template, {
+                       // substitution variables for normal mode
+                       color: this.toHex(),
+                       blankGif: blankGif,
+                       alt: this._alias,
 
-               _onBlur: function(){
-                       if(this.id){
-                               dojo.query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel");
-                       }
-                       this.inherited(arguments);
-               },
+                       // variables used for high contrast mode
+                       image: this._imagePaths[this.palette].toString(),
+                       left: this._col * -20 - 5,
+                       top: this._row * -20 - 5,
+                       size: this.palette == "7x10" ? "height: 145px; width: 206px" : "height: 64px; width: 86px"
+               });
 
-               _onClick: function(/*Event*/ e){
-                       // summary:
-                       //              Internal function to handle click actions - need to check
-                       //              readOnly, since button no longer does that check.
-                       if(this.readOnly){
-                               return false;
-                       }
-                       return this.inherited(arguments);
-               }
+               domConstruct.place(html, cell);
        }
-);
+});
 
-dojo.declare(
-       "dijit.form.RadioButton",
-       dijit.form.CheckBox,
-       {
-               // summary:
-               //              Same as an HTML radio, but with fancy styling.
 
-               type: "radio",
-               baseClass: "dijitRadio",
+return ColorPalette;
+});
 
-               _setCheckedAttr: function(/*Boolean*/ value){
-                       // If I am being checked then have to deselect currently checked radio button
-                       this.inherited(arguments);
-                       if(!this._created){ return; }
-                       if(value){
-                               var _this = this;
-                               // search for radio buttons with the same name that need to be unchecked
-                               dojo.query("INPUT[type=radio]", this.focusNode.form || dojo.doc).forEach( // can't use name= since dojo.query doesn't support [] in the name
-                                       function(inputNode){
-                                               if(inputNode.name == _this.name && inputNode != _this.focusNode && inputNode.form == _this.focusNode.form){
-                                                       var widget = dijit.getEnclosingWidget(inputNode);
-                                                       if(widget && widget.checked){
-                                                               widget.set('checked', false);
+},
+'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#x25CF;</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n",
+'dojo/_base/url':function(){
+define("dojo/_base/url", ["./kernel"], function(dojo) {
+       // module:
+       //              dojo/url
+       // summary:
+       //              This module contains dojo._Url
+
+       var
+               ore = new RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$"),
+               ire = new RegExp("^((([^\\[:]+):)?([^@]+)@)?(\\[([^\\]]+)\\]|([^\\[:]*))(:([0-9]+))?$"),
+               _Url = function(){
+                       var n = null,
+                               _a = arguments,
+                               uri = [_a[0]];
+                       // resolve uri components relative to each other
+                       for(var i = 1; i<_a.length; i++){
+                               if(!_a[i]){ continue; }
+
+                               // Safari doesn't support this.constructor so we have to be explicit
+                               // FIXME: Tracked (and fixed) in Webkit bug 3537.
+                               //              http://bugs.webkit.org/show_bug.cgi?id=3537
+                               var relobj = new _Url(_a[i]+""),
+                                       uriobj = new _Url(uri[0]+"");
+
+                               if(
+                                       relobj.path == "" &&
+                                       !relobj.scheme &&
+                                       !relobj.authority &&
+                                       !relobj.query
+                               ){
+                                       if(relobj.fragment != n){
+                                               uriobj.fragment = relobj.fragment;
+                                       }
+                                       relobj = uriobj;
+                               }else if(!relobj.scheme){
+                                       relobj.scheme = uriobj.scheme;
+
+                                       if(!relobj.authority){
+                                               relobj.authority = uriobj.authority;
+
+                                               if(relobj.path.charAt(0) != "/"){
+                                                       var path = uriobj.path.substring(0,
+                                                               uriobj.path.lastIndexOf("/") + 1) + relobj.path;
+
+                                                       var segs = path.split("/");
+                                                       for(var j = 0; j < segs.length; j++){
+                                                               if(segs[j] == "."){
+                                                                       // flatten "./" references
+                                                                       if(j == segs.length - 1){
+                                                                               segs[j] = "";
+                                                                       }else{
+                                                                               segs.splice(j, 1);
+                                                                               j--;
+                                                                       }
+                                                               }else if(j > 0 && !(j == 1 && segs[0] == "") &&
+                                                                       segs[j] == ".." && segs[j-1] != ".."){
+                                                                       // flatten "../" references
+                                                                       if(j == (segs.length - 1)){
+                                                                               segs.splice(j, 1);
+                                                                               segs[j - 1] = "";
+                                                                       }else{
+                                                                               segs.splice(j - 1, 2);
+                                                                               j -= 2;
+                                                                       }
+                                                               }
                                                        }
+                                                       relobj.path = segs.join("/");
                                                }
                                        }
-                               );
+                               }
+
+                               uri = [];
+                               if(relobj.scheme){
+                                       uri.push(relobj.scheme, ":");
+                               }
+                               if(relobj.authority){
+                                       uri.push("//", relobj.authority);
+                               }
+                               uri.push(relobj.path);
+                               if(relobj.query){
+                                       uri.push("?", relobj.query);
+                               }
+                               if(relobj.fragment){
+                                       uri.push("#", relobj.fragment);
+                               }
                        }
-               },
 
-               _clicked: function(/*Event*/ e){
-                       if(!this.checked){
-                               this.set('checked', true);
+                       this.uri = uri.join("");
+
+                       // break the uri into its main components
+                       var r = this.uri.match(ore);
+
+                       this.scheme = r[2] || (r[1] ? "" : n);
+                       this.authority = r[4] || (r[3] ? "" : n);
+                       this.path = r[5]; // can never be undefined
+                       this.query = r[7] || (r[6] ? "" : n);
+                       this.fragment    = r[9] || (r[8] ? "" : n);
+
+                       if(this.authority != n){
+                               // server based naming authority
+                               r = this.authority.match(ire);
+
+                               this.user = r[3] || n;
+                               this.password = r[4] || n;
+                               this.host = r[6] || r[7]; // ipv6 || ipv4
+                               this.port = r[9] || n;
                        }
+               };
+       _Url.prototype.toString = function(){ return this.uri; };
+
+       return dojo._Url = _Url;
+});
+
+},
+'dojo/text':function(){
+define("dojo/text", ["./_base/kernel", "require", "./has", "./_base/xhr"], function(dojo, require, has, xhr){
+       // module:
+       //              dojo/text
+       // summary:
+       //              This module implements the !dojo/text plugin and the dojo.cache API.
+       // description:
+       //              We choose to include our own plugin to leverage functionality already contained in dojo
+       //              and thereby reduce the size of the plugin compared to various foreign loader implementations.
+       //              Also, this allows foreign AMD loaders to be used without their plugins.
+       //
+       //              CAUTION: this module is designed to optionally function synchronously to support the dojo v1.x synchronous
+       //              loader. This feature is outside the scope of the CommonJS plugins specification.
+
+       var getText;
+       if(1){
+               getText= function(url, sync, load){
+                       xhr("GET", {url:url, sync:!!sync, load:load});
+               };
+       }else{
+               // TODOC: only works for dojo AMD loader
+               if(require.getText){
+                       getText= require.getText;
+               }else{
+                       console.error("dojo/text plugin failed to load because loader does not support getText");
                }
        }
-);
 
-}
+       var
+               theCache= {},
+
+               strip= function(text){
+                       //Strips <?xml ...?> declarations so that external SVG and XML
+                       //documents can be added to a document without worry. Also, if the string
+                       //is an HTML document, only the part inside the body tag is returned.
+                       if(text){
+                               text= text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im, "");
+                               var matches= text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+                               if(matches){
+                                       text= matches[1];
+                               }
+                       }else{
+                               text = "";
+                       }
+                       return text;
+               },
 
-if(!dojo._hasResource["dijit.form.DropDownButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.DropDownButton"] = true;
-dojo.provide("dijit.form.DropDownButton");
+               notFound = {},
 
+               pending = {},
 
+               result= {
+                       dynamic:
+                               // the dojo/text caches it's own resources because of dojo.cache
+                               true,
 
-}
+                       normalize:function(id, toAbsMid){
+                               // id is something like (path may be relative):
+                               //
+                               //       "path/to/text.html"
+                               //       "path/to/text.html!strip"
+                               var parts= id.split("!"),
+                                       url= parts[0];
+                               return (/^\./.test(url) ? toAbsMid(url) : url) + (parts[1] ? "!" + parts[1] : "");
+                       },
+
+                       load:function(id, require, load){
+                               // id is something like (path is always absolute):
+                               //
+                               //       "path/to/text.html"
+                               //       "path/to/text.html!strip"
+                               var
+                                       parts= id.split("!"),
+                                       stripFlag= parts.length>1,
+                                       absMid= parts[0],
+                                       url = require.toUrl(parts[0]),
+                                       text = notFound,
+                                       finish = function(text){
+                                               load(stripFlag ? strip(text) : text);
+                                       };
+                               if(absMid in theCache){
+                                       text = theCache[absMid];
+                               }else if(url in require.cache){
+                                       text = require.cache[url];
+                               }else if(url in theCache){
+                                       text = theCache[url];
+                               }
+                               if(text===notFound){
+                                       if(pending[url]){
+                                               pending[url].push(finish);
+                                       }else{
+                                               var pendingList = pending[url] = [finish];
+                                               getText(url, !require.async, function(text){
+                                                       theCache[absMid]= theCache[url]= text;
+                                                       for(var i = 0; i<pendingList.length;){
+                                                               pendingList[i++](text);
+                                                       }
+                                                       delete pending[url];
+                                               });
+                                       }
+                               }else{
+                                       finish(text);
+                               }
+                       }
+               };
+
+       dojo.cache= function(/*String||Object*/module, /*String*/url, /*String||Object?*/value){
+               //       * (string string [value]) => (module, url, value)
+               //       * (object [value])        => (module, value), url defaults to ""
+               //
+               //       * if module is an object, then it must be convertable to a string
+               //       * (module, url) module + (url ? ("/" + url) : "") must be a legal argument to require.toUrl
+               //       * value may be a string or an object; if an object then may have the properties "value" and/or "sanitize"
+               var key;
+               if(typeof module=="string"){
+                       if(/\//.test(module)){
+                               // module is a version 1.7+ resolved path
+                               key = module;
+                               value = url;
+                       }else{
+                               // module is a version 1.6- argument to dojo.moduleUrl
+                               key = require.toUrl(module.replace(/\./g, "/") + (url ? ("/" + url) : ""));
+                       }
+               }else{
+                       key = module + "";
+                       value = url;
+               }
+               var
+                       val = (value != undefined && typeof value != "string") ? value.value : value,
+                       sanitize = value && value.sanitize;
+
+               if(typeof val == "string"){
+                       //We have a string, set cache value
+                       theCache[key] = val;
+                       return sanitize ? strip(val) : val;
+               }else if(val === null){
+                       //Remove cached value
+                       delete theCache[key];
+                       return null;
+               }else{
+                       //Allow cache values to be empty strings. If key property does
+                       //not exist, fetch it.
+                       if(!(key in theCache)){
+                               getText(key, true, function(text){
+                                       theCache[key]= text;
+                               });
+                       }
+                       return sanitize ? strip(theCache[key]) : theCache[key];
+               }
+       };
 
-if(!dojo._hasResource["dojo.regexp"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.regexp"] = true;
-dojo.provide("dojo.regexp");
+       return result;
 
 /*=====
-dojo.regexp = {
-       // summary: Regular expressions and Builder resources
+dojo.cache = function(module, url, value){
+       // summary:
+       //              A getter and setter for storing the string content associated with the
+       //              module and url arguments.
+       // description:
+       //              If module is a string that contains slashes, then it is interpretted as a fully
+       //              resolved path (typically a result returned by require.toUrl), and url should not be
+       //              provided. This is the preferred signature. If module is a string that does not
+       //              contain slashes, then url must also be provided and module and url are used to
+       //              call `dojo.moduleUrl()` to generate a module URL. This signature is deprecated.
+       //              If value is specified, the cache value for the moduleUrl will be set to
+       //              that value. Otherwise, dojo.cache will fetch the moduleUrl and store it
+       //              in its internal cache and return that cached value for the URL. To clear
+       //              a cache value pass null for value. Since XMLHttpRequest (XHR) is used to fetch the
+       //              the URL contents, only modules on the same domain of the page can use this capability.
+       //              The build system can inline the cache values though, to allow for xdomain hosting.
+       // module: String||Object
+       //              If a String with slashes, a fully resolved path; if a String without slashes, the
+       //              module name to use for the base part of the URL, similar to module argument
+       //              to `dojo.moduleUrl`. If an Object, something that has a .toString() method that
+       //              generates a valid path for the cache item. For example, a dojo._Url object.
+       // url: String
+       //              The rest of the path to append to the path derived from the module argument. If
+       //              module is an object, then this second argument should be the "value" argument instead.
+       // value: String||Object?
+       //              If a String, the value to use in the cache for the module/url combination.
+       //              If an Object, it can have two properties: value and sanitize. The value property
+       //              should be the value to use in the cache, and sanitize can be set to true or false,
+       //              to indicate if XML declarations should be removed from the value and if the HTML
+       //              inside a body tag in the value should be extracted as the real value. The value argument
+       //              or the value property on the value argument are usually only used by the build system
+       //              as it inlines cache content.
+       //      example:
+       //              To ask dojo.cache to fetch content and store it in the cache (the dojo["cache"] style
+       //              of call is used to avoid an issue with the build system erroneously trying to intern
+       //              this example. To get the build system to intern your dojo.cache calls, use the
+       //              "dojo.cache" style of call):
+       //              | //If template.html contains "<h1>Hello</h1>" that will be
+       //              | //the value for the text variable.
+       //              | var text = dojo["cache"]("my.module", "template.html");
+       //      example:
+       //              To ask dojo.cache to fetch content and store it in the cache, and sanitize the input
+       //               (the dojo["cache"] style of call is used to avoid an issue with the build system
+       //              erroneously trying to intern this example. To get the build system to intern your
+       //              dojo.cache calls, use the "dojo.cache" style of call):
+       //              | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
+       //              | //text variable will contain just "<h1>Hello</h1>".
+       //              | var text = dojo["cache"]("my.module", "template.html", {sanitize: true});
+       //      example:
+       //              Same example as previous, but demostrates how an object can be passed in as
+       //              the first argument, then the value argument can then be the second argument.
+       //              | //If template.html contains "<html><body><h1>Hello</h1></body></html>", the
+       //              | //text variable will contain just "<h1>Hello</h1>".
+       //              | var text = dojo["cache"](new dojo._Url("my/module/template.html"), {sanitize: true});
+       return val; //String
 };
 =====*/
+});
 
-dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){
-       //      summary:
-       //              Adds escape sequences for special characters in regular expressions
-       // except:
-       //              a String with special characters to be left unescaped
 
-       return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){
-               if(except && except.indexOf(ch) != -1){
-                       return ch;
-               }
-               return "\\" + ch;
-       }); // String
-}
+},
+'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n",
+'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n",
+'dojo/uacss':function(){
+define("dojo/uacss", ["./dom-geometry", "./_base/lang", "./ready", "./_base/sniff", "./_base/window"],
+       function(geometry, lang, ready, has, baseWindow){
+       // module:
+       //              dojo/uacss
+       // summary:
+       //              Applies pre-set CSS classes to the top-level HTML node, based on:
+       //                      - browser (ex: dj_ie)
+       //                      - browser version (ex: dj_ie6)
+       //                      - box model (ex: dj_contentBox)
+       //                      - text direction (ex: dijitRtl)
+       //
+       //              In addition, browser, browser version, and box model are
+       //              combined with an RTL flag when browser text is RTL. ex: dj_ie-rtl.
 
-dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
-       //      summary:
-       //              Builds a regular expression that groups subexpressions
-       //      description:
-       //              A utility function used by some of the RE generators. The
-       //              subexpressions are constructed by the function, re, in the second
-       //              parameter.  re builds one subexpression for each elem in the array
-       //              a, in the first parameter. Returns a string for a regular
-       //              expression that groups all the subexpressions.
-       // arr:
-       //              A single value or an array of values.
-       // re:
-       //              A function. Takes one parameter and converts it to a regular
-       //              expression. 
-       // nonCapture:
-       //              If true, uses non-capturing match, otherwise matches are retained
-       //              by regular expression. Defaults to false
+       var
+               html = baseWindow.doc.documentElement,
+               ie = has("ie"),
+               opera = has("opera"),
+               maj = Math.floor,
+               ff = has("ff"),
+               boxModel = geometry.boxModel.replace(/-/,''),
 
-       // case 1: a is a single value.
-       if(!(arr instanceof Array)){
-               return re(arr); // String
-       }
+               classes = {
+                       "dj_ie": ie,
+                       "dj_ie6": maj(ie) == 6,
+                       "dj_ie7": maj(ie) == 7,
+                       "dj_ie8": maj(ie) == 8,
+                       "dj_ie9": maj(ie) == 9,
+                       "dj_quirks": has("quirks"),
+                       "dj_iequirks": ie && has("quirks"),
 
-       // case 2: a is an array
-       var b = [];
-       for(var i = 0; i < arr.length; i++){
-               // convert each elem to a RE
-               b.push(re(arr[i]));
-       }
+                       // NOTE: Opera not supported by dijit
+                       "dj_opera": opera,
 
-        // join the REs as alternatives in a RE group.
-       return dojo.regexp.group(b.join("|"), nonCapture); // String
-}
+                       "dj_khtml": has("khtml"),
 
-dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
-       // summary:
-       //              adds group match to expression
-       // nonCapture:
-       //              If true, uses non-capturing match, otherwise matches are retained
-       //              by regular expression. 
-       return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
-}
-
-}
-
-if(!dojo._hasResource["dojo.data.util.sorter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.data.util.sorter"] = true;
-dojo.provide("dojo.data.util.sorter");
+                       "dj_webkit": has("webkit"),
+                       "dj_safari": has("safari"),
+                       "dj_chrome": has("chrome"),
 
-dojo.data.util.sorter.basicComparator = function(      /*anything*/ a, 
-                                                                                                       /*anything*/ b){
-       //      summary:  
-       //              Basic comparision function that compares if an item is greater or less than another item
-       //      description:  
-       //              returns 1 if a > b, -1 if a < b, 0 if equal.
-       //              'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list.
-       //              And compared to each other, null is equivalent to undefined.
-       
-       //null is a problematic compare, so if null, we set to undefined.
-       //Makes the check logic simple, compact, and consistent
-       //And (null == undefined) === true, so the check later against null
-       //works for undefined and is less bytes.
-       var r = -1;
-       if(a === null){
-               a = undefined;
-       }
-       if(b === null){
-               b = undefined;
-       }
-       if(a == b){
-               r = 0; 
-       }else if(a > b || a == null){
-               r = 1; 
-       }
-       return r; //int {-1,0,1}
-};
+                       "dj_gecko": has("mozilla"),
+                       "dj_ff3": maj(ff) == 3
+               }; // no dojo unsupported browsers
 
-dojo.data.util.sorter.createSortFunction = function(   /* attributes array */sortSpec,
-                                                                                                               /*dojo.data.core.Read*/ store){
-       //      summary:  
-       //              Helper function to generate the sorting function based off the list of sort attributes.
-       //      description:  
-       //              The sort function creation will look for a property on the store called 'comparatorMap'.  If it exists
-       //              it will look in the mapping for comparisons function for the attributes.  If one is found, it will
-       //              use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.
-       //              Returns the sorting function for this particular list of attributes and sorting directions.
-       //
-       //      sortSpec: array
-       //              A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.
-       //              The objects should be formatted as follows:
-       //              {
-       //                      attribute: "attributeName-string" || attribute,
-       //                      descending: true|false;   // Default is false.
-       //              }
-       //      store: object
-       //              The datastore object to look up item values from.
-       //
-       var sortFunctions=[];
+       classes["dj_" + boxModel] = true;
 
-       function createSortFunction(attr, dir, comp, s){
-               //Passing in comp and s (comparator and store), makes this
-               //function much faster.
-               return function(itemA, itemB){
-                       var a = s.getValue(itemA, attr);
-                       var b = s.getValue(itemB, attr);
-                       return dir * comp(a,b); //int
-               };
-       }
-       var sortAttribute;
-       var map = store.comparatorMap;
-       var bc = dojo.data.util.sorter.basicComparator;
-       for(var i = 0; i < sortSpec.length; i++){
-               sortAttribute = sortSpec[i];
-               var attr = sortAttribute.attribute;
-               if(attr){
-                       var dir = (sortAttribute.descending) ? -1 : 1;
-                       var comp = bc;
-                       if(map){
-                               if(typeof attr !== "string" && ("toString" in attr)){
-                                        attr = attr.toString();
-                               }
-                               comp = map[attr] || bc;
-                       }
-                       sortFunctions.push(createSortFunction(attr, 
-                               dir, comp, store));
+       // apply browser, browser version, and box model class names
+       var classStr = "";
+       for(var clz in classes){
+               if(classes[clz]){
+                       classStr += clz + " ";
                }
        }
-       return function(rowA, rowB){
-               var i=0;
-               while(i < sortFunctions.length){
-                       var ret = sortFunctions[i++](rowA, rowB);
-                       if(ret !== 0){
-                               return ret;//int
-                       }
+       html.className = lang.trim(html.className + " " + classStr);
+
+       // If RTL mode, then add dj_rtl flag plus repeat existing classes with -rtl extension.
+       // We can't run the code below until the <body> tag has loaded (so we can check for dir=rtl).
+       // priority is 90 to run ahead of parser priority of 100
+       ready(90, function(){
+               if(!geometry.isBodyLtr()){
+                       var rtlClassStr = "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl ");
+                       html.className = lang.trim(html.className + " " + rtlClassStr + "dj_rtl dijitRtl " + classStr.replace(/ /g, "-rtl "));
                }
-               return 0; //int  
-       }; // Function
-};
+       });
+       return has;
+});
 
-}
+},
+'dijit/Tooltip':function(){
+require({cache:{
+'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n"}});
+define("dijit/Tooltip", [
+       "dojo/_base/array", // array.forEach array.indexOf array.map
+       "dojo/_base/declare", // declare
+       "dojo/_base/fx", // fx.fadeIn fx.fadeOut
+       "dojo/dom", // dom.byId
+       "dojo/dom-class", // domClass.add
+       "dojo/dom-geometry", // domGeometry.getMarginBox domGeometry.position
+       "dojo/dom-style", // domStyle.set, domStyle.get
+       "dojo/_base/lang", // lang.hitch lang.isArrayLike
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/window", // win.body
+       "./_base/manager",      // manager.defaultDuration
+       "./place",
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./BackgroundIframe",
+       "dojo/text!./templates/Tooltip.html",
+       "."             // sets dijit.showTooltip etc. for back-compat
+], function(array, declare, fx, dom, domClass, domGeometry, domStyle, lang, has, win,
+                       manager, place, _Widget, _TemplatedMixin, BackgroundIframe, template, dijit){
 
-if(!dojo._hasResource["dojo.data.util.simpleFetch"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.data.util.simpleFetch"] = true;
-dojo.provide("dojo.data.util.simpleFetch");
+/*=====
+       var _Widget = dijit._Widget;
+       var BackgroundIframe = dijit.BackgroundIframe;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+=====*/
 
+       // module:
+       //              dijit/Tooltip
+       // summary:
+       //              Defines dijit.Tooltip widget (to display a tooltip), showTooltip()/hideTooltip(), and _MasterTooltip
 
-dojo.data.util.simpleFetch.fetch = function(/* Object? */ request){
-       //      summary:
-       //              The simpleFetch mixin is designed to serve as a set of function(s) that can
-       //              be mixed into other datastore implementations to accelerate their development.  
-       //              The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems() 
-       //              call by returning an array of all the found items that matched the query.  The simpleFetch mixin
-       //              is not designed to work for datastores that respond to a fetch() call by incrementally
-       //              loading items, or sequentially loading partial batches of the result
-       //              set.  For datastores that mixin simpleFetch, simpleFetch 
-       //              implements a fetch method that automatically handles eight of the fetch()
-       //              arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope
-       //              The class mixing in simpleFetch should not implement fetch(),
-       //              but should instead implement a _fetchItems() method.  The _fetchItems() 
-       //              method takes three arguments, the keywordArgs object that was passed 
-       //              to fetch(), a callback function to be called when the result array is
-       //              available, and an error callback to be called if something goes wrong.
-       //              The _fetchItems() method should ignore any keywordArgs parameters for
-       //              start, count, onBegin, onItem, onComplete, onError, sort, and scope.  
-       //              The _fetchItems() method needs to correctly handle any other keywordArgs
-       //              parameters, including the query parameter and any optional parameters 
-       //              (such as includeChildren).  The _fetchItems() method should create an array of 
-       //              result items and pass it to the fetchHandler along with the original request object 
-       //              -- or, the _fetchItems() method may, if it wants to, create an new request object 
-       //              with other specifics about the request that are specific to the datastore and pass 
-       //              that as the request object to the handler.
-       //
-       //              For more information on this specific function, see dojo.data.api.Read.fetch()
-       request = request || {};
-       if(!request.store){
-               request.store = this;
-       }
-       var self = this;
 
-       var _errorHandler = function(errorData, requestObject){
-               if(requestObject.onError){
-                       var scope = requestObject.scope || dojo.global;
-                       requestObject.onError.call(scope, errorData, requestObject);
-               }
-       };
+       var MasterTooltip = declare("dijit._MasterTooltip", [_Widget, _TemplatedMixin], {
+               // summary:
+               //              Internal widget that holds the actual tooltip markup,
+               //              which occurs once per page.
+               //              Called by Tooltip widgets which are just containers to hold
+               //              the markup
+               // tags:
+               //              protected
 
-       var _fetchHandler = function(items, requestObject){
-               var oldAbortFunction = requestObject.abort || null;
-               var aborted = false;
+               // duration: Integer
+               //              Milliseconds to fade in/fade out
+               duration: manager.defaultDuration,
 
-               var startIndex = requestObject.start?requestObject.start:0;
-               var endIndex = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length;
+               templateString: template,
 
-               requestObject.abort = function(){
-                       aborted = true;
-                       if(oldAbortFunction){
-                               oldAbortFunction.call(requestObject);
-                       }
-               };
+               postCreate: function(){
+                       win.body().appendChild(this.domNode);
 
-               var scope = requestObject.scope || dojo.global;
-               if(!requestObject.store){
-                       requestObject.store = self;
-               }
-               if(requestObject.onBegin){
-                       requestObject.onBegin.call(scope, items.length, requestObject);
-               }
-               if(requestObject.sort){
-                       items.sort(dojo.data.util.sorter.createSortFunction(requestObject.sort, self));
-               }
-               if(requestObject.onItem){
-                       for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
-                               var item = items[i];
-                               if(!aborted){
-                                       requestObject.onItem.call(scope, item, requestObject);
-                               }
-                       }
-               }
-               if(requestObject.onComplete && !aborted){
-                       var subset = null;
-                       if(!requestObject.onItem){
-                               subset = items.slice(startIndex, endIndex);
-                       }
-                       requestObject.onComplete.call(scope, subset, requestObject);
-               }
-       };
-       this._fetchItems(request, _fetchHandler, _errorHandler);
-       return request; // Object
-};
+                       this.bgIframe = new BackgroundIframe(this.domNode);
 
-}
+                       // Setup fade-in and fade-out functions.
+                       this.fadeIn = fx.fadeIn({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onShow") });
+                       this.fadeOut = fx.fadeOut({ node: this.domNode, duration: this.duration, onEnd: lang.hitch(this, "_onHide") });
+               },
 
-if(!dojo._hasResource["dojo.data.util.filter"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.data.util.filter"] = true;
-dojo.provide("dojo.data.util.filter");
+               show: function(innerHTML, aroundNode, position, rtl, textDir){
+                       // summary:
+                       //              Display tooltip w/specified contents to right of specified node
+                       //              (To left if there's no space on the right, or if rtl == true)
+                       // innerHTML: String
+                       //              Contents of the tooltip
+                       // aroundNode: DomNode || dijit.__Rectangle
+                       //              Specifies that tooltip should be next to this node / area
+                       // position: String[]?
+                       //              List of positions to try to position tooltip (ex: ["right", "above"])
+                       // rtl: Boolean?
+                       //              Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
+                       //              means "rtl"; specifies GUI direction, not text direction.
+                       // textDir: String?
+                       //              Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
+
+
+                       if(this.aroundNode && this.aroundNode === aroundNode && this.containerNode.innerHTML == innerHTML){
+                               return;
+                       }
 
-dojo.data.util.filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){
-       //      summary:  
-       //              Helper function to convert a simple pattern to a regular expression for matching.
-       //      description:
-       //              Returns a regular expression object that conforms to the defined conversion rules.
-       //              For example:  
-       //                      ca*   -> /^ca.*$/
-       //                      *ca*  -> /^.*ca.*$/
-       //                      *c\*a*  -> /^.*c\*a.*$/
-       //                      *c\*a?*  -> /^.*c\*a..*$/
-       //                      and so on.
-       //
-       //      pattern: string
-       //              A simple matching pattern to convert that follows basic rules:
-       //                      * Means match anything, so ca* means match anything starting with ca
-       //                      ? Means match single character.  So, b?b will match to bob and bab, and so on.
-       //              \ is an escape character.  So for example, \* means do not treat * as a match, but literal character *.
-       //                              To use a \ as a character in the string, it must be escaped.  So in the pattern it should be 
-       //                              represented by \\ to be treated as an ordinary \ character instead of an escape.
-       //
-       //      ignoreCase:
-       //              An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing
-       //              By default, it is assumed case sensitive.
+                       // reset width; it may have been set by orient() on a previous tooltip show()
+                       this.domNode.width = "auto";
 
-       var rxp = "^";
-       var c = null;
-       for(var i = 0; i < pattern.length; i++){
-               c = pattern.charAt(i);
-               switch(c){
-                       case '\\':
-                               rxp += c;
-                               i++;
-                               rxp += pattern.charAt(i);
-                               break;
-                       case '*':
-                               rxp += ".*"; break;
-                       case '?':
-                               rxp += "."; break;
-                       case '$':
-                       case '^':
-                       case '/':
-                       case '+':
-                       case '.':
-                       case '|':
-                       case '(':
-                       case ')':
-                       case '{':
-                       case '}':
-                       case '[':
-                       case ']':
-                               rxp += "\\"; //fallthrough
-                       default:
-                               rxp += c;
-               }
-       }
-       rxp += "$";
-       if(ignoreCase){
-               return new RegExp(rxp,"mi"); //RegExp
-       }else{
-               return new RegExp(rxp,"m"); //RegExp
-       }
-       
-};
+                       if(this.fadeOut.status() == "playing"){
+                               // previous tooltip is being hidden; wait until the hide completes then show new one
+                               this._onDeck=arguments;
+                               return;
+                       }
+                       this.containerNode.innerHTML=innerHTML;
+                       
+                       this.set("textDir", textDir);
+                       this.containerNode.align = rtl? "right" : "left"; //fix the text alignment
 
-}
+                       var pos = place.around(this.domNode, aroundNode,
+                               position && position.length ? position : Tooltip.defaultPosition, !rtl, lang.hitch(this, "orient"));
 
-if(!dojo._hasResource["dijit.form.TextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.TextBox"] = true;
-dojo.provide("dijit.form.TextBox");
+                       // Position the tooltip connector for middle alignment.
+                       // This could not have been done in orient() since the tooltip wasn't positioned at that time.
+                       var aroundNodeCoords = pos.aroundNodePos;
+                       if(pos.corner.charAt(0) == 'M' && pos.aroundCorner.charAt(0) == 'M'){
+                               this.connectorNode.style.top = aroundNodeCoords.y + ((aroundNodeCoords.h - this.connectorNode.offsetHeight) >> 1) - pos.y + "px";
+                               this.connectorNode.style.left = "";
+                       }else if(pos.corner.charAt(1) == 'M' && pos.aroundCorner.charAt(1) == 'M'){
+                               this.connectorNode.style.left = aroundNodeCoords.x + ((aroundNodeCoords.w - this.connectorNode.offsetWidth) >> 1) - pos.x + "px";
+                       }
 
+                       // show it
+                       domStyle.set(this.domNode, "opacity", 0);
+                       this.fadeIn.play();
+                       this.isShowingNow = true;
+                       this.aroundNode = aroundNode;
+               },
 
+               orient: function(/*DomNode*/ node, /*String*/ aroundCorner, /*String*/ tooltipCorner, /*Object*/ spaceAvailable, /*Object*/ aroundNodeCoords){
+                       // summary:
+                       //              Private function to set CSS for tooltip node based on which position it's in.
+                       //              This is called by the dijit popup code.   It will also reduce the tooltip's
+                       //              width to whatever width is available
+                       // tags:
+                       //              protected
+                       this.connectorNode.style.top = ""; //reset to default
 
-dojo.declare(
-       "dijit.form.TextBox",
-       dijit.form._FormValueWidget,
-       {
-               // summary:
-               //              A base class for textbox form inputs
+                       //Adjust the spaceAvailable width, without changing the spaceAvailable object
+                       var tooltipSpaceAvaliableWidth = spaceAvailable.w - this.connectorNode.offsetWidth;
 
-               // trim: Boolean
-               //              Removes leading and trailing whitespace if true.  Default is false.
-               trim: false,
+                       node.className = "dijitTooltip " +
+                               {
+                                       "MR-ML": "dijitTooltipRight",
+                                       "ML-MR": "dijitTooltipLeft",
+                                       "TM-BM": "dijitTooltipAbove",
+                                       "BM-TM": "dijitTooltipBelow",
+                                       "BL-TL": "dijitTooltipBelow dijitTooltipABLeft",
+                                       "TL-BL": "dijitTooltipAbove dijitTooltipABLeft",
+                                       "BR-TR": "dijitTooltipBelow dijitTooltipABRight",
+                                       "TR-BR": "dijitTooltipAbove dijitTooltipABRight",
+                                       "BR-BL": "dijitTooltipRight",
+                                       "BL-BR": "dijitTooltipLeft"
+                               }[aroundCorner + "-" + tooltipCorner];
 
-               // uppercase: Boolean
-               //              Converts all characters to uppercase if true.  Default is false.
-               uppercase: false,
+                       // reduce tooltip's width to the amount of width available, so that it doesn't overflow screen
+                       this.domNode.style.width = "auto";
+                       var size = domGeometry.getContentBox(this.domNode);
 
-               // lowercase: Boolean
-               //              Converts all characters to lowercase if true.  Default is false.
-               lowercase: false,
+                       var width = Math.min((Math.max(tooltipSpaceAvaliableWidth,1)), size.w);
+                       var widthWasReduced = width < size.w;
 
-               // propercase: Boolean
-               //              Converts the first character of each word to uppercase if true.
-               propercase: false,
+                       this.domNode.style.width = width+"px";
 
-               //      maxLength: String
-               //              HTML INPUT tag maxLength declaration.
-               maxLength: "",
+                       //Adjust width for tooltips that have a really long word or a nowrap setting
+                       if(widthWasReduced){
+                               this.containerNode.style.overflow = "auto"; //temp change to overflow to detect if our tooltip needs to be wider to support the content
+                               var scrollWidth = this.containerNode.scrollWidth;
+                               this.containerNode.style.overflow = "visible"; //change it back
+                               if(scrollWidth > width){
+                                       scrollWidth = scrollWidth + domStyle.get(this.domNode,"paddingLeft") + domStyle.get(this.domNode,"paddingRight");
+                                       this.domNode.style.width = scrollWidth + "px";
+                               }
+                       }
 
-               //      selectOnClick: [const] Boolean
-               //              If true, all text will be selected when focused with mouse
-               selectOnClick: false,
+                       // Reposition the tooltip connector.
+                       if(tooltipCorner.charAt(0) == 'B' && aroundCorner.charAt(0) == 'B'){
+                               var mb = domGeometry.getMarginBox(node);
+                               var tooltipConnectorHeight = this.connectorNode.offsetHeight;
+                               if(mb.h > spaceAvailable.h){
+                                       // The tooltip starts at the top of the page and will extend past the aroundNode
+                                       var aroundNodePlacement = spaceAvailable.h - ((aroundNodeCoords.h + tooltipConnectorHeight) >> 1);
+                                       this.connectorNode.style.top = aroundNodePlacement + "px";
+                                       this.connectorNode.style.bottom = "";
+                               }else{
+                                       // Align center of connector with center of aroundNode, except don't let bottom
+                                       // of connector extend below bottom of tooltip content, or top of connector
+                                       // extend past top of tooltip content
+                                       this.connectorNode.style.bottom = Math.min(
+                                               Math.max(aroundNodeCoords.h/2 - tooltipConnectorHeight/2, 0),
+                                               mb.h - tooltipConnectorHeight) + "px";
+                                       this.connectorNode.style.top = "";
+                               }
+                       }else{
+                               // reset the tooltip back to the defaults
+                               this.connectorNode.style.top = "";
+                               this.connectorNode.style.bottom = "";
+                       }
 
-               //      placeHolder: String
-               //              Defines a hint to help users fill out the input field (as defined in HTML 5).
-               //              This should only contain plain text (no html markup).
-               placeHolder: "",
-               
-               templateString: dojo.cache("dijit.form", "templates/TextBox.html", "<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" waiRole=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" dojoAttachPoint='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"),
-               _singleNodeTemplate: '<input class="dijit dijitReset dijitLeft dijitInputField" dojoAttachPoint="textbox,focusNode" autocomplete="off" type="${type}" ${!nameAttrSetting} />',
+                       return Math.max(0, size.w - tooltipSpaceAvaliableWidth);
+               },
 
-               _buttonInputDisabled: dojo.isIE ? "disabled" : "", // allows IE to disallow focus, but Firefox cannot be disabled for mousedown events
+               _onShow: function(){
+                       // summary:
+                       //              Called at end of fade-in operation
+                       // tags:
+                       //              protected
+                       if(has("ie")){
+                               // the arrow won't show up on a node w/an opacity filter
+                               this.domNode.style.filter="";
+                       }
+               },
 
-               baseClass: "dijitTextBox",
+               hide: function(aroundNode){
+                       // summary:
+                       //              Hide the tooltip
 
-               attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
-                       maxLength: "focusNode"
-               }),
-               
-               postMixInProperties: function(){
-                       var type = this.type.toLowerCase();
-                       if(this.templateString.toLowerCase() == "input" || ((type == "hidden" || type == "file") && this.templateString == dijit.form.TextBox.prototype.templateString)){
-                               this.templateString = this._singleNodeTemplate;
+                       if(this._onDeck && this._onDeck[1] == aroundNode){
+                               // this hide request is for a show() that hasn't even started yet;
+                               // just cancel the pending show()
+                               this._onDeck=null;
+                       }else if(this.aroundNode === aroundNode){
+                               // this hide request is for the currently displayed tooltip
+                               this.fadeIn.stop();
+                               this.isShowingNow = false;
+                               this.aroundNode = null;
+                               this.fadeOut.play();
+                       }else{
+                               // just ignore the call, it's for a tooltip that has already been erased
                        }
-                       this.inherited(arguments);
                },
 
-               _setPlaceHolderAttr: function(v){
-                       this.placeHolder = v;
-                       if(!this._phspan){
-                               this._attachPoints.push('_phspan');
-                               /* dijitInputField class gives placeHolder same padding as the input field
-                                * parent node already has dijitInputField class but it doesn't affect this <span>
-                                * since it's position: absolute.
-                                */
-                               this._phspan = dojo.create('span',{className:'dijitPlaceHolder dijitInputField'},this.textbox,'after');
+               _onHide: function(){
+                       // summary:
+                       //              Called at end of fade-out operation
+                       // tags:
+                       //              protected
+
+                       this.domNode.style.cssText="";  // to position offscreen again
+                       this.containerNode.innerHTML="";
+                       if(this._onDeck){
+                               // a show request has been queued up; do it now
+                               this.show.apply(this, this._onDeck);
+                               this._onDeck=null;
                        }
-                       this._phspan.innerHTML="";
-                       this._phspan.appendChild(document.createTextNode(v));
-                       
-                       this._updatePlaceHolder();
                },
                
-               _updatePlaceHolder: function(){
-                       if(this._phspan){
-                               this._phspan.style.display=(this.placeHolder&&!this._focused&&!this.textbox.value)?"":"none";
-                       }
-               },
+               _setAutoTextDir: function(/*Object*/node){
+                   // summary:
+                   //      Resolve "auto" text direction for children nodes
+                   // tags:
+                   //          private
 
-               _getValueAttr: function(){
-                       // summary:
-                       //              Hook so attr('value') works as we like.
-                       // description:
-                       //              For `dijit.form.TextBox` this basically returns the value of the <input>.
-                       //
-                       //              For `dijit.form.MappedTextBox` subclasses, which have both
-                       //              a "displayed value" and a separate "submit value",
-                       //              This treats the "displayed value" as the master value, computing the
-                       //              submit value from it via this.parse().
-                       return this.parse(this.get('displayedValue'), this.constraints);
+            this.applyTextDir(node, has("ie") ? node.outerText : node.textContent);
+            array.forEach(node.children, function(child){this._setAutoTextDir(child); }, this);
                },
+               
+               _setTextDirAttr: function(/*String*/ textDir){
+                   // summary:
+                   //          Setter for textDir.
+                   // description:
+                   //          Users shouldn't call this function; they should be calling
+                   //          set('textDir', value)
+                   // tags:
+                   //          private
+       
+            this._set("textDir", typeof textDir != 'undefined'? textDir : "");
+           if (textDir == "auto"){
+               this._setAutoTextDir(this.containerNode);
+           }else{
+               this.containerNode.dir = this.textDir;
+           }                                           
+        }
+       });
 
-               _setValueAttr: function(value, /*Boolean?*/ priorityChange, /*String?*/ formattedValue){
-                       // summary:
-                       //              Hook so attr('value', ...) works.
-                       //
-                       // description:
-                       //              Sets the value of the widget to "value" which can be of
-                       //              any type as determined by the widget.
-                       //
-                       // value:
-                       //              The visual element value is also set to a corresponding,
-                       //              but not necessarily the same, value.
-                       //
-                       // formattedValue:
-                       //              If specified, used to set the visual element value,
-                       //              otherwise a computed visual value is used.
-                       //
-                       // priorityChange:
-                       //              If true, an onChange event is fired immediately instead of
-                       //              waiting for the next blur event.
+       dijit.showTooltip = function(innerHTML, aroundNode, position, rtl, textDir){
+               // summary:
+               //              Static method to display tooltip w/specified contents in specified position.
+               //              See description of dijit.Tooltip.defaultPosition for details on position parameter.
+               //              If position is not specified then dijit.Tooltip.defaultPosition is used.
+               // innerHTML: String
+               //              Contents of the tooltip
+               // aroundNode: dijit.__Rectangle
+               //              Specifies that tooltip should be next to this node / area
+               // position: String[]?
+               //              List of positions to try to position tooltip (ex: ["right", "above"])
+               // rtl: Boolean?
+               //              Corresponds to `WidgetBase.dir` attribute, where false means "ltr" and true
+               //              means "rtl"; specifies GUI direction, not text direction.
+               // textDir: String?
+               //              Corresponds to `WidgetBase.textdir` attribute; specifies direction of text.
+
+               // after/before don't work, but they used to, so for back-compat convert them to after-centered, before-centered
+               if(position){
+                       position = array.map(position, function(val){
+                               return {after: "after-centered", before: "before-centered"}[val] || val;
+                       });
+               }
 
-                       var filteredValue;
-                       if(value !== undefined){
-                               // TODO: this is calling filter() on both the display value and the actual value.
-                               // I added a comment to the filter() definition about this, but it should be changed.
-                               filteredValue = this.filter(value);
-                               if(typeof formattedValue != "string"){
-                                       if(filteredValue !== null && ((typeof filteredValue != "number") || !isNaN(filteredValue))){
-                                               formattedValue = this.filter(this.format(filteredValue, this.constraints));
-                                       }else{ formattedValue = ''; }
-                               }
-                       }
-                       if(formattedValue != null && formattedValue != undefined && ((typeof formattedValue) != "number" || !isNaN(formattedValue)) && this.textbox.value != formattedValue){
-                               this.textbox.value = formattedValue;
-                       }
+               if(!Tooltip._masterTT){ dijit._masterTT = Tooltip._masterTT = new MasterTooltip(); }
+               return Tooltip._masterTT.show(innerHTML, aroundNode, position, rtl, textDir);
+       };
 
-                       this._updatePlaceHolder();
+       dijit.hideTooltip = function(aroundNode){
+               // summary:
+               //              Static method to hide the tooltip displayed via showTooltip()
+               return Tooltip._masterTT && Tooltip._masterTT.hide(aroundNode);
+       };
 
-                       this.inherited(arguments, [filteredValue, priorityChange]);
-               },
+       var Tooltip = declare("dijit.Tooltip", _Widget, {
+               // summary:
+               //              Pops up a tooltip (a help message) when you hover over a node.
 
-               // displayedValue: String
-               //              For subclasses like ComboBox where the displayed value
-               //              (ex: Kentucky) and the serialized value (ex: KY) are different,
-               //              this represents the displayed value.
-               //
-               //              Setting 'displayedValue' through attr('displayedValue', ...)
-               //              updates 'value', and vice-versa.  Otherwise 'value' is updated
-               //              from 'displayedValue' periodically, like onBlur etc.
-               //
-               //              TODO: move declaration to MappedTextBox?
-               //              Problem is that ComboBox references displayedValue,
-               //              for benefit of FilteringSelect.
-               displayedValue: "",
+               // label: String
+               //              Text to display in the tooltip.
+               //              Specified as innerHTML when creating the widget from markup.
+               label: "",
 
-               getDisplayedValue: function(){
+               // showDelay: Integer
+               //              Number of milliseconds to wait after hovering over/focusing on the object, before
+               //              the tooltip is displayed.
+               showDelay: 400,
+
+               // connectId: String|String[]
+               //              Id of domNode(s) to attach the tooltip to.
+               //              When user hovers over specified dom node, the tooltip will appear.
+               connectId: [],
+
+               // position: String[]
+               //              See description of `dijit.Tooltip.defaultPosition` for details on position parameter.
+               position: [],
+
+               _setConnectIdAttr: function(/*String|String[]*/ newId){
                        // summary:
-                       //              Deprecated.   Use set('displayedValue') instead.
-                       // tags:
-                       //              deprecated
-                       dojo.deprecated(this.declaredClass+"::getDisplayedValue() is deprecated. Use set('displayedValue') instead.", "", "2.0");
-                       return this.get('displayedValue');
+                       //              Connect to specified node(s)
+
+                       // Remove connections to old nodes (if there are any)
+                       array.forEach(this._connections || [], function(nested){
+                               array.forEach(nested, lang.hitch(this, "disconnect"));
+                       }, this);
+
+                       // Make array of id's to connect to, excluding entries for nodes that don't exist yet, see startup()
+                       this._connectIds = array.filter(lang.isArrayLike(newId) ? newId : (newId ? [newId] : []),
+                                       function(id){ return dom.byId(id); });
+
+                       // Make connections
+                       this._connections = array.map(this._connectIds, function(id){
+                               var node = dom.byId(id);
+                               return [
+                                       this.connect(node, "onmouseenter", "_onHover"),
+                                       this.connect(node, "onmouseleave", "_onUnHover"),
+                                       this.connect(node, "onfocus", "_onHover"),
+                                       this.connect(node, "onblur", "_onUnHover")
+                               ];
+                       }, this);
+
+                       this._set("connectId", newId);
                },
 
-               _getDisplayedValueAttr: function(){
+               addTarget: function(/*DOMNODE || String*/ node){
                        // summary:
-                       //              Hook so attr('displayedValue') works.
-                       // description:
-                       //              Returns the displayed value (what the user sees on the screen),
-                       //              after filtering (ie, trimming spaces etc.).
-                       //
-                       //              For some subclasses of TextBox (like ComboBox), the displayed value
-                       //              is different from the serialized value that's actually
-                       //              sent to the server (see dijit.form.ValidationTextBox.serialize)
+                       //              Attach tooltip to specified node if it's not already connected
+
+                       // TODO: remove in 2.0 and just use set("connectId", ...) interface
 
-                       return this.filter(this.textbox.value);
+                       var id = node.id || node;
+                       if(array.indexOf(this._connectIds, id) == -1){
+                               this.set("connectId", this._connectIds.concat(id));
+                       }
                },
 
-               setDisplayedValue: function(/*String*/value){
+               removeTarget: function(/*DomNode || String*/ node){
                        // summary:
-                       //              Deprecated.   Use set('displayedValue', ...) instead.
-                       // tags:
-                       //              deprecated
-                       dojo.deprecated(this.declaredClass+"::setDisplayedValue() is deprecated. Use set('displayedValue', ...) instead.", "", "2.0");
-                       this.set('displayedValue', value);
+                       //              Detach tooltip from specified node
+
+                       // TODO: remove in 2.0 and just use set("connectId", ...) interface
+
+                       var id = node.id || node,       // map from DOMNode back to plain id string
+                               idx = array.indexOf(this._connectIds, id);
+                       if(idx >= 0){
+                               // remove id (modifies original this._connectIds but that's OK in this case)
+                               this._connectIds.splice(idx, 1);
+                               this.set("connectId", this._connectIds);
+                       }
                },
 
-               _setDisplayedValueAttr: function(/*String*/value){
-                       // summary:
-                       //              Hook so attr('displayedValue', ...) works.
-                       // description:
-                       //              Sets the value of the visual element to the string "value".
-                       //              The widget value is also set to a corresponding,
-                       //              but not necessarily the same, value.
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       domClass.add(this.domNode,"dijitTooltipData");
+               },
+
+               startup: function(){
+                       this.inherited(arguments);
 
-                       if(value === null || value === undefined){ value = '' }
-                       else if(typeof value != "string"){ value = String(value) }
-                       this.textbox.value = value;
-                       this._setValueAttr(this.get('value'), undefined, value);
+                       // If this tooltip was created in a template, or for some other reason the specified connectId[s]
+                       // didn't exist during the widget's initialization, then connect now.
+                       var ids = this.connectId;
+                       array.forEach(lang.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
                },
 
-               format: function(/* String */ value, /* Object */ constraints){
+               _onHover: function(/*Event*/ e){
                        // summary:
-                       //              Replacable function to convert a value to a properly formatted string.
+                       //              Despite the name of this method, it actually handles both hover and focus
+                       //              events on the target node, setting a timer to show the tooltip.
                        // tags:
-                       //              protected extension
-                       return ((value == null || value == undefined) ? "" : (value.toString ? value.toString() : value));
+                       //              private
+                       if(!this._showTimer){
+                               var target = e.target;
+                               this._showTimer = setTimeout(lang.hitch(this, function(){this.open(target)}), this.showDelay);
+                       }
                },
 
-               parse: function(/* String */ value, /* Object */ constraints){
+               _onUnHover: function(/*Event*/ /*===== e =====*/){
                        // summary:
-                       //              Replacable function to convert a formatted string to a value
+                       //              Despite the name of this method, it actually handles both mouseleave and blur
+                       //              events on the target node, hiding the tooltip.
                        // tags:
-                       //              protected extension
+                       //              private
 
-                       return value;   // String
+                       // keep a tooltip open if the associated element still has focus (even though the
+                       // mouse moved away)
+                       if(this._focus){ return; }
+
+                       if(this._showTimer){
+                               clearTimeout(this._showTimer);
+                               delete this._showTimer;
+                       }
+                       this.close();
                },
 
-               _refreshState: function(){
-                       // summary:
-                       //              After the user types some characters, etc., this method is
-                       //              called to check the field for validity etc.  The base method
-                       //              in `dijit.form.TextBox` does nothing, but subclasses override.
+               open: function(/*DomNode*/ target){
+                       // summary:
+                       //              Display the tooltip; usually not called directly.
                        // tags:
-                       //              protected
-               },
+                       //              private
 
-               _onInput: function(e){
-                       if(e && e.type && /key/i.test(e.type) && e.keyCode){
-                               switch(e.keyCode){
-                                       case dojo.keys.SHIFT:
-                                       case dojo.keys.ALT:
-                                       case dojo.keys.CTRL:
-                                       case dojo.keys.TAB:
-                                               return;
-                               }
-                       }
-                       if(this.intermediateChanges){
-                               var _this = this;
-                               // the setTimeout allows the key to post to the widget input box
-                               setTimeout(function(){ _this._handleOnChange(_this.get('value'), false); }, 0);
+                       if(this._showTimer){
+                               clearTimeout(this._showTimer);
+                               delete this._showTimer;
                        }
-                       this._refreshState();
+                       Tooltip.show(this.label || this.domNode.innerHTML, target, this.position, !this.isLeftToRight(), this.textDir);
+
+                       this._connectNode = target;
+                       this.onShow(target, this.position);
                },
 
-               postCreate: function(){
-                       // setting the value here is needed since value="" in the template causes "undefined"
-                       // and setting in the DOM (instead of the JS object) helps with form reset actions
-                       if(dojo.isIE){ // IE INPUT tag fontFamily has to be set directly using STYLE
-                               var s = dojo.getComputedStyle(this.domNode);
-                               if(s){
-                                       var ff = s.fontFamily;
-                                       if(ff){
-                                               var inputs = this.domNode.getElementsByTagName("INPUT");
-                                               if(inputs){
-                                                       for(var i=0; i < inputs.length; i++){
-                                                               inputs[i].style.fontFamily = ff;
-                                                       }
-                                               }
-                                       }
-                               }
+               close: function(){
+                       // summary:
+                       //              Hide the tooltip or cancel timer for show of tooltip
+                       // tags:
+                       //              private
+
+                       if(this._connectNode){
+                               // if tooltip is currently shown
+                               Tooltip.hide(this._connectNode);
+                               delete this._connectNode;
+                               this.onHide();
                        }
-                       this.textbox.setAttribute("value", this.textbox.value); // DOM and JS values shuld be the same
-                       this.inherited(arguments);
-                       if(dojo.isMoz || dojo.isOpera){
-                               this.connect(this.textbox, "oninput", this._onInput);
-                       }else{
-                               this.connect(this.textbox, "onkeydown", this._onInput);
-                               this.connect(this.textbox, "onkeyup", this._onInput);
-                               this.connect(this.textbox, "onpaste", this._onInput);
-                               this.connect(this.textbox, "oncut", this._onInput);
+                       if(this._showTimer){
+                               // if tooltip is scheduled to be shown (after a brief delay)
+                               clearTimeout(this._showTimer);
+                               delete this._showTimer;
                        }
                },
 
-               _blankValue: '', // if the textbox is blank, what value should be reported
-               filter: function(val){
+               onShow: function(/*===== target, position =====*/){
                        // summary:
-                       //              Auto-corrections (such as trimming) that are applied to textbox
-                       //              value on blur or form submit.
-                       // description:
-                       //              For MappedTextBox subclasses, this is called twice
-                       //                      - once with the display value
-                       //                      - once the value as set/returned by attr('value', ...)
-                       //              and attr('value'), ex: a Number for NumberTextBox.
-                       //
-                       //              In the latter case it does corrections like converting null to NaN.  In
-                       //              the former case the NumberTextBox.filter() method calls this.inherited()
-                       //              to execute standard trimming code in TextBox.filter().
-                       //
-                       //              TODO: break this into two methods in 2.0
-                       //
+                       //              Called when the tooltip is shown
                        // tags:
-                       //              protected extension
-                       if(val === null){ return this._blankValue; }
-                       if(typeof val != "string"){ return val; }
-                       if(this.trim){
-                               val = dojo.trim(val);
-                       }
-                       if(this.uppercase){
-                               val = val.toUpperCase();
-                       }
-                       if(this.lowercase){
-                               val = val.toLowerCase();
-                       }
-                       if(this.propercase){
-                               val = val.replace(/[^\s]+/g, function(word){
-                                       return word.substring(0,1).toUpperCase() + word.substring(1);
-                               });
-                       }
-                       return val;
+                       //              callback
                },
 
-               _setBlurValue: function(){
-                       this._setValueAttr(this.get('value'), true);
+               onHide: function(){
+                       // summary:
+                       //              Called when the tooltip is hidden
+                       // tags:
+                       //              callback
                },
 
-               _onBlur: function(e){
-                       if(this.disabled){ return; }
-                       this._setBlurValue();
+               uninitialize: function(){
+                       this.close();
                        this.inherited(arguments);
+               }
+       });
 
-                       if(this._selectOnClickHandle){
-                               this.disconnect(this._selectOnClickHandle);
-                       }
-                       if(this.selectOnClick && dojo.isMoz){
-                               this.textbox.selectionStart = this.textbox.selectionEnd = undefined; // clear selection so that the next mouse click doesn't reselect
-                       }
-                       
-                       this._updatePlaceHolder();
-               },
+       Tooltip._MasterTooltip = MasterTooltip;         // for monkey patching
+       Tooltip.show = dijit.showTooltip;               // export function through module return value
+       Tooltip.hide = dijit.hideTooltip;               // export function through module return value
 
-               _onFocus: function(/*String*/ by){
-                       if(this.disabled || this.readOnly){ return; }
+       // dijit.Tooltip.defaultPosition: String[]
+       //              This variable controls the position of tooltips, if the position is not specified to
+       //              the Tooltip widget or *TextBox widget itself.  It's an array of strings with the values
+       //              possible for `dijit/place::around()`.   The recommended values are:
+       //
+       //                      * before-centered: centers tooltip to the left of the anchor node/widget, or to the right
+       //                               in the case of RTL scripts like Hebrew and Arabic
+       //                      * after-centered: centers tooltip to the right of the anchor node/widget, or to the left
+       //                               in the case of RTL scripts like Hebrew and Arabic
+       //                      * above-centered: tooltip is centered above anchor node
+       //                      * below-centered: tooltip is centered above anchor node
+       //
+       //              The list is positions is tried, in order, until a position is found where the tooltip fits
+       //              within the viewport.
+       //
+       //              Be careful setting this parameter.  A value of "above-centered" may work fine until the user scrolls
+       //              the screen so that there's no room above the target node.   Nodes with drop downs, like
+       //              DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure
+       //              that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there
+       //              is only room below (or above) the target node, but not both.
+       Tooltip.defaultPosition = ["after-centered", "before-centered"];
 
-                       // Select all text on focus via click if nothing already selected.
-                       // Since mouse-up will clear the selection need to defer selection until after mouse-up.
-                       // Don't do anything on focus by tabbing into the widget since there's no associated mouse-up event.
-                       if(this.selectOnClick && by == "mouse"){
-                               this._selectOnClickHandle = this.connect(this.domNode, "onmouseup", function(){
-                                       // Only select all text on first click; otherwise users would have no way to clear
-                                       // the selection.
-                                       this.disconnect(this._selectOnClickHandle);
-
-                                       // Check if the user selected some text manually (mouse-down, mouse-move, mouse-up)
-                                       // and if not, then select all the text
-                                       var textIsNotSelected;
-                                       if(dojo.isIE){
-                                               var range = dojo.doc.selection.createRange();
-                                               var parent = range.parentElement();
-                                               textIsNotSelected = parent == this.textbox && range.text.length == 0;
-                                       }else{
-                                               textIsNotSelected = this.textbox.selectionStart == this.textbox.selectionEnd;
-                                       }
-                                       if(textIsNotSelected){
-                                               dijit.selectInputText(this.textbox);
-                                       }
-                               });
-                       }
 
-                       this._updatePlaceHolder();
-                       
-                       this._refreshState();
-                       this.inherited(arguments);
-               },
+       return Tooltip;
+});
 
-               reset: function(){
-                       // Overrides dijit._FormWidget.reset().
-                       // Additionally resets the displayed textbox value to ''
-                       this.textbox.value = '';
-                       this.inherited(arguments);
-               }
-       }
-);
+},
+'dojo/string':function(){
+define("dojo/string", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
+       // module:
+       //              dojo/string
+       // summary:
+       //              TODOC
+
+lang.getObject("string", true, dojo);
+
+/*=====
+dojo.string = {
+       // summary: String utilities for Dojo
+};
+=====*/
 
-dijit.selectInputText = function(/*DomNode*/element, /*Number?*/ start, /*Number?*/ stop){
+dojo.string.rep = function(/*String*/str, /*Integer*/num){
        // summary:
-       //              Select text in the input element argument, from start (default 0), to stop (default end).
+       //              Efficiently replicate a string `n` times.
+       // str:
+       //              the string to replicate
+       // num:
+       //              number of times to replicate the string
 
-       // TODO: use functions in _editor/selection.js?
-       var _window = dojo.global;
-       var _document = dojo.doc;
-       element = dojo.byId(element);
-       if(isNaN(start)){ start = 0; }
-       if(isNaN(stop)){ stop = element.value ? element.value.length : 0; }
-       dijit.focus(element);
-       if(_document["selection"] && dojo.body()["createTextRange"]){ // IE
-               if(element.createTextRange){
-                       var range = element.createTextRange();
-                       with(range){
-                               collapse(true);
-                               moveStart("character", -99999); // move to 0
-                               moveStart("character", start); // delta from 0 is the correct position
-                               moveEnd("character", stop-start);
-                               select();
-                       }
-               }
-       }else if(_window["getSelection"]){
-               if(element.setSelectionRange){
-                       element.setSelectionRange(start, stop);
+       if(num <= 0 || !str){ return ""; }
+
+       var buf = [];
+       for(;;){
+               if(num & 1){
+                       buf.push(str);
                }
+               if(!(num >>= 1)){ break; }
+               str += str;
        }
+       return buf.join("");    // String
 };
 
-}
-
-if(!dojo._hasResource["dijit.Tooltip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Tooltip"] = true;
-dojo.provide("dijit.Tooltip");
+dojo.string.pad = function(/*String*/text, /*Integer*/size, /*String?*/ch, /*Boolean?*/end){
+       // summary:
+       //              Pad a string to guarantee that it is at least `size` length by
+       //              filling with the character `ch` at either the start or end of the
+       //              string. Pads at the start, by default.
+       // text:
+       //              the string to pad
+       // size:
+       //              length to provide padding
+       // ch:
+       //              character to pad, defaults to '0'
+       // end:
+       //              adds padding at the end if true, otherwise pads at start
+       // example:
+       //      |       // Fill the string to length 10 with "+" characters on the right.  Yields "Dojo++++++".
+       //      |       dojo.string.pad("Dojo", 10, "+", true);
 
+       if(!ch){
+               ch = '0';
+       }
+       var out = String(text),
+               pad = dojo.string.rep(ch, Math.ceil((size - out.length) / ch.length));
+       return end ? out + pad : pad + out;     // String
+};
 
+dojo.string.substitute = function(     /*String*/              template,
+                                                                       /*Object|Array*/map,
+                                                                       /*Function?*/   transform,
+                                                                       /*Object?*/             thisObject){
+       // summary:
+       //              Performs parameterized substitutions on a string. Throws an
+       //              exception if any parameter is unmatched.
+       // template:
+       //              a string with expressions in the form `${key}` to be replaced or
+       //              `${key:format}` which specifies a format function. keys are case-sensitive.
+       // map:
+       //              hash to search for substitutions
+       // transform:
+       //              a function to process all parameters before substitution takes
+       //              place, e.g. mylib.encodeXML
+       // thisObject:
+       //              where to look for optional format function; default to the global
+       //              namespace
+       // example:
+       //              Substitutes two expressions in a string from an Array or Object
+       //      |       // returns "File 'foo.html' is not found in directory '/temp'."
+       //      |       // by providing substitution data in an Array
+       //      |       dojo.string.substitute(
+       //      |               "File '${0}' is not found in directory '${1}'.",
+       //      |               ["foo.html","/temp"]
+       //      |       );
+       //      |
+       //      |       // also returns "File 'foo.html' is not found in directory '/temp'."
+       //      |       // but provides substitution data in an Object structure.  Dotted
+       //      |       // notation may be used to traverse the structure.
+       //      |       dojo.string.substitute(
+       //      |               "File '${name}' is not found in directory '${info.dir}'.",
+       //      |               { name: "foo.html", info: { dir: "/temp" } }
+       //      |       );
+       // example:
+       //              Use a transform function to modify the values:
+       //      |       // returns "file 'foo.html' is not found in directory '/temp'."
+       //      |       dojo.string.substitute(
+       //      |               "${0} is not found in ${1}.",
+       //      |               ["foo.html","/temp"],
+       //      |               function(str){
+       //      |                       // try to figure out the type
+       //      |                       var prefix = (str.charAt(0) == "/") ? "directory": "file";
+       //      |                       return prefix + " '" + str + "'";
+       //      |               }
+       //      |       );
+       // example:
+       //              Use a formatter
+       //      |       // returns "thinger -- howdy"
+       //      |       dojo.string.substitute(
+       //      |               "${0:postfix}", ["thinger"], null, {
+       //      |                       postfix: function(value, key){
+       //      |                               return value + " -- howdy";
+       //      |                       }
+       //      |               }
+       //      |       );
 
+       thisObject = thisObject || dojo.global;
+       transform = transform ?
+               lang.hitch(thisObject, transform) : function(v){ return v; };
 
-dojo.declare(
-       "dijit._MasterTooltip",
-       [dijit._Widget, dijit._Templated],
-       {
-               // summary:
-               //              Internal widget that holds the actual tooltip markup,
-               //              which occurs once per page.
-               //              Called by Tooltip widgets which are just containers to hold
-               //              the markup
-               // tags:
-               //              protected
+       return template.replace(/\$\{([^\s\:\}]+)(?:\:([^\s\:\}]+))?\}/g,
+               function(match, key, format){
+                       var value = lang.getObject(key, false, map);
+                       if(format){
+                               value = lang.getObject(format, false, thisObject).call(thisObject, value, key);
+                       }
+                       return transform(value, key).toString();
+               }); // String
+};
 
-               // duration: Integer
-               //              Milliseconds to fade in/fade out
-               duration: dijit.defaultDuration,
+/*=====
+dojo.string.trim = function(str){
+       // summary:
+       //              Trims whitespace from both sides of the string
+       // str: String
+       //              String to be trimmed
+       // returns: String
+       //              Returns the trimmed string
+       // description:
+       //              This version of trim() was taken from [Steven Levithan's blog](http://blog.stevenlevithan.com/archives/faster-trim-javascript).
+       //              The short yet performant version of this function is dojo.trim(),
+       //              which is part of Dojo base.  Uses String.prototype.trim instead, if available.
+       return "";      // String
+}
+=====*/
 
-               templateString: dojo.cache("dijit", "templates/Tooltip.html", "<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\">\n\t<div class=\"dijitTooltipContainer dijitTooltipContents\" dojoAttachPoint=\"containerNode\" waiRole='alert'></div>\n\t<div class=\"dijitTooltipConnector\"></div>\n</div>\n"),
+dojo.string.trim = String.prototype.trim ?
+       lang.trim : // aliasing to the native function
+       function(str){
+               str = str.replace(/^\s+/, '');
+               for(var i = str.length - 1; i >= 0; i--){
+                       if(/\S/.test(str.charAt(i))){
+                               str = str.substring(0, i + 1);
+                               break;
+                       }
+               }
+               return str;
+       };
 
-               postCreate: function(){
-                       dojo.body().appendChild(this.domNode);
+return dojo.string;
+});
 
-                       this.bgIframe = new dijit.BackgroundIframe(this.domNode);
+},
+'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>",
+'dijit/dijit':function(){
+define("dijit/dijit", [
+       ".",
+       "./_base",
+       "dojo/parser",
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_Container",
+       "./layout/_LayoutWidget",
+       "./form/_FormWidget",
+       "./form/_FormValueWidget"
+], function(dijit){
+
+       // module:
+       //              dijit/dijit
+       // summary:
+       //              A roll-up for common dijit methods
+       //              All the stuff in _base (these are the function that are guaranteed available without an explicit dojo.require)
+       //              And some other stuff that we tend to pull in all the time anyway
 
-                       // Setup fade-in and fade-out functions.
-                       this.fadeIn = dojo.fadeIn({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onShow") });
-                       this.fadeOut = dojo.fadeOut({ node: this.domNode, duration: this.duration, onEnd: dojo.hitch(this, "_onHide") });
+       return dijit;
+});
 
-               },
+},
+'dijit/form/DropDownButton':function(){
+require({cache:{
+'url:dijit/form/templates/DropDownButton.html':"<span class=\"dijit dijitReset dijitInline\"\n\t><span class='dijitReset dijitInline dijitButtonNode'\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" data-dojo-attach-point=\"_buttonNode\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"focusNode,titleNode,_arrowWrapperNode\"\n\t\t\trole=\"button\" aria-haspopup=\"true\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\"\n\t\t\t\tdata-dojo-attach-point=\"iconNode\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode,_popupStateNode\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonInner\"></span\n\t\t\t><span class=\"dijitReset dijitInline dijitArrowButtonChar\">&#9660;</span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-point=\"valueNode\"\n/></span>\n"}});
+define("dijit/form/DropDownButton", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/lang",      // hitch
+       "dojo/query", // query
+       "../registry",  // registry.byNode
+       "../popup",             // dijit.popup2.hide
+       "./Button",
+       "../_Container",
+       "../_HasDropDown",
+       "dojo/text!./templates/DropDownButton.html"
+], function(declare, lang, query, registry, popup, Button, _Container, _HasDropDown, template){
 
-               show: function(/*String*/ innerHTML, /*DomNode*/ aroundNode, /*String[]?*/ position, /*Boolean*/ rtl){
-                       // summary:
-                       //              Display tooltip w/specified contents to right of specified node
-                       //              (To left if there's no space on the right, or if rtl == true)
+/*=====
+       Button = dijit.form.Button;
+       _Container = dijit._Container;
+       _HasDropDown = dijit._HasDropDown;
+=====*/
 
-                       if(this.aroundNode && this.aroundNode === aroundNode){
-                               return;
-                       }
+// module:
+//             dijit/form/DropDownButton
+// summary:
+//             A button with a drop down
 
-                       if(this.fadeOut.status() == "playing"){
-                               // previous tooltip is being hidden; wait until the hide completes then show new one
-                               this._onDeck=arguments;
-                               return;
-                       }
-                       this.containerNode.innerHTML=innerHTML;
 
-                       var pos = dijit.placeOnScreenAroundElement(this.domNode, aroundNode, dijit.getPopupAroundAlignment((position && position.length) ? position : dijit.Tooltip.defaultPosition, !rtl), dojo.hitch(this, "orient"));
+return declare("dijit.form.DropDownButton", [Button, _Container, _HasDropDown], {
+       // summary:
+       //              A button with a drop down
+       //
+       // example:
+       // |    <button data-dojo-type="dijit.form.DropDownButton">
+       // |            Hello world
+       // |            <div data-dojo-type="dijit.Menu">...</div>
+       // |    </button>
+       //
+       // example:
+       // |    var button1 = new dijit.form.DropDownButton({ label: "hi", dropDown: new dijit.Menu(...) });
+       // |    win.body().appendChild(button1);
+       //
 
-                       // show it
-                       dojo.style(this.domNode, "opacity", 0);
-                       this.fadeIn.play();
-                       this.isShowingNow = true;
-                       this.aroundNode = aroundNode;
-               },
+       baseClass : "dijitDropDownButton",
 
-               orient: function(/* DomNode */ node, /* String */ aroundCorner, /* String */ tooltipCorner){
-                       // summary:
-                       //              Private function to set CSS for tooltip node based on which position it's in.
-                       //              This is called by the dijit popup code.
-                       // tags:
-                       //              protected
+       templateString: template,
 
-                       node.className = "dijitTooltip " +
-                               {
-                                       "BL-TL": "dijitTooltipBelow dijitTooltipABLeft",
-                                       "TL-BL": "dijitTooltipAbove dijitTooltipABLeft",
-                                       "BR-TR": "dijitTooltipBelow dijitTooltipABRight",
-                                       "TR-BR": "dijitTooltipAbove dijitTooltipABRight",
-                                       "BR-BL": "dijitTooltipRight",
-                                       "BL-BR": "dijitTooltipLeft"
-                               }[aroundCorner + "-" + tooltipCorner];
-               },
+       _fillContent: function(){
+               // Overrides Button._fillContent().
+               //
+               // My inner HTML contains both the button contents and a drop down widget, like
+               // <DropDownButton>  <span>push me</span>  <Menu> ... </Menu> </DropDownButton>
+               // The first node is assumed to be the button content. The widget is the popup.
 
-               _onShow: function(){
-                       // summary:
-                       //              Called at end of fade-in operation
-                       // tags:
-                       //              protected
-                       if(dojo.isIE){
-                               // the arrow won't show up on a node w/an opacity filter
-                               this.domNode.style.filter="";
-                       }
-               },
+               if(this.srcNodeRef){ // programatically created buttons might not define srcNodeRef
+                       //FIXME: figure out how to filter out the widget and use all remaining nodes as button
+                       //      content, not just nodes[0]
+                       var nodes = query("*", this.srcNodeRef);
+                       this.inherited(arguments, [nodes[0]]);
 
-               hide: function(aroundNode){
-                       // summary:
-                       //              Hide the tooltip
-                       if(this._onDeck && this._onDeck[1] == aroundNode){
-                               // this hide request is for a show() that hasn't even started yet;
-                               // just cancel the pending show()
-                               this._onDeck=null;
-                       }else if(this.aroundNode === aroundNode){
-                               // this hide request is for the currently displayed tooltip
-                               this.fadeIn.stop();
-                               this.isShowingNow = false;
-                               this.aroundNode = null;
-                               this.fadeOut.play();
-                       }else{
-                               // just ignore the call, it's for a tooltip that has already been erased
-                       }
-               },
+                       // save pointer to srcNode so we can grab the drop down widget after it's instantiated
+                       this.dropDownContainer = this.srcNodeRef;
+               }
+       },
 
-               _onHide: function(){
-                       // summary:
-                       //              Called at end of fade-out operation
-                       // tags:
-                       //              protected
+       startup: function(){
+               if(this._started){ return; }
 
-                       this.domNode.style.cssText="";  // to position offscreen again
-                       this.containerNode.innerHTML="";
-                       if(this._onDeck){
-                               // a show request has been queued up; do it now
-                               this.show.apply(this, this._onDeck);
-                               this._onDeck=null;
-                       }
+               // the child widget from srcNodeRef is the dropdown widget.  Insert it in the page DOM,
+               // make it invisible, and store a reference to pass to the popup code.
+               if(!this.dropDown && this.dropDownContainer){
+                       var dropDownNode = query("[widgetId]", this.dropDownContainer)[0];
+                       this.dropDown = registry.byNode(dropDownNode);
+                       delete this.dropDownContainer;
+               }
+               if(this.dropDown){
+                       popup.hide(this.dropDown);
                }
 
-       }
-);
-
-dijit.showTooltip = function(/*String*/ innerHTML, /*DomNode*/ aroundNode, /*String[]?*/ position, /*Boolean*/ rtl){
-       // summary:
-       //              Display tooltip w/specified contents in specified position.
-       //              See description of dijit.Tooltip.defaultPosition for details on position parameter.
-       //              If position is not specified then dijit.Tooltip.defaultPosition is used.
-       if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
-       return dijit._masterTT.show(innerHTML, aroundNode, position, rtl);
-};
-
-dijit.hideTooltip = function(aroundNode){
-       // summary:
-       //              Hide the tooltip
-       if(!dijit._masterTT){ dijit._masterTT = new dijit._MasterTooltip(); }
-       return dijit._masterTT.hide(aroundNode);
-};
-
-dojo.declare(
-       "dijit.Tooltip",
-       dijit._Widget,
-       {
-               // summary:
-               //              Pops up a tooltip (a help message) when you hover over a node.
-
-               // label: String
-               //              Text to display in the tooltip.
-               //              Specified as innerHTML when creating the widget from markup.
-               label: "",
-
-               // showDelay: Integer
-               //              Number of milliseconds to wait after hovering over/focusing on the object, before
-               //              the tooltip is displayed.
-               showDelay: 400,
+               this.inherited(arguments);
+       },
 
-               // connectId: [const] String[]
-               //              Id's of domNodes to attach the tooltip to.
-               //              When user hovers over any of the specified dom nodes, the tooltip will appear.
-               //
-               //              Note: Currently connectId can only be specified on initialization, it cannot
-               //              be changed via attr('connectId', ...)
-               //
-               //              Note: in 2.0 this will be renamed to connectIds for less confusion.
-               connectId: [],
+       isLoaded: function(){
+               // Returns whether or not we are loaded - if our dropdown has an href,
+               // then we want to check that.
+               var dropDown = this.dropDown;
+               return (!!dropDown && (!dropDown.href || dropDown.isLoaded));
+       },
 
-               // position: String[]
-               //              See description of `dijit.Tooltip.defaultPosition` for details on position parameter.
-               position: [],
+       loadDropDown: function(/*Function*/ callback){
+               // Default implementation assumes that drop down already exists,
+               // but hasn't loaded it's data (ex: ContentPane w/href).
+               // App must override if the drop down is lazy-created.
+               var dropDown = this.dropDown;
+               var handler = dropDown.on("load", lang.hitch(this, function(){
+                       handler.remove();
+                       callback();
+               }));
+               dropDown.refresh();             // tell it to load
+       },
 
-               constructor: function(){
-                       // Map id's of nodes I'm connected to to a list of the this.connect() handles
-                       this._nodeConnectionsById = {};
-               },
+       isFocusable: function(){
+               // Overridden so that focus is handled by the _HasDropDown mixin, not by
+               // the _FormWidget mixin.
+               return this.inherited(arguments) && !this._mouseDown;
+       }
+});
 
-               _setConnectIdAttr: function(newIds){
-                       for(var oldId in this._nodeConnectionsById){
-                               this.removeTarget(oldId);
-                       }
-                       dojo.forEach(dojo.isArrayLike(newIds) ? newIds : [newIds], this.addTarget, this);
-               },
+});
 
-               _getConnectIdAttr: function(){
-                       var ary = [];
-                       for(var id in this._nodeConnectionsById){
-                               ary.push(id);
-                       }
-                       return ary;
-               },
+},
+'dijit/form/_FormValueMixin':function(){
+define("dijit/form/_FormValueMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/keys", // keys.ESCAPE
+       "dojo/_base/sniff", // has("ie"), has("quirks")
+       "./_FormWidgetMixin"
+], function(declare, domAttr, keys, has, _FormWidgetMixin){
 
-               addTarget: function(/*DOMNODE || String*/ id){
-                       // summary:
-                       //              Attach tooltip to specified node, if it's not already connected
-                       var node = dojo.byId(id);
-                       if(!node){ return; }
-                       if(node.id in this._nodeConnectionsById){ return; }//Already connected
+/*=====
+       var _FormWidgetMixin = dijit.form._FormWidgetMixin;
+=====*/
 
-                       this._nodeConnectionsById[node.id] = [
-                               this.connect(node, "onmouseenter", "_onTargetMouseEnter"),
-                               this.connect(node, "onmouseleave", "_onTargetMouseLeave"),
-                               this.connect(node, "onfocus", "_onTargetFocus"),
-                               this.connect(node, "onblur", "_onTargetBlur")
-                       ];
-               },
+       // module:
+       //              dijit/form/_FormValueMixin
+       // summary:
+       //              Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
 
-               removeTarget: function(/*DOMNODE || String*/ node){
-                       // summary:
-                       //              Detach tooltip from specified node
+       return declare("dijit.form._FormValueMixin", _FormWidgetMixin, {
+               // summary:
+               //              Mixin for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
+               // description:
+               //              Each _FormValueMixin represents a single input value, and has a (possibly hidden) <input> element,
+               //              to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
+               //              works as expected.
 
-                       // map from DOMNode back to plain id string
-                       var id = node.id || node;
+               // readOnly: Boolean
+               //              Should this widget respond to user input?
+               //              In markup, this is specified as "readOnly".
+               //              Similar to disabled except readOnly form values are submitted.
+               readOnly: false,
 
-                       if(id in this._nodeConnectionsById){
-                               dojo.forEach(this._nodeConnectionsById[id], this.disconnect, this);
-                               delete this._nodeConnectionsById[id];
-                       }
+               _setReadOnlyAttr: function(/*Boolean*/ value){
+                       domAttr.set(this.focusNode, 'readOnly', value);
+                       this.focusNode.setAttribute("aria-readonly", value);
+                       this._set("readOnly", value);
                },
 
                postCreate: function(){
-                       dojo.addClass(this.domNode,"dijitTooltipData");
-               },
-
-               startup: function(){
                        this.inherited(arguments);
 
-                       // If this tooltip was created in a template, or for some other reason the specified connectId[s]
-                       // didn't exist during the widget's initialization, then connect now.
-                       var ids = this.connectId;
-                       dojo.forEach(dojo.isArrayLike(ids) ? ids : [ids], this.addTarget, this);
-               },
-
-               _onTargetMouseEnter: function(/*Event*/ e){
-                       // summary:
-                       //              Handler for mouseenter event on the target node
-                       // tags:
-                       //              private
-                       this._onHover(e);
-               },
-
-               _onTargetMouseLeave: function(/*Event*/ e){
-                       // summary:
-                       //              Handler for mouseleave event on the target node
-                       // tags:
-                       //              private
-                       this._onUnHover(e);
+                       if(has("ie")){ // IE won't stop the event with keypress
+                               this.connect(this.focusNode || this.domNode, "onkeydown", this._onKeyDown);
+                       }
+                       // Update our reset value if it hasn't yet been set (because this.set()
+                       // is only called when there *is* a value)
+                       if(this._resetValue === undefined){
+                               this._lastValueReported = this._resetValue = this.value;
+                       }
                },
 
-               _onTargetFocus: function(/*Event*/ e){
+               _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
                        // summary:
-                       //              Handler for focus event on the target node
-                       // tags:
-                       //              private
-
-                       this._focus = true;
-                       this._onHover(e);
+                       //              Hook so set('value', value) works.
+                       // description:
+                       //              Sets the value of the widget.
+                       //              If the value has changed, then fire onChange event, unless priorityChange
+                       //              is specified as null (or false?)
+                       this._handleOnChange(newValue, priorityChange);
                },
 
-               _onTargetBlur: function(/*Event*/ e){
+               _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
                        // summary:
-                       //              Handler for blur event on the target node
-                       // tags:
-                       //              private
-
-                       this._focus = false;
-                       this._onUnHover(e);
+                       //              Called when the value of the widget has changed.  Saves the new value in this.value,
+                       //              and calls onChange() if appropriate.   See _FormWidget._handleOnChange() for details.
+                       this._set("value", newValue);
+                       this.inherited(arguments);
                },
 
-               _onHover: function(/*Event*/ e){
+               undo: function(){
                        // summary:
-                       //              Despite the name of this method, it actually handles both hover and focus
-                       //              events on the target node, setting a timer to show the tooltip.
-                       // tags:
-                       //              private
-                       if(!this._showTimer){
-                               var target = e.target;
-                               this._showTimer = setTimeout(dojo.hitch(this, function(){this.open(target)}), this.showDelay);
-                       }
+                       //              Restore the value to the last value passed to onChange
+                       this._setValueAttr(this._lastValueReported, false);
                },
 
-               _onUnHover: function(/*Event*/ e){
+               reset: function(){
                        // summary:
-                       //              Despite the name of this method, it actually handles both mouseleave and blur
-                       //              events on the target node, hiding the tooltip.
-                       // tags:
-                       //              private
-
-                       // keep a tooltip open if the associated element still has focus (even though the
-                       // mouse moved away)
-                       if(this._focus){ return; }
-
-                       if(this._showTimer){
-                               clearTimeout(this._showTimer);
-                               delete this._showTimer;
-                       }
-                       this.close();
-               },
-
-               open: function(/*DomNode*/ target){
-                       // summary:
-                       //              Display the tooltip; usually not called directly.
-                       // tags:
-                       //              private
-
-                       if(this._showTimer){
-                               clearTimeout(this._showTimer);
-                               delete this._showTimer;
+                       //              Reset the widget's value to what it was at initialization time
+                       this._hasBeenBlurred = false;
+                       this._setValueAttr(this._resetValue, true);
+               },
+
+               _onKeyDown: function(e){
+                       if(e.keyCode == keys.ESCAPE && !(e.ctrlKey || e.altKey || e.metaKey)){
+                               var te;
+                               if(has("ie") < 9 || (has("ie") && has("quirks"))){
+                                       e.preventDefault(); // default behavior needs to be stopped here since keypress is too late
+                                       te = document.createEventObject();
+                                       te.keyCode = keys.ESCAPE;
+                                       te.shiftKey = e.shiftKey;
+                                       e.srcElement.fireEvent('onkeypress', te);
+                               }
                        }
-                       dijit.showTooltip(this.label || this.domNode.innerHTML, target, this.position, !this.isLeftToRight());
-
-                       this._connectNode = target;
-                       this.onShow(target, this.position);
-               },
-
-               close: function(){
-                       // summary:
-                       //              Hide the tooltip or cancel timer for show of tooltip
-                       // tags:
-                       //              private
+               }
+       });
+});
 
-                       if(this._connectNode){
-                               // if tooltip is currently shown
-                               dijit.hideTooltip(this._connectNode);
-                               delete this._connectNode;
-                               this.onHide();
-                       }
-                       if(this._showTimer){
-                               // if tooltip is scheduled to be shown (after a brief delay)
-                               clearTimeout(this._showTimer);
-                               delete this._showTimer;
-                       }
-               },
+},
+'dijit/form/_FormWidgetMixin':function(){
+define("dijit/form/_FormWidgetMixin", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-style", // domStyle.get
+       "dojo/_base/lang", // lang.hitch lang.isArray
+       "dojo/mouse", // mouse.isLeft
+       "dojo/_base/sniff", // has("webkit")
+       "dojo/_base/window", // win.body
+       "dojo/window", // winUtils.scrollIntoView
+       "../a11y"       // a11y.hasDefaultTabStop
+], function(array, declare, domAttr, domStyle, lang, mouse, has, win, winUtils, a11y){
+
+// module:
+//             dijit/form/_FormWidgetMixin
+// summary:
+//             Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
+//             which can be children of a <form> node or a `dijit.form.Form` widget.
 
-               onShow: function(target, position){
-                       // summary:
-                       //              Called when the tooltip is shown
-                       // tags:
-                       //              callback
-               },
+return declare("dijit.form._FormWidgetMixin", null, {
+       // summary:
+       //              Mixin for widgets corresponding to native HTML elements such as <checkbox> or <button>,
+       //              which can be children of a <form> node or a `dijit.form.Form` widget.
+       //
+       // description:
+       //              Represents a single HTML element.
+       //              All these widgets should have these attributes just like native HTML input elements.
+       //              You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
+       //
+       //              They also share some common methods.
 
-               onHide: function(){
-                       // summary:
-                       //              Called when the tooltip is hidden
-                       // tags:
-                       //              callback
-               },
+       // name: [const] String
+       //              Name used when submitting form; same as "name" attribute or plain HTML elements
+       name: "",
 
-               uninitialize: function(){
-                       this.close();
-                       this.inherited(arguments);
-               }
-       }
-);
+       // alt: String
+       //              Corresponds to the native HTML <input> element's attribute.
+       alt: "",
 
-// dijit.Tooltip.defaultPosition: String[]
-//             This variable controls the position of tooltips, if the position is not specified to
-//             the Tooltip widget or *TextBox widget itself.  It's an array of strings with the following values:
-//
-//                     * before: places tooltip to the left of the target node/widget, or to the right in
-//                       the case of RTL scripts like Hebrew and Arabic
-//                     * after: places tooltip to the right of the target node/widget, or to the left in
-//                       the case of RTL scripts like Hebrew and Arabic
-//                     * above: tooltip goes above target node
-//                     * below: tooltip goes below target node
-//
-//             The list is positions is tried, in order, until a position is found where the tooltip fits
-//             within the viewport.
-//
-//             Be careful setting this parameter.  A value of "above" may work fine until the user scrolls
-//             the screen so that there's no room above the target node.   Nodes with drop downs, like
-//             DropDownButton or FilteringSelect, are especially problematic, in that you need to be sure
-//             that the drop down and tooltip don't overlap, even when the viewport is scrolled so that there
-//             is only room below (or above) the target node, but not both.
-dijit.Tooltip.defaultPosition = ["after", "before"];
+       // value: String
+       //              Corresponds to the native HTML <input> element's attribute.
+       value: "",
 
-}
+       // type: [const] String
+       //              Corresponds to the native HTML <input> element's attribute.
+       type: "text",
 
-if(!dojo._hasResource["dijit.form.ValidationTextBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.ValidationTextBox"] = true;
-dojo.provide("dijit.form.ValidationTextBox");
+       // tabIndex: Integer
+       //              Order fields are traversed when user hits the tab key
+       tabIndex: "0",
+       _setTabIndexAttr: "focusNode",  // force copy even when tabIndex default value, needed since Button is <span>
 
+       // disabled: Boolean
+       //              Should this widget respond to user input?
+       //              In markup, this is specified as "disabled='disabled'", or just "disabled".
+       disabled: false,
 
+       // intermediateChanges: Boolean
+       //              Fires onChange for each value change or only on demand
+       intermediateChanges: false,
 
+       // scrollOnFocus: Boolean
+       //              On focus, should this widget scroll into view?
+       scrollOnFocus: true,
 
+       // Override _WidgetBase mapping id to this.domNode, needs to be on focusNode so <label> etc.
+       // works with screen reader
+       _setIdAttr: "focusNode",
 
+       _setDisabledAttr: function(/*Boolean*/ value){
+               this._set("disabled", value);
+               domAttr.set(this.focusNode, 'disabled', value);
+               if(this.valueNode){
+                       domAttr.set(this.valueNode, 'disabled', value);
+               }
+               this.focusNode.setAttribute("aria-disabled", value ? "true" : "false");
 
+               if(value){
+                       // reset these, because after the domNode is disabled, we can no longer receive
+                       // mouse related events, see #4200
+                       this._set("hovering", false);
+                       this._set("active", false);
 
+                       // clear tab stop(s) on this widget's focusable node(s)  (ComboBox has two focusable nodes)
+                       var attachPointNames = "tabIndex" in this.attributeMap ? this.attributeMap.tabIndex :
+                               ("_setTabIndexAttr" in this) ? this._setTabIndexAttr : "focusNode";
+                       array.forEach(lang.isArray(attachPointNames) ? attachPointNames : [attachPointNames], function(attachPointName){
+                               var node = this[attachPointName];
+                               // complex code because tabIndex=-1 on a <div> doesn't work on FF
+                               if(has("webkit") || a11y.hasDefaultTabStop(node)){      // see #11064 about webkit bug
+                                       node.setAttribute('tabIndex', "-1");
+                               }else{
+                                       node.removeAttribute('tabIndex');
+                               }
+                       }, this);
+               }else{
+                       if(this.tabIndex != ""){
+                               this.set('tabIndex', this.tabIndex);
+                       }
+               }
+       },
 
-/*=====
-       dijit.form.ValidationTextBox.__Constraints = function(){
-               // locale: String
-               //              locale used for validation, picks up value from this widget's lang attribute
-               // _flags_: anything
-               //              various flags passed to regExpGen function
-               this.locale = "";
-               this._flags_ = "";
-       }
-=====*/
+       _onFocus: function(/*String*/ by){
+               // If user clicks on the widget, even if the mouse is released outside of it,
+               // this widget's focusNode should get focus (to mimic native browser hehavior).
+               // Browsers often need help to make sure the focus via mouse actually gets to the focusNode.
+               if(by == "mouse" && this.isFocusable()){
+                       // IE exhibits strange scrolling behavior when refocusing a node so only do it when !focused.
+                       var focusConnector = this.connect(this.focusNode, "onfocus", function(){
+                               this.disconnect(mouseUpConnector);
+                               this.disconnect(focusConnector);
+                       });
+                       // Set a global event to handle mouseup, so it fires properly
+                       // even if the cursor leaves this.domNode before the mouse up event.
+                       var mouseUpConnector = this.connect(win.body(), "onmouseup", function(){
+                               this.disconnect(mouseUpConnector);
+                               this.disconnect(focusConnector);
+                               // if here, then the mousedown did not focus the focusNode as the default action
+                               if(this.focused){
+                                       this.focus();
+                               }
+                       });
+               }
+               if(this.scrollOnFocus){
+                       this.defer(function(){ winUtils.scrollIntoView(this.domNode); }); // without defer, the input caret position can change on mouse click
+               }
+               this.inherited(arguments);
+       },
 
-dojo.declare(
-       "dijit.form.ValidationTextBox",
-       dijit.form.TextBox,
-       {
+       isFocusable: function(){
                // summary:
-               //              Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
+               //              Tells if this widget is focusable or not.  Used internally by dijit.
                // tags:
                //              protected
+               return !this.disabled && this.focusNode && (domStyle.get(this.domNode, "display") != "none");
+       },
 
-               templateString: dojo.cache("dijit.form", "templates/ValidationTextBox.html", "<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\" waiRole=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&Chi; \" type=\"text\" tabIndex=\"-1\" readOnly waiRole=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" dojoAttachPoint='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"),
-               baseClass: "dijitTextBox dijitValidationTextBox",
+       focus: function(){
+               // summary:
+               //              Put focus on this widget
+               if(!this.disabled && this.focusNode.focus){
+                       try{ this.focusNode.focus(); }catch(e){}/*squelch errors from hidden nodes*/
+               }
+       },
 
-               // required: Boolean
-               //              User is required to enter data into this field.
-               required: false,
+       compare: function(/*anything*/ val1, /*anything*/ val2){
+               // summary:
+               //              Compare 2 values (as returned by get('value') for this widget).
+               // tags:
+               //              protected
+               if(typeof val1 == "number" && typeof val2 == "number"){
+                       return (isNaN(val1) && isNaN(val2)) ? 0 : val1 - val2;
+               }else if(val1 > val2){
+                       return 1;
+               }else if(val1 < val2){
+                       return -1;
+               }else{
+                       return 0;
+               }
+       },
 
-               // promptMessage: String
-               //              If defined, display this hint string immediately on focus to the textbox, if empty.
-               //              Think of this like a tooltip that tells the user what to do, not an error message
-               //              that tells the user what they've done wrong.
-               //
-               //              Message disappears when user starts typing.
-               promptMessage: "",
+       onChange: function(/*===== newValue =====*/){
+               // summary:
+               //              Callback when this widget's value is changed.
+               // tags:
+               //              callback
+       },
 
-               // invalidMessage: String
-               //              The message to display if value is invalid.
-               //              The translated string value is read from the message file by default.
-               //              Set to "" to use the promptMessage instead.
-               invalidMessage: "$_unset_$",
+       // _onChangeActive: [private] Boolean
+       //              Indicates that changes to the value should call onChange() callback.
+       //              This is false during widget initialization, to avoid calling onChange()
+       //              when the initial value is set.
+       _onChangeActive: false,
 
-               // missingMessage: String
-               //              The message to display if value is empty and the field is required.
-               //              The translated string value is read from the message file by default.
-               //              Set to "" to use the invalidMessage instead.
-               missingMessage: "$_unset_$",
+       _handleOnChange: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
+               // summary:
+               //              Called when the value of the widget is set.  Calls onChange() if appropriate
+               // newValue:
+               //              the new value
+               // priorityChange:
+               //              For a slider, for example, dragging the slider is priorityChange==false,
+               //              but on mouse up, it's priorityChange==true.  If intermediateChanges==false,
+               //              onChange is only called form priorityChange=true events.
+               // tags:
+               //              private
+               if(this._lastValueReported == undefined && (priorityChange === null || !this._onChangeActive)){
+                       // this block executes not for a change, but during initialization,
+                       // and is used to store away the original value (or for ToggleButton, the original checked state)
+                       this._resetValue = this._lastValueReported = newValue;
+               }
+               this._pendingOnChange = this._pendingOnChange
+                       || (typeof newValue != typeof this._lastValueReported)
+                       || (this.compare(newValue, this._lastValueReported) != 0);
+               if((this.intermediateChanges || priorityChange || priorityChange === undefined) && this._pendingOnChange){
+                       this._lastValueReported = newValue;
+                       this._pendingOnChange = false;
+                       if(this._onChangeActive){
+                               if(this._onChangeHandle){
+                                       this._onChangeHandle.remove();
+                               }
+                               // defer allows hidden value processing to run and
+                               // also the onChange handler can safely adjust focus, etc
+                               this._onChangeHandle = this.defer(
+                                       function(){
+                                               this._onChangeHandle = null;
+                                               this.onChange(newValue);
+                                       }); // try to collapse multiple onChange's fired faster than can be processed
+                       }
+               }
+       },
 
-               // constraints: dijit.form.ValidationTextBox.__Constraints
-               //              user-defined object needed to pass parameters to the validator functions
-               constraints: {},
+       create: function(){
+               // Overrides _Widget.create()
+               this.inherited(arguments);
+               this._onChangeActive = true;
+       },
 
-               // regExp: [extension protected] String
-               //              regular expression string used to validate the input
-               //              Do not specify both regExp and regExpGen
-               regExp: ".*",
+       destroy: function(){
+               if(this._onChangeHandle){ // destroy called before last onChange has fired
+                       this._onChangeHandle.remove();
+                       this.onChange(this._lastValueReported);
+               }
+               this.inherited(arguments);
+       }
+});
 
-               regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/constraints){
-                       // summary:
-                       //              Overridable function used to generate regExp when dependent on constraints.
-                       //              Do not specify both regExp and regExpGen.
-                       // tags:
-                       //              extension protected
-                       return this.regExp; // String
-               },
+});
 
-               // state: [readonly] String
-               //              Shows current state (ie, validation result) of input (Normal, Warning, or Error)
-               state: "",
+},
+'url:dijit/templates/ProgressBar.html':"<div class=\"dijitProgressBar dijitProgressBarEmpty\" role=\"progressbar\"\n\t><div  data-dojo-attach-point=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\" role=\"presentation\"></div\n\t\t><span style=\"visibility:hidden\">&#160;</span\n\t></div\n\t><div data-dojo-attach-point=\"labelNode\" class=\"dijitProgressBarLabel\" id=\"${id}_label\"></div\n\t><img data-dojo-attach-point=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\n/></div>\n",
+'dijit/layout/_ContentPaneResizeMixin':function(){
+define("dijit/layout/_ContentPaneResizeMixin", [
+       "dojo/_base/array", // array.filter array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr",        // domAttr.has
+       "dojo/dom-class",       // domClass.contains domClass.toggle
+       "dojo/dom-geometry",// domGeometry.contentBox domGeometry.marginBox
+       "dojo/_base/lang", // lang.mixin
+       "dojo/query", // query
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/window", // win.global
+       "../registry",  // registry.byId
+       "./utils",      // marginBox2contextBox
+       "../_Contained"
+], function(array, declare, domAttr, domClass, domGeometry, lang, query, has, win,
+                       registry, layoutUtils, _Contained){
 
-               // tooltipPosition: String[]
-               //              See description of `dijit.Tooltip.defaultPosition` for details on this parameter.
-               tooltipPosition: [],
+/*=====
+var _Contained = dijit._Contained;
+=====*/
 
-               _setValueAttr: function(){
-                       // summary:
-                       //              Hook so attr('value', ...) works.
-                       this.inherited(arguments);
-                       this.validate(this._focused);
-               },
+// module:
+//             dijit/layout/_ContentPaneResizeMixin
+// summary:
+//             Resize() functionality of ContentPane.   If there's a single layout widget
+//             child then it will call resize() with the same dimensions as the ContentPane.
+//             Otherwise just calls resize on each child.
 
-               validator: function(/*anything*/value, /*dijit.form.ValidationTextBox.__Constraints*/constraints){
-                       // summary:
-                       //              Overridable function used to validate the text input against the regular expression.
-                       // tags:
-                       //              protected
-                       return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
-                               (!this.required || !this._isEmpty(value)) &&
-                               (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
-               },
 
-               _isValidSubset: function(){
-                       // summary:
-                       //              Returns true if the value is either already valid or could be made valid by appending characters.
-                       //              This is used for validation while the user [may be] still typing.
-                       return this.textbox.value.search(this._partialre) == 0;
-               },
+return declare("dijit.layout._ContentPaneResizeMixin", null, {
+       // summary:
+       //              Resize() functionality of ContentPane.   If there's a single layout widget
+       //              child then it will call resize() with the same dimensions as the ContentPane.
+       //              Otherwise just calls resize on each child.
+       //
+       //              Also implements basic startup() functionality, where starting the parent
+       //              will start the children
 
-               isValid: function(/*Boolean*/ isFocused){
-                       // summary:
-                       //              Tests if value is valid.
-                       //              Can override with your own routine in a subclass.
-                       // tags:
-                       //              protected
-                       return this.validator(this.textbox.value, this.constraints);
-               },
+       // doLayout: Boolean
+       //              - false - don't adjust size of children
+       //              - true - if there is a single visible child widget, set it's size to
+       //                              however big the ContentPane is
+       doLayout: true,
 
-               _isEmpty: function(value){
-                       // summary:
-                       //              Checks for whitespace
-                       return /^\s*$/.test(value); // Boolean
-               },
+       // isLayoutContainer: [protected] Boolean
+       //              Indicates that this widget will call resize() on it's child widgets
+       //              when they become visible.
+       isLayoutContainer: true,
 
-               getErrorMessage: function(/*Boolean*/ isFocused){
-                       // summary:
-                       //              Return an error message to show if appropriate
-                       // tags:
-                       //              protected
-                       return (this.required && this._isEmpty(this.textbox.value)) ? this.missingMessage : this.invalidMessage; // String
-               },
+       startup: function(){
+               // summary:
+               //              See `dijit.layout._LayoutWidget.startup` for description.
+               //              Although ContentPane doesn't extend _LayoutWidget, it does implement
+               //              the same API.
 
-               getPromptMessage: function(/*Boolean*/ isFocused){
-                       // summary:
-                       //              Return a hint message to show when widget is first focused
-                       // tags:
-                       //              protected
-                       return this.promptMessage; // String
-               },
+               if(this._started){ return; }
 
-               _maskValidSubsetError: true,
-               validate: function(/*Boolean*/ isFocused){
-                       // summary:
-                       //              Called by oninit, onblur, and onkeypress.
-                       // description:
-                       //              Show missing or invalid messages if appropriate, and highlight textbox field.
-                       // tags:
-                       //              protected
-                       var message = "";
-                       var isValid = this.disabled || this.isValid(isFocused);
-                       if(isValid){ this._maskValidSubsetError = true; }
-                       var isEmpty = this._isEmpty(this.textbox.value);
-                       var isValidSubset = !isValid && !isEmpty && isFocused && this._isValidSubset();
-                       this.state = ((isValid || ((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "" : "Error";
-                       if(this.state == "Error"){ this._maskValidSubsetError = isFocused; } // we want the error to show up afer a blur and refocus
-                       this._setStateClass();
-                       dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
-                       if(isFocused){
-                               if(this.state == "Error"){
-                                       message = this.getErrorMessage(true);
-                               }else{
-                                       message = this.getPromptMessage(true); // show the prompt whever there's no error
-                               }
-                               this._maskValidSubsetError = true; // since we're focused, always mask warnings
-                       }
-                       this.displayMessage(message);
-                       return isValid;
-               },
+               var parent = this.getParent();
+               this._childOfLayoutWidget = parent && parent.isLayoutContainer;
 
-               // _message: String
-               //              Currently displayed message
-               _message: "",
+               // I need to call resize() on my child/children (when I become visible), unless
+               // I'm the child of a layout widget in which case my parent will call resize() on me and I'll do it then.
+               this._needLayout = !this._childOfLayoutWidget;
 
-               displayMessage: function(/*String*/ message){
-                       // summary:
-                       //              Overridable method to display validation errors/hints.
-                       //              By default uses a tooltip.
-                       // tags:
-                       //              extension
-                       if(this._message == message){ return; }
-                       this._message = message;
-                       dijit.hideTooltip(this.domNode);
-                       if(message){
-                               dijit.showTooltip(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
-                       }
-               },
+               this.inherited(arguments);
 
-               _refreshState: function(){
-                       // Overrides TextBox._refreshState()
-                       this.validate(this._focused);
-                       this.inherited(arguments);
-               },
+               if(this._isShown()){
+                       this._onShow();
+               }
 
-               //////////// INITIALIZATION METHODS ///////////////////////////////////////
+               if(!this._childOfLayoutWidget){
+                       // If my parent isn't a layout container, since my style *may be* width=height=100%
+                       // or something similar (either set directly or via a CSS class),
+                       // monitor when my size changes so that I can re-layout.
+                       // For browsers where I can't directly monitor when my size changes,
+                       // monitor when the viewport changes size, which *may* indicate a size change for me.
+                       this.connect(has("ie") ? this.domNode : win.global, 'onresize', function(){
+                               // Using function(){} closure to ensure no arguments to resize.
+                               this._needLayout = !this._childOfLayoutWidget;
+                               this.resize();
+                       });
+               }
+       },
 
-               constructor: function(){
-                       this.constraints = {};
-               },
+       _checkIfSingleChild: function(){
+               // summary:
+               //              Test if we have exactly one visible widget as a child,
+               //              and if so assume that we are a container for that widget,
+               //              and should propagate startup() and resize() calls to it.
+               //              Skips over things like data stores since they aren't visible.
 
-               _setConstraintsAttr: function(/* Object */ constraints){
-                       if(!constraints.locale && this.lang){
-                               constraints.locale = this.lang;
-                       }
-                       this.constraints = constraints;
-                       this._computePartialRE();
-               },
+               var childNodes = query("> *", this.containerNode).filter(function(node){
+                               return node.tagName !== "SCRIPT"; // or a regexp for hidden elements like script|area|map|etc..
+                       }),
+                       childWidgetNodes = childNodes.filter(function(node){
+                               return domAttr.has(node, "data-dojo-type") || domAttr.has(node, "dojoType") || domAttr.has(node, "widgetId");
+                       }),
+                       candidateWidgets = array.filter(childWidgetNodes.map(registry.byNode), function(widget){
+                               return widget && widget.domNode && widget.resize;
+                       });
 
-               _computePartialRE: function(){
-                       var p = this.regExpGen(this.constraints);
-                       this.regExp = p;
-                       var partialre = "";
-                       // parse the regexp and produce a new regexp that matches valid subsets
-                       // if the regexp is .* then there's no use in matching subsets since everything is valid
-                       if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
-                               function (re){
-                                       switch(re.charAt(0)){
-                                               case '{':
-                                               case '+':
-                                               case '?':
-                                               case '*':
-                                               case '^':
-                                               case '$':
-                                               case '|':
-                                               case '(':
-                                                       partialre += re;
-                                                       break;
-                                               case ")":
-                                                       partialre += "|$)";
-                                                       break;
-                                                default:
-                                                       partialre += "(?:"+re+"|$)";
-                                                       break;
-                                       }
-                               }
-                       );}
-                       try{ // this is needed for now since the above regexp parsing needs more test verification
-                               "".search(partialre);
-                       }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
-                               partialre = this.regExp;
-                               console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp);
-                       } // should never be here unless the original RE is bad or the parsing is bad
-                       this._partialre = "^(?:" + partialre + ")$";
-               },
+               if(
+                       // all child nodes are widgets
+                       childNodes.length == childWidgetNodes.length &&
 
-               postMixInProperties: function(){
-                       this.inherited(arguments);
-                       this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
-                       if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
-                       if(!this.invalidMessage){ this.invalidMessage = this.promptMessage; }
-                       if(this.missingMessage == "$_unset_$"){ this.missingMessage = this.messages.missingMessage; }
-                       if(!this.missingMessage){ this.missingMessage = this.invalidMessage; }
-                       this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
-               },
+                       // all but one are invisible (like dojo.data)
+                       candidateWidgets.length == 1
+               ){
+                       this._singleChild = candidateWidgets[0];
+               }else{
+                       delete this._singleChild;
+               }
 
-               _setDisabledAttr: function(/*Boolean*/ value){
-                       this.inherited(arguments);      // call FormValueWidget._setDisabledAttr()
-                       this._refreshState();
-               },
+               // So we can set overflow: hidden to avoid a safari bug w/scrollbars showing up (#9449)
+               domClass.toggle(this.containerNode, this.baseClass + "SingleChild", !!this._singleChild);
+       },
 
-               _setRequiredAttr: function(/*Boolean*/ value){
-                       this.required = value;
-                       dijit.setWaiState(this.focusNode, "required", value);
-                       this._refreshState();
-               },
+       resize: function(changeSize, resultSize){
+               // summary:
+               //              See `dijit.layout._LayoutWidget.resize` for description.
+               //              Although ContentPane doesn't extend _LayoutWidget, it does implement
+               //              the same API.
 
-               reset:function(){
-                       // Overrides dijit.form.TextBox.reset() by also
-                       // hiding errors about partial matches
-                       this._maskValidSubsetError = true;
-                       this.inherited(arguments);
-               },
+               // For the TabContainer --> BorderContainer --> ContentPane case, _onShow() is
+               // never called, so resize() is our trigger to do the initial href download (see [20099]).
+               // However, don't load href for closed TitlePanes.
+               if(!this._wasShown && this.open !== false){
+                       this._onShow();
+               }
 
-               _onBlur: function(){
-                       this.displayMessage('');
-                       this.inherited(arguments);
+               this._resizeCalled = true;
+
+               this._scheduleLayout(changeSize, resultSize);
+       },
+
+       _scheduleLayout: function(changeSize, resultSize){
+               // summary:
+               //              Resize myself, and call resize() on each of my child layout widgets, either now
+               //              (if I'm currently visible) or when I become visible
+               if(this._isShown()){
+                       this._layout(changeSize, resultSize);
+               }else{
+                       this._needLayout = true;
+                       this._changeSize = changeSize;
+                       this._resultSize = resultSize;
                }
-       }
-);
+       },
 
-dojo.declare(
-       "dijit.form.MappedTextBox",
-       dijit.form.ValidationTextBox,
-       {
+       _layout: function(changeSize, resultSize){
                // summary:
-               //              A dijit.form.ValidationTextBox subclass which provides a base class for widgets that have
-               //              a visible formatted display value, and a serializable
-               //              value in a hidden input field which is actually sent to the server.
-               // description:
-               //              The visible display may
-               //              be locale-dependent and interactive.  The value sent to the server is stored in a hidden
-               //              input field which uses the `name` attribute declared by the original widget.  That value sent
-               //              to the server is defined by the dijit.form.MappedTextBox.serialize method and is typically
-               //              locale-neutral.
-               // tags:
-               //              protected
+               //              Resize myself according to optional changeSize/resultSize parameters, like a layout widget.
+               //              Also, since I am a Container widget, each of my children expects me to
+               //              call resize() or layout() on them.
+               //
+               //              Should be called on initialization and also whenever we get new content
+               //              (from an href, or from set('content', ...))... but deferred until
+               //              the ContentPane is visible
 
-               postMixInProperties: function(){
-                       this.inherited(arguments);
+               // Set margin box size, unless it wasn't specified, in which case use current size.
+               if(changeSize){
+                       domGeometry.setMarginBox(this.domNode, changeSize);
+               }
 
-                       // we want the name attribute to go to the hidden <input>, not the displayed <input>,
-                       // so override _FormWidget.postMixInProperties() setting of nameAttrSetting
-                       this.nameAttrSetting = "";
-               },
+               // Compute content box size of containerNode in case we [later] need to size our single child.
+               var cn = this.containerNode;
+               if(cn === this.domNode){
+                       // If changeSize or resultSize was passed to this method and this.containerNode ==
+                       // this.domNode then we can compute the content-box size without querying the node,
+                       // which is more reliable (similar to LayoutWidget.resize) (see for example #9449).
+                       var mb = resultSize || {};
+                       lang.mixin(mb, changeSize || {}); // changeSize overrides resultSize
+                       if(!("h" in mb) || !("w" in mb)){
+                               mb = lang.mixin(domGeometry.getMarginBox(cn), mb); // just use domGeometry.setMarginBox() to fill in missing values
+                       }
+                       this._contentBox = layoutUtils.marginBox2contentBox(cn, mb);
+               }else{
+                       this._contentBox = domGeometry.getContentBox(cn);
+               }
 
-               serialize: function(/*anything*/val, /*Object?*/options){
-                       // summary:
-                       //              Overridable function used to convert the attr('value') result to a canonical
-                       //              (non-localized) string.  For example, will print dates in ISO format, and
-                       //              numbers the same way as they are represented in javascript.
-                       // tags:
-                       //              protected extension
-                       return val.toString ? val.toString() : ""; // String
-               },
+               this._layoutChildren();
 
-               toString: function(){
-                       // summary:
-                       //              Returns widget as a printable string using the widget's value
-                       // tags:
-                       //              protected
-                       var val = this.filter(this.get('value')); // call filter in case value is nonstring and filter has been customized
-                       return val != null ? (typeof val == "string" ? val : this.serialize(val, this.constraints)) : ""; // String
-               },
+               delete this._needLayout;
+       },
 
-               validate: function(){
-                       // Overrides `dijit.form.TextBox.validate`
-                       this.valueNode.value = this.toString();
-                       return this.inherited(arguments);
-               },
+       _layoutChildren: function(){
+               // Call _checkIfSingleChild() again in case app has manually mucked w/the content
+               // of the ContentPane (rather than changing it through the set("content", ...) API.
+               if(this.doLayout){
+                       this._checkIfSingleChild();
+               }
 
-               buildRendering: function(){
-                       // Overrides `dijit._Templated.buildRendering`
+               if(this._singleChild && this._singleChild.resize){
+                       var cb = this._contentBox || domGeometry.getContentBox(this.containerNode);
 
-                       this.inherited(arguments);
+                       // note: if widget has padding this._contentBox will have l and t set,
+                       // but don't pass them to resize() or it will doubly-offset the child
+                       this._singleChild.resize({w: cb.w, h: cb.h});
+               }else{
+                       // All my child widgets are independently sized (rather than matching my size),
+                       // but I still need to call resize() on each child to make it layout.
+                       array.forEach(this.getChildren(), function(widget){
+                               if(widget.resize){
+                                       widget.resize();
+                               }
+                       });
+               }
+       },
 
-                       // Create a hidden <input> node with the serialized value used for submit
-                       // (as opposed to the displayed value).
-                       // Passing in name as markup rather than calling dojo.create() with an attrs argument
-                       // to make dojo.query(input[name=...]) work on IE. (see #8660)
-                       this.valueNode = dojo.place("<input type='hidden'" + (this.name ? " name='" + this.name + "'" : "") + ">", this.textbox, "after");
-               },
+       _isShown: function(){
+               // summary:
+               //              Returns true if the content is currently shown.
+               // description:
+               //              If I am a child of a layout widget then it actually returns true if I've ever been visible,
+               //              not whether I'm currently visible, since that's much faster than tracing up the DOM/widget
+               //              tree every call, and at least solves the performance problem on page load by deferring loading
+               //              hidden ContentPanes until they are first shown
 
-               reset:function(){
-                       // Overrides `dijit.form.ValidationTextBox.reset` to
-                       // reset the hidden textbox value to ''
-                       this.valueNode.value = '';
-                       this.inherited(arguments);
+               if(this._childOfLayoutWidget){
+                       // If we are TitlePane, etc - we return that only *IF* we've been resized
+                       if(this._resizeCalled && "open" in this){
+                               return this.open;
+                       }
+                       return this._resizeCalled;
+               }else if("open" in this){
+                       return this.open;               // for TitlePane, etc.
+               }else{
+                       var node = this.domNode, parent = this.domNode.parentNode;
+                       return (node.style.display != 'none') && (node.style.visibility != 'hidden') && !domClass.contains(node, "dijitHidden") &&
+                                       parent && parent.style && (parent.style.display != 'none');
                }
-       }
-);
+       },
 
-/*=====
-       dijit.form.RangeBoundTextBox.__Constraints = function(){
-               // min: Number
-               //              Minimum signed value.  Default is -Infinity
-               // max: Number
-               //              Maximum signed value.  Default is +Infinity
-               this.min = min;
-               this.max = max;
+       _onShow: function(){
+               // summary:
+               //              Called when the ContentPane is made visible
+               // description:
+               //              For a plain ContentPane, this is called on initialization, from startup().
+               //              If the ContentPane is a hidden pane of a TabContainer etc., then it's
+               //              called whenever the pane is made visible.
+               //
+               //              Does layout/resize of child widget(s)
+
+               if(this._needLayout){
+                       // If a layout has been scheduled for when we become visible, do it now
+                       this._layout(this._changeSize, this._resultSize);
+               }
+
+               this.inherited(arguments);
+
+               // Need to keep track of whether ContentPane has been shown (which is different than
+               // whether or not it's currently visible).
+               this._wasShown = true;
        }
-=====*/
+});
 
-dojo.declare(
-       "dijit.form.RangeBoundTextBox",
-       dijit.form.MappedTextBox,
-       {
-               // summary:
-               //              Base class for textbox form widgets which defines a range of valid values.
+});
 
-               // rangeMessage: String
-               //              The message to display if value is out-of-range
-               rangeMessage: "",
+},
+'dijit/WidgetSet':function(){
+define("dijit/WidgetSet", [
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/_base/declare", // declare
+       "dojo/_base/window", // win.global
+       "./registry"    // to add functions to dijit.registry
+], function(array, declare, win, registry){
+
+       // module:
+       //              dijit/WidgetSet
+       // summary:
+       //              Legacy registry code.   New modules should just use registry.
+       //              Will be removed in 2.0.
 
-               /*=====
-               // constraints: dijit.form.RangeBoundTextBox.__Constraints
-               constraints: {},
-               ======*/
+       var WidgetSet = declare("dijit.WidgetSet", null, {
+               // summary:
+               //              A set of widgets indexed by id. A default instance of this class is
+               //              available as `dijit.registry`
+               //
+               // example:
+               //              Create a small list of widgets:
+               //              |       var ws = new dijit.WidgetSet();
+               //              |       ws.add(dijit.byId("one"));
+               //              |       ws.add(dijit.byId("two"));
+               //              |       // destroy both:
+               //              |       ws.forEach(function(w){ w.destroy(); });
+               //
+               // example:
+               //              Using dijit.registry:
+               //              |       dijit.registry.forEach(function(w){ /* do something */ });
+
+               constructor: function(){
+                       this._hash = {};
+                       this.length = 0;
+               },
 
-               rangeCheck: function(/*Number*/ primitive, /*dijit.form.RangeBoundTextBox.__Constraints*/ constraints){
+               add: function(/*dijit._Widget*/ widget){
                        // summary:
-                       //              Overridable function used to validate the range of the numeric input value.
-                       // tags:
-                       //              protected
-                       return  ("min" in constraints? (this.compare(primitive,constraints.min) >= 0) : true) &&
-                               ("max" in constraints? (this.compare(primitive,constraints.max) <= 0) : true); // Boolean
+                       //              Add a widget to this list. If a duplicate ID is detected, a error is thrown.
+                       //
+                       // widget: dijit._Widget
+                       //              Any dijit._Widget subclass.
+                       if(this._hash[widget.id]){
+                               throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
+                       }
+                       this._hash[widget.id] = widget;
+                       this.length++;
                },
 
-               isInRange: function(/*Boolean*/ isFocused){
+               remove: function(/*String*/ id){
                        // summary:
-                       //              Tests if the value is in the min/max range specified in constraints
-                       // tags:
-                       //              protected
-                       return this.rangeCheck(this.get('value'), this.constraints);
+                       //              Remove a widget from this WidgetSet. Does not destroy the widget; simply
+                       //              removes the reference.
+                       if(this._hash[id]){
+                               delete this._hash[id];
+                               this.length--;
+                       }
                },
 
-               _isDefinitelyOutOfRange: function(){
+               forEach: function(/*Function*/ func, /* Object? */thisObj){
                        // summary:
-                       //              Returns true if the value is out of range and will remain
-                       //              out of range even if the user types more characters
-                       var val = this.get('value');
-                       var isTooLittle = false;
-                       var isTooMuch = false;
-                       if("min" in this.constraints){
-                               var min = this.constraints.min;
-                               min = this.compare(val, ((typeof min == "number") && min >= 0 && val !=0) ? 0 : min);
-                               isTooLittle = (typeof min == "number") && min < 0;
+                       //              Call specified function for each widget in this set.
+                       //
+                       // func:
+                       //              A callback function to run for each item. Is passed the widget, the index
+                       //              in the iteration, and the full hash, similar to `array.forEach`.
+                       //
+                       // thisObj:
+                       //              An optional scope parameter
+                       //
+                       // example:
+                       //              Using the default `dijit.registry` instance:
+                       //              |       dijit.registry.forEach(function(widget){
+                       //              |               console.log(widget.declaredClass);
+                       //              |       });
+                       //
+                       // returns:
+                       //              Returns self, in order to allow for further chaining.
+
+                       thisObj = thisObj || win.global;
+                       var i = 0, id;
+                       for(id in this._hash){
+                               func.call(thisObj, this._hash[id], i++, this._hash);
                        }
-                       if("max" in this.constraints){
-                               var max = this.constraints.max;
-                               max = this.compare(val, ((typeof max != "number") || max > 0) ? max : 0);
-                               isTooMuch = (typeof max == "number") && max > 0;
+                       return this;    // dijit.WidgetSet
+               },
+
+               filter: function(/*Function*/ filter, /* Object? */thisObj){
+                       // summary:
+                       //              Filter down this WidgetSet to a smaller new WidgetSet
+                       //              Works the same as `array.filter` and `NodeList.filter`
+                       //
+                       // filter:
+                       //              Callback function to test truthiness. Is passed the widget
+                       //              reference and the pseudo-index in the object.
+                       //
+                       // thisObj: Object?
+                       //              Option scope to use for the filter function.
+                       //
+                       // example:
+                       //              Arbitrary: select the odd widgets in this list
+                       //              |       dijit.registry.filter(function(w, i){
+                       //              |               return i % 2 == 0;
+                       //              |       }).forEach(function(w){ /* odd ones */ });
+
+                       thisObj = thisObj || win.global;
+                       var res = new WidgetSet(), i = 0, id;
+                       for(id in this._hash){
+                               var w = this._hash[id];
+                               if(filter.call(thisObj, w, i++, this._hash)){
+                                       res.add(w);
+                               }
                        }
-                       return isTooLittle || isTooMuch;
+                       return res; // dijit.WidgetSet
                },
 
-               _isValidSubset: function(){
+               byId: function(/*String*/ id){
                        // summary:
-                       //              Overrides `dijit.form.ValidationTextBox._isValidSubset`.
-                       //              Returns true if the input is syntactically valid, and either within
-                       //              range or could be made in range by more typing.
-                       return this.inherited(arguments) && !this._isDefinitelyOutOfRange();
+                       //              Find a widget in this list by it's id.
+                       // example:
+                       //              Test if an id is in a particular WidgetSet
+                       //              | var ws = new dijit.WidgetSet();
+                       //              | ws.add(dijit.byId("bar"));
+                       //              | var t = ws.byId("bar") // returns a widget
+                       //              | var x = ws.byId("foo"); // returns undefined
+
+                       return this._hash[id];  // dijit._Widget
                },
 
-               isValid: function(/*Boolean*/ isFocused){
-                       // Overrides dijit.form.ValidationTextBox.isValid to check that the value is also in range.
-                       return this.inherited(arguments) &&
-                               ((this._isEmpty(this.textbox.value) && !this.required) || this.isInRange(isFocused)); // Boolean
+               byClass: function(/*String*/ cls){
+                       // summary:
+                       //              Reduce this widgetset to a new WidgetSet of a particular `declaredClass`
+                       //
+                       // cls: String
+                       //              The Class to scan for. Full dot-notated string.
+                       //
+                       // example:
+                       //              Find all `dijit.TitlePane`s in a page:
+                       //              |       dijit.registry.byClass("dijit.TitlePane").forEach(function(tp){ tp.close(); });
+
+                       var res = new WidgetSet(), id, widget;
+                       for(id in this._hash){
+                               widget = this._hash[id];
+                               if(widget.declaredClass == cls){
+                                       res.add(widget);
+                               }
+                        }
+                        return res; // dijit.WidgetSet
                },
 
-               getErrorMessage: function(/*Boolean*/ isFocused){
-                       // Overrides dijit.form.ValidationTextBox.getErrorMessage to print "out of range" message if appropriate
-                       var v = this.get('value');
-                       if(v !== null && v !== '' && v !== undefined && (typeof v != "number" || !isNaN(v)) && !this.isInRange(isFocused)){ // don't check isInRange w/o a real value
-                               return this.rangeMessage; // String
+               toArray: function(){
+                       // summary:
+                       //              Convert this WidgetSet into a true Array
+                       //
+                       // example:
+                       //              Work with the widget .domNodes in a real Array
+                       //              |       array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
+
+                       var ar = [];
+                       for(var id in this._hash){
+                               ar.push(this._hash[id]);
                        }
-                       return this.inherited(arguments);
+                       return ar;      // dijit._Widget[]
                },
 
-               postMixInProperties: function(){
-                       this.inherited(arguments);
-                       if(!this.rangeMessage){
-                               this.messages = dojo.i18n.getLocalization("dijit.form", "validate", this.lang);
-                               this.rangeMessage = this.messages.rangeMessage;
-                       }
+               map: function(/* Function */func, /* Object? */thisObj){
+                       // summary:
+                       //              Create a new Array from this WidgetSet, following the same rules as `array.map`
+                       // example:
+                       //              |       var nodes = dijit.registry.map(function(w){ return w.domNode; });
+                       //
+                       // returns:
+                       //              A new array of the returned values.
+                       return array.map(this.toArray(), func, thisObj); // Array
                },
 
-               _setConstraintsAttr: function(/* Object */ constraints){
-                       this.inherited(arguments);
-                       if(this.focusNode){ // not set when called from postMixInProperties
-                               if(this.constraints.min !== undefined){
-                                       dijit.setWaiState(this.focusNode, "valuemin", this.constraints.min);
-                               }else{
-                                       dijit.removeWaiState(this.focusNode, "valuemin");
-                               }
-                               if(this.constraints.max !== undefined){
-                                       dijit.setWaiState(this.focusNode, "valuemax", this.constraints.max);
-                               }else{
-                                       dijit.removeWaiState(this.focusNode, "valuemax");
+               every: function(func, thisObj){
+                       // summary:
+                       //              A synthetic clone of `array.every` acting explicitly on this WidgetSet
+                       //
+                       // func: Function
+                       //              A callback function run for every widget in this list. Exits loop
+                       //              when the first false return is encountered.
+                       //
+                       // thisObj: Object?
+                       //              Optional scope parameter to use for the callback
+
+                       thisObj = thisObj || win.global;
+                       var x = 0, i;
+                       for(i in this._hash){
+                               if(!func.call(thisObj, this._hash[i], x++, this._hash)){
+                                       return false; // Boolean
                                }
                        }
+                       return true; // Boolean
                },
 
-               _setValueAttr: function(/*Number*/ value, /*Boolean?*/ priorityChange){
+               some: function(func, thisObj){
                        // summary:
-                       //              Hook so attr('value', ...) works.
+                       //              A synthetic clone of `array.some` acting explicitly on this WidgetSet
+                       //
+                       // func: Function
+                       //              A callback function run for every widget in this list. Exits loop
+                       //              when the first true return is encountered.
+                       //
+                       // thisObj: Object?
+                       //              Optional scope parameter to use for the callback
 
-                       dijit.setWaiState(this.focusNode, "valuenow", value);
-                       this.inherited(arguments);
+                       thisObj = thisObj || win.global;
+                       var x = 0, i;
+                       for(i in this._hash){
+                               if(func.call(thisObj, this._hash[i], x++, this._hash)){
+                                       return true; // Boolean
+                               }
+                       }
+                       return false; // Boolean
                }
-       }
-);
 
-}
+       });
 
-if(!dojo._hasResource["dijit.form.ComboBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.ComboBox"] = true;
-dojo.provide("dijit.form.ComboBox");
+       // Add in 1.x compatibility methods to dijit.registry.
+       // These functions won't show up in the API doc but since they are deprecated anyway,
+       // that's probably for the best.
+       array.forEach(["forEach", "filter", "byClass", "map", "every", "some"], function(func){
+               registry[func] = WidgetSet.prototype[func];
+       });
 
 
+       return WidgetSet;
+});
 
+},
+'dojo/dnd/Moveable':function(){
+define("dojo/dnd/Moveable", ["../main", "../Evented", "../touch", "./Mover"], function(dojo, Evented, touch) {
+       // module:
+       //              dojo/dnd/Moveable
+       // summary:
+       //              TODOC
 
 
+/*=====
+dojo.declare("dojo.dnd.__MoveableArgs", [], {
+       // handle: Node||String
+       //              A node (or node's id), which is used as a mouse handle.
+       //              If omitted, the node itself is used as a handle.
+       handle: null,
 
+       // delay: Number
+       //              delay move by this number of pixels
+       delay: 0,
 
+       // skip: Boolean
+       //              skip move of form elements
+       skip: false,
 
+       // mover: Object
+       //              a constructor of custom Mover
+       mover: dojo.dnd.Mover
+});
+=====*/
 
+dojo.declare("dojo.dnd.Moveable", [Evented], {
+       // object attributes (for markup)
+       handle: "",
+       delay: 0,
+       skip: false,
 
+       constructor: function(node, params){
+               // summary:
+               //              an object, which makes a node moveable
+               // node: Node
+               //              a node (or node's id) to be moved
+               // params: dojo.dnd.__MoveableArgs?
+               //              optional parameters
+               this.node = dojo.byId(node);
+               if(!params){ params = {}; }
+               this.handle = params.handle ? dojo.byId(params.handle) : null;
+               if(!this.handle){ this.handle = this.node; }
+               this.delay = params.delay > 0 ? params.delay : 0;
+               this.skip  = params.skip;
+               this.mover = params.mover ? params.mover : dojo.dnd.Mover;
+               this.events = [
+                       dojo.connect(this.handle, touch.press, this, "onMouseDown"),
+                       // cancel text selection and text dragging
+                       dojo.connect(this.handle, "ondragstart",   this, "onSelectStart"),
+                       dojo.connect(this.handle, "onselectstart", this, "onSelectStart")
+               ];
+       },
 
+       // markup methods
+       markupFactory: function(params, node, ctor){
+               return new ctor(node, params);
+       },
 
-dojo.declare(
-       "dijit.form.ComboBoxMixin",
-       null,
-       {
+       // methods
+       destroy: function(){
                // summary:
-               //              Implements the base functionality for `dijit.form.ComboBox`/`dijit.form.FilteringSelect`
-               // description:
-               //              All widgets that mix in dijit.form.ComboBoxMixin must extend `dijit.form._FormValueWidget`.
-               // tags:
-               //              protected
+               //              stops watching for possible move, deletes all references, so the object can be garbage-collected
+               dojo.forEach(this.events, dojo.disconnect);
+               this.events = this.node = this.handle = null;
+       },
 
-               // item: Object
-               //              This is the item returned by the dojo.data.store implementation that
-               //              provides the data for this ComboBox, it's the currently selected item.
-               item: null,
+       // mouse event processors
+       onMouseDown: function(e){
+               // summary:
+               //              event processor for onmousedown/ontouchstart, creates a Mover for the node
+               // e: Event
+               //              mouse/touch event
+               if(this.skip && dojo.dnd.isFormElement(e)){ return; }
+               if(this.delay){
+                       this.events.push(
+                               dojo.connect(this.handle, touch.move, this, "onMouseMove"),
+                               dojo.connect(this.handle, touch.release, this, "onMouseUp")
+                       );
+                       this._lastX = e.pageX;
+                       this._lastY = e.pageY;
+               }else{
+                       this.onDragDetected(e);
+               }
+               dojo.stopEvent(e);
+       },
+       onMouseMove: function(e){
+               // summary:
+               //              event processor for onmousemove/ontouchmove, used only for delayed drags
+               // e: Event
+               //              mouse/touch event
+               if(Math.abs(e.pageX - this._lastX) > this.delay || Math.abs(e.pageY - this._lastY) > this.delay){
+                       this.onMouseUp(e);
+                       this.onDragDetected(e);
+               }
+               dojo.stopEvent(e);
+       },
+       onMouseUp: function(e){
+               // summary:
+               //              event processor for onmouseup, used only for delayed drags
+               // e: Event
+               //              mouse event
+               for(var i = 0; i < 2; ++i){
+                       dojo.disconnect(this.events.pop());
+               }
+               dojo.stopEvent(e);
+       },
+       onSelectStart: function(e){
+               // summary:
+               //              event processor for onselectevent and ondragevent
+               // e: Event
+               //              mouse event
+               if(!this.skip || !dojo.dnd.isFormElement(e)){
+                       dojo.stopEvent(e);
+               }
+       },
 
-               // pageSize: Integer
-               //              Argument to data provider.
-               //              Specifies number of search results per page (before hitting "next" button)
-               pageSize: Infinity,
+       // local events
+       onDragDetected: function(/* Event */ e){
+               // summary:
+               //              called when the drag is detected;
+               //              responsible for creation of the mover
+               new this.mover(this.node, e, this);
+       },
+       onMoveStart: function(/* dojo.dnd.Mover */ mover){
+               // summary:
+               //              called before every move operation
+               dojo.publish("/dnd/move/start", [mover]);
+               dojo.addClass(dojo.body(), "dojoMove");
+               dojo.addClass(this.node, "dojoMoveItem");
+       },
+       onMoveStop: function(/* dojo.dnd.Mover */ mover){
+               // summary:
+               //              called after every move operation
+               dojo.publish("/dnd/move/stop", [mover]);
+               dojo.removeClass(dojo.body(), "dojoMove");
+               dojo.removeClass(this.node, "dojoMoveItem");
+       },
+       onFirstMove: function(/* dojo.dnd.Mover */ mover, /* Event */ e){
+               // summary:
+               //              called during the very first move notification;
+               //              can be used to initialize coordinates, can be overwritten.
 
-               // store: Object
-               //              Reference to data provider object used by this ComboBox
-               store: null,
+               // default implementation does nothing
+       },
+       onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop, /* Event */ e){
+               // summary:
+               //              called during every move notification;
+               //              should actually move the node; can be overwritten.
+               this.onMoving(mover, leftTop);
+               var s = mover.node.style;
+               s.left = leftTop.l + "px";
+               s.top  = leftTop.t + "px";
+               this.onMoved(mover, leftTop);
+       },
+       onMoving: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+               // summary:
+               //              called before every incremental move; can be overwritten.
 
-               // fetchProperties: Object
-               //              Mixin to the dojo.data store's fetch.
-               //              For example, to set the sort order of the ComboBox menu, pass:
-               //      |       { sort: {attribute:"name",descending: true} }
-               //              To override the default queryOptions so that deep=false, do:
-               //      |       { queryOptions: {ignoreCase: true, deep: false} }
-               fetchProperties:{},
+               // default implementation does nothing
+       },
+       onMoved: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
+               // summary:
+               //              called after every incremental move; can be overwritten.
 
-               // query: Object
-               //              A query that can be passed to 'store' to initially filter the items,
-               //              before doing further filtering based on `searchAttr` and the key.
-               //              Any reference to the `searchAttr` is ignored.
-               query: {},
+               // default implementation does nothing
+       }
+});
 
-               // autoComplete: Boolean
-               //              If user types in a partial string, and then tab out of the `<input>` box,
-               //              automatically copy the first entry displayed in the drop down list to
-               //              the `<input>` field
-               autoComplete: true,
+return dojo.dnd.Moveable;
+});
 
-               // highlightMatch: String
-               //              One of: "first", "all" or "none".
-               //
-               //              If the ComboBox/FilteringSelect opens with the search results and the searched
-               //              string can be found, it will be highlighted.  If set to "all"
-               //              then will probably want to change `queryExpr` parameter to '*${0}*'
-               //
-               //              Highlighting is only performed when `labelType` is "text", so as to not
-               //              interfere with any HTML markup an HTML label might contain.
-               highlightMatch: "first",
+},
+'dojo/store/util/SimpleQueryEngine':function(){
+define("dojo/store/util/SimpleQueryEngine", ["../../_base/array"], function(arrayUtil) {
+  //  module:
+  //    dojo/store/util/SimpleQueryEngine
+  //  summary:
+  //    The module defines a simple filtering query engine for object stores. 
+
+return function(query, options){
+       // summary:
+       //              Simple query engine that matches using filter functions, named filter
+       //              functions or objects by name-value on a query object hash
+       //
+       // description:
+       //              The SimpleQueryEngine provides a way of getting a QueryResults through
+       //              the use of a simple object hash as a filter.  The hash will be used to
+       //              match properties on data objects with the corresponding value given. In
+       //              other words, only exact matches will be returned.
+       //
+       //              This function can be used as a template for more complex query engines;
+       //              for example, an engine can be created that accepts an object hash that
+       //              contains filtering functions, or a string that gets evaluated, etc.
+       //
+       //              When creating a new dojo.store, simply set the store's queryEngine
+       //              field as a reference to this function.
+       //
+       // query: Object
+       //              An object hash with fields that may match fields of items in the store.
+       //              Values in the hash will be compared by normal == operator, but regular expressions
+       //              or any object that provides a test() method are also supported and can be
+       //              used to match strings by more complex expressions
+       //              (and then the regex's or object's test() method will be used to match values).
+       //
+       // options: dojo.store.util.SimpleQueryEngine.__queryOptions?
+       //              An object that contains optional information such as sort, start, and count.
+       //
+       // returns: Function
+       //              A function that caches the passed query under the field "matches".  See any
+       //              of the "query" methods on dojo.stores.
+       //
+       // example:
+       //              Define a store with a reference to this engine, and set up a query method.
+       //
+       //      |       var myStore = function(options){
+       //      |               //      ...more properties here
+       //      |               this.queryEngine = dojo.store.util.SimpleQueryEngine;
+       //      |               //      define our query method
+       //      |               this.query = function(query, options){
+       //      |                       return dojo.store.util.QueryResults(this.queryEngine(query, options)(this.data));
+       //      |               };
+       //      |       };
+
+       // create our matching query function
+       switch(typeof query){
+               default:
+                       throw new Error("Can not query with a " + typeof query);
+               case "object": case "undefined":
+                       var queryObject = query;
+                       query = function(object){
+                               for(var key in queryObject){
+                                       var required = queryObject[key];
+                                       if(required && required.test){
+                                               if(!required.test(object[key])){
+                                                       return false;
+                                               }
+                                       }else if(required != object[key]){
+                                               return false;
+                                       }
+                               }
+                               return true;
+                       };
+                       break;
+               case "string":
+                       // named query
+                       if(!this[query]){
+                               throw new Error("No filter function " + query + " was found in store");
+                       }
+                       query = this[query];
+                       // fall through
+               case "function":
+                       // fall through
+       }
+       function execute(array){
+               // execute the whole query, first we filter
+               var results = arrayUtil.filter(array, query);
+               // next we sort
+               if(options && options.sort){
+                       results.sort(function(a, b){
+                               for(var sort, i=0; sort = options.sort[i]; i++){
+                                       var aValue = a[sort.attribute];
+                                       var bValue = b[sort.attribute];
+                                       if (aValue != bValue) {
+                                               return !!sort.descending == aValue > bValue ? -1 : 1;
+                                       }
+                               }
+                               return 0;
+                       });
+               }
+               // now we paginate
+               if(options && (options.start || options.count)){
+                       var total = results.length;
+                       results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
+                       results.total = total;
+               }
+               return results;
+       }
+       execute.matches = query;
+       return execute;
+};
+});
 
-               // searchDelay: Integer
-               //              Delay in milliseconds between when user types something and we start
-               //              searching based on that value
-               searchDelay: 100,
+},
+'dijit/typematic':function(){
+define("dijit/typematic", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/connect", // connect.connect
+       "dojo/_base/event", // event.stop
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.mixin, lang.hitch
+       "dojo/on",
+       "dojo/_base/sniff", // has("ie")
+       "."             // setting dijit.typematic global
+], function(array, connect, event, kernel, lang, on, has, dijit){
+
+// module:
+//             dijit/typematic
+// summary:
+//             These functions are used to repetitively call a user specified callback
+//             method when a specific key or mouse click over a specific DOM node is
+//             held down for a specific amount of time.
+//             Only 1 such event is allowed to occur on the browser page at 1 time.
 
-               // searchAttr: String
-               //              Search for items in the data store where this attribute (in the item)
-               //              matches what the user typed
-               searchAttr: "name",
+var typematic = (dijit.typematic = {
+       // summary:
+       //              These functions are used to repetitively call a user specified callback
+       //              method when a specific key or mouse click over a specific DOM node is
+       //              held down for a specific amount of time.
+       //              Only 1 such event is allowed to occur on the browser page at 1 time.
 
-               // labelAttr: String?
-               //              The entries in the drop down list come from this attribute in the
-               //              dojo.data items.
-               //              If not specified, the searchAttr attribute is used instead.
-               labelAttr: "",
+       _fireEventAndReload: function(){
+               this._timer = null;
+               this._callback(++this._count, this._node, this._evt);
 
-               // labelType: String
-               //              Specifies how to interpret the labelAttr in the data store items.
-               //              Can be "html" or "text".
-               labelType: "text",
+               // Schedule next event, timer is at most minDelay (default 10ms) to avoid
+               // browser overload (particularly avoiding starving DOH robot so it never gets to send a mouseup)
+               this._currentTimeout = Math.max(
+                       this._currentTimeout < 0 ? this._initialDelay :
+                               (this._subsequentDelay > 1 ? this._subsequentDelay : Math.round(this._currentTimeout * this._subsequentDelay)),
+                       this._minDelay);
+               this._timer = setTimeout(lang.hitch(this, "_fireEventAndReload"), this._currentTimeout);
+       },
 
-               // queryExpr: String
-               //              This specifies what query ComboBox/FilteringSelect sends to the data store,
-               //              based on what the user has typed.  Changing this expression will modify
-               //              whether the drop down shows only exact matches, a "starting with" match,
-               //              etc.   Use it in conjunction with highlightMatch.
-               //              dojo.data query expression pattern.
-               //              `${0}` will be substituted for the user text.
-               //              `*` is used for wildcards.
-               //              `${0}*` means "starts with", `*${0}*` means "contains", `${0}` means "is"
-               queryExpr: "${0}*",
+       trigger: function(/*Event*/ evt, /*Object*/ _this, /*DOMNode*/ node, /*Function*/ callback, /*Object*/ obj, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+               // summary:
+               //              Start a timed, repeating callback sequence.
+               //              If already started, the function call is ignored.
+               //              This method is not normally called by the user but can be
+               //              when the normal listener code is insufficient.
+               // evt:
+               //              key or mouse event object to pass to the user callback
+               // _this:
+               //              pointer to the user's widget space.
+               // node:
+               //              the DOM node object to pass the the callback function
+               // callback:
+               //              function to call until the sequence is stopped called with 3 parameters:
+               // count:
+               //              integer representing number of repeated calls (0..n) with -1 indicating the iteration has stopped
+               // node:
+               //              the DOM node object passed in
+               // evt:
+               //              key or mouse event object
+               // obj:
+               //              user space object used to uniquely identify each typematic sequence
+               // subsequentDelay (optional):
+               //              if > 1, the number of milliseconds until the 3->n events occur
+               //              or else the fractional time multiplier for the next event's delay, default=0.9
+               // initialDelay (optional):
+               //              the number of milliseconds until the 2nd event occurs, default=500ms
+               // minDelay (optional):
+               //              the maximum delay in milliseconds for event to fire, default=10ms
+               if(obj != this._obj){
+                       this.stop();
+                       this._initialDelay = initialDelay || 500;
+                       this._subsequentDelay = subsequentDelay || 0.90;
+                       this._minDelay = minDelay || 10;
+                       this._obj = obj;
+                       this._evt = evt;
+                       this._node = node;
+                       this._currentTimeout = -1;
+                       this._count = -1;
+                       this._callback = lang.hitch(_this, callback);
+                       this._fireEventAndReload();
+                       this._evt = lang.mixin({faux: true}, evt);
+               }
+       },
 
-               // ignoreCase: Boolean
-               //              Set true if the ComboBox/FilteringSelect should ignore case when matching possible items
-               ignoreCase: true,
+       stop: function(){
+               // summary:
+               //              Stop an ongoing timed, repeating callback sequence.
+               if(this._timer){
+                       clearTimeout(this._timer);
+                       this._timer = null;
+               }
+               if(this._obj){
+                       this._callback(-1, this._node, this._evt);
+                       this._obj = null;
+               }
+       },
 
-               // hasDownArrow: [const] Boolean
-               //              Set this textbox to have a down arrow button, to display the drop down list.
-               //              Defaults to true.
-               hasDownArrow: true,
+       addKeyListener: function(/*DOMNode*/ node, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+               // summary:
+               //              Start listening for a specific typematic key.
+               //              See also the trigger method for other parameters.
+               // keyObject:
+               //              an object defining the key to listen for:
+               //              charOrCode:
+               //                      the printable character (string) or keyCode (number) to listen for.
+               //              keyCode:
+               //                      (deprecated - use charOrCode) the keyCode (number) to listen for (implies charCode = 0).
+               //              charCode:
+               //                      (deprecated - use charOrCode) the charCode (number) to listen for.
+               //              ctrlKey:
+               //                      desired ctrl key state to initiate the callback sequence:
+               //                      - pressed (true)
+               //                      - released (false)
+               //                      - either (unspecified)
+               //              altKey:
+               //                      same as ctrlKey but for the alt key
+               //              shiftKey:
+               //                      same as ctrlKey but for the shift key
+               // returns:
+               //              a connection handle
+               if(keyObject.keyCode){
+                       keyObject.charOrCode = keyObject.keyCode;
+                       kernel.deprecated("keyCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
+               }else if(keyObject.charCode){
+                       keyObject.charOrCode = String.fromCharCode(keyObject.charCode);
+                       kernel.deprecated("charCode attribute parameter for dijit.typematic.addKeyListener is deprecated. Use charOrCode instead.", "", "2.0");
+               }
+               var handles = [
+                       on(node, connect._keypress, lang.hitch(this, function(evt){
+                               if(evt.charOrCode == keyObject.charOrCode &&
+                               (keyObject.ctrlKey === undefined || keyObject.ctrlKey == evt.ctrlKey) &&
+                               (keyObject.altKey === undefined || keyObject.altKey == evt.altKey) &&
+                               (keyObject.metaKey === undefined || keyObject.metaKey == (evt.metaKey || false)) && // IE doesn't even set metaKey
+                               (keyObject.shiftKey === undefined || keyObject.shiftKey == evt.shiftKey)){
+                                       event.stop(evt);
+                                       typematic.trigger(evt, _this, node, callback, keyObject, subsequentDelay, initialDelay, minDelay);
+                               }else if(typematic._obj == keyObject){
+                                       typematic.stop();
+                               }
+                       })),
+                       on(node, "keyup", lang.hitch(this, function(){
+                               if(typematic._obj == keyObject){
+                                       typematic.stop();
+                               }
+                       }))
+               ];
+               return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
+       },
 
-               templateString: dojo.cache("dijit.form", "templates/ComboBox.html", "<div class=\"dijit dijitReset dijitInlineTable dijitLeft\"\n\tid=\"widget_${id}\"\n\tdojoAttachPoint=\"comboNode\" waiRole=\"combobox\"\n\t><div class='dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton dijitArrowButtonContainer'\n\t\tdojoAttachPoint=\"downArrowNode\" waiRole=\"presentation\"\n\t\tdojoAttachEvent=\"onmousedown:_onArrowMouseDown\"\n\t\t><input class=\"dijitReset dijitInputField dijitArrowButtonInner\" value=\"&#9660; \" type=\"text\" tabIndex=\"-1\" readOnly waiRole=\"presentation\"\n\t\t\t${_buttonInputDisabled}\n\t/></div\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&Chi; \" type=\"text\" tabIndex=\"-1\" readOnly waiRole=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class='dijitReset dijitInputInner' ${!nameAttrSetting} type=\"text\" autocomplete=\"off\"\n\t\t\tdojoAttachEvent=\"onkeypress:_onKeyPress,compositionend\"\n\t\t\tdojoAttachPoint=\"textbox,focusNode\" waiRole=\"textbox\" waiState=\"haspopup-true,autocomplete-list\"\n\t/></div\n></div>\n"),
+       addMouseListener: function(/*DOMNode*/ node, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+               // summary:
+               //              Start listening for a typematic mouse click.
+               //              See the trigger method for other parameters.
+               // returns:
+               //              a connection handle
+               var handles =  [
+                       on(node, "mousedown", lang.hitch(this, function(evt){
+                               event.stop(evt);
+                               typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
+                       })),
+                       on(node, "mouseup", lang.hitch(this, function(evt){
+                               if(this._obj){
+                                       event.stop(evt);
+                               }
+                               typematic.stop();
+                       })),
+                       on(node, "mouseout", lang.hitch(this, function(evt){
+                               event.stop(evt);
+                               typematic.stop();
+                       })),
+                       on(node, "mousemove", lang.hitch(this, function(evt){
+                               evt.preventDefault();
+                       })),
+                       on(node, "dblclick", lang.hitch(this, function(evt){
+                               event.stop(evt);
+                               if(has("ie")){
+                                       typematic.trigger(evt, _this, node, callback, node, subsequentDelay, initialDelay, minDelay);
+                                       setTimeout(lang.hitch(this, typematic.stop), 50);
+                               }
+                       }))
+               ];
+               return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
+       },
 
-               baseClass: "dijitTextBox dijitComboBox",
+       addListener: function(/*Node*/ mouseNode, /*Node*/ keyNode, /*Object*/ keyObject, /*Object*/ _this, /*Function*/ callback, /*Number*/ subsequentDelay, /*Number*/ initialDelay, /*Number?*/ minDelay){
+               // summary:
+               //              Start listening for a specific typematic key and mouseclick.
+               //              This is a thin wrapper to addKeyListener and addMouseListener.
+               //              See the addMouseListener and addKeyListener methods for other parameters.
+               // mouseNode:
+               //              the DOM node object to listen on for mouse events.
+               // keyNode:
+               //              the DOM node object to listen on for key events.
+               // returns:
+               //              a connection handle
+               var handles = [
+                       this.addKeyListener(keyNode, keyObject, _this, callback, subsequentDelay, initialDelay, minDelay),
+                       this.addMouseListener(mouseNode, _this, callback, subsequentDelay, initialDelay, minDelay)
+               ];
+               return { remove: function(){ array.forEach(handles, function(h){ h.remove(); }); } };
+       }
+});
 
-               // Set classes like dijitDownArrowButtonHover depending on
-               // mouse action over button node
-               cssStateNodes: {
-                       "downArrowNode": "dijitDownArrowButton"
+return typematic;
+
+});
+
+},
+'dijit/MenuItem':function(){
+require({cache:{
+'url:dijit/templates/MenuItem.html':"<tr class=\"dijitReset dijitMenuItem\" data-dojo-attach-point=\"focusNode\" role=\"menuitem\" tabIndex=\"-1\"\n\t\tdata-dojo-attach-event=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" role=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" data-dojo-attach-point=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" data-dojo-attach-point=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" data-dojo-attach-point=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" role=\"presentation\">\n\t\t<div data-dojo-attach-point=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n"}});
+define("dijit/MenuItem", [
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.setSelectable
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-class", // domClass.toggle
+       "dojo/_base/event", // event.stop
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/sniff", // has("ie")
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_Contained",
+       "./_CssStateMixin",
+       "dojo/text!./templates/MenuItem.html"
+], function(declare, dom, domAttr, domClass, event, kernel, has,
+                       _Widget, _TemplatedMixin, _Contained, _CssStateMixin, template){
+
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _Contained = dijit._Contained;
+       var _CssStateMixin = dijit._CssStateMixin;
+=====*/
+
+       // module:
+       //              dijit/MenuItem
+       // summary:
+       //              A line item in a Menu Widget
+
+
+       return declare("dijit.MenuItem",
+               [_Widget, _TemplatedMixin, _Contained, _CssStateMixin],
+               {
+               // summary:
+               //              A line item in a Menu Widget
+
+               // Make 3 columns
+               // icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
+               templateString: template,
+
+               baseClass: "dijitMenuItem",
+
+               // label: String
+               //              Menu text
+               label: '',
+               _setLabelAttr: { node: "containerNode", type: "innerHTML" },
+
+               // iconClass: String
+               //              Class to apply to DOMNode to make it display an icon.
+               iconClass: "dijitNoIcon",
+               _setIconClassAttr: { node: "iconNode", type: "class" },
+
+               // accelKey: String
+               //              Text for the accelerator (shortcut) key combination.
+               //              Note that although Menu can display accelerator keys there
+               //              is no infrastructure to actually catch and execute these
+               //              accelerators.
+               accelKey: "",
+
+               // disabled: Boolean
+               //              If true, the menu item is disabled.
+               //              If false, the menu item is enabled.
+               disabled: false,
+
+               _fillContent: function(/*DomNode*/ source){
+                       // If button label is specified as srcNodeRef.innerHTML rather than
+                       // this.params.label, handle it here.
+                       if(source && !("label" in this.params)){
+                               this.set('label', source.innerHTML);
+                       }
                },
 
-               _getCaretPos: function(/*DomNode*/ element){
-                       // khtml 3.5.2 has selection* methods as does webkit nightlies from 2005-06-22
-                       var pos = 0;
-                       if(typeof(element.selectionStart) == "number"){
-                               // FIXME: this is totally borked on Moz < 1.3. Any recourse?
-                               pos = element.selectionStart;
-                       }else if(dojo.isIE){
-                               // in the case of a mouse click in a popup being handled,
-                               // then the dojo.doc.selection is not the textarea, but the popup
-                               // var r = dojo.doc.selection.createRange();
-                               // hack to get IE 6 to play nice. What a POS browser.
-                               var tr = dojo.doc.selection.createRange().duplicate();
-                               var ntr = element.createTextRange();
-                               tr.move("character",0);
-                               ntr.move("character",0);
-                               try{
-                                       // If control doesnt have focus, you get an exception.
-                                       // Seems to happen on reverse-tab, but can also happen on tab (seems to be a race condition - only happens sometimes).
-                                       // There appears to be no workaround for this - googled for quite a while.
-                                       ntr.setEndPoint("EndToEnd", tr);
-                                       pos = String(ntr.text).replace(/\r/g,"").length;
-                               }catch(e){
-                                       // If focus has shifted, 0 is fine for caret pos.
-                               }
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       var label = this.id+"_text";
+                       domAttr.set(this.containerNode, "id", label);
+                       if(this.accelKeyNode){
+                               domAttr.set(this.accelKeyNode, "id", this.id + "_accel");
+                               label += " " + this.id + "_accel";
                        }
-                       return pos;
+                       this.domNode.setAttribute("aria-labelledby", label);
+                       dom.setSelectable(this.domNode, false);
                },
 
-               _setCaretPos: function(/*DomNode*/ element, /*Number*/ location){
-                       location = parseInt(location);
-                       dijit.selectInputText(element, location, location);
+               _onHover: function(){
+                       // summary:
+                       //              Handler when mouse is moved onto menu item
+                       // tags:
+                       //              protected
+                       this.getParent().onItemHover(this);
                },
 
-               _setDisabledAttr: function(/*Boolean*/ value){
-                       // Additional code to set disabled state of ComboBox node.
-                       // Overrides _FormValueWidget._setDisabledAttr() or ValidationTextBox._setDisabledAttr().
-                       this.inherited(arguments);
-                       dijit.setWaiState(this.comboNode, "disabled", value);
+               _onUnhover: function(){
+                       // summary:
+                       //              Handler when mouse is moved off of menu item,
+                       //              possibly to a child menu, or maybe to a sibling
+                       //              menuitem or somewhere else entirely.
+                       // tags:
+                       //              protected
+
+                       // if we are unhovering the currently selected item
+                       // then unselect it
+                       this.getParent().onItemUnhover(this);
+
+                       // When menu is hidden (collapsed) due to clicking a MenuItem and having it execute,
+                       // FF and IE don't generate an onmouseout event for the MenuItem.
+                       // So, help out _CssStateMixin in this case.
+                       this._set("hovering", false);
                },
 
-               _abortQuery: function(){
-                       // stop in-progress query
-                       if(this.searchTimer){
-                               clearTimeout(this.searchTimer);
-                               this.searchTimer = null;
-                       }
-                       if(this._fetchHandle){
-                               if(this._fetchHandle.abort){ this._fetchHandle.abort(); }
-                               this._fetchHandle = null;
-                       }
+               _onClick: function(evt){
+                       // summary:
+                       //              Internal handler for click events on MenuItem.
+                       // tags:
+                       //              private
+                       this.getParent().onItemClick(this, evt);
+                       event.stop(evt);
                },
 
-               _onInput: function(/*Event*/ evt){
+               onClick: function(/*Event*/){
                        // summary:
-                       //              Handles paste events
-                       if(!this.searchTimer && (evt.type == 'paste'/*IE|WebKit*/ || evt.type == 'input'/*Firefox*/) && this._lastInput != this.textbox.value){
-                               this.searchTimer = setTimeout(dojo.hitch(this, function(){
-                                       this._onKeyPress({charOrCode: 229}); // fake IME key to cause a search
-                               }), 100); // long delay that will probably be preempted by keyboard input
-                       }
-                       this.inherited(arguments);
+                       //              User defined function to handle clicks
+                       // tags:
+                       //              callback
                },
 
-               _onKeyPress: function(/*Event*/ evt){
+               focus: function(){
                        // summary:
-                       //              Handles keyboard events
-                       var key = evt.charOrCode;
-                       // except for cutting/pasting case - ctrl + x/v
-                       if(evt.altKey || ((evt.ctrlKey || evt.metaKey) && (key != 'x' && key != 'v')) || key == dojo.keys.SHIFT){
-                               return; // throw out weird key combinations and spurious events
+                       //              Focus on this MenuItem
+                       try{
+                               if(has("ie") == 8){
+                                       // needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
+                                       this.containerNode.focus();
+                               }
+                               this.focusNode.focus();
+                       }catch(e){
+                               // this throws on IE (at least) in some scenarios
                        }
-                       var doSearch = false;
-                       var searchFunction = "_startSearchFromInput";
-                       var pw = this._popupWidget;
-                       var dk = dojo.keys;
-                       var highlighted = null;
-                       this._prev_key_backspace = false;
-                       this._abortQuery();
-                       if(this._isShowingNow){
-                               pw.handleKey(key);
-                               highlighted = pw.getHighlightedOption();
-                       }
-                       switch(key){
-                               case dk.PAGE_DOWN:
-                               case dk.DOWN_ARROW:
-                               case dk.PAGE_UP:
-                               case dk.UP_ARROW:
-                                       if(!this._isShowingNow){
-                                               doSearch = true;
-                                               searchFunction = "_startSearchAll";
-                                       }else{
-                                               this._announceOption(highlighted);
-                                       }
-                                       dojo.stopEvent(evt);
-                                       break;
-
-                               case dk.ENTER:
-                                       // prevent submitting form if user presses enter. Also
-                                       // prevent accepting the value if either Next or Previous
-                                       // are selected
-                                       if(highlighted){
-                                               // only stop event on prev/next
-                                               if(highlighted == pw.nextButton){
-                                                       this._nextSearch(1);
-                                                       dojo.stopEvent(evt);
-                                                       break;
-                                               }else if(highlighted == pw.previousButton){
-                                                       this._nextSearch(-1);
-                                                       dojo.stopEvent(evt);
-                                                       break;
-                                               }
-                                       }else{
-                                               // Update 'value' (ex: KY) according to currently displayed text
-                                               this._setBlurValue(); // set value if needed
-                                               this._setCaretPos(this.focusNode, this.focusNode.value.length); // move cursor to end and cancel highlighting
-                                       }
-                                       // default case:
-                                       // prevent submit, but allow event to bubble
-                                       evt.preventDefault();
-                                       // fall through
+               },
 
-                               case dk.TAB:
-                                       var newvalue = this.get('displayedValue');
-                                       //      if the user had More Choices selected fall into the
-                                       //      _onBlur handler
-                                       if(pw && (
-                                               newvalue == pw._messages["previousMessage"] ||
-                                               newvalue == pw._messages["nextMessage"])
-                                       ){
-                                               break;
-                                       }
-                                       if(highlighted){
-                                               this._selectOption();
-                                       }
-                                       if(this._isShowingNow){
-                                               this._lastQuery = null; // in case results come back later
-                                               this._hideResultList();
-                                       }
-                                       break;
+               _onFocus: function(){
+                       // summary:
+                       //              This is called by the focus manager when focus
+                       //              goes to this MenuItem or a child menu.
+                       // tags:
+                       //              protected
+                       this._setSelected(true);
+                       this.getParent()._onItemFocus(this);
 
-                               case ' ':
-                                       if(highlighted){
-                                               dojo.stopEvent(evt);
-                                               this._selectOption();
-                                               this._hideResultList();
-                                       }else{
-                                               doSearch = true;
-                                       }
-                                       break;
+                       this.inherited(arguments);
+               },
 
-                               case dk.ESCAPE:
-                                       if(this._isShowingNow){
-                                               dojo.stopEvent(evt);
-                                               this._hideResultList();
-                                       }
-                                       break;
+               _setSelected: function(selected){
+                       // summary:
+                       //              Indicate that this node is the currently selected one
+                       // tags:
+                       //              private
 
-                               case dk.DELETE:
-                               case dk.BACKSPACE:
-                                       this._prev_key_backspace = true;
-                                       doSearch = true;
-                                       break;
+                       /***
+                        * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem.
+                        * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu.
+                        * That's not supposed to happen, but the problem is:
+                        * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent
+                        * points to the parent Menu, bypassing the parent MenuItem... thus the
+                        * MenuItem is not in the chain of active widgets and gets a premature call to
+                        * _onBlur()
+                        */
 
-                               default:
-                                       // Non char keys (F1-F12 etc..)  shouldn't open list.
-                                       // Ascii characters and IME input (Chinese, Japanese etc.) should.
-                                       // On IE and safari, IME input produces keycode == 229, and we simulate
-                                       // it on firefox by attaching to compositionend event (see compositionend method)
-                                       doSearch = typeof key == 'string' || key == 229;
-                       }
-                       if(doSearch){
-                               // need to wait a tad before start search so that the event
-                               // bubbles through DOM and we have value visible
-                               this.item = undefined; // undefined means item needs to be set
-                               this.searchTimer = setTimeout(dojo.hitch(this, searchFunction),1);
-                       }
+                       domClass.toggle(this.domNode, "dijitMenuItemSelected", selected);
                },
 
-               _autoCompleteText: function(/*String*/ text){
+               setLabel: function(/*String*/ content){
                        // summary:
-                       //              Fill in the textbox with the first item from the drop down
-                       //              list, and highlight the characters that were
-                       //              auto-completed. For example, if user typed "CA" and the
-                       //              drop down list appeared, the textbox would be changed to
-                       //              "California" and "ifornia" would be highlighted.
-
-                       var fn = this.focusNode;
+                       //              Deprecated.   Use set('label', ...) instead.
+                       // tags:
+                       //              deprecated
+                       kernel.deprecated("dijit.MenuItem.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
+                       this.set("label", content);
+               },
 
-                       // IE7: clear selection so next highlight works all the time
-                       dijit.selectInputText(fn, fn.value.length);
-                       // does text autoComplete the value in the textbox?
-                       var caseFilter = this.ignoreCase? 'toLowerCase' : 'substr';
-                       if(text[caseFilter](0).indexOf(this.focusNode.value[caseFilter](0)) == 0){
-                               var cpos = this._getCaretPos(fn);
-                               // only try to extend if we added the last character at the end of the input
-                               if((cpos+1) > fn.value.length){
-                                       // only add to input node as we would overwrite Capitalisation of chars
-                                       // actually, that is ok
-                                       fn.value = text;//.substr(cpos);
-                                       // visually highlight the autocompleted characters
-                                       dijit.selectInputText(fn, cpos);
-                               }
-                       }else{
-                               // text does not autoComplete; replace the whole value and highlight
-                               fn.value = text;
-                               dijit.selectInputText(fn);
-                       }
+               setDisabled: function(/*Boolean*/ disabled){
+                       // summary:
+                       //              Deprecated.   Use set('disabled', bool) instead.
+                       // tags:
+                       //              deprecated
+                       kernel.deprecated("dijit.Menu.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
+                       this.set('disabled', disabled);
                },
+               _setDisabledAttr: function(/*Boolean*/ value){
+                       // summary:
+                       //              Hook for attr('disabled', ...) to work.
+                       //              Enable or disable this menu item.
 
-               _openResultList: function(/*Object*/ results, /*Object*/ dataObject){
-                       this._fetchHandle = null;
-                       if(     this.disabled ||
-                               this.readOnly ||
-                               (dataObject.query[this.searchAttr] != this._lastQuery)
-                       ){
-                               return;
-                       }
-                       this._popupWidget.clearResultList();
-                       if(!results.length && !this._maxOptions){ // this condition needs to match !this._isvalid set in FilteringSelect::_openResultList
-                               this._hideResultList();
-                               return;
-                       }
+                       this.focusNode.setAttribute('aria-disabled', value ? 'true' : 'false');
+                       this._set("disabled", value);
+               },
+               _setAccelKeyAttr: function(/*String*/ value){
+                       // summary:
+                       //              Hook for attr('accelKey', ...) to work.
+                       //              Set accelKey on this menu item.
 
+                       this.accelKeyNode.style.display=value?"":"none";
+                       this.accelKeyNode.innerHTML=value;
+                       //have to use colSpan to make it work in IE
+                       domAttr.set(this.containerNode,'colSpan',value?"1":"2");
 
-                       // Fill in the textbox with the first item from the drop down list,
-                       // and highlight the characters that were auto-completed. For
-                       // example, if user typed "CA" and the drop down list appeared, the
-                       // textbox would be changed to "California" and "ifornia" would be
-                       // highlighted.
+                       this._set("accelKey", value);
+               }
+       });
+});
 
-                       dataObject._maxOptions = this._maxOptions;
-                       var nodes = this._popupWidget.createOptions(
-                               results,
-                               dataObject,
-                               dojo.hitch(this, "_getMenuLabelFromItem")
-                       );
+},
+'dijit/layout/TabController':function(){
+require({cache:{
+'url:dijit/layout/templates/_TabButton.html':"<div role=\"presentation\" data-dojo-attach-point=\"titleNode\" data-dojo-attach-event='onclick:onClick'>\n    <div role=\"presentation\" class='dijitTabInnerDiv' data-dojo-attach-point='innerDiv'>\n        <div role=\"presentation\" class='dijitTabContent' data-dojo-attach-point='tabContent'>\n        \t<div role=\"presentation\" data-dojo-attach-point='focusNode'>\n\t\t        <img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitTabButtonIcon\" data-dojo-attach-point='iconNode' />\n\t\t        <span data-dojo-attach-point='containerNode' class='tabLabel'></span>\n\t\t        <span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" data-dojo-attach-point='closeNode'\n\t\t        \t\tdata-dojo-attach-event='onclick: onClickCloseButton' role=\"presentation\">\n\t\t            <span data-dojo-attach-point='closeText' class='dijitTabCloseText'>[x]</span\n\t\t        ></span>\n\t\t\t</div>\n        </div>\n    </div>\n</div>\n"}});
+define("dijit/layout/TabController", [
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.setSelectable
+       "dojo/dom-attr", // domAttr.attr
+       "dojo/dom-class", // domClass.toggle
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/lang", // lang.hitch lang.trim
+       "./StackController",
+       "../Menu",
+       "../MenuItem",
+       "dojo/text!./templates/_TabButton.html",
+       "dojo/i18n!../nls/common"
+], function(declare, dom, domAttr, domClass, i18n, lang, StackController, Menu, MenuItem, template){
 
-                       // show our list (only if we have content, else nothing)
-                       this._showResultList();
+/*=====
+       var StackController = dijit.layout.StackController;
+       var Menu = dijit.Menu;
+       var MenuItem = dijit.MenuItem;
+=====*/
 
-                       // #4091:
-                       //              tell the screen reader that the paging callback finished by
-                       //              shouting the next choice
-                       if(dataObject.direction){
-                               if(1 == dataObject.direction){
-                                       this._popupWidget.highlightFirstOption();
-                               }else if(-1 == dataObject.direction){
-                                       this._popupWidget.highlightLastOption();
-                               }
-                               this._announceOption(this._popupWidget.getHighlightedOption());
-                       }else if(this.autoComplete && !this._prev_key_backspace /*&& !dataObject.direction*/
-                               // when the user clicks the arrow button to show the full list,
-                               // startSearch looks for "*".
-                               // it does not make sense to autocomplete
-                               // if they are just previewing the options available.
-                               && !/^[*]+$/.test(dataObject.query[this.searchAttr])){
-                                       this._announceOption(nodes[1]); // 1st real item
-                       }
-               },
+       // module:
+       //              dijit/layout/TabController
+       // summary:
+       //              Set of tabs (the things with titles and a close button, that you click to show a tab panel).
+       //              Used internally by `dijit.layout.TabContainer`.
 
-               _showResultList: function(){
-                       this._hideResultList();
-                       // hide the tooltip
-                       this.displayMessage("");
+       var TabButton = declare("dijit.layout._TabButton", StackController.StackButton, {
+               // summary:
+               //              A tab (the thing you click to select a pane).
+               // description:
+               //              Contains the title of the pane, and optionally a close-button to destroy the pane.
+               //              This is an internal widget and should not be instantiated directly.
+               // tags:
+               //              private
 
-                       // Position the list and if it's too big to fit on the screen then
-                       // size it to the maximum possible height
-                       // Our dear friend IE doesnt take max-height so we need to
-                       // calculate that on our own every time
-
-                       // TODO: want to redo this, see
-                       //              http://trac.dojotoolkit.org/ticket/3272
-                       //      and
-                       //              http://trac.dojotoolkit.org/ticket/4108
-
-
-                       // natural size of the list has changed, so erase old
-                       // width/height settings, which were hardcoded in a previous
-                       // call to this function (via dojo.marginBox() call)
-                       dojo.style(this._popupWidget.domNode, {width: "", height: ""});
-
-                       var best = this.open();
-                       // #3212:
-                       //              only set auto scroll bars if necessary prevents issues with
-                       //              scroll bars appearing when they shouldn't when node is made
-                       //              wider (fractional pixels cause this)
-                       var popupbox = dojo.marginBox(this._popupWidget.domNode);
-                       this._popupWidget.domNode.style.overflow =
-                               ((best.h == popupbox.h) && (best.w == popupbox.w)) ? "hidden" : "auto";
-                       // #4134:
-                       //              borrow TextArea scrollbar test so content isn't covered by
-                       //              scrollbar and horizontal scrollbar doesn't appear
-                       var newwidth = best.w;
-                       if(best.h < this._popupWidget.domNode.scrollHeight){
-                               newwidth += 16;
-                       }
-                       dojo.marginBox(this._popupWidget.domNode, {
-                               h: best.h,
-                               w: Math.max(newwidth, this.domNode.offsetWidth)
-                       });
-                       
-                       // If we increased the width of drop down to match the width of ComboBox.domNode,
-                       // then need to reposition the drop down (wrapper) so (all of) the drop down still
-                       // appears underneath the ComboBox.domNode
-                       if(newwidth < this.domNode.offsetWidth){
-                               this._popupWidget.domNode.parentNode.style.left = dojo.position(this.domNode, true).x + "px";
-                       }
+               // baseClass: String
+               //              The CSS class applied to the domNode.
+               baseClass: "dijitTab",
 
-                       dijit.setWaiState(this.comboNode, "expanded", "true");
+               // Apply dijitTabCloseButtonHover when close button is hovered
+               cssStateNodes: {
+                       closeNode: "dijitTabCloseButton"
                },
 
-               _hideResultList: function(){
-                       this._abortQuery();
-                       if(this._isShowingNow){
-                               dijit.popup.close(this._popupWidget);
-                               this._isShowingNow=false;
-                               dijit.setWaiState(this.comboNode, "expanded", "false");
-                               dijit.removeWaiState(this.focusNode,"activedescendant");
-                       }
-               },
+               templateString: template,
 
-               _setBlurValue: function(){
-                       // if the user clicks away from the textbox OR tabs away, set the
-                       // value to the textbox value
-                       // #4617:
-                       //              if value is now more choices or previous choices, revert
-                       //              the value
-                       var newvalue = this.get('displayedValue');
-                       var pw = this._popupWidget;
-                       if(pw && (
-                               newvalue == pw._messages["previousMessage"] ||
-                               newvalue == pw._messages["nextMessage"]
-                               )
-                       ){
-                               this._setValueAttr(this._lastValueReported, true);
-                       }else if(typeof this.item == "undefined"){
-                               // Update 'value' (ex: KY) according to currently displayed text
-                               this.item = null;
-                               this.set('displayedValue', newvalue);
-                       }else{
-                               if(this.value != this._lastValueReported){
-                                       dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true);
-                               }
-                               this._refreshState();
-                       }
-               },
+               // Override _FormWidget.scrollOnFocus.
+               // Don't scroll the whole tab container into view when the button is focused.
+               scrollOnFocus: false,
 
-               _onBlur: function(){
-                       // summary:
-                       //              Called magically when focus has shifted away from this widget and it's drop down
-                       this._hideResultList();
+               buildRendering: function(){
                        this.inherited(arguments);
+
+                       dom.setSelectable(this.containerNode, false);
                },
 
-               _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
-                       // summary:
-                       //              Set the displayed valued in the input box, and the hidden value
-                       //              that gets submitted, based on a dojo.data store item.
-                       // description:
-                       //              Users shouldn't call this function; they should be calling
-                       //              attr('item', value)
-                       // tags:
-                       //              private
-                       if(!displayedValue){ displayedValue = this.labelFunc(item, this.store); }
-                       this.value = this._getValueField() != this.searchAttr? this.store.getIdentity(item) : displayedValue;
-                       this.item = item;
-                       dijit.form.ComboBox.superclass._setValueAttr.call(this, this.value, priorityChange, displayedValue);
+               startup: function(){
+                       this.inherited(arguments);
+                       var n = this.domNode;
+
+                       // Required to give IE6 a kick, as it initially hides the
+                       // tabs until they are focused on.
+                       setTimeout(function(){
+                               n.className = n.className;
+                       }, 1);
                },
 
-               _announceOption: function(/*Node*/ node){
+               _setCloseButtonAttr: function(/*Boolean*/ disp){
                        // summary:
-                       //              a11y code that puts the highlighted option in the textbox.
-                       //              This way screen readers will know what is happening in the
-                       //              menu.
+                       //              Hide/show close button
+                       this._set("closeButton", disp);
+                       domClass.toggle(this.innerDiv, "dijitClosable", disp);
+                       this.closeNode.style.display = disp ? "" : "none";
+                       if(disp){
+                               var _nlsResources = i18n.getLocalization("dijit", "common");
+                               if(this.closeNode){
+                                       domAttr.set(this.closeNode,"title", _nlsResources.itemClose);
+                               }
+                               // add context menu onto title button
+                               this._closeMenu = new Menu({
+                                       id: this.id+"_Menu",
+                                       dir: this.dir,
+                                       lang: this.lang,
+                                       textDir: this.textDir,
+                                       targetNodeIds: [this.domNode]
+                               });
 
-                       if(!node){
-                               return;
-                       }
-                       // pull the text value from the item attached to the DOM node
-                       var newValue;
-                       if(node == this._popupWidget.nextButton ||
-                               node == this._popupWidget.previousButton){
-                               newValue = node.innerHTML;
-                               this.item = undefined;
-                               this.value = '';
+                               this._closeMenu.addChild(new MenuItem({
+                                       label: _nlsResources.itemClose,
+                                       dir: this.dir,
+                                       lang: this.lang,
+                                       textDir: this.textDir,
+                                       onClick: lang.hitch(this, "onClickCloseButton")
+                               }));
                        }else{
-                               newValue = this.labelFunc(node.item, this.store);
-                               this.set('item', node.item, false, newValue);
+                               if(this._closeMenu){
+                                       this._closeMenu.destroyRecursive();
+                                       delete this._closeMenu;
+                               }
                        }
-                       // get the text that the user manually entered (cut off autocompleted text)
-                       this.focusNode.value = this.focusNode.value.substring(0, this._lastInput.length);
-                       // set up ARIA activedescendant
-                       dijit.setWaiState(this.focusNode, "activedescendant", dojo.attr(node, "id"));
-                       // autocomplete the rest of the option to announce change
-                       this._autoCompleteText(newValue);
                },
-
-               _selectOption: function(/*Event*/ evt){
+               _setLabelAttr: function(/*String*/ content){
                        // summary:
-                       //              Menu callback function, called when an item in the menu is selected.
-                       if(evt){
-                               this._announceOption(evt.target);
+                       //              Hook for set('label', ...) to work.
+                       // description:
+                       //              takes an HTML string.
+                       //              Inherited ToggleButton implementation will Set the label (text) of the button;
+                       //              Need to set the alt attribute of icon on tab buttons if no label displayed
+                       this.inherited(arguments);
+                       if(!this.showLabel && !this.params.title){
+                               this.iconNode.alt = lang.trim(this.containerNode.innerText || this.containerNode.textContent || '');
                        }
-                       this._hideResultList();
-                       this._setCaretPos(this.focusNode, this.focusNode.value.length);
-                       dijit.form._FormValueWidget.prototype._setValueAttr.call(this, this.value, true); // set this.value and fire onChange
                },
 
-               _onArrowMouseDown: function(evt){
-                       // summary:
-                       //              Callback when arrow is clicked
-                       if(this.disabled || this.readOnly){
-                               return;
-                       }
-                       dojo.stopEvent(evt);
-                       this.focus();
-                       if(this._isShowingNow){
-                               this._hideResultList();
-                       }else{
-                               // forces full population of results, if they click
-                               // on the arrow it means they want to see more options
-                               this._startSearchAll();
+               destroy: function(){
+                       if(this._closeMenu){
+                               this._closeMenu.destroyRecursive();
+                               delete this._closeMenu;
                        }
-               },
+                       this.inherited(arguments);
+               }
+       });
 
-               _startSearchAll: function(){
-                       this._startSearch('');
-               },
+       var TabController = declare("dijit.layout.TabController", StackController, {
+               // summary:
+               //              Set of tabs (the things with titles and a close button, that you click to show a tab panel).
+               //              Used internally by `dijit.layout.TabContainer`.
+               // description:
+               //              Lets the user select the currently shown pane in a TabContainer or StackContainer.
+               //              TabController also monitors the TabContainer, and whenever a pane is
+               //              added or deleted updates itself accordingly.
+               // tags:
+               //              private
 
-               _startSearchFromInput: function(){
-                       this._startSearch(this.focusNode.value.replace(/([\\\*\?])/g, "\\$1"));
-               },
+               baseClass: "dijitTabController",
 
-               _getQueryString: function(/*String*/ text){
-                       return dojo.string.substitute(this.queryExpr, [text]);
-               },
+               templateString: "<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'></div>",
 
-               _startSearch: function(/*String*/ key){
-                       if(!this._popupWidget){
-                               var popupId = this.id + "_popup";
-                               this._popupWidget = new dijit.form._ComboBoxMenu({
-                                       onChange: dojo.hitch(this, this._selectOption),
-                                       id: popupId,
-                                       dir: this.dir
-                               });
-                               dijit.removeWaiState(this.focusNode,"activedescendant");
-                               dijit.setWaiState(this.textbox,"owns",popupId); // associate popup with textbox
-                       }
-                       // create a new query to prevent accidentally querying for a hidden
-                       // value from FilteringSelect's keyField
-                       var query = dojo.clone(this.query); // #5970
-                       this._lastInput = key; // Store exactly what was entered by the user.
-                       this._lastQuery = query[this.searchAttr] = this._getQueryString(key);
-                       // #5970: set _lastQuery, *then* start the timeout
-                       // otherwise, if the user types and the last query returns before the timeout,
-                       // _lastQuery won't be set and their input gets rewritten
-                       this.searchTimer=setTimeout(dojo.hitch(this, function(query, _this){
-                               this.searchTimer = null;
-                               var fetch = {
-                                       queryOptions: {
-                                               ignoreCase: this.ignoreCase,
-                                               deep: true
-                                       },
-                                       query: query,
-                                       onBegin: dojo.hitch(this, "_setMaxOptions"),
-                                       onComplete: dojo.hitch(this, "_openResultList"),
-                                       onError: function(errText){
-                                               _this._fetchHandle = null;
-                                               console.error('dijit.form.ComboBox: ' + errText);
-                                               dojo.hitch(_this, "_hideResultList")();
-                                       },
-                                       start: 0,
-                                       count: this.pageSize
-                               };
-                               dojo.mixin(fetch, _this.fetchProperties);
-                               this._fetchHandle = _this.store.fetch(fetch);
-
-                               var nextSearch = function(dataObject, direction){
-                                       dataObject.start += dataObject.count*direction;
-                                       // #4091:
-                                       //              tell callback the direction of the paging so the screen
-                                       //              reader knows which menu option to shout
-                                       dataObject.direction = direction;
-                                       this._fetchHandle = this.store.fetch(dataObject);
-                               };
-                               this._nextSearch = this._popupWidget.onPage = dojo.hitch(this, nextSearch, this._fetchHandle);
-                       }, query, this), this.searchDelay);
-               },
+               // tabPosition: String
+               //              Defines where tabs go relative to the content.
+               //              "top", "bottom", "left-h", "right-h"
+               tabPosition: "top",
 
-               _setMaxOptions: function(size, request){
-                        this._maxOptions = size;
-               },
+               // buttonWidget: Constructor
+               //              The tab widget to create to correspond to each page
+               buttonWidget: TabButton,
 
-               _getValueField: function(){
-                       // summmary:
-                       //              Helper for postMixInProperties() to set this.value based on data inlined into the markup.
-                       //              Returns the attribute name in the item (in dijit.form._ComboBoxDataStore) to use as the value.
-                       return this.searchAttr;
-               },
+               _rectifyRtlTabList: function(){
+                       // summary:
+                       //              For left/right TabContainer when page is RTL mode, rectify the width of all tabs to be equal, otherwise the tab widths are different in IE
 
-               /////////////// Event handlers /////////////////////
+                       if(0 >= this.tabPosition.indexOf('-h')){ return; }
+                       if(!this.pane2button){ return; }
 
-               // FIXME: For 2.0, rename to "_compositionEnd"
-               compositionend: function(/*Event*/ evt){
-                       // summary:
-                       //              When inputting characters using an input method, such as
-                       //              Asian languages, it will generate this event instead of
-                       //              onKeyDown event.
-                       //              Note: this event is only triggered in FF (not in IE/safari)
-                       // tags:
-                       //              private
+                       var maxWidth = 0;
+                       for(var pane in this.pane2button){
+                               var ow = this.pane2button[pane].innerDiv.scrollWidth;
+                               maxWidth = Math.max(maxWidth, ow);
+                       }
+                       //unify the length of all the tabs
+                       for(pane in this.pane2button){
+                               this.pane2button[pane].innerDiv.style.width = maxWidth + 'px';
+                       }
+               }
+       });
 
-                       // 229 is the code produced by IE and safari while pressing keys during
-                       // IME input mode
-                       this._onKeyPress({charOrCode: 229});
-               },
+       TabController.TabButton = TabButton;    // for monkey patching
 
-               //////////// INITIALIZATION METHODS ///////////////////////////////////////
+       return TabController;
+});
 
-               constructor: function(){
-                       this.query={};
-                       this.fetchProperties={};
-               },
+},
+'dijit/layout/_LayoutWidget':function(){
+define("dijit/layout/_LayoutWidget", [
+       "dojo/_base/lang", // lang.mixin
+       "../_Widget",
+       "../_Container",
+       "../_Contained",
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.remove
+       "dojo/dom-geometry", // domGeometry.marginBox
+       "dojo/dom-style", // domStyle.getComputedStyle
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/window" // win.global
+], function(lang, _Widget, _Container, _Contained,
+       declare, domClass, domGeometry, domStyle, has, win){
 
-               postMixInProperties: function(){
-                       if(!this.store){
-                               var srcNodeRef = this.srcNodeRef;
+/*=====
+       var _Widget = dijit._Widget;
+       var _Container = dijit._Container;
+       var _Contained = dijit._Contained;
+=====*/
 
-                               // if user didn't specify store, then assume there are option tags
-                               this.store = new dijit.form._ComboBoxDataStore(srcNodeRef);
+       // module:
+       //              dijit/layout/_LayoutWidget
+       // summary:
+       //              _LayoutWidget Base class for a _Container widget which is responsible for laying out its children.
+       //              Widgets which mixin this code must define layout() to manage placement and sizing of the children.
 
-                               // if there is no value set and there is an option list, set
-                               // the value to the first value to be consistent with native
-                               // Select
 
-                               // Firefox and Safari set value
-                               // IE6 and Opera set selectedIndex, which is automatically set
-                               // by the selected attribute of an option tag
-                               // IE6 does not set value, Opera sets value = selectedIndex
-                               if(!("value" in this.params)){
-                                       var item = this.store.fetchSelectedItem();
-                                       if(item){
-                                               var valueField = this._getValueField();
-                                               this.value = valueField != this.searchAttr? this.store.getValue(item, valueField) : this.labelFunc(item, this.store);
-                                       }
-                               }
-                       }
+       return declare("dijit.layout._LayoutWidget", [_Widget, _Container, _Contained], {
+               // summary:
+               //              Base class for a _Container widget which is responsible for laying out its children.
+               //              Widgets which mixin this code must define layout() to manage placement and sizing of the children.
+
+               // baseClass: [protected extension] String
+               //              This class name is applied to the widget's domNode
+               //              and also may be used to generate names for sub nodes,
+               //              for example dijitTabContainer-content.
+               baseClass: "dijitLayoutContainer",
+
+               // isLayoutContainer: [protected] Boolean
+               //              Indicates that this widget is going to call resize() on its
+               //              children widgets, setting their size, when they become visible.
+               isLayoutContainer: true,
+
+               buildRendering: function(){
                        this.inherited(arguments);
+                       domClass.add(this.domNode, "dijitContainer");
                },
 
-               postCreate: function(){
+               startup: function(){
                        // summary:
-                       //              Subclasses must call this method from their postCreate() methods
-                       // tags:
-                       //              protected
+                       //              Called after all the widgets have been instantiated and their
+                       //              dom nodes have been inserted somewhere under win.doc.body.
+                       //
+                       //              Widgets should override this method to do any initialization
+                       //              dependent on other widgets existing, and then call
+                       //              this superclass method to finish things off.
+                       //
+                       //              startup() in subclasses shouldn't do anything
+                       //              size related because the size of the widget hasn't been set yet.
 
-                       if(!this.hasDownArrow){
-                               this.downArrowNode.style.display = "none";
-                       }
+                       if(this._started){ return; }
 
-                       // find any associated label element and add to ComboBox node.
-                       var label=dojo.query('label[for="'+this.id+'"]');
-                       if(label.length){
-                               label[0].id = (this.id+"_label");
-                               var cn=this.comboNode;
-                               dijit.setWaiState(cn, "labelledby", label[0].id);
+                       // Need to call inherited first - so that child widgets get started
+                       // up correctly
+                       this.inherited(arguments);
+
+                       // If I am a not being controlled by a parent layout widget...
+                       var parent = this.getParent && this.getParent();
+                       if(!(parent && parent.isLayoutContainer)){
+                               // Do recursive sizing and layout of all my descendants
+                               // (passing in no argument to resize means that it has to glean the size itself)
+                               this.resize();
 
+                               // Since my parent isn't a layout container, and my style *may be* width=height=100%
+                               // or something similar (either set directly or via a CSS class),
+                               // monitor when viewport size changes so that I can re-layout.
+                               this.connect(win.global, 'onresize', function(){
+                                       // Using function(){} closure to ensure no arguments passed to resize().
+                                       this.resize();
+                               });
                        }
-                       this.inherited(arguments);
                },
 
-               uninitialize: function(){
-                       if(this._popupWidget && !this._popupWidget._destroyed){
-                               this._hideResultList();
-                               this._popupWidget.destroy();
+               resize: function(changeSize, resultSize){
+                       // summary:
+                       //              Call this to resize a widget, or after its size has changed.
+                       // description:
+                       //              Change size mode:
+                       //                      When changeSize is specified, changes the marginBox of this widget
+                       //                      and forces it to relayout its contents accordingly.
+                       //                      changeSize may specify height, width, or both.
+                       //
+                       //                      If resultSize is specified it indicates the size the widget will
+                       //                      become after changeSize has been applied.
+                       //
+                       //              Notification mode:
+                       //                      When changeSize is null, indicates that the caller has already changed
+                       //                      the size of the widget, or perhaps it changed because the browser
+                       //                      window was resized.  Tells widget to relayout its contents accordingly.
+                       //
+                       //                      If resultSize is also specified it indicates the size the widget has
+                       //                      become.
+                       //
+                       //              In either mode, this method also:
+                       //                      1. Sets this._borderBox and this._contentBox to the new size of
+                       //                              the widget.  Queries the current domNode size if necessary.
+                       //                      2. Calls layout() to resize contents (and maybe adjust child widgets).
+                       //
+                       // changeSize: Object?
+                       //              Sets the widget to this margin-box size and position.
+                       //              May include any/all of the following properties:
+                       //      |       {w: int, h: int, l: int, t: int}
+                       //
+                       // resultSize: Object?
+                       //              The margin-box size of this widget after applying changeSize (if
+                       //              changeSize is specified).  If caller knows this size and
+                       //              passes it in, we don't need to query the browser to get the size.
+                       //      |       {w: int, h: int}
+
+                       var node = this.domNode;
+
+                       // set margin box size, unless it wasn't specified, in which case use current size
+                       if(changeSize){
+                               domGeometry.setMarginBox(node, changeSize);
                        }
-                       this.inherited(arguments);
-               },
 
-               _getMenuLabelFromItem: function(/*Item*/ item){
-                       var label = this.labelAttr? this.store.getValue(item, this.labelAttr) : this.labelFunc(item, this.store);
-                       var labelType = this.labelType;
-                       // If labelType is not "text" we don't want to screw any markup ot whatever.
-                       if(this.highlightMatch != "none" && this.labelType == "text" && this._lastInput){
-                               label = this.doHighlight(label, this._escapeHtml(this._lastInput));
-                               labelType = "html";
+                       // If either height or width wasn't specified by the user, then query node for it.
+                       // But note that setting the margin box and then immediately querying dimensions may return
+                       // inaccurate results, so try not to depend on it.
+                       var mb = resultSize || {};
+                       lang.mixin(mb, changeSize || {});       // changeSize overrides resultSize
+                       if( !("h" in mb) || !("w" in mb) ){
+                               mb = lang.mixin(domGeometry.getMarginBox(node), mb);    // just use domGeometry.marginBox() to fill in missing values
                        }
-                       return {html: labelType == "html", label: label};
-               },
 
-               doHighlight: function(/*String*/label, /*String*/find){
-                       // summary:
-                       //              Highlights the string entered by the user in the menu.  By default this
-                       //              highlights the first occurence found. Override this method
-                       //              to implement your custom highlighing.
-                       // tags:
-                       //              protected
+                       // Compute and save the size of my border box and content box
+                       // (w/out calling domGeometry.getContentBox() since that may fail if size was recently set)
+                       var cs = domStyle.getComputedStyle(node);
+                       var me = domGeometry.getMarginExtents(node, cs);
+                       var be = domGeometry.getBorderExtents(node, cs);
+                       var bb = (this._borderBox = {
+                               w: mb.w - (me.w + be.w),
+                               h: mb.h - (me.h + be.h)
+                       });
+                       var pe = domGeometry.getPadExtents(node, cs);
+                       this._contentBox = {
+                               l: domStyle.toPixelValue(node, cs.paddingLeft),
+                               t: domStyle.toPixelValue(node, cs.paddingTop),
+                               w: bb.w - pe.w,
+                               h: bb.h - pe.h
+                       };
 
-                       // Add greedy when this.highlightMatch == "all"
-                       var modifiers = "i"+(this.highlightMatch == "all"?"g":"");
-                       var escapedLabel = this._escapeHtml(label);
-                       find = dojo.regexp.escapeString(find); // escape regexp special chars
-                       var ret = escapedLabel.replace(new RegExp("(^|\\s)("+ find +")", modifiers),
-                                       '$1<span class="dijitComboBoxHighlightMatch">$2</span>');
-                       return ret;// returns String, (almost) valid HTML (entities encoded)
+                       // Callback for widget to adjust size of its children
+                       this.layout();
                },
 
-               _escapeHtml: function(/*string*/str){
-                       // TODO Should become dojo.html.entities(), when exists use instead
+               layout: function(){
                        // summary:
-                       //              Adds escape sequences for special characters in XML: &<>"'
-                       str = String(str).replace(/&/gm, "&amp;").replace(/</gm, "&lt;")
-                               .replace(/>/gm, "&gt;").replace(/"/gm, "&quot;");
-                       return str; // string
+                       //              Widgets override this method to size and position their contents/children.
+                       //              When this is called this._contentBox is guaranteed to be set (see resize()).
+                       //
+                       //              This is called after startup(), and also when the widget's size has been
+                       //              changed.
+                       // tags:
+                       //              protected extension
                },
 
-               open: function(){
+               _setupChild: function(/*dijit._Widget*/child){
                        // summary:
-                       //              Opens the drop down menu.  TODO: rename to _open.
+                       //              Common setup for initial children and children which are added after startup
                        // tags:
-                       //              private
-                       this._isShowingNow=true;
-                       return dijit.popup.open({
-                               popup: this._popupWidget,
-                               around: this.domNode,
-                               parent: this
-                       });
+                       //              protected extension
+
+                       var cls = this.baseClass + "-child "
+                               + (child.baseClass ? this.baseClass + "-" + child.baseClass : "");
+                       domClass.add(child.domNode, cls);
                },
 
-               reset: function(){
-                       // Overrides the _FormWidget.reset().
-                       // Additionally reset the .item (to clean up).
-                       this.item = null;
+               addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+                       // Overrides _Container.addChild() to call _setupChild()
                        this.inherited(arguments);
+                       if(this._started){
+                               this._setupChild(child);
+                       }
                },
 
-               labelFunc: function(/*item*/ item, /*dojo.data.store*/ store){
-                       // summary:
-                       //              Computes the label to display based on the dojo.data store item.
-                       // returns:
-                       //              The label that the ComboBox should display
-                       // tags:
-                       //              private
+               removeChild: function(/*dijit._Widget*/ child){
+                       // Overrides _Container.removeChild() to remove class added by _setupChild()
+                       var cls = this.baseClass + "-child"
+                                       + (child.baseClass ?
+                                               " " + this.baseClass + "-" + child.baseClass : "");
+                       domClass.remove(child.domNode, cls);
 
-                       // Use toString() because XMLStore returns an XMLItem whereas this
-                       // method is expected to return a String (#9354)
-                       return store.getValue(item, this.searchAttr).toString(); // String
+                       this.inherited(arguments);
                }
-       }
-);
+       });
+});
 
-dojo.declare(
-       "dijit.form._ComboBoxMenu",
-       [dijit._Widget, dijit._Templated, dijit._CssStateMixin],
-       {
-               // summary:
-               //              Focus-less menu for internal use in `dijit.form.ComboBox`
-               // tags:
-               //              private
+},
+'dijit/popup':function(){
+define("dijit/popup", [
+       "dojo/_base/array", // array.forEach array.some
+       "dojo/aspect",
+       "dojo/_base/connect",   // connect._keypress
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.isDescendant
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-construct", // domConstruct.create domConstruct.destroy
+       "dojo/dom-geometry", // domGeometry.isBodyLtr
+       "dojo/dom-style", // domStyle.set
+       "dojo/_base/event", // event.stop
+       "dojo/keys",
+       "dojo/_base/lang", // lang.hitch
+       "dojo/on",
+       "dojo/_base/sniff", // has("ie") has("mozilla")
+       "dojo/_base/window", // win.body
+       "./place",
+       "./BackgroundIframe",
+       "."     // dijit (defining dijit.popup to match API doc)
+], function(array, aspect, connect, declare, dom, domAttr, domConstruct, domGeometry, domStyle, event, keys, lang, on, has, win,
+                       place, BackgroundIframe, dijit){
+
+       // module:
+       //              dijit/popup
+       // summary:
+       //              Used to show drop downs (ex: the select list of a ComboBox)
+       //              or popups (ex: right-click context menus)
 
-               templateString: "<ul class='dijitReset dijitMenu' dojoAttachEvent='onmousedown:_onMouseDown,onmouseup:_onMouseUp,onmouseover:_onMouseOver,onmouseout:_onMouseOut' tabIndex='-1' style='overflow: \"auto\"; overflow-x: \"hidden\";'>"
-                               +"<li class='dijitMenuItem dijitMenuPreviousButton' dojoAttachPoint='previousButton' waiRole='option'></li>"
-                               +"<li class='dijitMenuItem dijitMenuNextButton' dojoAttachPoint='nextButton' waiRole='option'></li>"
-                       +"</ul>",
 
-               // _messages: Object
-               //              Holds "next" and "previous" text for paging buttons on drop down
-               _messages: null,
-               
-               baseClass: "dijitComboBoxMenu",
+       /*=====
+       dijit.popup.__OpenArgs = function(){
+               // popup: Widget
+               //              widget to display
+               // parent: Widget
+               //              the button etc. that is displaying this popup
+               // around: DomNode
+               //              DOM node (typically a button); place popup relative to this node.  (Specify this *or* "x" and "y" parameters.)
+               // x: Integer
+               //              Absolute horizontal position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
+               // y: Integer
+               //              Absolute vertical position (in pixels) to place node at.  (Specify this *or* "around" parameter.)
+               // orient: Object|String
+               //              When the around parameter is specified, orient should be a list of positions to try, ex:
+               //      |       [ "below", "above" ]
+               //              For backwards compatibility it can also be an (ordered) hash of tuples of the form
+               //              (around-node-corner, popup-node-corner), ex:
+               //      |       { "BL": "TL", "TL": "BL" }
+               //              where BL means "bottom left" and "TL" means "top left", etc.
+               //
+               //              dijit.popup.open() tries to position the popup according to each specified position, in order,
+               //              until the popup appears fully within the viewport.
+               //
+               //              The default value is ["below", "above"]
+               //
+               //              When an (x,y) position is specified rather than an around node, orient is either
+               //              "R" or "L".  R (for right) means that it tries to put the popup to the right of the mouse,
+               //              specifically positioning the popup's top-right corner at the mouse position, and if that doesn't
+               //              fit in the viewport, then it tries, in order, the bottom-right corner, the top left corner,
+               //              and the top-right corner.
+               // onCancel: Function
+               //              callback when user has canceled the popup by
+               //                      1. hitting ESC or
+               //                      2. by using the popup widget's proprietary cancel mechanism (like a cancel button in a dialog);
+               //                         i.e. whenever popupWidget.onCancel() is called, args.onCancel is called
+               // onClose: Function
+               //              callback whenever this popup is closed
+               // onExecute: Function
+               //              callback when user "executed" on the popup/sub-popup by selecting a menu choice, etc. (top menu only)
+               // padding: dijit.__Position
+               //              adding a buffer around the opening position. This is only useful when around is not set.
+               this.popup = popup;
+               this.parent = parent;
+               this.around = around;
+               this.x = x;
+               this.y = y;
+               this.orient = orient;
+               this.onCancel = onCancel;
+               this.onClose = onClose;
+               this.onExecute = onExecute;
+               this.padding = padding;
+       }
+       =====*/
 
-               postMixInProperties: function(){
-                       this._messages = dojo.i18n.getLocalization("dijit.form", "ComboBox", this.lang);
-                       this.inherited(arguments);
-               },
+       /*=====
+       dijit.popup = {
+               // summary:
+               //              Used to show drop downs (ex: the select list of a ComboBox)
+               //              or popups (ex: right-click context menus).
+               //
+               //              Access via require(["dijit/popup"], function(popup){ ... }).
 
-               _setValueAttr: function(/*Object*/ value){
-                       this.value = value;
-                       this.onChange(value);
+               moveOffScreen: function(widget){
+                       // summary:
+                       //              Moves the popup widget off-screen.
+                       //              Do not use this method to hide popups when not in use, because
+                       //              that will create an accessibility issue: the offscreen popup is
+                       //              still in the tabbing order.
+                       // widget: dijit._WidgetBase
+                       //              The widget
                },
 
-               // stubs
-               onChange: function(/*Object*/ value){
+               hide: function(widget){
                        // summary:
-                       //              Notifies ComboBox/FilteringSelect that user clicked an option in the drop down menu.
-                       //              Probably should be called onSelect.
-                       // tags:
-                       //              callback
+                       //              Hide this popup widget (until it is ready to be shown).
+                       //              Initialization for widgets that will be used as popups
+                       //
+                       //              Also puts widget inside a wrapper DIV (if not already in one)
+                       //
+                       //              If popup widget needs to layout it should
+                       //              do so when it is made visible, and popup._onShow() is called.
+                       // widget: dijit._WidgetBase
+                       //              The widget
                },
-               onPage: function(/*Number*/ direction){
+
+               open: function(args){
                        // summary:
-                       //              Notifies ComboBox/FilteringSelect that user clicked to advance to next/previous page.
-                       // tags:
-                       //              callback
-               },
-
-               postCreate: function(){
-                       // fill in template with i18n messages
-                       this.previousButton.innerHTML = this._messages["previousMessage"];
-                       this.nextButton.innerHTML = this._messages["nextMessage"];
-                       this.inherited(arguments);
+                       //              Popup the widget at the specified position
+                       // example:
+                       //              opening at the mouse position
+                       //              |               popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
+                       // example:
+                       //              opening the widget as a dropdown
+                       //              |               popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
+                       //
+                       //              Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
+                       //              (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
+                       // args: dijit.popup.__OpenArgs
+                       //              Parameters
+                       return {};      // Object specifying which position was chosen
                },
 
-               onClose: function(){
+               close: function(popup){
                        // summary:
-                       //              Callback from dijit.popup code to this widget, notifying it that it closed
-                       // tags:
-                       //              private
-                       this._blurOptionNode();
-               },
+                       //              Close specified popup and any popups that it parented.
+                       //              If no popup is specified, closes all popups.
+                       // widget: dijit._WidgetBase?
+                       //              The widget, optional
+               }
+       };
+       =====*/
 
-               _createOption: function(/*Object*/ item, labelFunc){
-                       // summary:
-                       //              Creates an option to appear on the popup menu subclassed by
-                       //              `dijit.form.FilteringSelect`.
+       var PopupManager = declare(null, {
+               // _stack: dijit._Widget[]
+               //              Stack of currently popped up widgets.
+               //              (someone opened _stack[0], and then it opened _stack[1], etc.)
+               _stack: [],
 
-                       var labelObject = labelFunc(item);
-                       var menuitem = dojo.doc.createElement("li");
-                       dijit.setWaiRole(menuitem, "option");
-                       if(labelObject.html){
-                               menuitem.innerHTML = labelObject.label;
-                       }else{
-                               menuitem.appendChild(
-                                       dojo.doc.createTextNode(labelObject.label)
-                               );
-                       }
-                       // #3250: in blank options, assign a normal height
-                       if(menuitem.innerHTML == ""){
-                               menuitem.innerHTML = "&nbsp;";
-                       }
-                       menuitem.item=item;
-                       return menuitem;
-               },
-
-               createOptions: function(results, dataObject, labelFunc){
-                       // summary:
-                       //              Fills in the items in the drop down list
-                       // results:
-                       //              Array of dojo.data items
-                       // dataObject:
-                       //              dojo.data store
-                       // labelFunc:
-                       //              Function to produce a label in the drop down list from a dojo.data item
-
-                       //this._dataObject=dataObject;
-                       //this._dataObject.onComplete=dojo.hitch(comboBox, comboBox._openResultList);
-                       // display "Previous . . ." button
-                       this.previousButton.style.display = (dataObject.start == 0) ? "none" : "";
-                       dojo.attr(this.previousButton, "id", this.id + "_prev");
-                       // create options using _createOption function defined by parent
-                       // ComboBox (or FilteringSelect) class
-                       // #2309:
-                       //              iterate over cache nondestructively
-                       dojo.forEach(results, function(item, i){
-                               var menuitem = this._createOption(item, labelFunc);
-                               menuitem.className = "dijitReset dijitMenuItem" +
-                                       (this.isLeftToRight() ? "" : " dijitMenuItemRtl");
-                               dojo.attr(menuitem, "id", this.id + i);
-                               this.domNode.insertBefore(menuitem, this.nextButton);
-                       }, this);
-                       // display "Next . . ." button
-                       var displayMore = false;
-                       //Try to determine if we should show 'more'...
-                       if(dataObject._maxOptions && dataObject._maxOptions != -1){
-                               if((dataObject.start + dataObject.count) < dataObject._maxOptions){
-                                       displayMore = true;
-                               }else if((dataObject.start + dataObject.count) > dataObject._maxOptions && dataObject.count == results.length){
-                                       //Weird return from a datastore, where a start + count > maxOptions
-                                       // implies maxOptions isn't really valid and we have to go into faking it.
-                                       //And more or less assume more if count == results.length
-                                       displayMore = true;
-                               }
-                       }else if(dataObject.count == results.length){
-                               //Don't know the size, so we do the best we can based off count alone.
-                               //So, if we have an exact match to count, assume more.
-                               displayMore = true;
-                       }
+               // _beginZIndex: Number
+               //              Z-index of the first popup.   (If first popup opens other
+               //              popups they get a higher z-index.)
+               _beginZIndex: 1000,
 
-                       this.nextButton.style.display = displayMore ? "" : "none";
-                       dojo.attr(this.nextButton,"id", this.id + "_next");
-                       return this.domNode.childNodes;
-               },
+               _idGen: 1,
 
-               clearResultList: function(){
+               _createWrapper: function(/*Widget*/ widget){
                        // summary:
-                       //              Clears the entries in the drop down list, but of course keeps the previous and next buttons.
-                       while(this.domNode.childNodes.length>2){
-                               this.domNode.removeChild(this.domNode.childNodes[this.domNode.childNodes.length-2]);
+                       //              Initialization for widgets that will be used as popups.
+                       //              Puts widget inside a wrapper DIV (if not already in one),
+                       //              and returns pointer to that wrapper DIV.
+
+                       var wrapper = widget._popupWrapper,
+                               node = widget.domNode;
+
+                       if(!wrapper){
+                               // Create wrapper <div> for when this widget [in the future] will be used as a popup.
+                               // This is done early because of IE bugs where creating/moving DOM nodes causes focus
+                               // to go wonky, see tests/robot/Toolbar.html to reproduce
+                               wrapper = domConstruct.create("div",{
+                                       "class":"dijitPopup",
+                                       style:{ display: "none"},
+                                       role: "presentation"
+                               }, win.body());
+                               wrapper.appendChild(node);
+
+                               var s = node.style;
+                               s.display = "";
+                               s.visibility = "";
+                               s.position = "";
+                               s.top = "0px";
+
+                               widget._popupWrapper = wrapper;
+                               aspect.after(widget, "destroy", function(){
+                                       domConstruct.destroy(wrapper);
+                                       delete widget._popupWrapper;
+                               });
                        }
-               },
 
-               _onMouseDown: function(/*Event*/ evt){
-                       dojo.stopEvent(evt);
+                       return wrapper;
                },
 
-               _onMouseUp: function(/*Event*/ evt){
-                       if(evt.target === this.domNode || !this._highlighted_option){
-                               return;
-                       }else if(evt.target == this.previousButton){
-                               this.onPage(-1);
-                       }else if(evt.target == this.nextButton){
-                               this.onPage(1);
-                       }else{
-                               var tgt = evt.target;
-                               // while the clicked node is inside the div
-                               while(!tgt.item){
-                                       // recurse to the top
-                                       tgt = tgt.parentNode;
-                               }
-                               this._setValueAttr({ target: tgt }, true);
-                       }
+               moveOffScreen: function(/*Widget*/ widget){
+                       // summary:
+                       //              Moves the popup widget off-screen.
+                       //              Do not use this method to hide popups when not in use, because
+                       //              that will create an accessibility issue: the offscreen popup is
+                       //              still in the tabbing order.
+
+                       // Create wrapper if not already there
+                       var wrapper = this._createWrapper(widget);
+
+                       domStyle.set(wrapper, {
+                               visibility: "hidden",
+                               top: "-9999px",         // prevent transient scrollbar causing misalign (#5776), and initial flash in upper left (#10111)
+                               display: ""
+                       });
                },
 
-               _onMouseOver: function(/*Event*/ evt){
-                       if(evt.target === this.domNode){ return; }
-                       var tgt = evt.target;
-                       if(!(tgt == this.previousButton || tgt == this.nextButton)){
-                               // while the clicked node is inside the div
-                               while(!tgt.item){
-                                       // recurse to the top
-                                       tgt = tgt.parentNode;
-                               }
-                       }
-                       this._focusOptionNode(tgt);
-               },
+               hide: function(/*Widget*/ widget){
+                       // summary:
+                       //              Hide this popup widget (until it is ready to be shown).
+                       //              Initialization for widgets that will be used as popups
+                       //
+                       //              Also puts widget inside a wrapper DIV (if not already in one)
+                       //
+                       //              If popup widget needs to layout it should
+                       //              do so when it is made visible, and popup._onShow() is called.
 
-               _onMouseOut: function(/*Event*/ evt){
-                       if(evt.target === this.domNode){ return; }
-                       this._blurOptionNode();
-               },
+                       // Create wrapper if not already there
+                       var wrapper = this._createWrapper(widget);
 
-               _focusOptionNode: function(/*DomNode*/ node){
-                       // summary:
-                       //              Does the actual highlight.
-                       if(this._highlighted_option != node){
-                               this._blurOptionNode();
-                               this._highlighted_option = node;
-                               dojo.addClass(this._highlighted_option, "dijitMenuItemSelected");
-                       }
+                       domStyle.set(wrapper, "display", "none");
                },
 
-               _blurOptionNode: function(){
+               getTopPopup: function(){
                        // summary:
-                       //              Removes highlight on highlighted option.
-                       if(this._highlighted_option){
-                               dojo.removeClass(this._highlighted_option, "dijitMenuItemSelected");
-                               this._highlighted_option = null;
+                       //              Compute the closest ancestor popup that's *not* a child of another popup.
+                       //              Ex: For a TooltipDialog with a button that spawns a tree of menus, find the popup of the button.
+                       var stack = this._stack;
+                       for(var pi=stack.length-1; pi > 0 && stack[pi].parent === stack[pi-1].widget; pi--){
+                               /* do nothing, just trying to get right value for pi */
                        }
+                       return stack[pi];
                },
 
-               _highlightNextOption: function(){
+               open: function(/*dijit.popup.__OpenArgs*/ args){
                        // summary:
-                       //              Highlight the item just below the current selection.
-                       //              If nothing selected, highlight first option.
+                       //              Popup the widget at the specified position
+                       //
+                       // example:
+                       //              opening at the mouse position
+                       //              |               popup.open({popup: menuWidget, x: evt.pageX, y: evt.pageY});
+                       //
+                       // example:
+                       //              opening the widget as a dropdown
+                       //              |               popup.open({parent: this, popup: menuWidget, around: this.domNode, onClose: function(){...}});
+                       //
+                       //              Note that whatever widget called dijit.popup.open() should also listen to its own _onBlur callback
+                       //              (fired from _base/focus.js) to know that focus has moved somewhere else and thus the popup should be closed.
 
-                       // because each press of a button clears the menu,
-                       // the highlighted option sometimes becomes detached from the menu!
-                       // test to see if the option has a parent to see if this is the case.
-                       if(!this.getHighlightedOption()){
-                               var fc = this.domNode.firstChild;
-                               this._focusOptionNode(fc.style.display == "none" ? fc.nextSibling : fc);
-                       }else{
-                               var ns = this._highlighted_option.nextSibling;
-                               if(ns && ns.style.display != "none"){
-                                       this._focusOptionNode(ns);
-                               }else{
-                                       this.highlightFirstOption();
-                               }
+                       var stack = this._stack,
+                               widget = args.popup,
+                               orient = args.orient || ["below", "below-alt", "above", "above-alt"],
+                               ltr = args.parent ? args.parent.isLeftToRight() : domGeometry.isBodyLtr(),
+                               around = args.around,
+                               id = (args.around && args.around.id) ? (args.around.id+"_dropdown") : ("popup_"+this._idGen++);
+
+                       // If we are opening a new popup that isn't a child of a currently opened popup, then
+                       // close currently opened popup(s).   This should happen automatically when the old popups
+                       // gets the _onBlur() event, except that the _onBlur() event isn't reliable on IE, see [22198].
+                       while(stack.length && (!args.parent || !dom.isDescendant(args.parent.domNode, stack[stack.length-1].widget.domNode))){
+                               this.close(stack[stack.length-1].widget);
                        }
-                       // scrollIntoView is called outside of _focusOptionNode because in IE putting it inside causes the menu to scroll up on mouseover
-                       dojo.window.scrollIntoView(this._highlighted_option);
-               },
 
-               highlightFirstOption: function(){
-                       // summary:
-                       //              Highlight the first real item in the list (not Previous Choices).
-                       var first = this.domNode.firstChild;
-                       var second = first.nextSibling;
-                       this._focusOptionNode(second.style.display == "none" ? first : second); // remotely possible that Previous Choices is the only thing in the list
-                       dojo.window.scrollIntoView(this._highlighted_option);
-               },
+                       // Get pointer to popup wrapper, and create wrapper if it doesn't exist
+                       var wrapper = this._createWrapper(widget);
 
-               highlightLastOption: function(){
-                       // summary:
-                       //              Highlight the last real item in the list (not More Choices).
-                       this._focusOptionNode(this.domNode.lastChild.previousSibling);
-                       dojo.window.scrollIntoView(this._highlighted_option);
-               },
 
-               _highlightPrevOption: function(){
-                       // summary:
-                       //              Highlight the item just above the current selection.
-                       //              If nothing selected, highlight last option (if
-                       //              you select Previous and try to keep scrolling up the list).
-                       if(!this.getHighlightedOption()){
-                               var lc = this.domNode.lastChild;
-                               this._focusOptionNode(lc.style.display == "none" ? lc.previousSibling : lc);
-                       }else{
-                               var ps = this._highlighted_option.previousSibling;
-                               if(ps && ps.style.display != "none"){
-                                       this._focusOptionNode(ps);
-                               }else{
-                                       this.highlightLastOption();
+                       domAttr.set(wrapper, {
+                               id: id,
+                               style: {
+                                       zIndex: this._beginZIndex + stack.length
+                               },
+                               "class": "dijitPopup " + (widget.baseClass || widget["class"] || "").split(" ")[0] +"Popup",
+                               dijitPopupParent: args.parent ? args.parent.id : ""
+                       });
+
+                       if(has("ie") || has("mozilla")){
+                               if(!widget.bgIframe){
+                                       // setting widget.bgIframe triggers cleanup in _Widget.destroy()
+                                       widget.bgIframe = new BackgroundIframe(wrapper);
                                }
                        }
-                       dojo.window.scrollIntoView(this._highlighted_option);
-               },
 
-               _page: function(/*Boolean*/ up){
-                       // summary:
-                       //              Handles page-up and page-down keypresses
+                       // position the wrapper node and make it visible
+                       var best = around ?
+                               place.around(wrapper, around, orient, ltr, widget.orient ? lang.hitch(widget, "orient") : null) :
+                               place.at(wrapper, args, orient == 'R' ? ['TR','BR','TL','BL'] : ['TL','BL','TR','BR'], args.padding);
+
+                       wrapper.style.display = "";
+                       wrapper.style.visibility = "visible";
+                       widget.domNode.style.visibility = "visible";    // counteract effects from _HasDropDown
+
+                       var handlers = [];
+
+                       // provide default escape and tab key handling
+                       // (this will work for any widget, not just menu)
+                       handlers.push(on(wrapper, connect._keypress, lang.hitch(this, function(evt){
+                               if(evt.charOrCode == keys.ESCAPE && args.onCancel){
+                                       event.stop(evt);
+                                       args.onCancel();
+                               }else if(evt.charOrCode === keys.TAB){
+                                       event.stop(evt);
+                                       var topPopup = this.getTopPopup();
+                                       if(topPopup && topPopup.onCancel){
+                                               topPopup.onCancel();
+                                       }
+                               }
+                       })));
 
-                       var scrollamount = 0;
-                       var oldscroll = this.domNode.scrollTop;
-                       var height = dojo.style(this.domNode, "height");
-                       // if no item is highlighted, highlight the first option
-                       if(!this.getHighlightedOption()){
-                               this._highlightNextOption();
+                       // watch for cancel/execute events on the popup and notify the caller
+                       // (for a menu, "execute" means clicking an item)
+                       if(widget.onCancel && args.onCancel){
+                               handlers.push(widget.on("cancel", args.onCancel));
                        }
-                       while(scrollamount<height){
-                               if(up){
-                                       // stop at option 1
-                                       if(!this.getHighlightedOption().previousSibling ||
-                                               this._highlighted_option.previousSibling.style.display == "none"){
-                                               break;
-                                       }
-                                       this._highlightPrevOption();
-                               }else{
-                                       // stop at last option
-                                       if(!this.getHighlightedOption().nextSibling ||
-                                               this._highlighted_option.nextSibling.style.display == "none"){
-                                               break;
-                                       }
-                                       this._highlightNextOption();
+
+                       handlers.push(widget.on(widget.onExecute ? "execute" : "change", lang.hitch(this, function(){
+                               var topPopup = this.getTopPopup();
+                               if(topPopup && topPopup.onExecute){
+                                       topPopup.onExecute();
                                }
-                               // going backwards
-                               var newscroll=this.domNode.scrollTop;
-                               scrollamount+=(newscroll-oldscroll)*(up ? -1:1);
-                               oldscroll=newscroll;
+                       })));
+
+                       stack.push({
+                               widget: widget,
+                               parent: args.parent,
+                               onExecute: args.onExecute,
+                               onCancel: args.onCancel,
+                               onClose: args.onClose,
+                               handlers: handlers
+                       });
+
+                       if(widget.onOpen){
+                               // TODO: in 2.0 standardize onShow() (used by StackContainer) and onOpen() (used here)
+                               widget.onOpen(best);
                        }
-               },
 
-               pageUp: function(){
-                       // summary:
-                       //              Handles pageup keypress.
-                       //              TODO: just call _page directly from handleKey().
-                       // tags:
-                       //              private
-                       this._page(true);
+                       return best;
                },
 
-               pageDown: function(){
+               close: function(/*Widget?*/ popup){
                        // summary:
-                       //              Handles pagedown keypress.
-                       //              TODO: just call _page directly from handleKey().
-                       // tags:
-                       //              private
-                       this._page(false);
-               },
+                       //              Close specified popup and any popups that it parented.
+                       //              If no popup is specified, closes all popups.
+
+                       var stack = this._stack;
+
+                       // Basically work backwards from the top of the stack closing popups
+                       // until we hit the specified popup, but IIRC there was some issue where closing
+                       // a popup would cause others to close too.  Thus if we are trying to close B in [A,B,C]
+                       // closing C might close B indirectly and then the while() condition will run where stack==[A]...
+                       // so the while condition is constructed defensively.
+                       while((popup && array.some(stack, function(elem){return elem.widget == popup;})) ||
+                               (!popup && stack.length)){
+                               var top = stack.pop(),
+                                       widget = top.widget,
+                                       onClose = top.onClose;
+
+                               if(widget.onClose){
+                                       // TODO: in 2.0 standardize onHide() (used by StackContainer) and onClose() (used here)
+                                       widget.onClose();
+                               }
 
-               getHighlightedOption: function(){
-                       // summary:
-                       //              Returns the highlighted option.
-                       var ho = this._highlighted_option;
-                       return (ho && ho.parentNode) ? ho : null;
-               },
+                               var h;
+                               while(h = top.handlers.pop()){ h.remove(); }
 
-               handleKey: function(key){
-                       switch(key){
-                               case dojo.keys.DOWN_ARROW:
-                                       this._highlightNextOption();
-                                       break;
-                               case dojo.keys.PAGE_DOWN:
-                                       this.pageDown();
-                                       break;
-                               case dojo.keys.UP_ARROW:
-                                       this._highlightPrevOption();
-                                       break;
-                               case dojo.keys.PAGE_UP:
-                                       this.pageUp();
-                                       break;
+                               // Hide the widget and it's wrapper unless it has already been destroyed in above onClose() etc.
+                               if(widget && widget.domNode){
+                                       this.hide(widget);
+                               }
+
+                               if(onClose){
+                                       onClose();
+                               }
                        }
                }
-       }
-);
-
-dojo.declare(
-       "dijit.form.ComboBox",
-       [dijit.form.ValidationTextBox, dijit.form.ComboBoxMixin],
-       {
-               // summary:
-               //              Auto-completing text box, and base class for dijit.form.FilteringSelect.
-               //
-               // description:
-               //              The drop down box's values are populated from an class called
-               //              a data provider, which returns a list of values based on the characters
-               //              that the user has typed into the input box.
-               //              If OPTION tags are used as the data provider via markup,
-               //              then the OPTION tag's child text node is used as the widget value
-               //              when selected.  The OPTION tag's value attribute is ignored.
-               //              To set the default value when using OPTION tags, specify the selected
-               //              attribute on 1 of the child OPTION tags.
-               //
-               //              Some of the options to the ComboBox are actually arguments to the data
-               //              provider.
+       });
 
-               _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
-                       // summary:
-                       //              Hook so attr('value', value) works.
-                       // description:
-                       //              Sets the value of the select.
-                       this.item = null; // value not looked up in store
-                       if(!value){ value = ''; } // null translates to blank
-                       dijit.form.ValidationTextBox.prototype._setValueAttr.call(this, value, priorityChange, displayedValue);
-               }
-       }
-);
+       return (dijit.popup = new PopupManager());
+});
 
-dojo.declare("dijit.form._ComboBoxDataStore", null, {
+},
+'dijit/_base/manager':function(){
+define("dijit/_base/manager", [
+       "dojo/_base/array",
+       "dojo/_base/config", // defaultDuration
+       "../registry",
+       ".."    // for setting exports to dijit namespace
+], function(array, config, registry, dijit){
+
+       // module:
+       //              dijit/_base/manager
        // summary:
-       //              Inefficient but small data store specialized for inlined `dijit.form.ComboBox` data
-       //
-       // description:
-       //              Provides a store for inlined data like:
-       //
-       //      |       <select>
-       //      |               <option value="AL">Alabama</option>
-       //      |               ...
-       //
-       //              Actually. just implements the subset of dojo.data.Read/Notification
-       //              needed for ComboBox and FilteringSelect to work.
-       //
-       //              Note that an item is just a pointer to the <option> DomNode.
-
-       constructor: function( /*DomNode*/ root){
-               this.root = root;
-               if(root.tagName != "SELECT" && root.firstChild){
-                       root = dojo.query("select", root);
-                       if(root.length > 0){ // SELECT is a child of srcNodeRef
-                               root = root[0];
-                       }else{ // no select, so create 1 to parent the option tags to define selectedIndex
-                               this.root.innerHTML = "<SELECT>"+this.root.innerHTML+"</SELECT>";
-                               root = this.root.firstChild;
-                       }
-                       this.root = root;
-               }
-               dojo.query("> option", root).forEach(function(node){
-                       //      TODO: this was added in #3858 but unclear why/if it's needed;  doesn't seem to be.
-                       //      If it is needed then can we just hide the select itself instead?
-                       //node.style.display="none";
-                       node.innerHTML = dojo.trim(node.innerHTML);
-               });
-
-       },
-
-       getValue: function(     /* item */ item,
-                                               /* attribute-name-string */ attribute,
-                                               /* value? */ defaultValue){
-               return (attribute == "value") ? item.value : (item.innerText || item.textContent || '');
-       },
-
-       isItemLoaded: function(/* anything */ something){
-               return true;
-       },
+       //              Shim to methods on registry, plus a few other declarations.
+       //              New code should access dijit/registry directly when possible.
 
-       getFeatures: function(){
-               return {"dojo.data.api.Read": true, "dojo.data.api.Identity": true};
-       },
+       /*=====
+       dijit.byId = function(id){
+               // summary:
+               //              Returns a widget by it's id, or if passed a widget, no-op (like dom.byId())
+               // id: String|dijit._Widget
+               return registry.byId(id); // dijit._Widget
+       };
 
-       _fetchItems: function(  /* Object */ args,
-                                                       /* Function */ findCallback,
-                                                       /* Function */ errorCallback){
+       dijit.getUniqueId = function(widgetType){
                // summary:
-               //              See dojo.data.util.simpleFetch.fetch()
-               if(!args.query){ args.query = {}; }
-               if(!args.query.name){ args.query.name = ""; }
-               if(!args.queryOptions){ args.queryOptions = {}; }
-               var matcher = dojo.data.util.filter.patternToRegExp(args.query.name, args.queryOptions.ignoreCase),
-                       items = dojo.query("> option", this.root).filter(function(option){
-                               return (option.innerText || option.textContent || '').match(matcher);
-                       } );
-               if(args.sort){
-                       items.sort(dojo.data.util.sorter.createSortFunction(args.sort, this));
-               }
-               findCallback(items, args);
-       },
+               //              Generates a unique id for a given widgetType
+               // widgetType: String
+               return registry.getUniqueId(widgetType); // String
+       };
 
-       close: function(/*dojo.data.api.Request || args || null */ request){
-               return;
-       },
+       dijit.findWidgets = function(root){
+               // summary:
+               //              Search subtree under root returning widgets found.
+               //              Doesn't search for nested widgets (ie, widgets inside other widgets).
+               // root: DOMNode
+               return registry.findWidgets(root);
+       };
 
-       getLabel: function(/* item */ item){
-               return item.innerHTML;
-       },
+       dijit._destroyAll = function(){
+               // summary:
+               //              Code to destroy all widgets and do other cleanup on page unload
 
-       getIdentity: function(/* item */ item){
-               return dojo.attr(item, "value");
-       },
+               return registry._destroyAll();
+       };
 
-       fetchItemByIdentity: function(/* Object */ args){
+       dijit.byNode = function(node){
                // summary:
-               //              Given the identity of an item, this method returns the item that has
-               //              that identity through the onItem callback.
-               //              Refer to dojo.data.api.Identity.fetchItemByIdentity() for more details.
-               //
-               // description:
-               //              Given arguments like:
-               //
-               //      |               {identity: "CA", onItem: function(item){...}
-               //
-               //              Call `onItem()` with the DOM node `<option value="CA">California</option>`
-               var item = dojo.query("> option[value='" + args.identity + "']", this.root)[0];
-               args.onItem(item);
-       },
+               //              Returns the widget corresponding to the given DOMNode
+               // node: DOMNode
+               return registry.byNode(node); // dijit._Widget
+       };
 
-       fetchSelectedItem: function(){
+       dijit.getEnclosingWidget = function(node){
                // summary:
-               //              Get the option marked as selected, like `<option selected>`.
-               //              Not part of dojo.data API.
-               var root = this.root,
-                       si = root.selectedIndex;
-               return typeof si == "number"
-                       ? dojo.query("> option:nth-child(" + (si != -1 ? si+1 : 1) + ")", root)[0]
-                       : null; // dojo.data.Item
-       }
-});
-//Mix in the simple fetch implementation to this class.
-dojo.extend(dijit.form._ComboBoxDataStore,dojo.data.util.simpleFetch);
+               //              Returns the widget whose DOM tree contains the specified DOMNode, or null if
+               //              the node is not contained within the DOM tree of any widget
+               // node: DOMNode
+               return registry.getEnclosingWidget(node);
+       };
+       =====*/
+       array.forEach(["byId", "getUniqueId", "findWidgets", "_destroyAll", "byNode", "getEnclosingWidget"], function(name){
+               dijit[name] = registry[name];
+       });
 
-}
+       /*=====
+       dojo.mixin(dijit, {
+               // defaultDuration: Integer
+               //              The default fx.animation speed (in ms) to use for all Dijit
+               //              transitional fx.animations, unless otherwise specified
+               //              on a per-instance basis. Defaults to 200, overrided by
+               //              `djConfig.defaultDuration`
+               defaultDuration: 200
+       });
+       =====*/
+       dijit.defaultDuration = config["defaultDuration"] || 200;
+
+       return dijit;
+});
 
-if(!dojo._hasResource["dijit.form.FilteringSelect"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.FilteringSelect"] = true;
-dojo.provide("dijit.form.FilteringSelect");
+},
+'dijit/layout/StackController':function(){
+define("dijit/layout/StackController", [
+       "dojo/_base/array", // array.forEach array.indexOf array.map
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/keys", // keys
+       "dojo/_base/lang", // lang.getObject
+       "dojo/_base/sniff", // has("ie")
+       "../focus",             // focus.focus()
+       "../registry",  // registry.byId
+       "../_Widget",
+       "../_TemplatedMixin",
+       "../_Container",
+       "../form/ToggleButton",
+       "dojo/i18n!../nls/common"
+], function(array, declare, event, keys, lang, has,
+                       focus, registry, _Widget, _TemplatedMixin, _Container, ToggleButton){
 
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _Container = dijit._Container;
+       var ToggleButton = dijit.form.ToggleButton;
+=====*/
 
+       // module:
+       //              dijit/layout/StackController
+       // summary:
+       //              Set of buttons to select a page in a `dijit.layout.StackContainer`
 
-dojo.declare(
-       "dijit.form.FilteringSelect",
-       [dijit.form.MappedTextBox, dijit.form.ComboBoxMixin],
-       {
+       var StackButton = declare("dijit.layout._StackButton", ToggleButton, {
                // summary:
-               //              An enhanced version of the HTML SELECT tag, populated dynamically
-               //
+               //              Internal widget used by StackContainer.
                // description:
-               //              An enhanced version of the HTML SELECT tag, populated dynamically. It works
-               //              very nicely with very large data sets because it can load and page data as needed.
-               //              It also resembles ComboBox, but does not allow values outside of the provided ones.
-               //              If OPTION tags are used as the data provider via markup, then the
-               //              OPTION tag's child text node is used as the displayed value when selected
-               //              while the OPTION tag's value attribute is used as the widget value on form submit.
-               //              To set the default value when using OPTION tags, specify the selected
-               //              attribute on 1 of the child OPTION tags.
-               //
-               //              Similar features:
-               //                      - There is a drop down list of possible values.
-               //                      - You can only enter a value from the drop down list.  (You can't
-               //                              enter an arbitrary value.)
-               //                      - The value submitted with the form is the hidden value (ex: CA),
-               //                              not the displayed value a.k.a. label (ex: California)
-               //
-               //              Enhancements over plain HTML version:
-               //                      - If you type in some text then it will filter down the list of
-               //                              possible values in the drop down list.
-               //                      - List can be specified either as a static list or via a javascript
-               //                              function (that can get the list from a server)
-
-               _isvalid: true,
-
-               // required: Boolean
-               //              True (default) if user is required to enter a value into this field.
-               required: true,
+               //              The button-like or tab-like object you click to select or delete a page
+               // tags:
+               //              private
 
-               _lastDisplayedValue: "",
+               // Override _FormWidget.tabIndex.
+               // StackContainer buttons are not in the tab order by default.
+               // Probably we should be calling this.startupKeyNavChildren() instead.
+               tabIndex: "-1",
 
-               isValid: function(){
-                       // Overrides ValidationTextBox.isValid()
-                       return this._isvalid || (!this.required && this.get('displayedValue') == ""); // #5974
+               // closeButton: Boolean
+               //              When true, display close button for this tab
+               closeButton: false,
+               
+               _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){
+                       this.inherited(arguments);
+                       this.focusNode.removeAttribute("aria-pressed");
                },
 
-               _refreshState: function(){
-                       if(!this.searchTimer){ // state will be refreshed after results are returned
-                               this.inherited(arguments);
-                       }
+               buildRendering: function(/*Event*/ evt){
+                       this.inherited(arguments);
+                       (this.focusNode || this.domNode).setAttribute("role", "tab");
                },
 
-               _callbackSetLabel: function(    /*Array*/ result,
-                                               /*Object*/ dataObject,
-                                               /*Boolean?*/ priorityChange){
+               onClick: function(/*Event*/ /*===== evt =====*/){
                        // summary:
-                       //              Callback function that dynamically sets the label of the
-                       //              ComboBox
+                       //              This is for TabContainer where the tabs are <span> rather than button,
+                       //              so need to set focus explicitly (on some browsers)
+                       //              Note that you shouldn't override this method, but you can connect to it.
+                       focus.focus(this.focusNode);
 
-                       // setValue does a synchronous lookup,
-                       // so it calls _callbackSetLabel directly,
-                       // and so does not pass dataObject
-                       // still need to test against _lastQuery in case it came too late
-                       if((dataObject && dataObject.query[this.searchAttr] != this._lastQuery) || (!dataObject && result.length && this.store.getIdentity(result[0]) != this._lastQuery)){
-                               return;
-                       }
-                       if(!result.length){
-                               //#3268: do nothing on bad input
-                               //#3285: change CSS to indicate error
-                               this.valueNode.value = "";
-                               dijit.form.TextBox.superclass._setValueAttr.call(this, "", priorityChange || (priorityChange === undefined && !this._focused));
-                               this._isvalid = false;
-                               this.validate(this._focused);
-                               this.item = null;
-                       }else{
-                               this.set('item', result[0], priorityChange);
-                       }
+                       // ... now let StackController catch the event and tell me what to do
                },
 
-               _openResultList: function(/*Object*/ results, /*Object*/ dataObject){
-                       // Overrides ComboBox._openResultList()
+               onClickCloseButton: function(/*Event*/ evt){
+                       // summary:
+                       //              StackContainer connects to this function; if your widget contains a close button
+                       //              then clicking it should call this function.
+                       //              Note that you shouldn't override this method, but you can connect to it.
+                       evt.stopPropagation();
+               }
+       });
 
-                       // #3285: tap into search callback to see if user's query resembles a match
-                       if(dataObject.query[this.searchAttr] != this._lastQuery){
-                               return;
-                       }
-                       if(this.item === undefined){ // item == undefined for keyboard search
-                               this._isvalid = results.length != 0 || this._maxOptions != 0; // result.length==0 && maxOptions != 0 implies the nextChoices item selected but then the datastore returned 0 more entries
-                               this.validate(true);
-                       }
-                       dijit.form.ComboBoxMixin.prototype._openResultList.apply(this, arguments);
-               },
 
-               _getValueAttr: function(){
-                       // summary:
-                       //              Hook for attr('value') to work.
+       var StackController = declare("dijit.layout.StackController", [_Widget, _TemplatedMixin, _Container], {
+               // summary:
+               //              Set of buttons to select a page in a `dijit.layout.StackContainer`
+               // description:
+               //              Monitors the specified StackContainer, and whenever a page is
+               //              added, deleted, or selected, updates itself accordingly.
 
-                       // don't get the textbox value but rather the previously set hidden value.
-                       // Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur
-                       return this.valueNode.value;
-               },
+               baseClass: "dijitStackController",
 
-               _getValueField: function(){
-                       // Overrides ComboBox._getValueField()
-                       return "value";
-               },
+               templateString: "<span role='tablist' data-dojo-attach-event='onkeypress'></span>",
 
-               _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange){
-                       // summary:
-                       //              Hook so attr('value', value) works.
-                       // description:
-                       //              Sets the value of the select.
-                       //              Also sets the label to the corresponding value by reverse lookup.
-                       if(!this._onChangeActive){ priorityChange = null; }
-                       this._lastQuery = value;
+               // containerId: [const] String
+               //              The id of the page container that I point to
+               containerId: "",
 
-                       if(value === null || value === ''){
-                               this._setDisplayedValueAttr('', priorityChange);
-                               return;
-                       }
+               // buttonWidget: [const] Constructor
+               //              The button widget to create to correspond to each page
+               buttonWidget: StackButton,
 
-                       //#3347: fetchItemByIdentity if no keyAttr specified
-                       var self = this;
-                       this.store.fetchItemByIdentity({
-                               identity: value,
-                               onItem: function(item){
-                                       self._callbackSetLabel(item? [item] : [], undefined, priorityChange);
-                               }
-                       });
+               constructor: function(){
+                       this.pane2button = {};          // mapping from pane id to buttons
+                       this.pane2connects = {};        // mapping from pane id to this.connect() handles
+                       this.pane2watches = {};         // mapping from pane id to watch() handles
                },
 
-               _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
-                       // summary:
-                       //              Set the displayed valued in the input box, and the hidden value
-                       //              that gets submitted, based on a dojo.data store item.
-                       // description:
-                       //              Users shouldn't call this function; they should be calling
-                       //              attr('item', value)
-                       // tags:
-                       //              private
-                       this._isvalid = true;
+               postCreate: function(){
                        this.inherited(arguments);
-                       this.valueNode.value = this.value;
-                       this._lastDisplayedValue = this.textbox.value;
-               },
 
-               _getDisplayQueryString: function(/*String*/ text){
-                       return text.replace(/([\\\*\?])/g, "\\$1");
+                       // Listen to notifications from StackContainer
+                       this.subscribe(this.containerId+"-startup", "onStartup");
+                       this.subscribe(this.containerId+"-addChild", "onAddChild");
+                       this.subscribe(this.containerId+"-removeChild", "onRemoveChild");
+                       this.subscribe(this.containerId+"-selectChild", "onSelectChild");
+                       this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress");
                },
 
-               _setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){
+               onStartup: function(/*Object*/ info){
                        // summary:
-                       //              Hook so attr('displayedValue', label) works.
-                       // description:
-                       //              Sets textbox to display label. Also performs reverse lookup
-                       //              to set the hidden value.
-
-                       // When this is called during initialization it'll ping the datastore
-                       // for reverse lookup, and when that completes (after an XHR request)
-                       // will call setValueAttr()... but that shouldn't trigger an onChange()
-                       // event, even when it happens after creation has finished
-                       if(!this._created){
-                               priorityChange = false;
-                       }
-
-                       if(this.store){
-                               this._hideResultList();
-                               var query = dojo.clone(this.query); // #6196: populate query with user-specifics
-                               // escape meta characters of dojo.data.util.filter.patternToRegExp().
-                               this._lastQuery = query[this.searchAttr] = this._getDisplayQueryString(label);
-                               // if the label is not valid, the callback will never set it,
-                               // so the last valid value will get the warning textbox set the
-                               // textbox value now so that the impending warning will make
-                               // sense to the user
-                               this.textbox.value = label;
-                               this._lastDisplayedValue = label;
-                               var _this = this;
-                               var fetch = {
-                                       query: query,
-                                       queryOptions: {
-                                               ignoreCase: this.ignoreCase,
-                                               deep: true
-                                       },
-                                       onComplete: function(result, dataObject){
-                                               _this._fetchHandle = null;
-                                               dojo.hitch(_this, "_callbackSetLabel")(result, dataObject, priorityChange);
-                                       },
-                                       onError: function(errText){
-                                               _this._fetchHandle = null;
-                                               console.error('dijit.form.FilteringSelect: ' + errText);
-                                               dojo.hitch(_this, "_callbackSetLabel")([], undefined, false);
-                                       }
-                               };
-                               dojo.mixin(fetch, this.fetchProperties);
-                               this._fetchHandle = this.store.fetch(fetch);
+                       //              Called after StackContainer has finished initializing
+                       // tags:
+                       //              private
+                       array.forEach(info.children, this.onAddChild, this);
+                       if(info.selected){
+                               // Show button corresponding to selected pane (unless selected
+                               // is null because there are no panes)
+                               this.onSelectChild(info.selected);
                        }
                },
 
-               postMixInProperties: function(){
+               destroy: function(){
+                       for(var pane in this.pane2button){
+                               this.onRemoveChild(registry.byId(pane));
+                       }
                        this.inherited(arguments);
-                       this._isvalid = !this.required;
                },
 
-               undo: function(){
-                       this.set('displayedValue', this._lastDisplayedValue);
-               }
-       }
-);
-
-}
-
-if(!dojo._hasResource["dijit.form.Form"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.Form"] = true;
-dojo.provide("dijit.form.Form");
-
-
+               onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){
+                       // summary:
+                       //              Called whenever a page is added to the container.
+                       //              Create button corresponding to the page.
+                       // tags:
+                       //              private
 
+                       // create an instance of the button widget
+                       // (remove typeof buttonWidget == string support in 2.0)
+                       var cls = lang.isString(this.buttonWidget) ? lang.getObject(this.buttonWidget) : this.buttonWidget;
+                       var button = new cls({
+                               id: this.id + "_" + page.id,
+                               label: page.title,
+                               dir: page.dir,
+                               lang: page.lang,
+                               textDir: page.textDir,
+                               showLabel: page.showTitle,
+                               iconClass: page.iconClass,
+                               closeButton: page.closable,
+                               title: page.tooltip
+                       });
+                       button.focusNode.setAttribute("aria-selected", "false");
 
 
-dojo.declare(
-       "dijit.form.Form",
-       [dijit._Widget, dijit._Templated, dijit.form._FormMixin],
-       {
-               // summary:
-               //              Widget corresponding to HTML form tag, for validation and serialization
-               //
-               // example:
-               //      |       <form dojoType="dijit.form.Form" id="myForm">
-               //      |               Name: <input type="text" name="name" />
-               //      |       </form>
-               //      |       myObj = {name: "John Doe"};
-               //      |       dijit.byId('myForm').set('value', myObj);
-               //      |
-               //      |       myObj=dijit.byId('myForm').get('value');
+                       // map from page attribute to corresponding tab button attribute
+                       var pageAttrList = ["title", "showTitle", "iconClass", "closable", "tooltip"],
+                               buttonAttrList = ["label", "showLabel", "iconClass", "closeButton", "title"];
 
-               // HTML <FORM> attributes
+                       // watch() so events like page title changes are reflected in tab button
+                       this.pane2watches[page.id] = array.map(pageAttrList, function(pageAttr, idx){
+                               return page.watch(pageAttr, function(name, oldVal, newVal){
+                                       button.set(buttonAttrList[idx], newVal);
+                               });
+                       });
 
-               // name: String?
-               //              Name of form for scripting.
-               name: "",
+                       // connections so that clicking a tab button selects the corresponding page
+                       this.pane2connects[page.id] = [
+                               this.connect(button, 'onClick', lang.hitch(this,"onButtonClick", page)),
+                               this.connect(button, 'onClickCloseButton', lang.hitch(this,"onCloseButtonClick", page))
+                       ];
 
-               // action: String?
-               //              Server-side form handler.
-               action: "",
+                       this.addChild(button, insertIndex);
+                       this.pane2button[page.id] = button;
+                       page.controlButton = button;    // this value might be overwritten if two tabs point to same container
+                       if(!this._currentChild){ // put the first child into the tab order
+                               button.focusNode.setAttribute("tabIndex", "0");
+                               button.focusNode.setAttribute("aria-selected", "true");
+                               this._currentChild = page;
+                       }
+                       // make sure all tabs have the same length
+                       if(!this.isLeftToRight() && has("ie") && this._rectifyRtlTabList){
+                               this._rectifyRtlTabList();
+                       }
+               },
 
-               // method: String?
-               //              HTTP method used to submit the form, either "GET" or "POST".
-               method: "",
+               onRemoveChild: function(/*dijit._Widget*/ page){
+                       // summary:
+                       //              Called whenever a page is removed from the container.
+                       //              Remove the button corresponding to the page.
+                       // tags:
+                       //              private
 
-               // encType: String?
-               //              Encoding type for the form, ex: application/x-www-form-urlencoded.
-               encType: "",
+                       if(this._currentChild === page){ this._currentChild = null; }
 
-               // accept-charset: String?
-               //              List of supported charsets.
-               "accept-charset": "",
+                       // disconnect/unwatch connections/watches related to page being removed
+                       array.forEach(this.pane2connects[page.id], lang.hitch(this, "disconnect"));
+                       delete this.pane2connects[page.id];
+                       array.forEach(this.pane2watches[page.id], function(w){ w.unwatch(); });
+                       delete this.pane2watches[page.id];
 
-               // accept: String?
-               //              List of MIME types for file upload.
-               accept: "",
+                       var button = this.pane2button[page.id];
+                       if(button){
+                               this.removeChild(button);
+                               delete this.pane2button[page.id];
+                               button.destroy();
+                       }
+                       delete page.controlButton;
+               },
 
-               // target: String?
-               //              Target frame for the document to be opened in.
-               target: "",
+               onSelectChild: function(/*dijit._Widget*/ page){
+                       // summary:
+                       //              Called when a page has been selected in the StackContainer, either by me or by another StackController
+                       // tags:
+                       //              private
 
-               templateString: "<form dojoAttachPoint='containerNode' dojoAttachEvent='onreset:_onReset,onsubmit:_onSubmit' ${!nameAttrSetting}></form>",
+                       if(!page){ return; }
 
-               attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-                       action: "",
-                       method: "",
-                       encType: "",
-                       "accept-charset": "",
-                       accept: "",
-                       target: ""
-               }),
+                       if(this._currentChild){
+                               var oldButton=this.pane2button[this._currentChild.id];
+                               oldButton.set('checked', false);
+                               oldButton.focusNode.setAttribute("aria-selected", "false");
+                               oldButton.focusNode.setAttribute("tabIndex", "-1");
+                       }
 
-               postMixInProperties: function(){
-                       // Setup name=foo string to be referenced from the template (but only if a name has been specified)
-                       // Unfortunately we can't use attributeMap to set the name due to IE limitations, see #8660
-                       this.nameAttrSetting = this.name ? ("name='" + this.name + "'") : "";
-                       this.inherited(arguments);
+                       var newButton=this.pane2button[page.id];
+                       newButton.set('checked', true);
+                       newButton.focusNode.setAttribute("aria-selected", "true");
+                       this._currentChild = page;
+                       newButton.focusNode.setAttribute("tabIndex", "0");
+                       var container = registry.byId(this.containerId);
+                       container.containerNode.setAttribute("aria-labelledby", newButton.id);
                },
 
-               execute: function(/*Object*/ formContents){
+               onButtonClick: function(/*dijit._Widget*/ page){
                        // summary:
-                       //              Deprecated: use submit()
+                       //              Called whenever one of my child buttons is pressed in an attempt to select a page
                        // tags:
-                       //              deprecated
+                       //              private
+
+                       if(this._currentChild.id === page.id) {
+                               //In case the user clicked the checked button, keep it in the checked state because it remains to be the selected stack page.
+                               var button=this.pane2button[page.id];
+                               button.set('checked', true);
+                       }
+                       var container = registry.byId(this.containerId);
+                       container.selectChild(page);
                },
 
-               onExecute: function(){
+               onCloseButtonClick: function(/*dijit._Widget*/ page){
                        // summary:
-                       //              Deprecated: use onSubmit()
+                       //              Called whenever one of my child buttons [X] is pressed in an attempt to close a page
                        // tags:
-                       //              deprecated
-               },
-
-               _setEncTypeAttr: function(/*String*/ value){
-                       this.encType = value;
-                       dojo.attr(this.domNode, "encType", value);
-                       if(dojo.isIE){ this.domNode.encoding = value; }
-               },
+                       //              private
 
-               postCreate: function(){
-                       // IE tries to hide encType
-                       // TODO: this code should be in parser, not here.
-                       if(dojo.isIE && this.srcNodeRef && this.srcNodeRef.attributes){
-                               var item = this.srcNodeRef.attributes.getNamedItem('encType');
-                               if(item && !item.specified && (typeof item.value == "string")){
-                                       this.set('encType', item.value);
+                       var container = registry.byId(this.containerId);
+                       container.closeChild(page);
+                       if(this._currentChild){
+                               var b = this.pane2button[this._currentChild.id];
+                               if(b){
+                                       focus.focus(b.focusNode || b.domNode);
                                }
                        }
-                       this.inherited(arguments);
                },
 
-               reset: function(/*Event?*/ e){
+               // TODO: this is a bit redundant with forward, back api in StackContainer
+               adjacent: function(/*Boolean*/ forward){
                        // summary:
-                       //              restores all widget values back to their init values,
-                       //              calls onReset() which can cancel the reset by returning false
+                       //              Helper for onkeypress to find next/previous button
+                       // tags:
+                       //              private
 
-                       // create fake event so we can know if preventDefault() is called
-                       var faux = {
-                               returnValue: true, // the IE way
-                               preventDefault: function(){ // not IE
-                                                       this.returnValue = false;
-                                               },
-                               stopPropagation: function(){}, 
-                               currentTarget: e ? e.target : this.domNode, 
-                               target: e ? e.target : this.domNode
-                       };
-                       // if return value is not exactly false, and haven't called preventDefault(), then reset
-                       if(!(this.onReset(faux) === false) && faux.returnValue){
-                               this.inherited(arguments, []);
-                       }
+                       if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; }
+                       // find currently focused button in children array
+                       var children = this.getChildren();
+                       var current = array.indexOf(children, this.pane2button[this._currentChild.id]);
+                       // pick next button to focus on
+                       var offset = forward ? 1 : children.length - 1;
+                       return children[ (current + offset) % children.length ]; // dijit._Widget
                },
 
-               onReset: function(/*Event?*/ e){
+               onkeypress: function(/*Event*/ e){
                        // summary:
-                       //              Callback when user resets the form. This method is intended
-                       //              to be over-ridden. When the `reset` method is called
-                       //              programmatically, the return value from `onReset` is used
-                       //              to compute whether or not resetting should proceed
+                       //              Handle keystrokes on the page list, for advancing to next/previous button
+                       //              and closing the current page if the page is closable.
                        // tags:
-                       //              callback
-                       return true; // Boolean
-               },
-
-               _onReset: function(e){
-                       this.reset(e);
-                       dojo.stopEvent(e);
-                       return false;
-               },
+                       //              private
 
-               _onSubmit: function(e){
-                       var fp = dijit.form.Form.prototype;
-                       // TODO: remove this if statement beginning with 2.0
-                       if(this.execute != fp.execute || this.onExecute != fp.onExecute){
-                               dojo.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0");
-                               this.onExecute();
-                               this.execute(this.getValues());
-                       }
-                       if(this.onSubmit(e) === false){ // only exactly false stops submit
-                               dojo.stopEvent(e);
+                       if(this.disabled || e.altKey ){ return; }
+                       var forward = null;
+                       if(e.ctrlKey || !e._djpage){
+                               switch(e.charOrCode){
+                                       case keys.LEFT_ARROW:
+                                       case keys.UP_ARROW:
+                                               if(!e._djpage){ forward = false; }
+                                               break;
+                                       case keys.PAGE_UP:
+                                               if(e.ctrlKey){ forward = false; }
+                                               break;
+                                       case keys.RIGHT_ARROW:
+                                       case keys.DOWN_ARROW:
+                                               if(!e._djpage){ forward = true; }
+                                               break;
+                                       case keys.PAGE_DOWN:
+                                               if(e.ctrlKey){ forward = true; }
+                                               break;
+                                       case keys.HOME:
+                                       case keys.END:
+                                               var children = this.getChildren();
+                                               if(children && children.length){
+                                                       children[e.charOrCode == keys.HOME ? 0 : children.length-1].onClick();
+                                               }
+                                               event.stop(e);
+                                               break;
+                                       case keys.DELETE:
+                                               if(this._currentChild.closable){
+                                                       this.onCloseButtonClick(this._currentChild);
+                                               }
+                                               event.stop(e);
+                                               break;
+                                       default:
+                                               if(e.ctrlKey){
+                                                       if(e.charOrCode === keys.TAB){
+                                                               this.adjacent(!e.shiftKey).onClick();
+                                                               event.stop(e);
+                                                       }else if(e.charOrCode == "w"){
+                                                               if(this._currentChild.closable){
+                                                                       this.onCloseButtonClick(this._currentChild);
+                                                               }
+                                                               event.stop(e); // avoid browser tab closing.
+                                                       }
+                                               }
+                               }
+                               // handle next/previous page navigation (left/right arrow, etc.)
+                               if(forward !== null){
+                                       this.adjacent(forward).onClick();
+                                       event.stop(e);
+                               }
                        }
                },
 
-               onSubmit: function(/*Event?*/e){
+               onContainerKeyPress: function(/*Object*/ info){
                        // summary:
-                       //              Callback when user submits the form.
-                       // description:
-                       //              This method is intended to be over-ridden, but by default it checks and
-                       //              returns the validity of form elements. When the `submit`
-                       //              method is called programmatically, the return value from
-                       //              `onSubmit` is used to compute whether or not submission
-                       //              should proceed
+                       //              Called when there was a keypress on the container
                        // tags:
-                       //              extension
-
-                       return this.isValid(); // Boolean
-               },
-
-               submit: function(){
-                       // summary:
-                       //              programmatically submit form if and only if the `onSubmit` returns true
-                       if(!(this.onSubmit() === false)){
-                               this.containerNode.submit();
-                       }
+                       //              private
+                       info.e._djpage = info.page;
+                       this.onkeypress(info.e);
                }
-       }
-);
-
-}
-
-if(!dojo._hasResource["dijit.form.RadioButton"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.RadioButton"] = true;
-dojo.provide("dijit.form.RadioButton");
-
-
-// TODO: for 2.0, move the RadioButton code into this file
-
-}
+       });
 
-if(!dojo._hasResource["dijit.form._FormSelectWidget"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form._FormSelectWidget"] = true;
-dojo.provide("dijit.form._FormSelectWidget");
+       StackController.StackButton = StackButton;      // for monkey patching
 
+       return StackController;
+});
 
+},
+'dojo/dnd/Mover':function(){
+define("dojo/dnd/Mover", ["../main", "../Evented", "../touch", "./common", "./autoscroll"], function(dojo, Evented, touch) {
+       // module:
+       //              dojo/dnd/Mover
+       // summary:
+       //              TODOC
 
 
-/*=====
-dijit.form.__SelectOption = function(){
-       // value: String
-       //              The value of the option.  Setting to empty (or missing) will
-       //              place a separator at that location
-       // label: String
-       //              The label for our option.  It can contain html tags.
-       //  selected: Boolean
-       //              Whether or not we are a selected option
-       // disabled: Boolean
-       //              Whether or not this specific option is disabled
-       this.value = value;
-       this.label = label;
-       this.selected = selected;
-       this.disabled = disabled;
-}
+dojo.declare("dojo.dnd.Mover", [Evented], {
+       constructor: function(node, e, host){
+               // summary:
+               //              an object which makes a node follow the mouse, or touch-drag on touch devices.
+               //              Used as a default mover, and as a base class for custom movers.
+               // node: Node
+               //              a node (or node's id) to be moved
+               // e: Event
+               //              a mouse event, which started the move;
+               //              only pageX and pageY properties are used
+               // host: Object?
+               //              object which implements the functionality of the move,
+               //              and defines proper events (onMoveStart and onMoveStop)
+               this.node = dojo.byId(node);
+               this.marginBox = {l: e.pageX, t: e.pageY};
+               this.mouseButton = e.button;
+               var h = (this.host = host), d = node.ownerDocument;
+               this.events = [
+                       // At the start of a drag, onFirstMove is called, and then the following two
+                       // connects are disconnected
+                       dojo.connect(d, touch.move, this, "onFirstMove"),
+
+                       // These are called continually during the drag
+                       dojo.connect(d, touch.move, this, "onMouseMove"),
+
+                       // And these are called at the end of the drag
+                       dojo.connect(d, touch.release,   this, "onMouseUp"),
+
+                       // cancel text selection and text dragging
+                       dojo.connect(d, "ondragstart",   dojo.stopEvent),
+                       dojo.connect(d.body, "onselectstart", dojo.stopEvent)
+               ];
+               // notify that the move has started
+               if(h && h.onMoveStart){
+                       h.onMoveStart(this);
+               }
+       },
+       // mouse event processors
+       onMouseMove: function(e){
+               // summary:
+               //              event processor for onmousemove/ontouchmove
+               // e: Event
+               //              mouse/touch event
+               dojo.dnd.autoScroll(e);
+               var m = this.marginBox;
+               this.host.onMove(this, {l: m.l + e.pageX, t: m.t + e.pageY}, e);
+               dojo.stopEvent(e);
+       },
+       onMouseUp: function(e){
+               if(dojo.isWebKit && dojo.isMac && this.mouseButton == 2 ?
+                               e.button == 0 : this.mouseButton == e.button){ // TODO Should condition be met for touch devices, too?
+                       this.destroy();
+               }
+               dojo.stopEvent(e);
+       },
+       // utilities
+       onFirstMove: function(e){
+               // summary:
+               //              makes the node absolute; it is meant to be called only once.
+               //              relative and absolutely positioned nodes are assumed to use pixel units
+               var s = this.node.style, l, t, h = this.host;
+               switch(s.position){
+                       case "relative":
+                       case "absolute":
+                               // assume that left and top values are in pixels already
+                               l = Math.round(parseFloat(s.left)) || 0;
+                               t = Math.round(parseFloat(s.top)) || 0;
+                               break;
+                       default:
+                               s.position = "absolute";        // enforcing the absolute mode
+                               var m = dojo.marginBox(this.node);
+                               // event.pageX/pageY (which we used to generate the initial
+                               // margin box) includes padding and margin set on the body.
+                               // However, setting the node's position to absolute and then
+                               // doing dojo.marginBox on it *doesn't* take that additional
+                               // space into account - so we need to subtract the combined
+                               // padding and margin.  We use getComputedStyle and
+                               // _getMarginBox/_getContentBox to avoid the extra lookup of
+                               // the computed style.
+                               var b = dojo.doc.body;
+                               var bs = dojo.getComputedStyle(b);
+                               var bm = dojo._getMarginBox(b, bs);
+                               var bc = dojo._getContentBox(b, bs);
+                               l = m.l - (bc.l - bm.l);
+                               t = m.t - (bc.t - bm.t);
+                               break;
+               }
+               this.marginBox.l = l - this.marginBox.l;
+               this.marginBox.t = t - this.marginBox.t;
+               if(h && h.onFirstMove){
+                       h.onFirstMove(this, e);
+               }
+
+               // Disconnect onmousemove and ontouchmove events that call this function
+               dojo.disconnect(this.events.shift());
+       },
+       destroy: function(){
+               // summary:
+               //              stops the move, deletes all references, so the object can be garbage-collected
+               dojo.forEach(this.events, dojo.disconnect);
+               // undo global settings
+               var h = this.host;
+               if(h && h.onMoveStop){
+                       h.onMoveStop(this);
+               }
+               // destroy objects
+               this.events = this.node = this.host = null;
+       }
+});
+
+return dojo.dnd.Mover;
+});
+
+},
+'dijit/layout/TabContainer':function(){
+define("dijit/layout/TabContainer", [
+       "dojo/_base/lang", // lang.getObject
+       "dojo/_base/declare", // declare
+       "./_TabContainerBase",
+       "./TabController",
+       "./ScrollingTabController"
+], function(lang, declare, _TabContainerBase, TabController, ScrollingTabController){
+
+/*=====
+       var _TabContainerBase = dijit.layout._TabContainerBase;
+       var TabController = dijit.layout.TabController;
+       var ScrollingTabController = dijit.layout.ScrollingTabController;
 =====*/
 
-dojo.declare("dijit.form._FormSelectWidget", dijit.form._FormValueWidget, {
+       // module:
+       //              dijit/layout/TabContainer
        // summary:
-       //              Extends _FormValueWidget in order to provide "select-specific"
-       //              values - i.e., those values that are unique to <select> elements.
-       //              This also provides the mechanism for reading the elements from
-       //              a store, if desired.
+       //              A Container with tabs to select each child (only one of which is displayed at a time).
 
-       // multiple: Boolean
-       //              Whether or not we are multi-valued
-       multiple: false,
 
-       // options: dijit.form.__SelectOption[]
-       //              The set of options for our select item.  Roughly corresponds to
-       //      the html <option> tag.
-       options: null,
+       return declare("dijit.layout.TabContainer", _TabContainerBase, {
+               // summary:
+               //              A Container with tabs to select each child (only one of which is displayed at a time).
+               // description:
+               //              A TabContainer is a container that has multiple panes, but shows only
+               //              one pane at a time.  There are a set of tabs corresponding to each pane,
+               //              where each tab has the name (aka title) of the pane, and optionally a close button.
 
-       // store: dojo.data.api.Identity
-       //              A store which, at the very least impelements dojo.data.api.Identity
-       //              to use for getting our list of options - rather than reading them
-       //              from the <option> html tags.
-       store: null,
+               // useMenu: [const] Boolean
+               //              True if a menu should be used to select tabs when they are too
+               //              wide to fit the TabContainer, false otherwise.
+               useMenu: true,
 
-       // query: object
-       //              A query to use when fetching items from our store
-       query: null,
+               // useSlider: [const] Boolean
+               //              True if a slider should be used to select tabs when they are too
+               //              wide to fit the TabContainer, false otherwise.
+               useSlider: true,
 
-       // queryOptions: object
-       //              Query options to use when fetching from the store
-       queryOptions: null,
+               // controllerWidget: String
+               //              An optional parameter to override the widget used to display the tab labels
+               controllerWidget: "",
 
-       // onFetch: Function
-       //              A callback to do with an onFetch - but before any items are actually
-       //              iterated over (i.e. to filter even futher what you want to add)
-       onFetch: null,
+               _makeController: function(/*DomNode*/ srcNode){
+                       // summary:
+                       //              Instantiate tablist controller widget and return reference to it.
+                       //              Callback from _TabContainerBase.postCreate().
+                       // tags:
+                       //              protected extension
 
-       // sortByLabel: boolean
-       //              Flag to sort the options returned from a store by the label of
-       //              the store.
-       sortByLabel: true,
+                       var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"),
+                               TabController = lang.getObject(this.controllerWidget);
+
+                       return new TabController({
+                               id: this.id + "_tablist",
+                               dir: this.dir,
+                               lang: this.lang,
+                               textDir: this.textDir,
+                               tabPosition: this.tabPosition,
+                               doLayout: this.doLayout,
+                               containerId: this.id,
+                               "class": cls,
+                               nested: this.nested,
+                               useMenu: this.useMenu,
+                               useSlider: this.useSlider,
+                               tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null
+                       }, srcNode);
+               },
 
+               postMixInProperties: function(){
+                       this.inherited(arguments);
 
-       // loadChildrenOnOpen: boolean
-       //              By default loadChildren is called when the items are fetched from the
-       //              store.  This property allows delaying loadChildren (and the creation
-       //              of the options/menuitems) until the user opens the click the button.
-       //              dropdown
-       loadChildrenOnOpen: false,
+                       // Scrolling controller only works for horizontal non-nested tabs
+                       if(!this.controllerWidget){
+                               this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ?
+                                                       "dijit.layout.ScrollingTabController" : "dijit.layout.TabController";
+                       }
+               }
+       });
+});
 
-       getOptions: function(/* anything */ valueOrIdx){
+},
+'dijit/BackgroundIframe':function(){
+define("dijit/BackgroundIframe", [
+       "require",                      // require.toUrl
+       ".",    // to export dijit.BackgroundIframe
+       "dojo/_base/config",
+       "dojo/dom-construct", // domConstruct.create
+       "dojo/dom-style", // domStyle.set
+       "dojo/_base/lang", // lang.extend lang.hitch
+       "dojo/on",
+       "dojo/_base/sniff", // has("ie"), has("mozilla"), has("quirks")
+       "dojo/_base/window" // win.doc.createElement
+], function(require, dijit, config, domConstruct, domStyle, lang, on, has, win){
+
+       // module:
+       //              dijit/BackgroundIFrame
+       // summary:
+       //              new dijit.BackgroundIframe(node)
+       //              Makes a background iframe as a child of node, that fills
+       //              area (and position) of node
+
+       // TODO: remove _frames, it isn't being used much, since popups never release their
+       // iframes (see [22236])
+       var _frames = new function(){
                // summary:
-               //              Returns a given option (or options).
-               // valueOrIdx:
-               //              If passed in as a string, that string is used to look up the option
-               //              in the array of options - based on the value property.
-               //              (See dijit.form.__SelectOption).
-               //
-               //              If passed in a number, then the option with the given index (0-based)
-               //              within this select will be returned.
-               //
-               //              If passed in a dijit.form.__SelectOption, the same option will be
-               //              returned if and only if it exists within this select.
-               //
-               //              If passed an array, then an array will be returned with each element
-               //              in the array being looked up.
-               //
-               //              If not passed a value, then all options will be returned
-               //
-               // returns:
-               //              The option corresponding with the given value or index.  null
-               //              is returned if any of the following are true:
-               //                      - A string value is passed in which doesn't exist
-               //                      - An index is passed in which is outside the bounds of the array of options
-               //                      - A dijit.form.__SelectOption is passed in which is not a part of the select
+               //              cache of iframes
 
-               // NOTE: the compare for passing in a dijit.form.__SelectOption checks
-               //              if the value property matches - NOT if the exact option exists
-               // NOTE: if passing in an array, null elements will be placed in the returned
-               //              array when a value is not found.
-               var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length;
+               var queue = [];
 
-               if(lookupValue === undefined){
-                       return opts; // dijit.form.__SelectOption[]
-               }
-               if(dojo.isArray(lookupValue)){
-                       return dojo.map(lookupValue, "return this.getOptions(item);", this); // dijit.form.__SelectOption[]
-               }
-               if(dojo.isObject(valueOrIdx)){
-                       // We were passed an option - so see if it's in our array (directly),
-                       // and if it's not, try and find it by value.
-                       if(!dojo.some(this.options, function(o, idx){
-                               if(o === lookupValue ||
-                                       (o.value && o.value === lookupValue.value)){
-                                       lookupValue = idx;
-                                       return true;
-                               }
-                               return false;
-                       })){
-                               lookupValue = -1;
-                       }
-               }
-               if(typeof lookupValue == "string"){
-                       for(var i=0; i<l; i++){
-                               if(opts[i].value === lookupValue){
-                                       lookupValue = i;
-                                       break;
+               this.pop = function(){
+                       var iframe;
+                       if(queue.length){
+                               iframe = queue.pop();
+                               iframe.style.display="";
+                       }else{
+                               if(has("ie") < 9){
+                                       var burl = config["dojoBlankHtmlUrl"] || require.toUrl("dojo/resources/blank.html") || "javascript:\"\"";
+                                       var html="<iframe src='" + burl + "' role='presentation'"
+                                               + " style='position: absolute; left: 0px; top: 0px;"
+                                               + "z-index: -1; filter:Alpha(Opacity=\"0\");'>";
+                                       iframe = win.doc.createElement(html);
+                               }else{
+                                       iframe = domConstruct.create("iframe");
+                                       iframe.src = 'javascript:""';
+                                       iframe.className = "dijitBackgroundIframe";
+                                       iframe.setAttribute("role", "presentation");
+                                       domStyle.set(iframe, "opacity", 0.1);
                                }
+                               iframe.tabIndex = -1; // Magic to prevent iframe from getting focus on tab keypress - as style didn't work.
                        }
+                       return iframe;
+               };
+
+               this.push = function(iframe){
+                       iframe.style.display="none";
+                       queue.push(iframe);
                }
-               if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){
-                       return this.options[lookupValue] // dijit.form.__SelectOption
-               }
-               return null; // null
-       },
+       }();
 
-       addOption: function(/* dijit.form.__SelectOption, dijit.form.__SelectOption[] */ option){
-               // summary:
-               //              Adds an option or options to the end of the select.  If value
-               //              of the option is empty or missing, a separator is created instead.
-               //              Passing in an array of options will yield slightly better performance
-               //              since the children are only loaded once.
-               if(!dojo.isArray(option)){ option = [option]; }
-               dojo.forEach(option, function(i){
-                       if(i && dojo.isObject(i)){
-                               this.options.push(i);
-                       }
-               }, this);
-               this._loadChildren();
-       },
 
-       removeOption: function(/* string, dijit.form.__SelectOption, number, or array */ valueOrIdx){
+       dijit.BackgroundIframe = function(/*DomNode*/ node){
                // summary:
-               //              Removes the given option or options.  You can remove by string
-               //              (in which case the value is removed), number (in which case the
-               //              index in the options array is removed), or select option (in
-               //              which case, the select option with a matching value is removed).
-               //              You can also pass in an array of those values for a slightly
-               //              better performance since the children are only loaded once.
-               if(!dojo.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; }
-               var oldOpts = this.getOptions(valueOrIdx);
-               dojo.forEach(oldOpts, function(i){
-                       // We can get null back in our array - if our option was not found.  In
-                       // that case, we don't want to blow up...
-                       if(i){
-                               this.options = dojo.filter(this.options, function(node, idx){
-                                       return (node.value !== i.value);
+               //              For IE/FF z-index schenanigans. id attribute is required.
+               //
+               // description:
+               //              new dijit.BackgroundIframe(node)
+               //                      Makes a background iframe as a child of node, that fills
+               //                      area (and position) of node
+
+               if(!node.id){ throw new Error("no id"); }
+               if(has("ie") || has("mozilla")){
+                       var iframe = (this.iframe = _frames.pop());
+                       node.appendChild(iframe);
+                       if(has("ie")<7 || has("quirks")){
+                               this.resize(node);
+                               this._conn = on(node, 'resize', lang.hitch(this, function(){
+                                       this.resize(node);
+                               }));
+                       }else{
+                               domStyle.set(iframe, {
+                                       width: '100%',
+                                       height: '100%'
                                });
-                               this._removeOptionItem(i);
                        }
-               }, this);
-               this._loadChildren();
-       },
+               }
+       };
 
-       updateOption: function(/* dijit.form.__SelectOption, dijit.form.__SelectOption[] */ newOption){
-               // summary:
-               //              Updates the values of the given option.  The option to update
-               //              is matched based on the value of the entered option.  Passing
-               //              in an array of new options will yeild better performance since
-               //              the children will only be loaded once.
-               if(!dojo.isArray(newOption)){ newOption = [newOption]; }
-               dojo.forEach(newOption, function(i){
-                       var oldOpt = this.getOptions(i), k;
-                       if(oldOpt){
-                               for(k in i){ oldOpt[k] = i[k]; }
+       lang.extend(dijit.BackgroundIframe, {
+               resize: function(node){
+                       // summary:
+                       //              Resize the iframe so it's the same size as node.
+                       //              Needed on IE6 and IE/quirks because height:100% doesn't work right.
+                       if(this.iframe){
+                               domStyle.set(this.iframe, {
+                                       width: node.offsetWidth + 'px',
+                                       height: node.offsetHeight + 'px'
+                               });
                        }
-               }, this);
-               this._loadChildren();
-       },
-
-       setStore: function(/* dojo.data.api.Identity */ store,
-                                               /* anything? */ selectedValue,
-                                               /* Object? */ fetchArgs){
-               // summary:
-               //              Sets the store you would like to use with this select widget.
-               //              The selected value is the value of the new store to set.  This
-               //              function returns the original store, in case you want to reuse
-               //              it or something.
-               // store: dojo.data.api.Identity
-               //              The store you would like to use - it MUST implement Identity,
-               //              and MAY implement Notification.
-               // selectedValue: anything?
-               //              The value that this widget should set itself to *after* the store
-               //              has been loaded
-               // fetchArgs: Object?
-               //              The arguments that will be passed to the store's fetch() function
-               var oStore = this.store;
-               fetchArgs = fetchArgs || {};
-               if(oStore !== store){
-                       // Our store has changed, so update our notifications
-                       dojo.forEach(this._notifyConnections || [], dojo.disconnect);
-                       delete this._notifyConnections;
-                       if(store && store.getFeatures()["dojo.data.api.Notification"]){
-                               this._notifyConnections = [
-                                       dojo.connect(store, "onNew", this, "_onNewItem"),
-                                       dojo.connect(store, "onDelete", this, "_onDeleteItem"),
-                                       dojo.connect(store, "onSet", this, "_onSetItem")
-                               ];
+               },
+               destroy: function(){
+                       // summary:
+                       //              destroy the iframe
+                       if(this._conn){
+                               this._conn.remove();
+                               this._conn = null;
+                       }
+                       if(this.iframe){
+                               _frames.push(this.iframe);
+                               delete this.iframe;
                        }
-                       this.store = store;
                }
+       });
 
-               // Turn off change notifications while we make all these changes
-               this._onChangeActive = false;
-
-               // Remove existing options (if there are any)
-               if(this.options && this.options.length){
-                       this.removeOption(this.options);
-               }
+       return dijit.BackgroundIframe;
+});
 
-               // Add our new options
-               if(store){
-                       var cb = function(items){
-                               if(this.sortByLabel && !fetchArgs.sort && items.length){
-                                       items.sort(dojo.data.util.sorter.createSortFunction([{
-                                               attribute: store.getLabelAttributes(items[0])[0]
-                                       }], store));
-                               }
+},
+'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n",
+'dojo/dnd/Avatar':function(){
+define("dojo/dnd/Avatar", ["../main", "./common"], function(dojo) {
+       // module:
+       //              dojo/dnd/Avatar
+       // summary:
+       //              TODOC
 
-                               if(fetchArgs.onFetch){
-                                       items = fetchArgs.onFetch(items);
-                               }
-                               // TODO: Add these guys as a batch, instead of separately
-                               dojo.forEach(items, function(i){
-                                       this._addOptionForItem(i);
-                               }, this);
 
-                               // Set our value (which might be undefined), and then tweak
-                               // it to send a change event with the real value
-                               this._loadingStore = false;
-                               this.set("value", (("_pendingValue" in this) ? this._pendingValue : selectedValue));
-                               delete this._pendingValue;
+dojo.declare("dojo.dnd.Avatar", null, {
+       // summary:
+       //              Object that represents transferred DnD items visually
+       // manager: Object
+       //              a DnD manager object
 
-                               if(!this.loadChildrenOnOpen){
-                                       this._loadChildren();
-                               }else{
-                                       this._pseudoLoadChildren(items);
-                               }
-                               this._fetchedWith = opts;
-                               this._lastValueReported = this.multiple ? [] : null;
-                               this._onChangeActive = true;
-                               this.onSetStore();
-                               this._handleOnChange(this.value);
-                       };
-                       var opts = dojo.mixin({onComplete:cb, scope: this}, fetchArgs);
-                       this._loadingStore = true;
-                       store.fetch(opts);
-               }else{
-                       delete this._fetchedWith;
-               }
-               return oStore;  // dojo.data.api.Identity
+       constructor: function(manager){
+               this.manager = manager;
+               this.construct();
        },
 
-       _setValueAttr: function(/*anything*/ newValue, /*Boolean, optional*/ priorityChange){
+       // methods
+       construct: function(){
                // summary:
-               //              set the value of the widget.
-               //              If a string is passed, then we set our value from looking it up.
-               if(this._loadingStore){
-                       // Our store is loading - so save our value, and we'll set it when
-                       // we're done
-                       this._pendingValue = newValue;
-                       return;
-               }
-               var opts = this.getOptions() || [];
-               if(!dojo.isArray(newValue)){
-                       newValue = [newValue];
-               }
-               dojo.forEach(newValue, function(i, idx){
-                       if(!dojo.isObject(i)){
-                               i = i + "";
-                       }
-                       if(typeof i === "string"){
-                               newValue[idx] = dojo.filter(opts, function(node){
-                                       return node.value === i;
-                               })[0] || {value: "", label: ""};
+               //              constructor function;
+               //              it is separate so it can be (dynamically) overwritten in case of need
+               this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
+               var a = dojo.create("table", {
+                               "class": "dojoDndAvatar",
+                               style: {
+                                       position: "absolute",
+                                       zIndex:   "1999",
+                                       margin:   "0px"
+                               }
+                       }),
+                       source = this.manager.source, node,
+                       b = dojo.create("tbody", null, a),
+                       tr = dojo.create("tr", null, b),
+                       td = dojo.create("td", null, tr),
+                       icon = this.isA11y ? dojo.create("span", {
+                                               id : "a11yIcon",
+                                               innerHTML : this.manager.copy ? '+' : "<"
+                                       }, td) : null,
+                       span = dojo.create("span", {
+                               innerHTML: source.generateText ? this._generateText() : ""
+                       }, td),
+                       k = Math.min(5, this.manager.nodes.length), i = 0;
+               // we have to set the opacity on IE only after the node is live
+               dojo.attr(tr, {
+                       "class": "dojoDndAvatarHeader",
+                       style: {opacity: 0.9}
+               });
+               for(; i < k; ++i){
+                       if(source.creator){
+                               // create an avatar representation of the node
+                               node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
+                       }else{
+                               // or just clone the node and hope it works
+                               node = this.manager.nodes[i].cloneNode(true);
+                               if(node.tagName.toLowerCase() == "tr"){
+                                       // insert extra table nodes
+                                       var table = dojo.create("table"),
+                                               tbody = dojo.create("tbody", null, table);
+                                       tbody.appendChild(node);
+                                       node = table;
+                               }
                        }
-               }, this);
-
-               // Make sure some sane default is set
-               newValue = dojo.filter(newValue, function(i){ return i && i.value; });
-               if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){
-                       newValue[0] = opts[0];
+                       node.id = "";
+                       tr = dojo.create("tr", null, b);
+                       td = dojo.create("td", null, tr);
+                       td.appendChild(node);
+                       dojo.attr(tr, {
+                               "class": "dojoDndAvatarItem",
+                               style: {opacity: (9 - i) / 10}
+                       });
                }
-               dojo.forEach(opts, function(i){
-                       i.selected = dojo.some(newValue, function(v){ return v.value === i.value; });
-               });
-               var val = dojo.map(newValue, function(i){ return i.value; }),
-                       disp = dojo.map(newValue, function(i){ return i.label; });
-
-               this.value = this.multiple ? val : val[0];
-               this._setDisplay(this.multiple ? disp : disp[0]);
-               this._updateSelection();
-               this._handleOnChange(this.value, priorityChange);
+               this.node = a;
        },
-
-       _getDisplayedValueAttr: function(){
+       destroy: function(){
                // summary:
-               //              returns the displayed value of the widget
-               var val = this.get("value");
-               if(!dojo.isArray(val)){
-                       val = [val];
-               }
-               var ret = dojo.map(this.getOptions(val), function(v){
-                       if(v && "label" in v){
-                               return v.label;
-                       }else if(v){
-                               return v.value;
-                       }
-                       return null;
-               }, this);
-               return this.multiple ? ret : ret[0];
+               //              destructor for the avatar; called to remove all references so it can be garbage-collected
+               dojo.destroy(this.node);
+               this.node = false;
        },
-
-       _getValueDeprecated: false, // remove when _FormWidget:getValue is removed
-       getValue: function(){
+       update: function(){
                // summary:
-               //              get the value of the widget.
-               return this._lastValue;
+               //              updates the avatar to reflect the current DnD state
+               dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
+               if (this.isA11y){
+                       var icon = dojo.byId("a11yIcon");
+                       var text = '+';   // assume canDrop && copy
+                       if (this.manager.canDropFlag && !this.manager.copy) {
+                               text = '< '; // canDrop && move
+                       }else if (!this.manager.canDropFlag && !this.manager.copy) {
+                               text = "o"; //!canDrop && move
+                       }else if(!this.manager.canDropFlag){
+                               text = 'x';  // !canDrop && copy
+                       }
+                       icon.innerHTML=text;
+               }
+               // replace text
+               dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
+                       function(node){
+                               node.innerHTML = this._generateText();
+                       }, this);
        },
+       _generateText: function(){
+               // summary: generates a proper text to reflect copying or moving of items
+               return this.manager.nodes.length.toString();
+       }
+});
 
-       undo: function(){
-               // summary:
-               //              restore the value to the last value passed to onChange
-               this._setValueAttr(this._lastValueReported, false);
-       },
+return dojo.dnd.Avatar;
+});
 
-       _loadChildren: function(){
-               // summary:
-               //              Loads the children represented by this widget's options.
-               //              reset the menu to make it "populatable on the next click
-               if(this._loadingStore){ return; }
-               dojo.forEach(this._getChildren(), function(child){
-                       child.destroyRecursive();
-               });
-               // Add each menu item
-               dojo.forEach(this.options, this._addOptionItem, this);
+},
+'dijit/form/Button':function(){
+require({cache:{
+'url:dijit/form/templates/Button.html':"<span class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><span class=\"dijitReset dijitInline dijitButtonNode\"\n\t\tdata-dojo-attach-event=\"ondijitclick:_onClick\" role=\"presentation\"\n\t\t><span class=\"dijitReset dijitStretch dijitButtonContents\"\n\t\t\tdata-dojo-attach-point=\"titleNode,focusNode\"\n\t\t\trole=\"button\" aria-labelledby=\"${id}_label\"\n\t\t\t><span class=\"dijitReset dijitInline dijitIcon\" data-dojo-attach-point=\"iconNode\"></span\n\t\t\t><span class=\"dijitReset dijitToggleButtonIconChar\">&#x25CF;</span\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"\n\t\t\t\tid=\"${id}_label\"\n\t\t\t\tdata-dojo-attach-point=\"containerNode\"\n\t\t\t></span\n\t\t></span\n\t></span\n\t><input ${!nameAttrSetting} type=\"${type}\" value=\"${value}\" class=\"dijitOffScreen\"\n\t\ttabIndex=\"-1\" role=\"presentation\" data-dojo-attach-point=\"valueNode\"\n/></span>\n"}});
+define("dijit/form/Button", [
+       "require",
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.toggle
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.trim
+       "dojo/ready",
+       "./_FormWidget",
+       "./_ButtonMixin",
+       "dojo/text!./templates/Button.html"
+], function(require, declare, domClass, kernel, lang, ready, _FormWidget, _ButtonMixin, template){
 
-               // Update states
-               this._updateSelection();
-       },
+/*=====
+       var _FormWidget = dijit.form._FormWidget;
+       var _ButtonMixin = dijit.form._ButtonMixin;
+=====*/
 
-       _updateSelection: function(){
-               // summary:
-               //              Sets the "selected" class on the item for styling purposes
-               this.value = this._getValueFromOpts();
-               var val = this.value;
-               if(!dojo.isArray(val)){
-                       val = [val];
-               }
-               if(val && val[0]){
-                       dojo.forEach(this._getChildren(), function(child){
-                               var isSelected = dojo.some(val, function(v){
-                                       return child.option && (v === child.option.value);
-                               });
-                               dojo.toggleClass(child.domNode, this.baseClass + "SelectedOption", isSelected);
-                               dijit.setWaiState(child.domNode, "selected", isSelected);
-                       }, this);
-               }
-               this._handleOnChange(this.value);
-       },
+// module:
+//             dijit/form/Button
+// summary:
+//             Button widget
 
-       _getValueFromOpts: function(){
-               // summary:
-               //              Returns the value of the widget by reading the options for
-               //              the selected flag
-               var opts = this.getOptions() || [];
-               if(!this.multiple && opts.length){
-                       // Mirror what a select does - choose the first one
-                       var opt = dojo.filter(opts, function(i){
-                               return i.selected;
-                       })[0];
-                       if(opt && opt.value){
-                               return opt.value
-                       }else{
-                               opts[0].selected = true;
-                               return opts[0].value;
-                       }
-               }else if(this.multiple){
-                       // Set value to be the sum of all selected
-                       return dojo.map(dojo.filter(opts, function(i){
-                               return i.selected;
-                       }), function(i){
-                               return i.value;
-                       }) || [];
-               }
-               return "";
-       },
+// Back compat w/1.6, remove for 2.0
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/form/DropDownButton", "dijit/form/ComboButton", "dijit/form/ToggleButton"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
 
-       // Internal functions to call when we have store notifications come in
-       _onNewItem: function(/* item */ item, /* Object? */ parentInfo){
-               if(!parentInfo || !parentInfo.parent){
-                       // Only add it if we are top-level
-                       this._addOptionForItem(item);
-               }
-       },
-       _onDeleteItem: function(/* item */ item){
-               var store = this.store;
-               this.removeOption(store.getIdentity(item));
-       },
-       _onSetItem: function(/* item */ item){
-               this.updateOption(this._getOptionObjForItem(item));
-       },
+return declare("dijit.form.Button", [_FormWidget, _ButtonMixin], {
+       // summary:
+       //              Basically the same thing as a normal HTML button, but with special styling.
+       // description:
+       //              Buttons can display a label, an icon, or both.
+       //              A label should always be specified (through innerHTML) or the label
+       //              attribute.  It can be hidden via showLabel=false.
+       // example:
+       // |    <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
+       //
+       // example:
+       // |    var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
+       // |    dojo.body().appendChild(button1.domNode);
 
-       _getOptionObjForItem: function(item){
-               // summary:
-               //              Returns an option object based off the given item.  The "value"
-               //              of the option item will be the identity of the item, the "label"
-               //              of the option will be the label of the item.  If the item contains
-               //              children, the children value of the item will be set
-               var store = this.store, label = store.getLabel(item),
-                       value = (label ? store.getIdentity(item) : null);
-               return {value: value, label: label, item:item}; // dijit.form.__SelectOption
-       },
+       // showLabel: Boolean
+       //              Set this to true to hide the label text and display only the icon.
+       //              (If showLabel=false then iconClass must be specified.)
+       //              Especially useful for toolbars.
+       //              If showLabel=true, the label will become the title (a.k.a. tooltip/hint) of the icon.
+       //
+       //              The exception case is for computers in high-contrast mode, where the label
+       //              will still be displayed, since the icon doesn't appear.
+       showLabel: true,
+
+       // iconClass: String
+       //              Class to apply to DOMNode in button to make it display an icon
+       iconClass: "dijitNoIcon",
+       _setIconClassAttr: { node: "iconNode", type: "class" },
+
+       baseClass: "dijitButton",
+
+       templateString: template,
 
-       _addOptionForItem: function(/* item */ item){
+       // Map widget attributes to DOMNode attributes.
+       _setValueAttr: "valueNode",
+
+       _onClick: function(/*Event*/ e){
                // summary:
-               //              Creates (and adds) the option for the given item
-               var store = this.store;
-               if(!store.isItemLoaded(item)){
-                       // We are not loaded - so let's load it and add later
-                       store.loadItem({item: item, onComplete: function(i){
-                               this._addOptionForItem(item);
-                       },
-                       scope: this});
-                       return;
+               //              Internal function to handle click actions
+               var ok = this.inherited(arguments);
+               if(ok){
+                       if(this.valueNode){
+                               this.valueNode.click();
+                               e.preventDefault(); // cancel BUTTON click and continue with hidden INPUT click
+                               // leave ok = true so that subclasses can do what they need to do
+                       }
                }
-               var newOpt = this._getOptionObjForItem(item);
-               this.addOption(newOpt);
+               return ok;
        },
 
-       constructor: function(/* Object */ keywordArgs){
-               // summary:
-               //              Saves off our value, if we have an initial one set so we
-               //              can use it if we have a store as well (see startup())
-               this._oValue = (keywordArgs || {}).value || null;
+       _fillContent: function(/*DomNode*/ source){
+               // Overrides _Templated._fillContent().
+               // If button label is specified as srcNodeRef.innerHTML rather than
+               // this.params.label, handle it here.
+               // TODO: remove the method in 2.0, parser will do it all for me
+               if(source && (!this.params || !("label" in this.params))){
+                       var sourceLabel = lang.trim(source.innerHTML);
+                       if(sourceLabel){
+                               this.label = sourceLabel; // _applyAttributes will be called after buildRendering completes to update the DOM
+                       }
+               }
        },
 
-       _fillContent: function(){
-               // summary:
-               //              Loads our options and sets up our dropdown correctly.  We
-               //              don't want any content, so we don't call any inherit chain
-               //              function.
-               var opts = this.options;
-               if(!opts){
-                       opts = this.options = this.srcNodeRef ? dojo.query(">",
-                                               this.srcNodeRef).map(function(node){
-                                                       if(node.getAttribute("type") === "separator"){
-                                                               return { value: "", label: "", selected: false, disabled: false };
-                                                       }
-                                                       return { value: node.getAttribute("value"),
-                                                                               label: String(node.innerHTML),
-                                                                               selected: node.getAttribute("selected") || false,
-                                                                               disabled: node.getAttribute("disabled") || false };
-                                               }, this) : [];
-               }
-               if(!this.value){
-                       this.value = this._getValueFromOpts();
-               }else if(this.multiple && typeof this.value == "string"){
-                       this.value = this.value.split(",");
+       _setShowLabelAttr: function(val){
+               if(this.containerNode){
+                       domClass.toggle(this.containerNode, "dijitDisplayNone", !val);
                }
+               this._set("showLabel", val);
        },
 
-       postCreate: function(){
+       setLabel: function(/*String*/ content){
                // summary:
-               //              sets up our event handling that we need for functioning
-               //              as a select
-               dojo.setSelectable(this.focusNode, false);
-               this.inherited(arguments);
-
-               // Make our event connections for updating state
-               this.connect(this, "onChange", "_updateSelection");
-               this.connect(this, "startup", "_loadChildren");
-
-               this._setValueAttr(this.value, null);
+               //              Deprecated.  Use set('label', ...) instead.
+               kernel.deprecated("dijit.form.Button.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
+               this.set("label", content);
        },
 
-       startup: function(){
+       _setLabelAttr: function(/*String*/ content){
                // summary:
-               //              Connects in our store, if we have one defined
+               //              Hook for set('label', ...) to work.
+               // description:
+               //              Set the label (text) of the button; takes an HTML string.
+               //              If the label is hidden (showLabel=false) then and no title has
+               //              been specified, then label is also set as title attribute of icon.
                this.inherited(arguments);
-               var store = this.store, fetchArgs = {};
-               dojo.forEach(["query", "queryOptions", "onFetch"], function(i){
-                       if(this[i]){
-                               fetchArgs[i] = this[i];
-                       }
-                       delete this[i];
-               }, this);
-               if(store && store.getFeatures()["dojo.data.api.Identity"]){
-                       // Temporarily set our store to null so that it will get set
-                       // and connected appropriately
-                       this.store = null;
-                       this.setStore(store, this._oValue, fetchArgs);
+               if(!this.showLabel && !("title" in this.params)){
+                       this.titleNode.title = lang.trim(this.containerNode.innerText || this.containerNode.textContent || '');
                }
-       },
+       }
+});
 
-       destroy: function(){
-               // summary:
-               //              Clean up our connections
-               dojo.forEach(this._notifyConnections || [], dojo.disconnect);
-               this.inherited(arguments);
-       },
 
-       _addOptionItem: function(/* dijit.form.__SelectOption */ option){
-               // summary:
-               //              User-overridable function which, for the given option, adds an
-               //              item to the select.  If the option doesn't have a value, then a
-               //              separator is added in that place.  Make sure to store the option
-               //              in the created option widget.
-       },
+});
 
-       _removeOptionItem: function(/* dijit.form.__SelectOption */ option){
-               // summary:
-               //              User-overridable function which, for the given option, removes
-               //              its item from the select.
-       },
 
-       _setDisplay: function(/*String or String[]*/ newDisplay){
-               // summary:
-               //              Overridable function which will set the display for the
-               //              widget.  newDisplay is either a string (in the case of
-               //              single selects) or array of strings (in the case of multi-selects)
-       },
+},
+'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n",
+'dojo/dnd/move':function(){
+define("dojo/dnd/move", ["../main", "./Mover", "./Moveable"], function(dojo) {
+       // module:
+       //              dojo/dnd/move
+       // summary:
+       //              TODOC
 
-       _getChildren: function(){
-               // summary:
-               //              Overridable function to return the children that this widget contains.
-               return [];
-       },
 
-       _getSelectedOptionsAttr: function(){
+/*=====
+dojo.declare("dojo.dnd.move.__constrainedMoveableArgs", [dojo.dnd.__MoveableArgs], {
+       // constraints: Function
+       //              Calculates a constraint box.
+       //              It is called in a context of the moveable object.
+       constraints: function(){},
+
+       // within: Boolean
+       //              restrict move within boundaries.
+       within: false
+});
+=====*/
+
+dojo.declare("dojo.dnd.move.constrainedMoveable", dojo.dnd.Moveable, {
+       // object attributes (for markup)
+       constraints: function(){},
+       within: false,
+
+       constructor: function(node, params){
                // summary:
-               //              hooks into this.attr to provide a mechanism for getting the
-               //              option items for the current value of the widget.
-               return this.getOptions(this.get("value"));
+               //              an object that makes a node moveable
+               // node: Node
+               //              a node (or node's id) to be moved
+               // params: dojo.dnd.move.__constrainedMoveableArgs?
+               //              an optional object with additional parameters;
+               //              the rest is passed to the base class
+               if(!params){ params = {}; }
+               this.constraints = params.constraints;
+               this.within = params.within;
        },
-
-       _pseudoLoadChildren: function(/* item[] */ items){
+       onFirstMove: function(/* dojo.dnd.Mover */ mover){
                // summary:
-               //              a function that will "fake" loading children, if needed, and
-               //              if we have set to not load children until the widget opens.
-               // items:
-               //              An array of items that will be loaded, when needed
+               //              called during the very first move notification;
+               //              can be used to initialize coordinates, can be overwritten.
+               var c = this.constraintBox = this.constraints.call(this, mover);
+               c.r = c.l + c.w;
+               c.b = c.t + c.h;
+               if(this.within){
+                       var mb = dojo._getMarginSize(mover.node);
+                       c.r -= mb.w;
+                       c.b -= mb.h;
+               }
        },
-
-       onSetStore: function(){
+       onMove: function(/* dojo.dnd.Mover */ mover, /* Object */ leftTop){
                // summary:
-               //              a function that can be connected to in order to receive a
-               //              notification that the store has finished loading and all options
-               //              from that store are available
+               //              called during every move notification;
+               //              should actually move the node; can be overwritten.
+               var c = this.constraintBox, s = mover.node.style;
+               this.onMoving(mover, leftTop);
+               leftTop.l = leftTop.l < c.l ? c.l : c.r < leftTop.l ? c.r : leftTop.l;
+               leftTop.t = leftTop.t < c.t ? c.t : c.b < leftTop.t ? c.b : leftTop.t;
+               s.left = leftTop.l + "px";
+               s.top  = leftTop.t + "px";
+               this.onMoved(mover, leftTop);
        }
 });
 
-}
-
-if(!dojo._hasResource["dijit._KeyNavContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit._KeyNavContainer"] = true;
-dojo.provide("dijit._KeyNavContainer");
-
-
-dojo.declare("dijit._KeyNavContainer",
-       dijit._Container,
-       {
-
-               // summary:
-               //              A _Container with keyboard navigation of its children.
-               // description:
-               //              To use this mixin, call connectKeyNavHandlers() in
-               //              postCreate() and call startupKeyNavChildren() in startup().
-               //              It provides normalized keyboard and focusing code for Container
-               //              widgets.
 /*=====
-               // focusedChild: [protected] Widget
-               //              The currently focused child widget, or null if there isn't one
-               focusedChild: null,
+dojo.declare("dojo.dnd.move.__boxConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
+       // box: Object
+       //              a constraint box
+       box: {}
+});
 =====*/
 
-               // tabIndex: Integer
-               //              Tab index of the container; same as HTML tabIndex attribute.
-               //              Note then when user tabs into the container, focus is immediately
-               //              moved to the first item in the container.
-               tabIndex: "0",
-
-               _keyNavCodes: {},
+dojo.declare("dojo.dnd.move.boxConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+       // box:
+       //              object attributes (for markup)
+       box: {},
 
-               connectKeyNavHandlers: function(/*dojo.keys[]*/ prevKeyCodes, /*dojo.keys[]*/ nextKeyCodes){
-                       // summary:
-                       //              Call in postCreate() to attach the keyboard handlers
-                       //              to the container.
-                       // preKeyCodes: dojo.keys[]
-                       //              Key codes for navigating to the previous child.
-                       // nextKeyCodes: dojo.keys[]
-                       //              Key codes for navigating to the next child.
-                       // tags:
-                       //              protected
-
-                       var keyCodes = (this._keyNavCodes = {});
-                       var prev = dojo.hitch(this, this.focusPrev);
-                       var next = dojo.hitch(this, this.focusNext);
-                       dojo.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; });
-                       dojo.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; });
-                       this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
-                       this.connect(this.domNode, "onfocus", "_onContainerFocus");
-               },
-
-               startupKeyNavChildren: function(){
-                       // summary:
-                       //              Call in startup() to set child tabindexes to -1
-                       // tags:
-                       //              protected
-                       dojo.forEach(this.getChildren(), dojo.hitch(this, "_startupChild"));
-               },
+       constructor: function(node, params){
+               // summary:
+               //              an object, which makes a node moveable
+               // node: Node
+               //              a node (or node's id) to be moved
+               // params: dojo.dnd.move.__boxConstrainedMoveableArgs?
+               //              an optional object with parameters
+               var box = params && params.box;
+               this.constraints = function(){ return box; };
+       }
+});
 
-               addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
-                       // summary:
-                       //              Add a child to our _Container
-                       dijit._KeyNavContainer.superclass.addChild.apply(this, arguments);
-                       this._startupChild(widget);
-               },
+/*=====
+dojo.declare("dojo.dnd.move.__parentConstrainedMoveableArgs", [dojo.dnd.move.__constrainedMoveableArgs], {
+       // area: String
+       //              A parent's area to restrict the move.
+       //              Can be "margin", "border", "padding", or "content".
+       area: ""
+});
+=====*/
 
-               focus: function(){
-                       // summary:
-                       //              Default focus() implementation: focus the first child.
-                       this.focusFirstChild();
-               },
+dojo.declare("dojo.dnd.move.parentConstrainedMoveable", dojo.dnd.move.constrainedMoveable, {
+       // area:
+       //              object attributes (for markup)
+       area: "content",
 
-               focusFirstChild: function(){
-                       // summary:
-                       //              Focus the first focusable child in the container.
-                       // tags:
-                       //              protected
-                       var child = this._getFirstFocusableChild();
-                       if(child){ // edge case: Menu could be empty or hidden
-                               this.focusChild(child);
+       constructor: function(node, params){
+               // summary:
+               //              an object, which makes a node moveable
+               // node: Node
+               //              a node (or node's id) to be moved
+               // params: dojo.dnd.move.__parentConstrainedMoveableArgs?
+               //              an optional object with parameters
+               var area = params && params.area;
+               this.constraints = function(){
+                       var n = this.node.parentNode,
+                               s = dojo.getComputedStyle(n),
+                               mb = dojo._getMarginBox(n, s);
+                       if(area == "margin"){
+                               return mb;      // Object
                        }
-               },
-
-               focusNext: function(){
-                       // summary:
-                       //              Focus the next widget
-                       // tags:
-                       //              protected
-                       var child = this._getNextFocusableChild(this.focusedChild, 1);
-                       this.focusChild(child);
-               },
-
-               focusPrev: function(){
-                       // summary:
-                       //              Focus the last focusable node in the previous widget
-                       //              (ex: go to the ComboButton icon section rather than button section)
-                       // tags:
-                       //              protected
-                       var child = this._getNextFocusableChild(this.focusedChild, -1);
-                       this.focusChild(child, true);
-               },
-
-               focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
-                       // summary:
-                       //              Focus widget.
-                       // widget:
-                       //              Reference to container's child widget
-                       // last:
-                       //              If true and if widget has multiple focusable nodes, focus the
-                       //              last one instead of the first one
-                       // tags:
-                       //              protected
-                       
-                       if(this.focusedChild && widget !== this.focusedChild){
-                               this._onChildBlur(this.focusedChild);
+                       var t = dojo._getMarginExtents(n, s);
+                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+                       if(area == "border"){
+                               return mb;      // Object
                        }
-                       widget.focus(last ? "end" : "start");
-                       this.focusedChild = widget;
-               },
-
-               _startupChild: function(/*dijit._Widget*/ widget){
-                       // summary:
-                       //              Setup for each child widget
-                       // description:
-                       //              Sets tabIndex=-1 on each child, so that the tab key will 
-                       //              leave the container rather than visiting each child.
-                       // tags:
-                       //              private
-                       
-                       widget.set("tabIndex", "-1");
-                       
-                       this.connect(widget, "_onFocus", function(){
-                               // Set valid tabIndex so tabbing away from widget goes to right place, see #10272
-                               widget.set("tabIndex", this.tabIndex);
-                       });
-                       this.connect(widget, "_onBlur", function(){
-                               widget.set("tabIndex", "-1");
-                       });
-               },
-
-               _onContainerFocus: function(evt){
-                       // summary:
-                       //              Handler for when the container gets focus
-                       // description:
-                       //              Initially the container itself has a tabIndex, but when it gets
-                       //              focus, switch focus to first child...
-                       // tags:
-                       //              private
-
-                       // Note that we can't use _onFocus() because switching focus from the
-                       // _onFocus() handler confuses the focus.js code
-                       // (because it causes _onFocusNode() to be called recursively)
+                       t = dojo._getBorderExtents(n, s);
+                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+                       if(area == "padding"){
+                               return mb;      // Object
+                       }
+                       t = dojo._getPadExtents(n, s);
+                       mb.l += t.l, mb.t += t.t, mb.w -= t.w, mb.h -= t.h;
+                       return mb;      // Object
+               };
+       }
+});
 
-                       // focus bubbles on Firefox,
-                       // so just make sure that focus has really gone to the container
-                       if(evt.target !== this.domNode){ return; }
+// patching functions one level up for compatibility
 
-                       this.focusFirstChild();
+dojo.dnd.constrainedMover = dojo.dnd.move.constrainedMover;
+dojo.dnd.boxConstrainedMover = dojo.dnd.move.boxConstrainedMover;
+dojo.dnd.parentConstrainedMover = dojo.dnd.move.parentConstrainedMover;
 
-                       // and then set the container's tabIndex to -1,
-                       // (don't remove as that breaks Safari 4)
-                       // so that tab or shift-tab will go to the fields after/before
-                       // the container, rather than the container itself
-                       dojo.attr(this.domNode, "tabIndex", "-1");
-               },
+return dojo.dnd.move;
+});
 
-               _onBlur: function(evt){
-                       // When focus is moved away the container, and its descendant (popup) widgets,
-                       // then restore the container's tabIndex so that user can tab to it again.
-                       // Note that using _onBlur() so that this doesn't happen when focus is shifted
-                       // to one of my child widgets (typically a popup)
-                       if(this.tabIndex){
-                               dojo.attr(this.domNode, "tabIndex", this.tabIndex);
-                       }
-                       this.inherited(arguments);
-               },
+},
+'dijit/_WidgetBase':function(){
+define("dijit/_WidgetBase", [
+       "require",                      // require.toUrl
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/aspect",
+       "dojo/_base/config", // config.blankGif
+       "dojo/_base/connect", // connect.connect
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.byId
+       "dojo/dom-attr", // domAttr.set domAttr.remove
+       "dojo/dom-class", // domClass.add domClass.replace
+       "dojo/dom-construct", // domConstruct.create domConstruct.destroy domConstruct.place
+       "dojo/dom-geometry",    // isBodyLtr
+       "dojo/dom-style", // domStyle.set, domStyle.get
+       "dojo/_base/kernel",
+       "dojo/_base/lang", // mixin(), isArray(), etc.
+       "dojo/on",
+       "dojo/ready",
+       "dojo/Stateful", // Stateful
+       "dojo/topic",
+       "dojo/_base/window", // win.doc.createTextNode
+       "./registry"    // registry.getUniqueId(), registry.findWidgets()
+], function(require, array, aspect, config, connect, declare,
+                       dom, domAttr, domClass, domConstruct, domGeometry, domStyle, kernel,
+                       lang, on, ready, Stateful, topic, win, registry){
 
-               _onContainerKeypress: function(evt){
-                       // summary:
-                       //              When a key is pressed, if it's an arrow key etc. then
-                       //              it's handled here.
-                       // tags:
-                       //              private
-                       if(evt.ctrlKey || evt.altKey){ return; }
-                       var func = this._keyNavCodes[evt.charOrCode];
-                       if(func){
-                               func();
-                               dojo.stopEvent(evt);
-                       }
-               },
+/*=====
+var Stateful = dojo.Stateful;
+=====*/
 
-               _onChildBlur: function(/*dijit._Widget*/ widget){
-                       // summary:
-                       //              Called when focus leaves a child widget to go
-                       //              to a sibling widget.
-                       // tags:
-                       //              protected
-               },
+// module:
+//             dijit/_WidgetBase
+// summary:
+//             Future base class for all Dijit widgets.
 
-               _getFirstFocusableChild: function(){
-                       // summary:
-                       //              Returns first child that can be focused
-                       return this._getNextFocusableChild(null, 1);    // dijit._Widget
-               },
+// For back-compat, remove in 2.0.
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/_base/manager"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
 
-               _getNextFocusableChild: function(child, dir){
-                       // summary:
-                       //              Returns the next or previous focusable child, compared
-                       //              to "child"
-                       // child: Widget
-                       //              The current widget
-                       // dir: Integer
-                       //              * 1 = after
-                       //              * -1 = before
-                       if(child){
-                               child = this._getSiblingOfChild(child, dir);
-                       }
-                       var children = this.getChildren();
-                       for(var i=0; i < children.length; i++){
-                               if(!child){
-                                       child = children[(dir>0) ? 0 : (children.length-1)];
-                               }
-                               if(child.isFocusable()){
-                                       return child;   // dijit._Widget
-                               }
-                               child = this._getSiblingOfChild(child, dir);
-                       }
-                       // no focusable child found
-                       return null;    // dijit._Widget
-               }
+// Nested hash listing attributes for each tag, all strings in lowercase.
+// ex: {"div": {"style": true, "tabindex" true}, "form": { ...
+var tagAttrs = {};
+function getAttrs(obj){
+       var ret = {};
+       for(var attr in obj){
+               ret[attr.toLowerCase()] = true;
        }
-);
-
+       return ret;
 }
 
-if(!dojo._hasResource["dijit.MenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.MenuItem"] = true;
-dojo.provide("dijit.MenuItem");
+function nonEmptyAttrToDom(attr){
+       // summary:
+       //              Returns a setter function that copies the attribute to this.domNode,
+       //              or removes the attribute from this.domNode, depending on whether the
+       //              value is defined or not.
+       return function(val){
+               domAttr[val ? "set" : "remove"](this.domNode, attr, val);
+               this._set(attr, val);
+       };
+}
 
+return declare("dijit._WidgetBase", Stateful, {
+       // summary:
+       //              Future base class for all Dijit widgets.
+       // description:
+       //              Future base class for all Dijit widgets.
+       //              _Widget extends this class adding support for various features needed by desktop.
+       //
+       //              Provides stubs for widget lifecycle methods for subclasses to extend, like postMixInProperties(), buildRendering(),
+       //              postCreate(), startup(), and destroy(), and also public API methods like set(), get(), and watch().
+       //
+       //              Widgets can provide custom setters/getters for widget attributes, which are called automatically by set(name, value).
+       //              For an attribute XXX, define methods _setXXXAttr() and/or _getXXXAttr().
+       //
+       //              _setXXXAttr can also be a string/hash/array mapping from a widget attribute XXX to the widget's DOMNodes:
+       //
+       //              - DOM node attribute
+       // |            _setFocusAttr: {node: "focusNode", type: "attribute"}
+       // |            _setFocusAttr: "focusNode"      (shorthand)
+       // |            _setFocusAttr: ""               (shorthand, maps to this.domNode)
+       //              Maps this.focus to this.focusNode.focus, or (last example) this.domNode.focus
+       //
+       //              - DOM node innerHTML
+       //      |               _setTitleAttr: { node: "titleNode", type: "innerHTML" }
+       //              Maps this.title to this.titleNode.innerHTML
+       //
+       //              - DOM node innerText
+       //      |               _setTitleAttr: { node: "titleNode", type: "innerText" }
+       //              Maps this.title to this.titleNode.innerText
+       //
+       //              - DOM node CSS class
+       // |            _setMyClassAttr: { node: "domNode", type: "class" }
+       //              Maps this.myClass to this.domNode.className
+       //
+       //              If the value of _setXXXAttr is an array, then each element in the array matches one of the
+       //              formats of the above list.
+       //
+       //              If the custom setter is null, no action is performed other than saving the new value
+       //              in the widget (in this).
+       //
+       //              If no custom setter is defined for an attribute, then it will be copied
+       //              to this.focusNode (if the widget defines a focusNode), or this.domNode otherwise.
+       //              That's only done though for attributes that match DOMNode attributes (title,
+       //              alt, aria-labelledby, etc.)
 
+       // id: [const] String
+       //              A unique, opaque ID string that can be assigned by users or by the
+       //              system. If the developer passes an ID which is known not to be
+       //              unique, the specified ID is ignored and the system-generated ID is
+       //              used instead.
+       id: "",
+       _setIdAttr: "domNode",  // to copy to this.domNode even for auto-generated id's
 
+       // lang: [const] String
+       //              Rarely used.  Overrides the default Dojo locale used to render this widget,
+       //              as defined by the [HTML LANG](http://www.w3.org/TR/html401/struct/dirlang.html#adef-lang) attribute.
+       //              Value must be among the list of locales specified during by the Dojo bootstrap,
+       //              formatted according to [RFC 3066](http://www.ietf.org/rfc/rfc3066.txt) (like en-us).
+       lang: "",
+       // set on domNode even when there's a focus node.   but don't set lang="", since that's invalid.
+       _setLangAttr: nonEmptyAttrToDom("lang"),
 
+       // dir: [const] String
+       //              Bi-directional support, as defined by the [HTML DIR](http://www.w3.org/TR/html401/struct/dirlang.html#adef-dir)
+       //              attribute. Either left-to-right "ltr" or right-to-left "rtl".  If undefined, widgets renders in page's
+       //              default direction.
+       dir: "",
+       // set on domNode even when there's a focus node.   but don't set dir="", since that's invalid.
+       _setDirAttr: nonEmptyAttrToDom("dir"),  // to set on domNode even when there's a focus node
+
+       // textDir: String
+       //              Bi-directional support, the main variable which is responsible for the direction of the text.
+       //              The text direction can be different than the GUI direction by using this parameter in creation
+       //              of a widget.
+       //              Allowed values:
+       //                      1. "ltr"
+       //                      2. "rtl"
+       //                      3. "auto" - contextual the direction of a text defined by first strong letter.
+       //              By default is as the page direction.
+       textDir: "",
 
+       // class: String
+       //              HTML class attribute
+       "class": "",
+       _setClassAttr: { node: "domNode", type: "class" },
 
-dojo.declare("dijit.MenuItem",
-               [dijit._Widget, dijit._Templated, dijit._Contained, dijit._CssStateMixin],
-               {
-               // summary:
-               //              A line item in a Menu Widget
+       // style: String||Object
+       //              HTML style attributes as cssText string or name/value hash
+       style: "",
 
-               // Make 3 columns
-               // icon, label, and expand arrow (BiDi-dependent) indicating sub-menu
-               templateString: dojo.cache("dijit", "templates/MenuItem.html", "<tr class=\"dijitReset dijitMenuItem\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitem\" tabIndex=\"-1\"\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" waiRole=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon dijitMenuItemIcon\" dojoAttachPoint=\"iconNode\"/>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" dojoAttachPoint=\"containerNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" dojoAttachPoint=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" waiRole=\"presentation\">\n\t\t<div dojoAttachPoint=\"arrowWrapper\" style=\"visibility: hidden\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuExpand\"/>\n\t\t\t<span class=\"dijitMenuExpandA11y\">+</span>\n\t\t</div>\n\t</td>\n</tr>\n"),
+       // title: String
+       //              HTML title attribute.
+       //
+       //              For form widgets this specifies a tooltip to display when hovering over
+       //              the widget (just like the native HTML title attribute).
+       //
+       //              For TitlePane or for when this widget is a child of a TabContainer, AccordionContainer,
+       //              etc., it's used to specify the tab label, accordion pane title, etc.
+       title: "",
 
-               attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-                       label: { node: "containerNode", type: "innerHTML" },
-                       iconClass: { node: "iconNode", type: "class" }
-               }),
+       // tooltip: String
+       //              When this widget's title attribute is used to for a tab label, accordion pane title, etc.,
+       //              this specifies the tooltip to appear when the mouse is hovered over that text.
+       tooltip: "",
 
-               baseClass: "dijitMenuItem",
+       // baseClass: [protected] String
+       //              Root CSS class of the widget (ex: dijitTextBox), used to construct CSS classes to indicate
+       //              widget state.
+       baseClass: "",
 
-               // label: String
-               //              Menu text
-               label: '',
+       // srcNodeRef: [readonly] DomNode
+       //              pointer to original DOM node
+       srcNodeRef: null,
 
-               // iconClass: String
-               //              Class to apply to DOMNode to make it display an icon.
-               iconClass: "",
+       // domNode: [readonly] DomNode
+       //              This is our visible representation of the widget! Other DOM
+       //              Nodes may by assigned to other properties, usually through the
+       //              template system's data-dojo-attach-point syntax, but the domNode
+       //              property is the canonical "top level" node in widget UI.
+       domNode: null,
 
-               // accelKey: String
-               //              Text for the accelerator (shortcut) key combination.
-               //              Note that although Menu can display accelerator keys there
-               //              is no infrastructure to actually catch and execute these
-               //              accelerators.
-               accelKey: "",
+       // containerNode: [readonly] DomNode
+       //              Designates where children of the source DOM node will be placed.
+       //              "Children" in this case refers to both DOM nodes and widgets.
+       //              For example, for myWidget:
+       //
+       //              |       <div data-dojo-type=myWidget>
+       //              |               <b> here's a plain DOM node
+       //              |               <span data-dojo-type=subWidget>and a widget</span>
+       //              |               <i> and another plain DOM node </i>
+       //              |       </div>
+       //
+       //              containerNode would point to:
+       //
+       //              |               <b> here's a plain DOM node
+       //              |               <span data-dojo-type=subWidget>and a widget</span>
+       //              |               <i> and another plain DOM node </i>
+       //
+       //              In templated widgets, "containerNode" is set via a
+       //              data-dojo-attach-point assignment.
+       //
+       //              containerNode must be defined for any widget that accepts innerHTML
+       //              (like ContentPane or BorderContainer or even Button), and conversely
+       //              is null for widgets that don't, like TextBox.
+       containerNode: null,
 
-               // disabled: Boolean
-               //              If true, the menu item is disabled.
-               //              If false, the menu item is enabled.
-               disabled: false,
+/*=====
+       // _started: Boolean
+       //              startup() has completed.
+       _started: false,
+=====*/
 
-               _fillContent: function(/*DomNode*/ source){
-                       // If button label is specified as srcNodeRef.innerHTML rather than
-                       // this.params.label, handle it here.
-                       if(source && !("label" in this.params)){
-                               this.set('label', source.innerHTML);
-                       }
-               },
+       // attributeMap: [protected] Object
+       //              Deprecated.   Instead of attributeMap, widget should have a _setXXXAttr attribute
+       //              for each XXX attribute to be mapped to the DOM.
+       //
+       //              attributeMap sets up a "binding" between attributes (aka properties)
+       //              of the widget and the widget's DOM.
+       //              Changes to widget attributes listed in attributeMap will be
+       //              reflected into the DOM.
+       //
+       //              For example, calling set('title', 'hello')
+       //              on a TitlePane will automatically cause the TitlePane's DOM to update
+       //              with the new title.
+       //
+       //              attributeMap is a hash where the key is an attribute of the widget,
+       //              and the value reflects a binding to a:
+       //
+       //              - DOM node attribute
+       // |            focus: {node: "focusNode", type: "attribute"}
+       //              Maps this.focus to this.focusNode.focus
+       //
+       //              - DOM node innerHTML
+       //      |               title: { node: "titleNode", type: "innerHTML" }
+       //              Maps this.title to this.titleNode.innerHTML
+       //
+       //              - DOM node innerText
+       //      |               title: { node: "titleNode", type: "innerText" }
+       //              Maps this.title to this.titleNode.innerText
+       //
+       //              - DOM node CSS class
+       // |            myClass: { node: "domNode", type: "class" }
+       //              Maps this.myClass to this.domNode.className
+       //
+       //              If the value is an array, then each element in the array matches one of the
+       //              formats of the above list.
+       //
+       //              There are also some shorthands for backwards compatibility:
+       //              - string --> { node: string, type: "attribute" }, for example:
+       //      |       "focusNode" ---> { node: "focusNode", type: "attribute" }
+       //              - "" --> { node: "domNode", type: "attribute" }
+       attributeMap: {},
 
-               postCreate: function(){
-                       this.inherited(arguments);
-                       dojo.setSelectable(this.domNode, false);
-                       var label = this.id+"_text";
-                       dojo.attr(this.containerNode, "id", label);
-                       if(this.accelKeyNode){
-                               dojo.attr(this.accelKeyNode, "id", this.id + "_accel");
-                               label += " " + this.id + "_accel";
-                       }
-                       dijit.setWaiState(this.domNode, "labelledby", label);
-               },
+       // _blankGif: [protected] String
+       //              Path to a blank 1x1 image.
+       //              Used by <img> nodes in templates that really get their image via CSS background-image.
+       _blankGif: config.blankGif || require.toUrl("dojo/resources/blank.gif"),
 
-               _onHover: function(){
-                       // summary:
-                       //              Handler when mouse is moved onto menu item
-                       // tags:
-                       //              protected
-                       this.getParent().onItemHover(this);
-               },
+       //////////// INITIALIZATION METHODS ///////////////////////////////////////
 
-               _onUnhover: function(){
-                       // summary:
-                       //              Handler when mouse is moved off of menu item,
-                       //              possibly to a child menu, or maybe to a sibling
-                       //              menuitem or somewhere else entirely.
-                       // tags:
-                       //              protected
+       postscript: function(/*Object?*/params, /*DomNode|String*/srcNodeRef){
+               // summary:
+               //              Kicks off widget instantiation.  See create() for details.
+               // tags:
+               //              private
+               this.create(params, srcNodeRef);
+       },
 
-                       // if we are unhovering the currently selected item
-                       // then unselect it
-                       this.getParent().onItemUnhover(this);
+       create: function(/*Object?*/params, /*DomNode|String?*/srcNodeRef){
+               // summary:
+               //              Kick off the life-cycle of a widget
+               // params:
+               //              Hash of initialization parameters for widget, including
+               //              scalar values (like title, duration etc.) and functions,
+               //              typically callbacks like onClick.
+               // srcNodeRef:
+               //              If a srcNodeRef (DOM node) is specified:
+               //                      - use srcNodeRef.innerHTML as my contents
+               //                      - if this is a behavioral widget then apply behavior
+               //                        to that srcNodeRef
+               //                      - otherwise, replace srcNodeRef with my generated DOM
+               //                        tree
+               // description:
+               //              Create calls a number of widget methods (postMixInProperties, buildRendering, postCreate,
+               //              etc.), some of which of you'll want to override. See http://dojotoolkit.org/reference-guide/dijit/_WidgetBase.html
+               //              for a discussion of the widget creation lifecycle.
+               //
+               //              Of course, adventurous developers could override create entirely, but this should
+               //              only be done as a last resort.
+               // tags:
+               //              private
 
-                       // _onUnhover() is called when the menu is hidden (collapsed), due to clicking
-                       // a MenuItem and having it execut.  When that happens, FF and IE don't generate
-                       // an onmouseout event for the MenuItem, so give _CssStateMixin some help
-                       this._hovering = false;
-                       this._setStateClass();
-               },
+               // store pointer to original DOM tree
+               this.srcNodeRef = dom.byId(srcNodeRef);
 
-               _onClick: function(evt){
-                       // summary:
-                       //              Internal handler for click events on MenuItem.
-                       // tags:
-                       //              private
-                       this.getParent().onItemClick(this, evt);
-                       dojo.stopEvent(evt);
-               },
+               // For garbage collection.  An array of listener handles returned by this.connect() / this.subscribe()
+               this._connects = [];
 
-               onClick: function(/*Event*/ evt){
-                       // summary:
-                       //              User defined function to handle clicks
-                       // tags:
-                       //              callback
-               },
+               // For widgets internal to this widget, invisible to calling code
+               this._supportingWidgets = [];
 
-               focus: function(){
-                       // summary:
-                       //              Focus on this MenuItem
-                       try{
-                               if(dojo.isIE == 8){
-                                       // needed for IE8 which won't scroll TR tags into view on focus yet calling scrollIntoView creates flicker (#10275)
-                                       this.containerNode.focus();
-                               }
-                               dijit.focus(this.focusNode);
-                       }catch(e){
-                               // this throws on IE (at least) in some scenarios
-                       }
-               },
+               // this is here for back-compat, remove in 2.0 (but check NodeList-instantiate.html test)
+               if(this.srcNodeRef && (typeof this.srcNodeRef.id == "string")){ this.id = this.srcNodeRef.id; }
 
-               _onFocus: function(){
-                       // summary:
-                       //              This is called by the focus manager when focus
-                       //              goes to this MenuItem or a child menu.
-                       // tags:
-                       //              protected
-                       this._setSelected(true);
-                       this.getParent()._onItemFocus(this);
+               // mix in our passed parameters
+               if(params){
+                       this.params = params;
+                       lang.mixin(this, params);
+               }
+               this.postMixInProperties();
 
-                       this.inherited(arguments);
-               },
+               // generate an id for the widget if one wasn't specified
+               // (be sure to do this before buildRendering() because that function might
+               // expect the id to be there.)
+               if(!this.id){
+                       this.id = registry.getUniqueId(this.declaredClass.replace(/\./g,"_"));
+               }
+               registry.add(this);
 
-               _setSelected: function(selected){
-                       // summary:
-                       //              Indicate that this node is the currently selected one
-                       // tags:
-                       //              private
+               this.buildRendering();
 
-                       /***
-                        * TODO: remove this method and calls to it, when _onBlur() is working for MenuItem.
-                        * Currently _onBlur() gets called when focus is moved from the MenuItem to a child menu.
-                        * That's not supposed to happen, but the problem is:
-                        * In order to allow dijit.popup's getTopPopup() to work,a sub menu's popupParent
-                        * points to the parent Menu, bypassing the parent MenuItem... thus the
-                        * MenuItem is not in the chain of active widgets and gets a premature call to
-                        * _onBlur()
-                        */
+               if(this.domNode){
+                       // Copy attributes listed in attributeMap into the [newly created] DOM for the widget.
+                       // Also calls custom setters for all attributes with custom setters.
+                       this._applyAttributes();
 
-                       dojo.toggleClass(this.domNode, "dijitMenuItemSelected", selected);
-               },
+                       // If srcNodeRef was specified, then swap out original srcNode for this widget's DOM tree.
+                       // For 2.0, move this after postCreate().  postCreate() shouldn't depend on the
+                       // widget being attached to the DOM since it isn't when a widget is created programmatically like
+                       // new MyWidget({}).   See #11635.
+                       var source = this.srcNodeRef;
+                       if(source && source.parentNode && this.domNode !== source){
+                               source.parentNode.replaceChild(this.domNode, source);
+                       }
+               }
 
-               setLabel: function(/*String*/ content){
-                       // summary:
-                       //              Deprecated.   Use set('label', ...) instead.
-                       // tags:
-                       //              deprecated
-                       dojo.deprecated("dijit.MenuItem.setLabel() is deprecated.  Use set('label', ...) instead.", "", "2.0");
-                       this.set("label", content);
-               },
+               if(this.domNode){
+                       // Note: for 2.0 may want to rename widgetId to dojo._scopeName + "_widgetId",
+                       // assuming that dojo._scopeName even exists in 2.0
+                       this.domNode.setAttribute("widgetId", this.id);
+               }
+               this.postCreate();
 
-               setDisabled: function(/*Boolean*/ disabled){
-                       // summary:
-                       //              Deprecated.   Use set('disabled', bool) instead.
-                       // tags:
-                       //              deprecated
-                       dojo.deprecated("dijit.Menu.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
-                       this.set('disabled', disabled);
-               },
-               _setDisabledAttr: function(/*Boolean*/ value){
-                       // summary:
-                       //              Hook for attr('disabled', ...) to work.
-                       //              Enable or disable this menu item.
-                       this.disabled = value;
-                       dijit.setWaiState(this.focusNode, 'disabled', value ? 'true' : 'false');
-               },
-               _setAccelKeyAttr: function(/*String*/ value){
-                       // summary:
-                       //              Hook for attr('accelKey', ...) to work.
-                       //              Set accelKey on this menu item.
-                       this.accelKey=value;
-
-                       this.accelKeyNode.style.display=value?"":"none";
-                       this.accelKeyNode.innerHTML=value;
-                       //have to use colSpan to make it work in IE
-                       dojo.attr(this.containerNode,'colSpan',value?"1":"2");
+               // If srcNodeRef has been processed and removed from the DOM (e.g. TemplatedWidget) then delete it to allow GC.
+               if(this.srcNodeRef && !this.srcNodeRef.parentNode){
+                       delete this.srcNodeRef;
                }
-       });
-
-}
-
-if(!dojo._hasResource["dijit.PopupMenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.PopupMenuItem"] = true;
-dojo.provide("dijit.PopupMenuItem");
-
-
-
-dojo.declare("dijit.PopupMenuItem",
-               dijit.MenuItem,
-               {
-               _fillContent: function(){
-                       // summary:
-                       //              When Menu is declared in markup, this code gets the menu label and
-                       //              the popup widget from the srcNodeRef.
-                       // description:
-                       //              srcNodeRefinnerHTML contains both the menu item text and a popup widget
-                       //              The first part holds the menu item text and the second part is the popup
-                       // example:
-                       // |    <div dojoType="dijit.PopupMenuItem">
-                       // |            <span>pick me</span>
-                       // |            <popup> ... </popup>
-                       // |    </div>
-                       // tags:
-                       //              protected
-
-                       if(this.srcNodeRef){
-                               var nodes = dojo.query("*", this.srcNodeRef);
-                               dijit.PopupMenuItem.superclass._fillContent.call(this, nodes[0]);
-
-                               // save pointer to srcNode so we can grab the drop down widget after it's instantiated
-                               this.dropDownContainer = this.srcNodeRef;
-                       }
-               },
 
-               startup: function(){
-                       if(this._started){ return; }
-                       this.inherited(arguments);
+               this._created = true;
+       },
 
-                       // we didn't copy the dropdown widget from the this.srcNodeRef, so it's in no-man's
-                       // land now.  move it to dojo.doc.body.
-                       if(!this.popup){
-                               var node = dojo.query("[widgetId]", this.dropDownContainer)[0];
-                               this.popup = dijit.byNode(node);
-                       }
-                       dojo.body().appendChild(this.popup.domNode);
-                       this.popup.startup();
+       _applyAttributes: function(){
+               // summary:
+               //              Step during widget creation to copy  widget attributes to the
+               //              DOM according to attributeMap and _setXXXAttr objects, and also to call
+               //              custom _setXXXAttr() methods.
+               //
+               //              Skips over blank/false attribute values, unless they were explicitly specified
+               //              as parameters to the widget, since those are the default anyway,
+               //              and setting tabIndex="" is different than not setting tabIndex at all.
+               //
+               //              For backwards-compatibility reasons attributeMap overrides _setXXXAttr when
+               //              _setXXXAttr is a hash/string/array, but _setXXXAttr as a functions override attributeMap.
+               // tags:
+               //              private
 
-                       this.popup.domNode.style.display="none";
-                       if(this.arrowWrapper){
-                               dojo.style(this.arrowWrapper, "visibility", "");
+               // Get list of attributes where this.set(name, value) will do something beyond
+               // setting this[name] = value.  Specifically, attributes that have:
+               //              - associated _setXXXAttr() method/hash/string/array
+               //              - entries in attributeMap.
+               var ctor = this.constructor,
+                       list = ctor._setterAttrs;
+               if(!list){
+                       list = (ctor._setterAttrs = []);
+                       for(var attr in this.attributeMap){
+                               list.push(attr);
                        }
-                       dijit.setWaiState(this.focusNode, "haspopup", "true");
-               },
 
-               destroyDescendants: function(){
-                       if(this.popup){
-                               // Destroy the popup, unless it's already been destroyed.  This can happen because
-                               // the popup is a direct child of <body> even though it's logically my child.
-                               if(!this.popup._destroyed){
-                                       this.popup.destroyRecursive();
+                       var proto = ctor.prototype;
+                       for(var fxName in proto){
+                               if(fxName in this.attributeMap){ continue; }
+                               var setterName = "_set" + fxName.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); }) + "Attr";
+                               if(setterName in proto){
+                                       list.push(fxName);
                                }
-                               delete this.popup;
                        }
-                       this.inherited(arguments);
                }
-       });
-
-
-}
-
-if(!dojo._hasResource["dijit.CheckedMenuItem"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.CheckedMenuItem"] = true;
-dojo.provide("dijit.CheckedMenuItem");
-
 
+               // Call this.set() for each attribute that was either specified as parameter to constructor,
+               // or was found above and has a default non-null value.   For correlated attributes like value and displayedValue, the one
+               // specified as a parameter should take precedence, so apply attributes in this.params last.
+               // Particularly important for new DateTextBox({displayedValue: ...}) since DateTextBox's default value is
+               // NaN and thus is not ignored like a default value of "".
+               array.forEach(list, function(attr){
+                       if(this.params && attr in this.params){
+                               // skip this one, do it below
+                       }else if(this[attr]){
+                               this.set(attr, this[attr]);
+                       }
+               }, this);
+               for(var param in this.params){
+                       this.set(param, this[param]);
+               }
+       },
 
-dojo.declare("dijit.CheckedMenuItem",
-               dijit.MenuItem,
-               {
+       postMixInProperties: function(){
                // summary:
-               //              A checkbox-like menu item for toggling on and off
-
-               templateString: dojo.cache("dijit", "templates/CheckedMenuItem.html", "<tr class=\"dijitReset dijitMenuItem\" dojoAttachPoint=\"focusNode\" waiRole=\"menuitemcheckbox\" tabIndex=\"-1\"\n\t\tdojoAttachEvent=\"onmouseenter:_onHover,onmouseleave:_onUnhover,ondijitclick:_onClick\">\n\t<td class=\"dijitReset dijitMenuItemIconCell\" waiRole=\"presentation\">\n\t\t<img src=\"${_blankGif}\" alt=\"\" class=\"dijitMenuItemIcon dijitCheckedMenuItemIcon\" dojoAttachPoint=\"iconNode\"/>\n\t\t<span class=\"dijitCheckedMenuItemIconChar\">&#10003;</span>\n\t</td>\n\t<td class=\"dijitReset dijitMenuItemLabel\" colspan=\"2\" dojoAttachPoint=\"containerNode,labelNode\"></td>\n\t<td class=\"dijitReset dijitMenuItemAccelKey\" style=\"display: none\" dojoAttachPoint=\"accelKeyNode\"></td>\n\t<td class=\"dijitReset dijitMenuArrowCell\" waiRole=\"presentation\">&nbsp;</td>\n</tr>\n"),
+               //              Called after the parameters to the widget have been read-in,
+               //              but before the widget template is instantiated. Especially
+               //              useful to set properties that are referenced in the widget
+               //              template.
+               // tags:
+               //              protected
+       },
 
-               // checked: Boolean
-               //              Our checked state
-               checked: false,
-               _setCheckedAttr: function(/*Boolean*/ checked){
-                       // summary:
-                       //              Hook so attr('checked', bool) works.
-                       //              Sets the class and state for the check box.
-                       dojo.toggleClass(this.domNode, "dijitCheckedMenuItemChecked", checked);
-                       dijit.setWaiState(this.domNode, "checked", checked);
-                       this.checked = checked;
-               },
+       buildRendering: function(){
+               // summary:
+               //              Construct the UI for this widget, setting this.domNode.
+               //              Most widgets will mixin `dijit._TemplatedMixin`, which implements this method.
+               // tags:
+               //              protected
 
-               onChange: function(/*Boolean*/ checked){
-                       // summary:
-                       //              User defined function to handle check/uncheck events
-                       // tags:
-                       //              callback
-               },
+               if(!this.domNode){
+                       // Create root node if it wasn't created by _Templated
+                       this.domNode = this.srcNodeRef || domConstruct.create('div');
+               }
 
-               _onClick: function(/*Event*/ e){
-                       // summary:
-                       //              Clicking this item just toggles its state
-                       // tags:
-                       //              private
-                       if(!this.disabled){
-                               this.set("checked", !this.checked);
-                               this.onChange(this.checked);
+               // baseClass is a single class name or occasionally a space-separated list of names.
+               // Add those classes to the DOMNode.  If RTL mode then also add with Rtl suffix.
+               // TODO: make baseClass custom setter
+               if(this.baseClass){
+                       var classes = this.baseClass.split(" ");
+                       if(!this.isLeftToRight()){
+                               classes = classes.concat( array.map(classes, function(name){ return name+"Rtl"; }));
                        }
-                       this.inherited(arguments);
+                       domClass.add(this.domNode, classes);
                }
-       });
-
-}
-
-if(!dojo._hasResource["dijit.MenuSeparator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.MenuSeparator"] = true;
-dojo.provide("dijit.MenuSeparator");
-
+       },
 
+       postCreate: function(){
+               // summary:
+               //              Processing after the DOM fragment is created
+               // description:
+               //              Called after the DOM fragment has been created, but not necessarily
+               //              added to the document.  Do not include any operations which rely on
+               //              node dimensions or placement.
+               // tags:
+               //              protected
+       },
 
+       startup: function(){
+               // summary:
+               //              Processing after the DOM fragment is added to the document
+               // description:
+               //              Called after a widget and its children have been created and added to the page,
+               //              and all related widgets have finished their create() cycle, up through postCreate().
+               //              This is useful for composite widgets that need to control or layout sub-widgets.
+               //              Many layout widgets can use this as a wiring phase.
+               if(this._started){ return; }
+               this._started = true;
+               array.forEach(this.getChildren(), function(obj){
+                       if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
+                               obj.startup();
+                               obj._started = true;
+                       }
+               });
+       },
 
+       //////////// DESTROY FUNCTIONS ////////////////////////////////
 
-dojo.declare("dijit.MenuSeparator",
-               [dijit._Widget, dijit._Templated, dijit._Contained],
-               {
+       destroyRecursive: function(/*Boolean?*/ preserveDom){
                // summary:
-               //              A line between two menu items
+               //              Destroy this widget and its descendants
+               // description:
+               //              This is the generic "destructor" function that all widget users
+               //              should call to cleanly discard with a widget. Once a widget is
+               //              destroyed, it is removed from the manager object.
+               // preserveDom:
+               //              If true, this method will leave the original DOM structure
+               //              alone of descendant Widgets. Note: This will NOT work with
+               //              dijit._Templated widgets.
 
-               templateString: dojo.cache("dijit", "templates/MenuSeparator.html", "<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>\n"),
+               this._beingDestroyed = true;
+               this.destroyDescendants(preserveDom);
+               this.destroy(preserveDom);
+       },
 
-               postCreate: function(){
-                       dojo.setSelectable(this.domNode, false);
-               },
+       destroy: function(/*Boolean*/ preserveDom){
+               // summary:
+               //              Destroy this widget, but not its descendants.
+               //              This method will, however, destroy internal widgets such as those used within a template.
+               // preserveDom: Boolean
+               //              If true, this method will leave the original DOM structure alone.
+               //              Note: This will not yet work with _Templated widgets
 
-               isFocusable: function(){
-                       // summary:
-                       //              Override to always return false
-                       // tags:
-                       //              protected
+               this._beingDestroyed = true;
+               this.uninitialize();
 
-                       return false; // Boolean
+               // remove this.connect() and this.subscribe() listeners
+               var c;
+               while((c = this._connects.pop())){
+                       c.remove();
                }
-       });
-
-
-}
-
-if(!dojo._hasResource["dijit.Menu"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Menu"] = true;
-dojo.provide("dijit.Menu");
-
-
-
-
 
+               // destroy widgets created as part of template, etc.
+               var w;
+               while((w = this._supportingWidgets.pop())){
+                       if(w.destroyRecursive){
+                               w.destroyRecursive();
+                       }else if(w.destroy){
+                               w.destroy();
+                       }
+               }
 
+               this.destroyRendering(preserveDom);
+               registry.remove(this.id);
+               this._destroyed = true;
+       },
 
-dojo.declare("dijit._MenuBase",
-       [dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
-{
-       // summary:
-       //              Base class for Menu and MenuBar
+       destroyRendering: function(/*Boolean?*/ preserveDom){
+               // summary:
+               //              Destroys the DOM nodes associated with this widget
+               // preserveDom:
+               //              If true, this method will leave the original DOM structure alone
+               //              during tear-down. Note: this will not work with _Templated
+               //              widgets yet.
+               // tags:
+               //              protected
 
-       // parentMenu: [readonly] Widget
-       //              pointer to menu that displayed me
-       parentMenu: null,
+               if(this.bgIframe){
+                       this.bgIframe.destroy(preserveDom);
+                       delete this.bgIframe;
+               }
 
-       // popupDelay: Integer
-       //              number of milliseconds before hovering (without clicking) causes the popup to automatically open.
-       popupDelay: 500,
+               if(this.domNode){
+                       if(preserveDom){
+                               domAttr.remove(this.domNode, "widgetId");
+                       }else{
+                               domConstruct.destroy(this.domNode);
+                       }
+                       delete this.domNode;
+               }
 
-       startup: function(){
-               if(this._started){ return; }
+               if(this.srcNodeRef){
+                       if(!preserveDom){
+                               domConstruct.destroy(this.srcNodeRef);
+                       }
+                       delete this.srcNodeRef;
+               }
+       },
 
-               dojo.forEach(this.getChildren(), function(child){ child.startup(); });
-               this.startupKeyNavChildren();
+       destroyDescendants: function(/*Boolean?*/ preserveDom){
+               // summary:
+               //              Recursively destroy the children of this widget and their
+               //              descendants.
+               // preserveDom:
+               //              If true, the preserveDom attribute is passed to all descendant
+               //              widget's .destroy() method. Not for use with _Templated
+               //              widgets.
 
-               this.inherited(arguments);
+               // get all direct descendants and destroy them recursively
+               array.forEach(this.getChildren(), function(widget){
+                       if(widget.destroyRecursive){
+                               widget.destroyRecursive(preserveDom);
+                       }
+               });
        },
 
-       onExecute: function(){
+       uninitialize: function(){
                // summary:
-               //              Attach point for notification about when a menu item has been executed.
-               //              This is an internal mechanism used for Menus to signal to their parent to
-               //              close them, because they are about to execute the onClick handler.   In
-               //              general developers should not attach to or override this method.
+               //              Stub function. Override to implement custom widget tear-down
+               //              behavior.
                // tags:
                //              protected
+               return false;
        },
 
-       onCancel: function(/*Boolean*/ closeAll){
+       ////////////////// GET/SET, CUSTOM SETTERS, ETC. ///////////////////
+
+       _setStyleAttr: function(/*String||Object*/ value){
                // summary:
-               //              Attach point for notification about when the user cancels the current menu
-               //              This is an internal mechanism used for Menus to signal to their parent to
-               //              close them.  In general developers should not attach to or override this method.
+               //              Sets the style attribute of the widget according to value,
+               //              which is either a hash like {height: "5px", width: "3px"}
+               //              or a plain string
+               // description:
+               //              Determines which node to set the style on based on style setting
+               //              in attributeMap.
                // tags:
                //              protected
-       },
 
-       _moveToPopup: function(/*Event*/ evt){
-               // summary:
-               //              This handles the right arrow key (left arrow key on RTL systems),
-               //              which will either open a submenu, or move to the next item in the
-               //              ancestor MenuBar
-               // tags:
-               //              private
+               var mapNode = this.domNode;
 
-               if(this.focusedChild && this.focusedChild.popup && !this.focusedChild.disabled){
-                       this.focusedChild._onClick(evt);
+               // Note: technically we should revert any style setting made in a previous call
+               // to his method, but that's difficult to keep track of.
+
+               if(lang.isObject(value)){
+                       domStyle.set(mapNode, value);
                }else{
-                       var topMenu = this._getTopMenu();
-                       if(topMenu && topMenu._isMenuBar){
-                               topMenu.focusNext();
+                       if(mapNode.style.cssText){
+                               mapNode.style.cssText += "; " + value;
+                       }else{
+                               mapNode.style.cssText = value;
                        }
                }
+
+               this._set("style", value);
        },
 
-       _onPopupHover: function(/*Event*/ evt){
+       _attrToDom: function(/*String*/ attr, /*String*/ value, /*Object?*/ commands){
                // summary:
-               //              This handler is called when the mouse moves over the popup.
+               //              Reflect a widget attribute (title, tabIndex, duration etc.) to
+               //              the widget DOM, as specified by commands parameter.
+               //              If commands isn't specified then it's looked up from attributeMap.
+               //              Note some attributes like "type"
+               //              cannot be processed this way as they are not mutable.
+               //
                // tags:
                //              private
 
-               // if the mouse hovers over a menu popup that is in pending-close state,
-               // then stop the close operation.
-               // This can't be done in onItemHover since some popup targets don't have MenuItems (e.g. ColorPicker)
-               if(this.currentPopup && this.currentPopup._pendingClose_timer){
-                       var parentMenu = this.currentPopup.parentMenu;
-                       // highlight the parent menu item pointing to this popup
-                       if(parentMenu.focusedChild){
-                               parentMenu.focusedChild._setSelected(false);
+               commands = arguments.length >= 3 ? commands : this.attributeMap[attr];
+
+               array.forEach(lang.isArray(commands) ? commands : [commands], function(command){
+
+                       // Get target node and what we are doing to that node
+                       var mapNode = this[command.node || command || "domNode"];       // DOM node
+                       var type = command.type || "attribute"; // class, innerHTML, innerText, or attribute
+
+                       switch(type){
+                               case "attribute":
+                                       if(lang.isFunction(value)){ // functions execute in the context of the widget
+                                               value = lang.hitch(this, value);
+                                       }
+
+                                       // Get the name of the DOM node attribute; usually it's the same
+                                       // as the name of the attribute in the widget (attr), but can be overridden.
+                                       // Also maps handler names to lowercase, like onSubmit --> onsubmit
+                                       var attrName = command.attribute ? command.attribute :
+                                               (/^on[A-Z][a-zA-Z]*$/.test(attr) ? attr.toLowerCase() : attr);
+
+                                       domAttr.set(mapNode, attrName, value);
+                                       break;
+                               case "innerText":
+                                       mapNode.innerHTML = "";
+                                       mapNode.appendChild(win.doc.createTextNode(value));
+                                       break;
+                               case "innerHTML":
+                                       mapNode.innerHTML = value;
+                                       break;
+                               case "class":
+                                       domClass.replace(mapNode, value, this[attr]);
+                                       break;
                        }
-                       parentMenu.focusedChild = this.currentPopup.from_item;
-                       parentMenu.focusedChild._setSelected(true);
-                       // cancel the pending close
-                       this._stopPendingCloseTimer(this.currentPopup);
-               }
+               }, this);
        },
 
-       onItemHover: function(/*MenuItem*/ item){
+       get: function(name){
                // summary:
-               //              Called when cursor is over a MenuItem.
-               // tags:
-               //              protected
+               //              Get a property from a widget.
+               //      name:
+               //              The property to get.
+               // description:
+               //              Get a named property from a widget. The property may
+               //              potentially be retrieved via a getter method. If no getter is defined, this
+               //              just retrieves the object's property.
+               //
+               //              For example, if the widget has properties `foo` and `bar`
+               //              and a method named `_getFooAttr()`, calling:
+               //              `myWidget.get("foo")` would be equivalent to calling
+               //              `widget._getFooAttr()` and `myWidget.get("bar")`
+               //              would be equivalent to the expression
+               //              `widget.bar2`
+               var names = this._getAttrNames(name);
+               return this[names.g] ? this[names.g]() : this[name];
+       },
 
-               // Don't do anything unless user has "activated" the menu by:
-               //              1) clicking it
-               //              2) opening it from a parent menu (which automatically focuses it)
-               if(this.isActive){
-                       this.focusChild(item);
-                       if(this.focusedChild.popup && !this.focusedChild.disabled && !this.hover_timer){
-                               this.hover_timer = setTimeout(dojo.hitch(this, "_openPopup"), this.popupDelay);
+       set: function(name, value){
+               // summary:
+               //              Set a property on a widget
+               //      name:
+               //              The property to set.
+               //      value:
+               //              The value to set in the property.
+               // description:
+               //              Sets named properties on a widget which may potentially be handled by a
+               //              setter in the widget.
+               //
+               //              For example, if the widget has properties `foo` and `bar`
+               //              and a method named `_setFooAttr()`, calling
+               //              `myWidget.set("foo", "Howdy!")` would be equivalent to calling
+               //              `widget._setFooAttr("Howdy!")` and `myWidget.set("bar", 3)`
+               //              would be equivalent to the statement `widget.bar = 3;`
+               //
+               //              set() may also be called with a hash of name/value pairs, ex:
+               //
+               //      |       myWidget.set({
+               //      |               foo: "Howdy",
+               //      |               bar: 3
+               //      |       });
+               //
+               //      This is equivalent to calling `set(foo, "Howdy")` and `set(bar, 3)`
+
+               if(typeof name === "object"){
+                       for(var x in name){
+                               this.set(x, name[x]);
                        }
+                       return this;
                }
-               // if the user is mixing mouse and keyboard navigation,
-               // then the menu may not be active but a menu item has focus,
-               // but it's not the item that the mouse just hovered over.
-               // To avoid both keyboard and mouse selections, use the latest.
-               if(this.focusedChild){
-                       this.focusChild(item);
+               var names = this._getAttrNames(name),
+                       setter = this[names.s];
+               if(lang.isFunction(setter)){
+                       // use the explicit setter
+                       var result = setter.apply(this, Array.prototype.slice.call(arguments, 1));
+               }else{
+                       // Mapping from widget attribute to DOMNode attribute/value/etc.
+                       // Map according to:
+                       //              1. attributeMap setting, if one exists (TODO: attributeMap deprecated, remove in 2.0)
+                       //              2. _setFooAttr: {...} type attribute in the widget (if one exists)
+                       //              3. apply to focusNode or domNode if standard attribute name, excluding funcs like onClick.
+                       // Checks if an attribute is a "standard attribute" by whether the DOMNode JS object has a similar
+                       // attribute name (ex: accept-charset attribute matches jsObject.acceptCharset).
+                       // Note also that Tree.focusNode() is a function not a DOMNode, so test for that.
+                       var defaultNode = this.focusNode && !lang.isFunction(this.focusNode) ? "focusNode" : "domNode",
+                               tag = this[defaultNode].tagName,
+                               attrsForTag = tagAttrs[tag] || (tagAttrs[tag] = getAttrs(this[defaultNode])),
+                               map =   name in this.attributeMap ? this.attributeMap[name] :
+                                               names.s in this ? this[names.s] :
+                                               ((names.l in attrsForTag && typeof value != "function") ||
+                                                       /^aria-|^data-|^role$/.test(name)) ? defaultNode : null;
+                       if(map != null){
+                               this._attrToDom(name, value, map);
+                       }
+                       this._set(name, value);
                }
-               this._hoveredChild = item;
+               return result || this;
        },
 
-       _onChildBlur: function(item){
+       _attrPairNames: {},             // shared between all widgets
+       _getAttrNames: function(name){
                // summary:
-               //              Called when a child MenuItem becomes inactive because focus
-               //              has been removed from the MenuItem *and* it's descendant menus.
+               //              Helper function for get() and set().
+               //              Caches attribute name values so we don't do the string ops every time.
                // tags:
                //              private
-               this._stopPopupTimer();
-               item._setSelected(false);
-               // Close all popups that are open and descendants of this menu
-               var itemPopup = item.popup;
-               if(itemPopup){
-                       this._stopPendingCloseTimer(itemPopup);
-                       itemPopup._pendingClose_timer = setTimeout(function(){
-                               itemPopup._pendingClose_timer = null;
-                               if(itemPopup.parentMenu){
-                                       itemPopup.parentMenu.currentPopup = null;
-                               }
-                               dijit.popup.close(itemPopup); // this calls onClose
-                       }, this.popupDelay);
+
+               var apn = this._attrPairNames;
+               if(apn[name]){ return apn[name]; }
+               var uc = name.replace(/^[a-z]|-[a-zA-Z]/g, function(c){ return c.charAt(c.length-1).toUpperCase(); });
+               return (apn[name] = {
+                       n: name+"Node",
+                       s: "_set"+uc+"Attr",    // converts dashes to camel case, ex: accept-charset --> _setAcceptCharsetAttr
+                       g: "_get"+uc+"Attr",
+                       l: uc.toLowerCase()             // lowercase name w/out dashes, ex: acceptcharset
+               });
+       },
+
+       _set: function(/*String*/ name, /*anything*/ value){
+               // summary:
+               //              Helper function to set new value for specified attribute, and call handlers
+               //              registered with watch() if the value has changed.
+               var oldValue = this[name];
+               this[name] = value;
+               if(this._watchCallbacks && this._created && value !== oldValue){
+                       this._watchCallbacks(name, oldValue, value);
                }
        },
 
-       onItemUnhover: function(/*MenuItem*/ item){
+       on: function(/*String*/ type, /*Function*/ func){
                // summary:
-               //              Callback fires when mouse exits a MenuItem
-               // tags:
-               //              protected
+               //              Call specified function when event occurs, ex: myWidget.on("click", function(){ ... }).
+               // description:
+               //              Call specified function when event `type` occurs, ex: `myWidget.on("click", function(){ ... })`.
+               //              Note that the function is not run in any particular scope, so if (for example) you want it to run in the
+               //              widget's scope you must do `myWidget.on("click", lang.hitch(myWidget, func))`.
 
-               if(this.isActive){
-                       this._stopPopupTimer();
-               }
-               if(this._hoveredChild == item){ this._hoveredChild = null; }
+               return aspect.after(this, this._onMap(type), func, true);
        },
 
-       _stopPopupTimer: function(){
+       _onMap: function(/*String*/ type){
                // summary:
-               //              Cancels the popup timer because the user has stop hovering
-               //              on the MenuItem, etc.
-               // tags:
-               //              private
-               if(this.hover_timer){
-                       clearTimeout(this.hover_timer);
-                       this.hover_timer = null;
+               //              Maps on() type parameter (ex: "mousemove") to method name (ex: "onMouseMove")
+               var ctor = this.constructor, map = ctor._onMap;
+               if(!map){
+                       map = (ctor._onMap = {});
+                       for(var attr in ctor.prototype){
+                               if(/^on/.test(attr)){
+                                       map[attr.replace(/^on/, "").toLowerCase()] = attr;
+                               }
+                       }
                }
+               return map[type.toLowerCase()]; // String
        },
 
-       _stopPendingCloseTimer: function(/*dijit._Widget*/ popup){
+       toString: function(){
                // summary:
-               //              Cancels the pending-close timer because the close has been preempted
-               // tags:
-               //              private
-               if(popup._pendingClose_timer){
-                       clearTimeout(popup._pendingClose_timer);
-                       popup._pendingClose_timer = null;
-               }
+               //              Returns a string that represents the widget
+               // description:
+               //              When a widget is cast to a string, this method will be used to generate the
+               //              output. Currently, it does not implement any sort of reversible
+               //              serialization.
+               return '[Widget ' + this.declaredClass + ', ' + (this.id || 'NO ID') + ']'; // String
        },
 
-       _stopFocusTimer: function(){
+       getChildren: function(){
                // summary:
-               //              Cancels the pending-focus timer because the menu was closed before focus occured
-               // tags:
-               //              private
-               if(this._focus_timer){
-                       clearTimeout(this._focus_timer);
-                       this._focus_timer = null;
-               }
+               //              Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
+               //              Does not return nested widgets, nor widgets that are part of this widget's template.
+               return this.containerNode ? registry.findWidgets(this.containerNode) : []; // dijit._Widget[]
        },
 
-       _getTopMenu: function(){
+       getParent: function(){
                // summary:
-               //              Returns the top menu in this chain of Menus
-               // tags:
-               //              private
-               for(var top=this; top.parentMenu; top=top.parentMenu);
-               return top;
+               //              Returns the parent widget of this widget
+               return registry.getEnclosingWidget(this.domNode.parentNode);
        },
 
-       onItemClick: function(/*dijit._Widget*/ item, /*Event*/ evt){
+       connect: function(
+                       /*Object|null*/ obj,
+                       /*String|Function*/ event,
+                       /*String|Function*/ method){
                // summary:
-               //              Handle clicks on an item.
+               //              Connects specified obj/event to specified method of this object
+               //              and registers for disconnect() on widget destroy.
+               // description:
+               //              Provide widget-specific analog to dojo.connect, except with the
+               //              implicit use of this widget as the target object.
+               //              Events connected with `this.connect` are disconnected upon
+               //              destruction.
+               // returns:
+               //              A handle that can be passed to `disconnect` in order to disconnect before
+               //              the widget is destroyed.
+               // example:
+               //      |       var btn = new dijit.form.Button();
+               //      |       // when foo.bar() is called, call the listener we're going to
+               //      |       // provide in the scope of btn
+               //      |       btn.connect(foo, "bar", function(){
+               //      |               console.debug(this.toString());
+               //      |       });
                // tags:
-               //              private
-
-               // this can't be done in _onFocus since the _onFocus events occurs asynchronously
-               if(typeof this.isShowingNow == 'undefined'){ // non-popup menu
-                       this._markActive();
-               }
-
-               this.focusChild(item);
-
-               if(item.disabled){ return false; }
+               //              protected
 
-               if(item.popup){
-                       this._openPopup();
-               }else{
-                       // before calling user defined handler, close hierarchy of menus
-                       // and restore focus to place it was when menu was opened
-                       this.onExecute();
+               var handle = connect.connect(obj, event, this, method);
+               this._connects.push(handle);
+               return handle;          // _Widget.Handle
+       },
 
-                       // user defined handler for click
-                       item.onClick(evt);
+       disconnect: function(handle){
+               // summary:
+               //              Disconnects handle created by `connect`.
+               //              Also removes handle from this widget's list of connects.
+               // tags:
+               //              protected
+               var i = array.indexOf(this._connects, handle);
+               if(i != -1){
+                       handle.remove();
+                       this._connects.splice(i, 1);
                }
        },
 
-       _openPopup: function(){
+       subscribe: function(t, method){
                // summary:
-               //              Open the popup to the side of/underneath the current menu item
+               //              Subscribes to the specified topic and calls the specified method
+               //              of this object and registers for unsubscribe() on widget destroy.
+               // description:
+               //              Provide widget-specific analog to dojo.subscribe, except with the
+               //              implicit use of this widget as the target object.
+               // t: String
+               //              The topic
+               // method: Function
+               //              The callback
+               // example:
+               //      |       var btn = new dijit.form.Button();
+               //      |       // when /my/topic is published, this button changes its label to
+               //      |   // be the parameter of the topic.
+               //      |       btn.subscribe("/my/topic", function(v){
+               //      |               this.set("label", v);
+               //      |       });
                // tags:
                //              protected
+               var handle = topic.subscribe(t, lang.hitch(this, method));
+               this._connects.push(handle);
+               return handle;          // _Widget.Handle
+       },
 
-               this._stopPopupTimer();
-               var from_item = this.focusedChild;
-               if(!from_item){ return; } // the focused child lost focus since the timer was started
-               var popup = from_item.popup;
-               if(popup.isShowingNow){ return; }
-               if(this.currentPopup){
-                       this._stopPendingCloseTimer(this.currentPopup);
-                       dijit.popup.close(this.currentPopup);
-               }
-               popup.parentMenu = this;
-               popup.from_item = from_item; // helps finding the parent item that should be focused for this popup
-               var self = this;
-               dijit.popup.open({
-                       parent: this,
-                       popup: popup,
-                       around: from_item.domNode,
-                       orient: this._orient || (this.isLeftToRight() ?
-                                                                       {'TR': 'TL', 'TL': 'TR', 'BR': 'BL', 'BL': 'BR'} :
-                                                                       {'TL': 'TR', 'TR': 'TL', 'BL': 'BR', 'BR': 'BL'}),
-                       onCancel: function(){ // called when the child menu is canceled
-                               // set isActive=false (_closeChild vs _cleanUp) so that subsequent hovering will NOT open child menus
-                               // which seems aligned with the UX of most applications (e.g. notepad, wordpad, paint shop pro)
-                               self.focusChild(from_item);     // put focus back on my node
-                               self._cleanUp();                        // close the submenu (be sure this is done _after_ focus is moved)
-                               from_item._setSelected(true); // oops, _cleanUp() deselected the item
-                               self.focusedChild = from_item;  // and unset focusedChild
-                       },
-                       onExecute: dojo.hitch(this, "_cleanUp")
-               });
-
-               this.currentPopup = popup;
-               // detect mouseovers to handle lazy mouse movements that temporarily focus other menu items
-               popup.connect(popup.domNode, "onmouseenter", dojo.hitch(self, "_onPopupHover")); // cleaned up when the popped-up widget is destroyed on close
-
-               if(popup.focus){
-                       // If user is opening the popup via keyboard (right arrow, or down arrow for MenuBar),
-                       // if the cursor happens to collide with the popup, it will generate an onmouseover event
-                       // even though the mouse wasn't moved.   Use a setTimeout() to call popup.focus so that
-                       // our focus() call overrides the onmouseover event, rather than vice-versa.  (#8742)
-                       popup._focus_timer = setTimeout(dojo.hitch(popup, function(){
-                               this._focus_timer = null;
-                               this.focus();
-                       }), 0);
-               }
-       },
-
-       _markActive: function(){
+       unsubscribe: function(/*Object*/ handle){
                // summary:
-               //              Mark this menu's state as active.
-               //              Called when this Menu gets focus from:
-               //                      1) clicking it (mouse or via space/arrow key)
-               //                      2) being opened by a parent menu.
-               //              This is not called just from mouse hover.
-               //              Focusing a menu via TAB does NOT automatically set isActive
-               //              since TAB is a navigation operation and not a selection one.
-               //              For Windows apps, pressing the ALT key focuses the menubar
-               //              menus (similar to TAB navigation) but the menu is not active
-               //              (ie no dropdown) until an item is clicked.
-               this.isActive = true;
-               dojo.addClass(this.domNode, "dijitMenuActive");
-               dojo.removeClass(this.domNode, "dijitMenuPassive");
+               //              Unsubscribes handle created by this.subscribe.
+               //              Also removes handle from this widget's list of subscriptions
+               // tags:
+               //              protected
+               this.disconnect(handle);
        },
 
-       onOpen: function(/*Event*/ e){
+       isLeftToRight: function(){
                // summary:
-               //              Callback when this menu is opened.
-               //              This is called by the popup manager as notification that the menu
-               //              was opened.
+               //              Return this widget's explicit or implicit orientation (true for LTR, false for RTL)
                // tags:
-               //              private
-
-               this.isShowingNow = true;
-               this._markActive();
+               //              protected
+               return this.dir ? (this.dir == "ltr") : domGeometry.isBodyLtr(); //Boolean
        },
 
-       _markInactive: function(){
+       isFocusable: function(){
                // summary:
-               //              Mark this menu's state as inactive.
-               this.isActive = false; // don't do this in _onBlur since the state is pending-close until we get here
-               dojo.removeClass(this.domNode, "dijitMenuActive");
-               dojo.addClass(this.domNode, "dijitMenuPassive");
+               //              Return true if this widget can currently be focused
+               //              and false if not
+               return this.focus && (domStyle.get(this.domNode, "display") != "none");
        },
 
-       onClose: function(){
+       placeAt: function(/* String|DomNode|_Widget */reference, /* String?|Int? */position){
                // summary:
-               //              Callback when this menu is closed.
-               //              This is called by the popup manager as notification that the menu
-               //              was closed.
-               // tags:
-               //              private
-
-               this._stopFocusTimer();
-               this._markInactive();
-               this.isShowingNow = false;
-               this.parentMenu = null;
-       },
+               //              Place this widget's domNode reference somewhere in the DOM based
+               //              on standard domConstruct.place conventions, or passing a Widget reference that
+               //              contains and addChild member.
+               //
+               // description:
+               //              A convenience function provided in all _Widgets, providing a simple
+               //              shorthand mechanism to put an existing (or newly created) Widget
+               //              somewhere in the dom, and allow chaining.
+               //
+               // reference:
+               //              The String id of a domNode, a domNode reference, or a reference to a Widget possessing
+               //              an addChild method.
+               //
+               // position:
+               //              If passed a string or domNode reference, the position argument
+               //              accepts a string just as domConstruct.place does, one of: "first", "last",
+               //              "before", or "after".
+               //
+               //              If passed a _Widget reference, and that widget reference has an ".addChild" method,
+               //              it will be called passing this widget instance into that method, supplying the optional
+               //              position index passed.
+               //
+               // returns:
+               //              dijit._Widget
+               //              Provides a useful return of the newly created dijit._Widget instance so you
+               //              can "chain" this function by instantiating, placing, then saving the return value
+               //              to a variable.
+               //
+               // example:
+               // |    // create a Button with no srcNodeRef, and place it in the body:
+               // |    var button = new dijit.form.Button({ label:"click" }).placeAt(win.body());
+               // |    // now, 'button' is still the widget reference to the newly created button
+               // |    button.on("click", function(e){ console.log('click'); }));
+               //
+               // example:
+               // |    // create a button out of a node with id="src" and append it to id="wrapper":
+               // |    var button = new dijit.form.Button({},"src").placeAt("wrapper");
+               //
+               // example:
+               // |    // place a new button as the first element of some div
+               // |    var button = new dijit.form.Button({ label:"click" }).placeAt("wrapper","first");
+               //
+               // example:
+               // |    // create a contentpane and add it to a TabContainer
+               // |    var tc = dijit.byId("myTabs");
+               // |    new dijit.layout.ContentPane({ href:"foo.html", title:"Wow!" }).placeAt(tc)
 
-       _closeChild: function(){
-               // summary:
-               //              Called when submenu is clicked or focus is lost.  Close hierarchy of menus.
-               // tags:
-               //              private
-               this._stopPopupTimer();
-               if(this.focusedChild){ // unhighlight the focused item
-                       this.focusedChild._setSelected(false);
-                       this.focusedChild._onUnhover();
-                       this.focusedChild = null;
-               }
-               if(this.currentPopup){
-                       // Close all popups that are open and descendants of this menu
-                       dijit.popup.close(this.currentPopup);
-                       this.currentPopup = null;
+               if(reference.declaredClass && reference.addChild){
+                       reference.addChild(this, position);
+               }else{
+                       domConstruct.place(this.domNode, reference, position);
                }
+               return this;
        },
 
-       _onItemFocus: function(/*MenuItem*/ item){
+       getTextDir: function(/*String*/ text,/*String*/ originalDir){
                // summary:
-               //              Called when child of this Menu gets focus from:
-               //                      1) clicking it
-               //                      2) tabbing into it
-               //                      3) being opened by a parent menu.
-               //              This is not called just from mouse hover.
-               if(this._hoveredChild && this._hoveredChild != item){
-                       this._hoveredChild._onUnhover(); // any previous mouse movement is trumped by focus selection
-               }
+               //              Return direction of the text.
+               //              The function overridden in the _BidiSupport module,
+               //              its main purpose is to calculate the direction of the
+               //              text, if was defined by the programmer through textDir.
+               //      tags:
+               //              protected.
+               return originalDir;
        },
 
-       _onBlur: function(){
+       applyTextDir: function(/*===== element, text =====*/){
                // summary:
-               //              Called when focus is moved away from this Menu and it's submenus.
+               //              The function overridden in the _BidiSupport module,
+               //              originally used for setting element.dir according to this.textDir.
+               //              In this case does nothing.
+               // element: DOMNode
+               // text: String
                // tags:
-               //              protected
-               this._cleanUp();
-               this.inherited(arguments);
+               //              protected.
        },
 
-       _cleanUp: function(){
+       defer: function(fcn, delay){ 
                // summary:
-               //              Called when the user is done with this menu.  Closes hierarchy of menus.
+               //              Wrapper to setTimeout to avoid deferred functions executing
+               //              after the originating widget has been destroyed.
+               //              Returns an object handle with a remove method (that returns null) (replaces clearTimeout).
+               // fcn: function reference
+               // delay: Optional number (defaults to 0)
                // tags:
-               //              private
-
-               this._closeChild(); // don't call this.onClose since that's incorrect for MenuBar's that never close
-               if(typeof this.isShowingNow == 'undefined'){ // non-popup menu doesn't call onClose
-                       this._markInactive();
-               }
+               //              protected.
+               var timer = setTimeout(lang.hitch(this, 
+                       function(){ 
+                               timer = null;
+                               if(!this._destroyed){ 
+                                       lang.hitch(this, fcn)(); 
+                               } 
+                       }),
+                       delay || 0
+               );
+               return {
+                       remove: function(){
+                                       if(timer){
+                                               clearTimeout(timer);
+                                               timer = null;
+                                       }
+                                       return null; // so this works well: handle = handle.remove();
+                               }
+               };
        }
 });
 
-dojo.declare("dijit.Menu",
-       dijit._MenuBase,
-       {
-       // summary
-       //              A context menu you can assign to multiple elements
-
-       // TODO: most of the code in here is just for context menu (right-click menu)
-       // support.  In retrospect that should have been a separate class (dijit.ContextMenu).
-       // Split them for 2.0
-
-       constructor: function(){
-               this._bindings = [];
-       },
+});
 
-       templateString: dojo.cache("dijit", "templates/Menu.html", "<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" waiRole=\"menu\" tabIndex=\"${tabIndex}\" dojoAttachEvent=\"onkeypress:_onKeyPress\" cellspacing=0>\n\t<tbody class=\"dijitReset\" dojoAttachPoint=\"containerNode\"></tbody>\n</table>\n"),
+},
+'dijit/form/Form':function(){
+define("dijit/form/Form", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/event", // event.stop
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/sniff", // has("ie")
+       "../_Widget",
+       "../_TemplatedMixin",
+       "./_FormMixin",
+       "../layout/_ContentPaneResizeMixin"
+], function(declare, domAttr, event, kernel, has, _Widget, _TemplatedMixin, _FormMixin, _ContentPaneResizeMixin){
 
-       baseClass: "dijitMenu",
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _FormMixin = dijit.form._FormMixin;
+       var _ContentPaneResizeMixin = dijit.layout._ContentPaneResizeMixin;
+=====*/
 
-       // targetNodeIds: [const] String[]
-       //              Array of dom node ids of nodes to attach to.
-       //              Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.
-       targetNodeIds: [],
+       // module:
+       //              dijit/form/Form
+       // summary:
+       //              Widget corresponding to HTML form tag, for validation and serialization
 
-       // contextMenuForWindow: [const] Boolean
-       //              If true, right clicking anywhere on the window will cause this context menu to open.
-       //              If false, must specify targetNodeIds.
-       contextMenuForWindow: false,
 
-       // leftClickToOpen: [const] Boolean
-       //              If true, menu will open on left click instead of right click, similiar to a file menu.
-       leftClickToOpen: false,
+       return declare("dijit.form.Form", [_Widget, _TemplatedMixin, _FormMixin, _ContentPaneResizeMixin], {
+               // summary:
+               //              Widget corresponding to HTML form tag, for validation and serialization
+               //
+               // example:
+               //      |       <form data-dojo-type="dijit.form.Form" id="myForm">
+               //      |               Name: <input type="text" name="name" />
+               //      |       </form>
+               //      |       myObj = {name: "John Doe"};
+               //      |       dijit.byId('myForm').set('value', myObj);
+               //      |
+               //      |       myObj=dijit.byId('myForm').get('value');
 
-       // refocus: Boolean
-       //              When this menu closes, re-focus the element which had focus before it was opened.
-       refocus: true,
+               // HTML <FORM> attributes
 
-       postCreate: function(){
-               if(this.contextMenuForWindow){
-                       this.bindDomNode(dojo.body());
-               }else{
-                       // TODO: should have _setTargetNodeIds() method to handle initialization and a possible
-                       // later attr('targetNodeIds', ...) call.   There's also a problem that targetNodeIds[]
-                       // gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
-                       dojo.forEach(this.targetNodeIds, this.bindDomNode, this);
-               }
-               var k = dojo.keys, l = this.isLeftToRight();
-               this._openSubMenuKey = l ? k.RIGHT_ARROW : k.LEFT_ARROW;
-               this._closeSubMenuKey = l ? k.LEFT_ARROW : k.RIGHT_ARROW;
-               this.connectKeyNavHandlers([k.UP_ARROW], [k.DOWN_ARROW]);
-       },
+               // name: String?
+               //              Name of form for scripting.
+               name: "",
 
-       _onKeyPress: function(/*Event*/ evt){
-               // summary:
-               //              Handle keyboard based menu navigation.
-               // tags:
-               //              protected
+               // action: String?
+               //              Server-side form handler.
+               action: "",
 
-               if(evt.ctrlKey || evt.altKey){ return; }
+               // method: String?
+               //              HTTP method used to submit the form, either "GET" or "POST".
+               method: "",
 
-               switch(evt.charOrCode){
-                       case this._openSubMenuKey:
-                               this._moveToPopup(evt);
-                               dojo.stopEvent(evt);
-                               break;
-                       case this._closeSubMenuKey:
-                               if(this.parentMenu){
-                                       if(this.parentMenu._isMenuBar){
-                                               this.parentMenu.focusPrev();
-                                       }else{
-                                               this.onCancel(false);
-                                       }
-                               }else{
-                                       dojo.stopEvent(evt);
-                               }
-                               break;
-               }
-       },
+               // encType: String?
+               //              Encoding type for the form, ex: application/x-www-form-urlencoded.
+               encType: "",
 
-       // thanks burstlib!
-       _iframeContentWindow: function(/* HTMLIFrameElement */iframe_el){
-               // summary:
-               //              Returns the window reference of the passed iframe
-               // tags:
-               //              private
-               var win = dojo.window.get(this._iframeContentDocument(iframe_el)) ||
-                       // Moz. TODO: is this available when defaultView isn't?
-                       this._iframeContentDocument(iframe_el)['__parent__'] ||
-                       (iframe_el.name && dojo.doc.frames[iframe_el.name]) || null;
-               return win;     //      Window
-       },
+               // accept-charset: String?
+               //              List of supported charsets.
+               "accept-charset": "",
 
-       _iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){
-               // summary:
-               //              Returns a reference to the document object inside iframe_el
-               // tags:
-               //              protected
-               var doc = iframe_el.contentDocument // W3
-                       || (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
-                       || (iframe_el.name && dojo.doc.frames[iframe_el.name] && dojo.doc.frames[iframe_el.name].document)
-                       || null;
-               return doc;     //      HTMLDocument
-       },
+               // accept: String?
+               //              List of MIME types for file upload.
+               accept: "",
 
-       bindDomNode: function(/*String|DomNode*/ node){
-               // summary:
-               //              Attach menu to given node
-               node = dojo.byId(node);
+               // target: String?
+               //              Target frame for the document to be opened in.
+               target: "",
 
-               var cn; // Connect node
+               templateString: "<form data-dojo-attach-point='containerNode' data-dojo-attach-event='onreset:_onReset,onsubmit:_onSubmit' ${!nameAttrSetting}></form>",
 
-               // Support context menus on iframes.   Rather than binding to the iframe itself we need
-               // to bind to the <body> node inside the iframe.
-               if(node.tagName.toLowerCase() == "iframe"){
-                       var iframe = node,
-                               win = this._iframeContentWindow(iframe);
-                       cn = dojo.withGlobal(win, dojo.body);
-               }else{
-                       
-                       // To capture these events at the top level, attach to <html>, not <body>.
-                       // Otherwise right-click context menu just doesn't work.
-                       cn = (node == dojo.body() ? dojo.doc.documentElement : node);
-               }
-
-
-               // "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
-               var binding = {
-                       node: node,
-                       iframe: iframe
-               };
+               postMixInProperties: function(){
+                       // Setup name=foo string to be referenced from the template (but only if a name has been specified)
+                       // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8660
+                       this.nameAttrSetting = this.name ? ("name='" + this.name + "'") : "";
+                       this.inherited(arguments);
+               },
 
-               // Save info about binding in _bindings[], and make node itself record index(+1) into
-               // _bindings[] array.   Prefix w/_dijitMenu to avoid setting an attribute that may
-               // start with a number, which fails on FF/safari.
-               dojo.attr(node, "_dijitMenu" + this.id, this._bindings.push(binding));
+               execute: function(/*Object*/ /*===== formContents =====*/){
+                       // summary:
+                       //              Deprecated: use submit()
+                       // tags:
+                       //              deprecated
+               },
 
-               // Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
-               // loading yet, in which case we need to wait for the onload event first, and then connect
-               // On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so
-               // we need to monitor keyboard events in addition to the oncontextmenu event.
-               var doConnects = dojo.hitch(this, function(cn){
-                       return [
-                               // TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu,
-                               // rather than shift-F10?
-                               dojo.connect(cn, this.leftClickToOpen ? "onclick" : "oncontextmenu", this, function(evt){
-                                       // Schedule context menu to be opened unless it's already been scheduled from onkeydown handler
-                                       dojo.stopEvent(evt);
-                                       this._scheduleOpen(evt.target, iframe, {x: evt.pageX, y: evt.pageY});
-                               }),
-                               dojo.connect(cn, "onkeydown", this, function(evt){
-                                       if(evt.shiftKey && evt.keyCode == dojo.keys.F10){
-                                               dojo.stopEvent(evt);
-                                               this._scheduleOpen(evt.target, iframe); // no coords - open near target node
-                                       }
-                               })
-                       ];      
-               });
-               binding.connects = cn ? doConnects(cn) : [];
+               onExecute: function(){
+                       // summary:
+                       //              Deprecated: use onSubmit()
+                       // tags:
+                       //              deprecated
+               },
 
-               if(iframe){
-                       // Setup handler to [re]bind to the iframe when the contents are initially loaded,
-                       // and every time the contents change.
-                       // Need to do this b/c we are actually binding to the iframe's <body> node.
-                       // Note: can't use dojo.connect(), see #9609.
+               _setEncTypeAttr: function(/*String*/ value){
+                       this.encType = value;
+                       domAttr.set(this.domNode, "encType", value);
+                       if(has("ie")){ this.domNode.encoding = value; }
+               },
 
-                       binding.onloadHandler = dojo.hitch(this, function(){
-                               // want to remove old connections, but IE throws exceptions when trying to
-                               // access the <body> node because it's already gone, or at least in a state of limbo
+               reset: function(/*Event?*/ e){
+                       // summary:
+                       //              restores all widget values back to their init values,
+                       //              calls onReset() which can cancel the reset by returning false
 
-                               var win = this._iframeContentWindow(iframe);
-                                       cn = dojo.withGlobal(win, dojo.body);
-                               binding.connects = doConnects(cn);
-                       });
-                       if(iframe.addEventListener){
-                               iframe.addEventListener("load", binding.onloadHandler, false);
-                       }else{
-                               iframe.attachEvent("onload", binding.onloadHandler);
+                       // create fake event so we can know if preventDefault() is called
+                       var faux = {
+                               returnValue: true, // the IE way
+                               preventDefault: function(){ // not IE
+                                                       this.returnValue = false;
+                                               },
+                               stopPropagation: function(){},
+                               currentTarget: e ? e.target : this.domNode,
+                               target: e ? e.target : this.domNode
+                       };
+                       // if return value is not exactly false, and haven't called preventDefault(), then reset
+                       if(!(this.onReset(faux) === false) && faux.returnValue){
+                               this.inherited(arguments, []);
                        }
-               }
-       },
-
-       unBindDomNode: function(/*String|DomNode*/ nodeName){
-               // summary:
-               //              Detach menu from given node
+               },
 
-               var node;
-               try{
-                       node = dojo.byId(nodeName);
-               }catch(e){
-                       // On IE the dojo.byId() call will get an exception if the attach point was
-                       // the <body> node of an <iframe> that has since been reloaded (and thus the
-                       // <body> node is in a limbo state of destruction.
-                       return;
-               }
+               onReset: function(/*Event?*/ /*===== e =====*/){
+                       // summary:
+                       //              Callback when user resets the form. This method is intended
+                       //              to be over-ridden. When the `reset` method is called
+                       //              programmatically, the return value from `onReset` is used
+                       //              to compute whether or not resetting should proceed
+                       // tags:
+                       //              callback
+                       return true; // Boolean
+               },
 
-               // node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
-               var attrName = "_dijitMenu" + this.id;
-               if(node && dojo.hasAttr(node, attrName)){
-                       var bid = dojo.attr(node, attrName)-1, b = this._bindings[bid];
-                       dojo.forEach(b.connects, dojo.disconnect);
+               _onReset: function(e){
+                       this.reset(e);
+                       event.stop(e);
+                       return false;
+               },
 
-                       // Remove listener for iframe onload events
-                       var iframe = b.iframe;
-                       if(iframe){
-                               if(iframe.removeEventListener){
-                                       iframe.removeEventListener("load", b.onloadHandler, false);
-                               }else{
-                                       iframe.detachEvent("onload", b.onloadHandler);
-                               }
+               _onSubmit: function(e){
+                       var fp = this.constructor.prototype;
+                       // TODO: remove this if statement beginning with 2.0
+                       if(this.execute != fp.execute || this.onExecute != fp.onExecute){
+                               kernel.deprecated("dijit.form.Form:execute()/onExecute() are deprecated. Use onSubmit() instead.", "", "2.0");
+                               this.onExecute();
+                               this.execute(this.getValues());
                        }
+                       if(this.onSubmit(e) === false){ // only exactly false stops submit
+                               event.stop(e);
+                       }
+               },
 
-                       dojo.removeAttr(node, attrName);
-                       delete this._bindings[bid];
-               }
-       },
+               onSubmit: function(/*Event?*/ /*===== e =====*/){
+                       // summary:
+                       //              Callback when user submits the form.
+                       // description:
+                       //              This method is intended to be over-ridden, but by default it checks and
+                       //              returns the validity of form elements. When the `submit`
+                       //              method is called programmatically, the return value from
+                       //              `onSubmit` is used to compute whether or not submission
+                       //              should proceed
+                       // tags:
+                       //              extension
 
-       _scheduleOpen: function(/*DomNode?*/ target, /*DomNode?*/ iframe, /*Object?*/ coords){
-               // summary:
-               //              Set timer to display myself.  Using a timer rather than displaying immediately solves
-               //              two problems:
-               //
-               //              1. IE: without the delay, focus work in "open" causes the system
-               //              context menu to appear in spite of stopEvent.
-               //
-               //              2. Avoid double-shows on linux, where shift-F10 generates an oncontextmenu event
-               //              even after a dojo.stopEvent(e).  (Shift-F10 on windows doesn't generate the
-               //              oncontextmenu event.)
+                       return this.isValid(); // Boolean
+               },
 
-               if(!this._openTimer){
-                       this._openTimer = setTimeout(dojo.hitch(this, function(){
-                               delete this._openTimer;
-                               this._openMyself({
-                                       target: target,
-                                       iframe: iframe,
-                                       coords: coords
-                               });
-                       }), 1);
+               submit: function(){
+                       // summary:
+                       //              programmatically submit form if and only if the `onSubmit` returns true
+                       if(!(this.onSubmit() === false)){
+                               this.containerNode.submit();
+                       }
                }
-       },
-
-       _openMyself: function(args){
-               // summary:
-               //              Internal function for opening myself when the user does a right-click or something similar.
-               // args:
-               //              This is an Object containing:
-               //              * target:
-               //                      The node that is being clicked
-               //              * iframe:
-               //                      If an <iframe> is being clicked, iframe points to that iframe
-               //              * coords:
-               //                      Put menu at specified x/y position in viewport, or if iframe is
-               //                      specified, then relative to iframe.
-               //
-               //              _openMyself() formerly took the event object, and since various code references
-               //              evt.target (after connecting to _openMyself()), using an Object for parameters
-               //              (so that old code still works).
+       });
+});
 
-               var target = args.target,
-                       iframe = args.iframe,
-                       coords = args.coords;
+},
+'dijit/layout/_TabContainerBase':function(){
+require({cache:{
+'url:dijit/layout/templates/TabContainer.html':"<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" data-dojo-attach-point=\"tablistNode\"></div>\n\t<div data-dojo-attach-point=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" data-dojo-attach-point=\"containerNode\"></div>\n</div>\n"}});
+define("dijit/layout/_TabContainerBase", [
+       "dojo/text!./templates/TabContainer.html",
+       "./StackContainer",
+       "./utils",      // marginBox2contextBox, layoutChildren
+       "../_TemplatedMixin",
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add
+       "dojo/dom-geometry", // domGeometry.contentBox
+       "dojo/dom-style" // domStyle.style
+], function(template, StackContainer, layoutUtils, _TemplatedMixin, declare, domClass, domGeometry, domStyle){
 
-               // Get coordinates to open menu, either at specified (mouse) position or (if triggered via keyboard)
-               // then near the node the menu is assigned to.
-               if(coords){
-                       if(iframe){
-                               // Specified coordinates are on <body> node of an <iframe>, convert to match main document
-                               var od = target.ownerDocument,
-                                       ifc = dojo.position(iframe, true),
-                                       win = this._iframeContentWindow(iframe),
-                                       scroll = dojo.withGlobal(win, "_docScroll", dojo);
-       
-                               var cs = dojo.getComputedStyle(iframe),
-                                       tp = dojo._toPixelValue,
-                                       left = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingLeft)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderLeftWidth) : 0),
-                                       top = (dojo.isIE && dojo.isQuirks ? 0 : tp(iframe, cs.paddingTop)) + (dojo.isIE && dojo.isQuirks ? tp(iframe, cs.borderTopWidth) : 0);
 
-                               coords.x += ifc.x + left - scroll.x;
-                               coords.y += ifc.y + top - scroll.y;
-                       }
-               }else{
-                       coords = dojo.position(target, true);
-                       coords.x += 10;
-                       coords.y += 10;
-               }
+/*=====
+       var StackContainer = dijit.layout.StackContainer;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+=====*/
 
-               var self=this;
-               var savedFocus = dijit.getFocus(this);
-               function closeAndRestoreFocus(){
-                       // user has clicked on a menu or popup
-                       if(self.refocus){
-                               dijit.focus(savedFocus);
-                       }
-                       dijit.popup.close(self);
-               }
-               dijit.popup.open({
-                       popup: this,
-                       x: coords.x,
-                       y: coords.y,
-                       onExecute: closeAndRestoreFocus,
-                       onCancel: closeAndRestoreFocus,
-                       orient: this.isLeftToRight() ? 'L' : 'R'
-               });
-               this.focus();
+// module:
+//             dijit/layout/_TabContainerBase
+// summary:
+//             Abstract base class for TabContainer.   Must define _makeController() to instantiate
+//             and return the widget that displays the tab labels
 
-               this._onBlur = function(){
-                       this.inherited('_onBlur', arguments);
-                       // Usually the parent closes the child widget but if this is a context
-                       // menu then there is no parent
-                       dijit.popup.close(this);
-                       // don't try to restore focus; user has clicked another part of the screen
-                       // and set focus there
-               };
-       },
 
-       uninitialize: function(){
-               dojo.forEach(this._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
-               this.inherited(arguments);
-       }
-}
-);
+return declare("dijit.layout._TabContainerBase", [StackContainer, _TemplatedMixin], {
+       // summary:
+       //              Abstract base class for TabContainer.   Must define _makeController() to instantiate
+       //              and return the widget that displays the tab labels
+       // description:
+       //              A TabContainer is a container that has multiple panes, but shows only
+       //              one pane at a time.  There are a set of tabs corresponding to each pane,
+       //              where each tab has the name (aka title) of the pane, and optionally a close button.
 
-// Back-compat (TODO: remove in 2.0)
+       // tabPosition: String
+       //              Defines where tabs go relative to tab content.
+       //              "top", "bottom", "left-h", "right-h"
+       tabPosition: "top",
 
+       baseClass: "dijitTabContainer",
 
+       // tabStrip: [const] Boolean
+       //              Defines whether the tablist gets an extra class for layouting, putting a border/shading
+       //              around the set of tabs.   Not supported by claro theme.
+       tabStrip: false,
 
+       // nested: [const] Boolean
+       //              If true, use styling for a TabContainer nested inside another TabContainer.
+       //              For tundra etc., makes tabs look like links, and hides the outer
+       //              border since the outer TabContainer already has a border.
+       nested: false,
 
+       templateString: template,
 
+       postMixInProperties: function(){
+               // set class name according to tab position, ex: dijitTabContainerTop
+               this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");
 
-}
+               this.srcNodeRef && domStyle.set(this.srcNodeRef, "visibility", "hidden");
 
-if(!dojo._hasResource["dijit.form.Select"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.Select"] = true;
-dojo.provide("dijit.form.Select");
+               this.inherited(arguments);
+       },
 
+       buildRendering: function(){
+               this.inherited(arguments);
 
+               // Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
+               this.tablist = this._makeController(this.tablistNode);
 
+               if(!this.doLayout){ domClass.add(this.domNode, "dijitTabContainerNoLayout"); }
 
+               if(this.nested){
+                       /* workaround IE's lack of support for "a > b" selectors by
+                        * tagging each node in the template.
+                        */
+                       domClass.add(this.domNode, "dijitTabContainerNested");
+                       domClass.add(this.tablist.containerNode, "dijitTabContainerTabListNested");
+                       domClass.add(this.tablistSpacer, "dijitTabContainerSpacerNested");
+                       domClass.add(this.containerNode, "dijitTabPaneWrapperNested");
+               }else{
+                       domClass.add(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
+               }
+       },
 
+       _setupChild: function(/*dijit._Widget*/ tab){
+               // Overrides StackContainer._setupChild().
+               domClass.add(tab.domNode, "dijitTabPane");
+               this.inherited(arguments);
+       },
 
+       startup: function(){
+               if(this._started){ return; }
 
+               // wire up the tablist and its tabs
+               this.tablist.startup();
 
-dojo.declare("dijit.form._SelectMenu", dijit.Menu, {
-       // summary:
-       //              An internally-used menu for dropdown that allows us a vertical scrollbar
-       buildRendering: function(){
-               // summary:
-               //              Stub in our own changes, so that our domNode is not a table
-               //              otherwise, we won't respond correctly to heights/overflows
                this.inherited(arguments);
-               var o = (this.menuTableNode = this.domNode);
-               var n = (this.domNode = dojo.create("div", {style: {overflowX: "hidden", overflowY: "scroll"}}));
-               if(o.parentNode){
-                       o.parentNode.replaceChild(n, o);
-               }
-               dojo.removeClass(o, "dijitMenuTable");
-               n.className = o.className + " dijitSelectMenu";
-               o.className = "dijitReset dijitMenuTable";
-               dijit.setWaiRole(o,"listbox");
-               dijit.setWaiRole(n,"presentation");
-               n.appendChild(o);
        },
-       resize: function(/*Object*/ mb){
-               // summary:
-               //              Overridden so that we are able to handle resizing our
-               //              internal widget.  Note that this is not a "full" resize
-               //              implementation - it only works correctly if you pass it a
-               //              marginBox.
-               //
-               // mb: Object
-               //              The margin box to set this dropdown to.
-               if(mb){
-                       dojo.marginBox(this.domNode, mb);
-                       if("w" in mb){
-                               // We've explicitly set the wrapper <div>'s width, so set <table> width to match.
-                               // 100% is safer than a pixel value because there may be a scroll bar with
-                               // browser/OS specific width.
-                               this.menuTableNode.style.width = "100%";
-                       }
-               }
-       }
-});
-
-dojo.declare("dijit.form.Select", [dijit.form._FormSelectWidget, dijit._HasDropDown], {
-       // summary:
-       //              This is a "styleable" select box - it is basically a DropDownButton which
-       //              can take a <select> as its input.
 
-       baseClass: "dijitSelect",
+       layout: function(){
+               // Overrides StackContainer.layout().
+               // Configure the content pane to take up all the space except for where the tabs are
 
-       templateString: dojo.cache("dijit.form", "templates/Select.html", "<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdojoAttachPoint=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\twaiRole=\"combobox\" waiState=\"haspopup-true\"\n\t><tbody waiRole=\"presentation\"><tr waiRole=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\" waiRole=\"presentation\"\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"  dojoAttachPoint=\"containerNode,_popupStateNode\"></span\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} dojoAttachPoint=\"valueNode\" value=\"${value}\" waiState=\"hidden-true\"\n\t\t/></td><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdojoAttachPoint=\"titleNode\" waiRole=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" waiRole=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" waiRole=\"presentation\">&#9660;</div\n\t\t></td\n\t></tr></tbody\n></table>\n"),
+               if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;}
 
-       // attributeMap: Object
-       //              Add in our style to be applied to the focus node
-       attributeMap: dojo.mixin(dojo.clone(dijit.form._FormSelectWidget.prototype.attributeMap),{style:"tableNode"}),
+               var sc = this.selectedChildWidget;
 
-       // required: Boolean
-       //              Can be true or false, default is false.
-       required: false,
+               if(this.doLayout){
+                       // position and size the titles and the container node
+                       var titleAlign = this.tabPosition.replace(/-h/, "");
+                       this.tablist.layoutAlign = titleAlign;
+                       var children = [this.tablist, {
+                               domNode: this.tablistSpacer,
+                               layoutAlign: titleAlign
+                       }, {
+                               domNode: this.containerNode,
+                               layoutAlign: "client"
+                       }];
+                       layoutUtils.layoutChildren(this.domNode, this._contentBox, children);
 
-       // state: String
-       //              Shows current state (ie, validation result) of input (Normal, Warning, or Error)
-       state: "",
+                       // Compute size to make each of my children.
+                       // children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
+                       this._containerContentBox = layoutUtils.marginBox2contentBox(this.containerNode, children[2]);
 
-       //      tooltipPosition: String[]
-       //              See description of dijit.Tooltip.defaultPosition for details on this parameter.
-       tooltipPosition: [],
+                       if(sc && sc.resize){
+                               sc.resize(this._containerContentBox);
+                       }
+               }else{
+                       // just layout the tab controller, so it can position left/right buttons etc.
+                       if(this.tablist.resize){
+                               //make the tabs zero width so that they don't interfere with width calc, then reset
+                               var s = this.tablist.domNode.style;
+                               s.width="0";
+                               var width = domGeometry.getContentBox(this.domNode).w;
+                               s.width="";
+                               this.tablist.resize({w: width});
+                       }
 
-       // emptyLabel: string
-       //              What to display in an "empty" dropdown
-       emptyLabel: "",
+                       // and call resize() on the selected pane just to tell it that it's been made visible
+                       if(sc && sc.resize){
+                               sc.resize();
+                       }
+               }
+       },
 
-       // _isLoaded: Boolean
-       //              Whether or not we have been loaded
-       _isLoaded: false,
+       destroy: function(){
+               if(this.tablist){
+                       this.tablist.destroy();
+               }
+               this.inherited(arguments);
+       }
+});
 
-       // _childrenLoaded: Boolean
-       //              Whether or not our children have been loaded
-       _childrenLoaded: false,
+});
 
-       _fillContent: function(){
-               // summary:
-               //              Set the value to be the first, or the selected index
-               this.inherited(arguments);
-               if(this.options.length && !this.value && this.srcNodeRef){
-                       var si = this.srcNodeRef.selectedIndex;
-                       this.value = this.options[si != -1 ? si : 0].value;
-               }
+},
+'dojo/store/Memory':function(){
+define("dojo/store/Memory", ["../_base/declare", "./util/QueryResults", "./util/SimpleQueryEngine"], function(declare, QueryResults, SimpleQueryEngine) {
+  //  module:
+  //    dojo/store/Memory
+  //  summary:
+  //    The module defines an in-memory object store.
 
-               // Create the dropDown widget
-               this.dropDown = new dijit.form._SelectMenu({id: this.id + "_menu"});
-               dojo.addClass(this.dropDown.domNode, this.baseClass + "Menu");
-       },
 
-       _getMenuItemForOption: function(/*dijit.form.__SelectOption*/ option){
-               // summary:
-               //              For the given option, return the menu item that should be
-               //              used to display it.  This can be overridden as needed
-               if(!option.value){
-                       // We are a separator (no label set for it)
-                       return new dijit.MenuSeparator();
+return declare("dojo.store.Memory", null, {
+       // summary:
+       //              This is a basic in-memory object store. It implements dojo.store.api.Store.
+       constructor: function(/*dojo.store.Memory*/ options){
+               // summary:
+               //              Creates a memory object store.
+               // options:
+               //              This provides any configuration information that will be mixed into the store.
+               //              This should generally include the data property to provide the starting set of data.
+               for(var i in options){
+                       this[i] = options[i];
+               }
+               this.setData(this.data || []);
+       },
+       // data: Array
+       //              The array of all the objects in the memory store
+       data:null,
+
+       // idProperty: String
+       //              Indicates the property to use as the identity property. The values of this
+       //              property should be unique.
+       idProperty: "id",
+
+       // index: Object
+       //              An index of data indices into the data array by id
+       index:null,
+
+       // queryEngine: Function
+       //              Defines the query engine to use for querying the data store
+       queryEngine: SimpleQueryEngine,
+       get: function(id){
+               //      summary:
+               //              Retrieves an object by its identity
+               //      id: Number
+               //              The identity to use to lookup the object
+               //      returns: Object
+               //              The object in the store that matches the given id.
+               return this.data[this.index[id]];
+       },
+       getIdentity: function(object){
+               //      summary:
+               //              Returns an object's identity
+               //      object: Object
+               //              The object to get the identity from
+               //      returns: Number
+               return object[this.idProperty];
+       },
+       put: function(object, options){
+               //      summary:
+               //              Stores an object
+               //      object: Object
+               //              The object to store.
+               //      options: dojo.store.api.Store.PutDirectives??
+               //              Additional metadata for storing the data.  Includes an "id"
+               //              property if a specific id is to be used.
+               //      returns: Number
+               var data = this.data,
+                       index = this.index,
+                       idProperty = this.idProperty;
+               var id = (options && "id" in options) ? options.id : idProperty in object ? object[idProperty] : Math.random();
+               if(id in index){
+                       // object exists
+                       if(options && options.overwrite === false){
+                               throw new Error("Object already exists");
+                       }
+                       // replace the entry in data
+                       data[index[id]] = object;
                }else{
-                       // Just a regular menu option
-                       var click = dojo.hitch(this, "_setValueAttr", option);
-                       var item = new dijit.MenuItem({
-                               option: option,
-                               label: option.label,
-                               onClick: click,
-                               disabled: option.disabled || false
-                       });
-                       dijit.setWaiRole(item.focusNode, "listitem");
-                       return item;
+                       // add the new object
+                       index[id] = data.push(object) - 1;
+               }
+               return id;
+       },
+       add: function(object, options){
+               //      summary:
+               //              Creates an object, throws an error if the object already exists
+               //      object: Object
+               //              The object to store.
+               //      options: dojo.store.api.Store.PutDirectives??
+               //              Additional metadata for storing the data.  Includes an "id"
+               //              property if a specific id is to be used.
+               //      returns: Number
+               (options = options || {}).overwrite = false;
+               // call put with overwrite being false
+               return this.put(object, options);
+       },
+       remove: function(id){
+               //      summary:
+               //              Deletes an object by its identity
+               //      id: Number
+               //              The identity to use to delete the object
+               // returns: Boolean
+               //              Returns true if an object was removed, falsy (undefined) if no object matched the id
+               var index = this.index;
+               var data = this.data;
+               if(id in index){
+                       data.splice(index[id], 1);
+                       // now we have to reindex
+                       this.setData(data);
+                       return true;
                }
        },
-
-       _addOptionItem: function(/*dijit.form.__SelectOption*/ option){
-               // summary:
-               //              For the given option, add an option to our dropdown.
-               //              If the option doesn't have a value, then a separator is added
-               //              in that place.
-               if(this.dropDown){
-                       this.dropDown.addChild(this._getMenuItemForOption(option));
+       query: function(query, options){
+               //      summary:
+               //              Queries the store for objects.
+               //      query: Object
+               //              The query to use for retrieving objects from the store.
+               //      options: dojo.store.api.Store.QueryOptions?
+               //              The optional arguments to apply to the resultset.
+               //      returns: dojo.store.api.Store.QueryResults
+               //              The results of the query, extended with iterative methods.
+               //
+               //      example:
+               //              Given the following store:
+               //
+               //      |       var store = new dojo.store.Memory({
+               //      |               data: [
+               //      |                       {id: 1, name: "one", prime: false },
+               //      |                       {id: 2, name: "two", even: true, prime: true},
+               //      |                       {id: 3, name: "three", prime: true},
+               //      |                       {id: 4, name: "four", even: true, prime: false},
+               //      |                       {id: 5, name: "five", prime: true}
+               //      |               ]
+               //      |       });
+               //
+               //      ...find all items where "prime" is true:
+               //
+               //      |       var results = store.query({ prime: true });
+               //
+               //      ...or find all items where "even" is true:
+               //
+               //      |       var results = store.query({ even: true });
+               return QueryResults(this.queryEngine(query, options)(this.data));
+       },
+       setData: function(data){
+               //      summary:
+               //              Sets the given data as the source for this store, and indexes it
+               //      data: Object[]
+               //              An array of objects to use as the source of data.
+               if(data.items){
+                       // just for convenience with the data format IFRS expects
+                       this.idProperty = data.identifier;
+                       data = this.data = data.items;
+               }else{
+                       this.data = data;
                }
-       },
-
-       _getChildren: function(){
-               if(!this.dropDown){
-                       return [];
+               this.index = {};
+               for(var i = 0, l = data.length; i < l; i++){
+                       this.index[data[i][this.idProperty]] = i;
                }
-               return this.dropDown.getChildren();
-       },
+       }
+});
 
-       _loadChildren: function(/*Boolean*/ loadMenuItems){
-               // summary:
-               //              Resets the menu and the length attribute of the button - and
-               //              ensures that the label is appropriately set.
-               //      loadMenuItems: Boolean
-               //              actually loads the child menu items - we only do this when we are
-               //              populating for showing the dropdown.
+});
 
-               if(loadMenuItems === true){
-                       // this.inherited destroys this.dropDown's child widgets (MenuItems).
-                       // Avoid this.dropDown (Menu widget) having a pointer to a destroyed widget (which will cause
-                       // issues later in _setSelected). (see #10296)
-                       if(this.dropDown){
-                               delete this.dropDown.focusedChild;
-                       }
-                       if(this.options.length){
-                               this.inherited(arguments);
-                       }else{
-                               // Drop down menu is blank but add one blank entry just so something appears on the screen
-                               // to let users know that they are no choices (mimicing native select behavior)
-                               dojo.forEach(this._getChildren(), function(child){ child.destroyRecursive(); });
-                               var item = new dijit.MenuItem({label: "&nbsp;"});
-                               this.dropDown.addChild(item);
-                       }
-               }else{
-                       this._updateSelection();
-               }
+},
+'url:dijit/templates/Tooltip.html':"<div class=\"dijitTooltip dijitTooltipLeft\" id=\"dojoTooltip\"\n\t><div class=\"dijitTooltipContainer dijitTooltipContents\" data-dojo-attach-point=\"containerNode\" role='alert'></div\n\t><div class=\"dijitTooltipConnector\" data-dojo-attach-point=\"connectorNode\"></div\n></div>\n",
+'dijit/_base/sniff':function(){
+define("dijit/_base/sniff", [ "dojo/uacss" ], function(){
+       // module:
+       //              dijit/_base/sniff
+       // summary:
+       //              Back compatibility module, new code should require dojo/uacss directly instead of this module.
+});
 
-               var len = this.options.length;
-               this._isLoaded = false;
-               this._childrenLoaded = true;
+},
+'dijit/Toolbar':function(){
+define("dijit/Toolbar", [
+       "require",
+       "dojo/_base/declare", // declare
+       "dojo/_base/kernel",
+       "dojo/keys", // keys.LEFT_ARROW keys.RIGHT_ARROW
+       "dojo/ready",
+       "./_Widget",
+       "./_KeyNavContainer",
+       "./_TemplatedMixin"
+], function(require, declare, kernel, keys, ready, _Widget, _KeyNavContainer, _TemplatedMixin){
 
-               if(!this._loadingStore){
-                       // Don't call this if we are loading - since we will handle it later
-                       this._setValueAttr(this.value);
-               }
-       },
+/*=====
+       var _Widget = dijit._Widget;
+       var _KeyNavContainer = dijit._KeyNavContainer;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+=====*/
 
-       _setValueAttr: function(value){
-               this.inherited(arguments);
-               dojo.attr(this.valueNode, "value", this.get("value"));
-       },
+       // module:
+       //              dijit/Toolbar
+       // summary:
+       //              A Toolbar widget, used to hold things like `dijit.Editor` buttons
 
-       _setDisplay: function(/*String*/ newDisplay){
-               // summary:
-               //              sets the display for the given value (or values)
-               this.containerNode.innerHTML = '<span class="dijitReset dijitInline ' + this.baseClass + 'Label">' +
-                                       (newDisplay || this.emptyLabel || "&nbsp;") +
-                                       '</span>';
-               dijit.setWaiState(this.focusNode, "valuetext", (newDisplay || this.emptyLabel || "&nbsp;") );
-       },
 
-       validate: function(/*Boolean*/ isFocused){
-               // summary:
-               //              Called by oninit, onblur, and onkeypress.
-               // description:
-               //              Show missing or invalid messages if appropriate, and highlight textbox field.
-               //              Used when a select is initially set to no value and the user is required to
-               //              set the value.
-               
-               var isValid = this.isValid(isFocused);
-               this.state = isValid ? "" : "Error";
-               this._setStateClass();
-               dijit.setWaiState(this.focusNode, "invalid", isValid ? "false" : "true");
-               var message = isValid ? "" : this._missingMsg;
-               if(this._message !== message){
-                       this._message = message;
-                       dijit.hideTooltip(this.domNode);
-                       if(message){
-                               dijit.showTooltip(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
-                       }
-               }
-               return isValid;
-       },
+       // Back compat w/1.6, remove for 2.0
+       if(!kernel.isAsync){
+               ready(0, function(){
+                       var requires = ["dijit/ToolbarSeparator"];
+                       require(requires);      // use indirection so modules not rolled into a build
+               });
+       }
 
-       isValid: function(/*Boolean*/ isFocused){
+       return declare("dijit.Toolbar", [_Widget, _TemplatedMixin, _KeyNavContainer], {
                // summary:
-               //              Whether or not this is a valid value.   The only way a Select
-               //              can be invalid is when it's required but nothing is selected.
-               return (!this.required || !(/^\s*$/.test(this.value)));
-       },
+               //              A Toolbar widget, used to hold things like `dijit.Editor` buttons
 
-       reset: function(){
-               // summary:
-               //              Overridden so that the state will be cleared.
-               this.inherited(arguments);
-               dijit.hideTooltip(this.domNode);
-               this.state = "";
-               this._setStateClass();
-               delete this._message;
-       },
+               templateString:
+                       '<div class="dijit" role="toolbar" tabIndex="${tabIndex}" data-dojo-attach-point="containerNode">' +
+                       '</div>',
 
-       postMixInProperties: function(){
-               // summary:
-               //              set the missing message
-               this.inherited(arguments);
-               this._missingMsg = dojo.i18n.getLocalization("dijit.form", "validate",
-                                                                       this.lang).missingMessage;
-       },
+               baseClass: "dijitToolbar",
 
-       postCreate: function(){
-               this.inherited(arguments);
-               if(this.tableNode.style.width){
-                       dojo.addClass(this.domNode, this.baseClass + "FixedWidth");
+               postCreate: function(){
+                       this.inherited(arguments);
+
+                       this.connectKeyNavHandlers(
+                               this.isLeftToRight() ? [keys.LEFT_ARROW] : [keys.RIGHT_ARROW],
+                               this.isLeftToRight() ? [keys.RIGHT_ARROW] : [keys.LEFT_ARROW]
+                       );
                }
-       },
+       });
+});
 
-       isLoaded: function(){
-               return this._isLoaded;
-       },
+},
+'dijit/layout/StackContainer':function(){
+define("dijit/layout/StackContainer", [
+       "dojo/_base/array", // array.forEach array.indexOf array.some
+       "dojo/cookie", // cookie
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.replace
+       "dojo/_base/kernel",    // kernel.isAsync
+       "dojo/_base/lang",      // lang.extend
+       "dojo/ready",
+       "dojo/topic", // publish
+       "../registry",  // registry.byId
+       "../_WidgetBase",
+       "./_LayoutWidget",
+       "dojo/i18n!../nls/common"
+], function(array, cookie, declare, domClass, kernel, lang, ready, topic,
+                       registry, _WidgetBase, _LayoutWidget){
 
-       loadDropDown: function(/*Function*/ loadCallback){
-               // summary:
-               //              populates the menu
-               this._loadChildren(true);
-               this._isLoaded = true;
-               loadCallback();
-       },
+/*=====
+var _WidgetBase = dijit._WidgetBase;
+var _LayoutWidget = dijit.layout._LayoutWidget;
+var StackController = dijit.layout.StackController;
+=====*/
 
-       closeDropDown: function(){
-               // overriding _HasDropDown.closeDropDown()
-               this.inherited(arguments);
-
-               if(this.dropDown && this.dropDown.menuTableNode){
-                       // Erase possible width: 100% setting from _SelectMenu.resize().
-                       // Leaving it would interfere with the next openDropDown() call, which
-                       // queries the natural size of the drop down.
-                       this.dropDown.menuTableNode.style.width = "";
-               }
-       },
-
-       uninitialize: function(preserveDom){
-               if(this.dropDown && !this.dropDown._destroyed){
-                       this.dropDown.destroyRecursive(preserveDom);
-                       delete this.dropDown;
-               }
-               this.inherited(arguments);
-       }
-});
+// module:
+//             dijit/layout/StackContainer
+// summary:
+//             A container that has multiple children, but shows only one child at a time.
 
+// Back compat w/1.6, remove for 2.0
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/layout/StackController"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
 }
 
-if(!dojo._hasResource["dijit.form.SimpleTextarea"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.form.SimpleTextarea"] = true;
-dojo.provide("dijit.form.SimpleTextarea");
+// These arguments can be specified for the children of a StackContainer.
+// Since any widget can be specified as a StackContainer child, mix them
+// into the base widget class.  (This is a hack, but it's effective.)
+lang.extend(_WidgetBase, {
+       // selected: Boolean
+       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
+       //              Specifies that this widget should be the initially displayed pane.
+       //              Note: to change the selected child use `dijit.layout.StackContainer.selectChild`
+       selected: false,
+
+       // closable: Boolean
+       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
+       //              True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
+       closable: false,
 
+       // iconClass: String
+       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
+       //              CSS Class specifying icon to use in label associated with this pane.
+       iconClass: "dijitNoIcon",
 
+       // showTitle: Boolean
+       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
+       //              When true, display title of this widget as tab label etc., rather than just using
+       //              icon specified in iconClass
+       showTitle: true
+});
 
-dojo.declare("dijit.form.SimpleTextarea",
-       dijit.form.TextBox,
-       {
+return declare("dijit.layout.StackContainer", _LayoutWidget, {
        // summary:
-       //              A simple textarea that degrades, and responds to
-       //              minimal LayoutContainer usage, and works with dijit.form.Form.
-       //              Doesn't automatically size according to input, like Textarea.
+       //              A container that has multiple children, but shows only
+       //              one child at a time
        //
-       // example:
-       //      |       <textarea dojoType="dijit.form.SimpleTextarea" name="foo" value="bar" rows=30 cols=40></textarea>
+       // description:
+       //              A container for widgets (ContentPanes, for example) That displays
+       //              only one Widget at a time.
        //
-       // example:
-       //      |       new dijit.form.SimpleTextarea({ rows:20, cols:30 }, "foo");
+       //              Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild
+       //
+       //              Can be base class for container, Wizard, Show, etc.
 
-       baseClass: "dijitTextBox dijitTextArea",
+       // doLayout: Boolean
+       //              If true, change the size of my currently displayed child to match my size
+       doLayout: true,
 
-       attributeMap: dojo.delegate(dijit.form._FormValueWidget.prototype.attributeMap, {
-               rows:"textbox", cols: "textbox"
-       }),
+       // persist: Boolean
+       //              Remembers the selected child across sessions
+       persist: false,
 
-       // rows: Number
-       //              The number of rows of text.
-       rows: "3",
+       baseClass: "dijitStackContainer",
 
-       // rows: Number
-       //              The number of characters per line.
-       cols: "20",
+/*=====
+       // selectedChildWidget: [readonly] dijit._Widget
+       //              References the currently selected child widget, if any.
+       //              Adjust selected child with selectChild() method.
+       selectedChildWidget: null,
+=====*/
 
-       templateString: "<textarea ${!nameAttrSetting} dojoAttachPoint='focusNode,containerNode,textbox' autocomplete='off'></textarea>",
+       buildRendering: function(){
+               this.inherited(arguments);
+               domClass.add(this.domNode, "dijitLayoutContainer");
+               this.containerNode.setAttribute("role", "tabpanel");
+       },
 
-       postMixInProperties: function(){
-               // Copy value from srcNodeRef, unless user specified a value explicitly (or there is no srcNodeRef)
-               if(!this.value && this.srcNodeRef){
-                       this.value = this.srcNodeRef.value;
-               }
+       postCreate: function(){
                this.inherited(arguments);
+               this.connect(this.domNode, "onkeypress", this._onKeyPress);
        },
 
-       filter: function(/*String*/ value){
-               // Override TextBox.filter to deal with newlines... specifically (IIRC) this is for IE which writes newlines
-               // as \r\n instead of just \n
-               if(value){
-                       value = value.replace(/\r/g,"");
+       startup: function(){
+               if(this._started){ return; }
+
+               var children = this.getChildren();
+
+               // Setup each page panel to be initially hidden
+               array.forEach(children, this._setupChild, this);
+
+               // Figure out which child to initially display, defaulting to first one
+               if(this.persist){
+                       this.selectedChildWidget = registry.byId(cookie(this.id + "_selectedChild"));
+               }else{
+                       array.some(children, function(child){
+                               if(child.selected){
+                                       this.selectedChildWidget = child;
+                               }
+                               return child.selected;
+                       }, this);
+               }
+               var selected = this.selectedChildWidget;
+               if(!selected && children[0]){
+                       selected = this.selectedChildWidget = children[0];
+                       selected.selected = true;
                }
-               return this.inherited(arguments);
-       },
 
-       postCreate: function(){
+               // Publish information about myself so any StackControllers can initialize.
+               // This needs to happen before this.inherited(arguments) so that for
+               // TabContainer, this._contentBox doesn't include the space for the tab labels.
+               topic.publish(this.id+"-startup", {children: children, selected: selected});
+
+               // Startup each child widget, and do initial layout like setting this._contentBox,
+               // then calls this.resize() which does the initial sizing on the selected child.
                this.inherited(arguments);
-               if(dojo.isIE && this.cols){ // attribute selectors is not supported in IE6
-                       dojo.addClass(this.textbox, "dijitTextAreaCols");
-               }
        },
 
-       _previousValue: "",
-       _onInput: function(/*Event?*/ e){
-               // Override TextBox._onInput() to enforce maxLength restriction
-               if(this.maxLength){
-                       var maxLength = parseInt(this.maxLength);
-                       var value = this.textbox.value.replace(/\r/g,'');
-                       var overflow = value.length - maxLength;
-                       if(overflow > 0){
-                               if(e){ dojo.stopEvent(e); }
-                               var textarea = this.textbox;
-                               if(textarea.selectionStart){
-                                       var pos = textarea.selectionStart;
-                                       var cr = 0;
-                                       if(dojo.isOpera){
-                                               cr = (this.textbox.value.substring(0,pos).match(/\r/g) || []).length;
-                                       }
-                                       this.textbox.value = value.substring(0,pos-overflow-cr)+value.substring(pos-cr);
-                                       textarea.setSelectionRange(pos-overflow, pos-overflow);
-                               }else if(dojo.doc.selection){ //IE
-                                       textarea.focus();
-                                       var range = dojo.doc.selection.createRange();
-                                       // delete overflow characters
-                                       range.moveStart("character", -overflow);
-                                       range.text = '';
-                                       // show cursor
-                                       range.select();
-                               }
+       resize: function(){
+               // Resize is called when we are first made visible (it's called from startup()
+               // if we are initially visible). If this is the first time we've been made
+               // visible then show our first child.
+               if(!this._hasBeenShown){
+                       this._hasBeenShown = true;
+                       var selected = this.selectedChildWidget;
+                       if(selected){
+                               this._showChild(selected);
                        }
-                       this._previousValue = this.textbox.value;
                }
                this.inherited(arguments);
-       }
-});
-
-}
+       },
 
-if(!dojo._hasResource["dijit.InlineEditBox"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.InlineEditBox"] = true;
-dojo.provide("dijit.InlineEditBox");
+       _setupChild: function(/*dijit._Widget*/ child){
+               // Overrides _LayoutWidget._setupChild()
 
+               this.inherited(arguments);
 
+               domClass.replace(child.domNode, "dijitHidden", "dijitVisible");
 
+               // remove the title attribute so it doesn't show up when i hover
+               // over a node
+               child.domNode.title = "";
+       },
 
+       addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+               // Overrides _Container.addChild() to do layout and publish events
 
+               this.inherited(arguments);
 
+               if(this._started){
+                       topic.publish(this.id+"-addChild", child, insertIndex); // publish
 
+                       // in case the tab titles have overflowed from one line to two lines
+                       // (or, if this if first child, from zero lines to one line)
+                       // TODO: w/ScrollingTabController this is no longer necessary, although
+                       // ScrollTabController.resize() does need to get called to show/hide
+                       // the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild().
+                       // If this is updated to not layout [except for initial child added / last child removed], update
+                       // "childless startup" test in StackContainer.html to check for no resize event after second addChild()
+                       this.layout();
 
+                       // if this is the first child, then select it
+                       if(!this.selectedChildWidget){
+                               this.selectChild(child);
+                       }
+               }
+       },
 
+       removeChild: function(/*dijit._Widget*/ page){
+               // Overrides _Container.removeChild() to do layout and publish events
 
-dojo.declare("dijit.InlineEditBox",
-       dijit._Widget,
-       {
-       // summary:
-       //              An element with in-line edit capabilites
-       //
-       // description:
-       //              Behavior for an existing node (`<p>`, `<div>`, `<span>`, etc.) so that
-       //              when you click it, an editor shows up in place of the original
-       //              text.  Optionally, Save and Cancel button are displayed below the edit widget.
-       //              When Save is clicked, the text is pulled from the edit
-       //              widget and redisplayed and the edit widget is again hidden.
-       //              By default a plain Textarea widget is used as the editor (or for
-       //              inline values a TextBox), but you can specify an editor such as
-       //              dijit.Editor (for editing HTML) or a Slider (for adjusting a number).
-       //              An edit widget must support the following API to be used:
-       //                      - displayedValue or value as initialization parameter,
-       //                      and available through set('displayedValue') / set('value')
-       //                      - void focus()
-       //                      - DOM-node focusNode = node containing editable text
+               this.inherited(arguments);
 
-       // editing: [readonly] Boolean
-       //              Is the node currently in edit mode?
-       editing: false,
+               if(this._started){
+                       // this will notify any tablists to remove a button; do this first because it may affect sizing
+                       topic.publish(this.id + "-removeChild", page);  // publish
+               }
 
-       // autoSave: Boolean
-       //              Changing the value automatically saves it; don't have to push save button
-       //              (and save button isn't even displayed)
-       autoSave: true,
+               // If all our children are being destroyed than don't run the code below (to select another page),
+               //  because we are deleting every page one by one
+               if(this._descendantsBeingDestroyed){ return; }
 
-       // buttonSave: String
-       //              Save button label
-       buttonSave: "",
+               // Select new page to display, also updating TabController to show the respective tab.
+               // Do this before layout call because it can affect the height of the TabController.
+               if(this.selectedChildWidget === page){
+                       this.selectedChildWidget = undefined;
+                       if(this._started){
+                               var children = this.getChildren();
+                               if(children.length){
+                                       this.selectChild(children[0]);
+                               }
+                       }
+               }
 
-       // buttonCancel: String
-       //              Cancel button label
-       buttonCancel: "",
+               if(this._started){
+                       // In case the tab titles now take up one line instead of two lines
+                       // (note though that ScrollingTabController never overflows to multiple lines),
+                       // or the height has changed slightly because of addition/removal of tab which close icon
+                       this.layout();
+               }
+       },
 
-       // renderAsHtml: Boolean
-       //              Set this to true if the specified Editor's value should be interpreted as HTML
-       //              rather than plain text (ex: `dijit.Editor`)
-       renderAsHtml: false,
+       selectChild: function(/*dijit._Widget|String*/ page, /*Boolean*/ animate){
+               // summary:
+               //              Show the given widget (which must be one of my children)
+               // page:
+               //              Reference to child widget or id of child widget
 
-       // editor: String
-       //              Class name for Editor widget
-       editor: "dijit.form.TextBox",
+               page = registry.byId(page);
 
-       // editorWrapper: String
-       //              Class name for widget that wraps the editor widget, displaying save/cancel
-       //              buttons.
-       editorWrapper: "dijit._InlineEditor",
+               if(this.selectedChildWidget != page){
+                       // Deselect old page and select new one
+                       var d = this._transition(page, this.selectedChildWidget, animate);
+                       this._set("selectedChildWidget", page);
+                       topic.publish(this.id+"-selectChild", page);    // publish
 
-       // editorParams: Object
-       //              Set of parameters for editor, like {required: true}
-       editorParams: {},
+                       if(this.persist){
+                               cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
+                       }
+               }
 
-       onChange: function(value){
-               // summary:
-               //              Set this handler to be notified of changes to value.
-               // tags:
-               //              callback
+               return d;               // If child has an href, promise that fires when the child's href finishes loading
        },
 
-       onCancel: function(){
+       _transition: function(newWidget, oldWidget /*===== ,  animate =====*/){
                // summary:
-               //              Set this handler to be notified when editing is cancelled.
+               //              Hide the old widget and display the new widget.
+               //              Subclasses should override this.
+               // newWidget: dijit._Widget
+               //              The newly selected widget.
+               // oldWidget: dijit._Widget
+               //              The previously selected widget.
+               // animate: Boolean
+               //              Used by AccordionContainer to turn on/off slide effect.
                // tags:
-               //              callback
-       },
-
-       // width: String
-       //              Width of editor.  By default it's width=100% (ie, block mode).
-       width: "100%",
-
-       // value: String
-       //              The display value of the widget in read-only mode
-       value: "",
-
-       // noValueIndicator: [const] String
-       //              The text that gets displayed when there is no value (so that the user has a place to click to edit)
-       noValueIndicator: dojo.isIE <= 6 ?      // font-family needed on IE6 but it messes up IE8
-               "<span style='font-family: wingdings; text-decoration: underline;'>&nbsp;&nbsp;&nbsp;&nbsp;&#x270d;&nbsp;&nbsp;&nbsp;&nbsp;</span>" :
-               "<span style='text-decoration: underline;'>&nbsp;&nbsp;&nbsp;&nbsp;&#x270d;&nbsp;&nbsp;&nbsp;&nbsp;</span>",
-
-       constructor: function(){
-               // summary:
-               //              Sets up private arrays etc.
-               // tags:
-               //              private
-               this.editorParams = {};
-       },
-
-       postMixInProperties: function(){
-               this.inherited(arguments);
-
-               // save pointer to original source node, since Widget nulls-out srcNodeRef
-               this.displayNode = this.srcNodeRef;
-
-               // connect handlers to the display node
-               var events = {
-                       ondijitclick: "_onClick",
-                       onmouseover: "_onMouseOver",
-                       onmouseout: "_onMouseOut",
-                       onfocus: "_onMouseOver",
-                       onblur: "_onMouseOut"
-               };
-               for(var name in events){
-                       this.connect(this.displayNode, name, events[name]);
-               }
-               dijit.setWaiRole(this.displayNode, "button");
-               if(!this.displayNode.getAttribute("tabIndex")){
-                       this.displayNode.setAttribute("tabIndex", 0);
+               //              protected extension
+               if(oldWidget){
+                       this._hideChild(oldWidget);
                }
+               var d = this._showChild(newWidget);
 
-               if(!this.value && !("value" in this.params)){ // "" is a good value if specified directly so check params){
-                  this.value = dojo.trim(this.renderAsHtml ? this.displayNode.innerHTML :
-                     (this.displayNode.innerText||this.displayNode.textContent||""));
-               }
-               if(!this.value){
-                   this.displayNode.innerHTML = this.noValueIndicator;
+               // Size the new widget, in case this is the first time it's being shown,
+               // or I have been resized since the last time it was shown.
+               // Note that page must be visible for resizing to work.
+               if(newWidget.resize){
+                       if(this.doLayout){
+                               newWidget.resize(this._containerContentBox || this._contentBox);
+                       }else{
+                               // the child should pick it's own size but we still need to call resize()
+                               // (with no arguments) to let the widget lay itself out
+                               newWidget.resize();
+                       }
                }
 
-               dojo.addClass(this.displayNode, 'dijitInlineEditBoxDisplayMode');
+               return d;       // If child has an href, promise that fires when the child's href finishes loading
        },
 
-       setDisabled: function(/*Boolean*/ disabled){
+       _adjacent: function(/*Boolean*/ forward){
                // summary:
-               //              Deprecated.   Use set('disabled', ...) instead.
-               // tags:
-               //              deprecated
-               dojo.deprecated("dijit.InlineEditBox.setDisabled() is deprecated.  Use set('disabled', bool) instead.", "", "2.0");
-               this.set('disabled', disabled);
+               //              Gets the next/previous child widget in this container from the current selection.
+               var children = this.getChildren();
+               var index = array.indexOf(children, this.selectedChildWidget);
+               index += forward ? 1 : children.length - 1;
+               return children[ index % children.length ]; // dijit._Widget
        },
 
-       _setDisabledAttr: function(/*Boolean*/ disabled){
+       forward: function(){
                // summary:
-               //              Hook to make set("disabled", ...) work.
-               //              Set disabled state of widget.
-               this.disabled = disabled;
-               dijit.setWaiState(this.domNode, "disabled", disabled);
-               if(disabled){
-                       this.displayNode.removeAttribute("tabIndex");
-               }else{
-                       this.displayNode.setAttribute("tabIndex", 0);
-               }
-               dojo.toggleClass(this.displayNode, "dijitInlineEditBoxDisplayModeDisabled", disabled);
+               //              Advance to next page.
+               return this.selectChild(this._adjacent(true), true);
        },
 
-       _onMouseOver: function(){
+       back: function(){
                // summary:
-               //              Handler for onmouseover and onfocus event.
-               // tags:
-               //              private
-               if(!this.disabled){
-                       dojo.addClass(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
-               }
+               //              Go back to previous page.
+               return this.selectChild(this._adjacent(false), true);
        },
 
-       _onMouseOut: function(){
-               // summary:
-               //              Handler for onmouseout and onblur event.
-               // tags:
-               //              private
-               dojo.removeClass(this.displayNode, "dijitInlineEditBoxDisplayModeHover");
+       _onKeyPress: function(e){
+               topic.publish(this.id+"-containerKeyPress", { e: e, page: this});       // publish
        },
 
-       _onClick: function(/*Event*/ e){
-               // summary:
-               //              Handler for onclick event.
-               // tags:
-               //              private
-               if(this.disabled){ return; }
-               if(e){ dojo.stopEvent(e); }
-               this._onMouseOut();
-
-               // Since FF gets upset if you move a node while in an event handler for that node...
-               setTimeout(dojo.hitch(this, "edit"), 0);
+       layout: function(){
+               // Implement _LayoutWidget.layout() virtual method.
+               var child = this.selectedChildWidget;
+               if(child && child.resize){
+                       if(this.doLayout){
+                               child.resize(this._containerContentBox || this._contentBox);
+                       }else{
+                               child.resize();
+                       }
+               }
        },
 
-       edit: function(){
+       _showChild: function(/*dijit._Widget*/ page){
                // summary:
-               //              Display the editor widget in place of the original (read only) markup.
-               // tags:
-               //              private
-
-               if(this.disabled || this.editing){ return; }
-               this.editing = true;
-
-               // save some display node values that can be restored later
-               this._savedPosition = dojo.style(this.displayNode, "position") || "static";
-               this._savedOpacity = dojo.style(this.displayNode, "opacity") || "1";
-               this._savedTabIndex = dojo.attr(this.displayNode, "tabIndex") || "0";
-
-               if(this.wrapperWidget){
-                       var ew = this.wrapperWidget.editWidget;
-                       ew.set("displayedValue" in ew ? "displayedValue" : "value", this.value);
-               }else{
-                       // Placeholder for edit widget
-                       // Put place holder (and eventually editWidget) before the display node so that it's positioned correctly
-                       // when Calendar dropdown appears, which happens automatically on focus.
-                       var placeholder = dojo.create("span", null, this.domNode, "before");
-
-                       // Create the editor wrapper (the thing that holds the editor widget and the save/cancel buttons)
-                       var ewc = dojo.getObject(this.editorWrapper);
-                       this.wrapperWidget = new ewc({
-                               value: this.value,
-                               buttonSave: this.buttonSave,
-                               buttonCancel: this.buttonCancel,
-                               dir: this.dir,
-                               lang: this.lang,
-                               tabIndex: this._savedTabIndex,
-                               editor: this.editor,
-                               inlineEditBox: this,
-                               sourceStyle: dojo.getComputedStyle(this.displayNode),
-                               save: dojo.hitch(this, "save"),
-                               cancel: dojo.hitch(this, "cancel")
-                       }, placeholder);
-               }
-               var ww = this.wrapperWidget;
-
-               if(dojo.isIE){
-                       dijit.focus(dijit.getFocus()); // IE (at least 8) needs help with tab order changes
-               }
-               // to avoid screen jitter, we first create the editor with position:absolute, visibility:hidden,
-               // and then when it's finished rendering, we switch from display mode to editor
-               // position:absolute releases screen space allocated to the display node
-               // opacity:0 is the same as visibility:hidden but is still focusable
-               // visiblity:hidden removes focus outline
+               //              Show the specified child by changing it's CSS, and call _onShow()/onShow() so
+               //              it can do any updates it needs regarding loading href's etc.
+               // returns:
+               //              Promise that fires when page has finished showing, or true if there's no href
+               var children = this.getChildren();
+               page.isFirstChild = (page == children[0]);
+               page.isLastChild = (page == children[children.length-1]);
+               page._set("selected", true);
 
-               dojo.style(this.displayNode, { position: "absolute", opacity: "0", display: "none" }); // makes display node invisible, display style used for focus-ability
-               dojo.style(ww.domNode, { position: this._savedPosition, visibility: "visible", opacity: "1" });
-               dojo.attr(this.displayNode, "tabIndex", "-1"); // needed by WebKit for TAB from editor to skip displayNode
+               domClass.replace(page.domNode, "dijitVisible", "dijitHidden");
 
-               // Replace the display widget with edit widget, leaving them both displayed for a brief time so that
-               // focus can be shifted without incident.  (browser may needs some time to render the editor.)
-               setTimeout(dojo.hitch(this, function(){
-                       ww.focus(); // both nodes are showing, so we can switch focus safely
-                       ww._resetValue = ww.getValue();
-               }), 0);
+               return (page._onShow && page._onShow()) || true;
        },
 
-       _onBlur: function(){
+       _hideChild: function(/*dijit._Widget*/ page){
                // summary:
-               //              Called when focus moves outside the InlineEditBox.
-               //              Performs garbage collection.
-               // tags:
-               //              private
-
-               this.inherited(arguments);
-               if(!this.editing){
-                       /* causes IE focus problems, see TooltipDialog_a11y.html...
-                       setTimeout(dojo.hitch(this, function(){
-                               if(this.wrapperWidget){
-                                       this.wrapperWidget.destroy();
-                                       delete this.wrapperWidget;
-                               }
-                       }), 0);
-                       */
-               }
-       },
+               //              Hide the specified child by changing it's CSS, and call _onHide() so
+               //              it's notified.
+               page._set("selected", false);
+               domClass.replace(page.domNode, "dijitHidden", "dijitVisible");
 
-       destroy: function(){
-               if(this.wrapperWidget){
-                       this.wrapperWidget.destroy();
-                       delete this.wrapperWidget;
-               }
-               this.inherited(arguments);
+               page.onHide && page.onHide();
        },
 
-       _showText: function(/*Boolean*/ focus){
+       closeChild: function(/*dijit._Widget*/ page){
                // summary:
-               //              Revert to display mode, and optionally focus on display node
+               //              Callback when user clicks the [X] to remove a page.
+               //              If onClose() returns true then remove and destroy the child.
                // tags:
                //              private
-
-               var ww = this.wrapperWidget;
-               dojo.style(ww.domNode, { position: "absolute", visibility: "hidden", opacity: "0" }); // hide the editor from mouse/keyboard events
-               dojo.style(this.displayNode, { position: this._savedPosition, opacity: this._savedOpacity, display: "" }); // make the original text visible
-               dojo.attr(this.displayNode, "tabIndex", this._savedTabIndex);
-               if(focus){
-                       dijit.focus(this.displayNode);
+               var remove = page.onClose(this, page);
+               if(remove){
+                       this.removeChild(page);
+                       // makes sure we can clean up executeScripts in ContentPane onUnLoad
+                       page.destroyRecursive();
                }
        },
 
-       save: function(/*Boolean*/ focus){
-               // summary:
-               //              Save the contents of the editor and revert to display mode.
-               // focus: Boolean
-               //              Focus on the display mode text
-               // tags:
-               //              private
-
-               if(this.disabled || !this.editing){ return; }
-               this.editing = false;
+       destroyDescendants: function(/*Boolean*/ preserveDom){
+               this._descendantsBeingDestroyed = true;
+               this.selectedChildWidget = undefined;
+               array.forEach(this.getChildren(), function(child){
+                       if(!preserveDom){
+                               this.removeChild(child);
+                       }
+                       child.destroyRecursive(preserveDom);
+               }, this);
+               this._descendantsBeingDestroyed = false;
+       }
+});
 
-               var ww = this.wrapperWidget;
-               var value = ww.getValue();
-               this.set('value', value); // display changed, formatted value
+});
 
-               // tell the world that we have changed
-               setTimeout(dojo.hitch(this, "onChange", value), 0); // setTimeout prevents browser freeze for long-running event handlers
+},
+'dojo/regexp':function(){
+define("dojo/regexp", ["./_base/kernel", "./_base/lang"], function(dojo, lang) {
+       // module:
+       //              dojo/regexp
+       // summary:
+       //              TODOC
 
-               this._showText(focus); // set focus as needed
-       },
+lang.getObject("regexp", true, dojo);
 
-       setValue: function(/*String*/ val){
-               // summary:
-               //              Deprecated.   Use set('value', ...) instead.
-               // tags:
-               //              deprecated
-               dojo.deprecated("dijit.InlineEditBox.setValue() is deprecated.  Use set('value', ...) instead.", "", "2.0");
-               return this.set("value", val);
-       },
+/*=====
+dojo.regexp = {
+       // summary: Regular expressions and Builder resources
+};
+=====*/
 
-       _setValueAttr: function(/*String*/ val){
-               // summary:
-               //              Hook to make set("value", ...) work.
-               //              Inserts specified HTML value into this node, or an "input needed" character if node is blank.
+dojo.regexp.escapeString = function(/*String*/str, /*String?*/except){
+       //      summary:
+       //              Adds escape sequences for special characters in regular expressions
+       // except:
+       //              a String with special characters to be left unescaped
 
-               this.value = val = dojo.trim(val);
-               if(!this.renderAsHtml){
-                       val = val.replace(/&/gm, "&amp;").replace(/</gm, "&lt;").replace(/>/gm, "&gt;").replace(/"/gm, "&quot;").replace(/\n/g, "<br>");
+       return str.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, function(ch){
+               if(except && except.indexOf(ch) != -1){
+                       return ch;
                }
-               this.displayNode.innerHTML = val || this.noValueIndicator;
-       },
-
-       getValue: function(){
-               // summary:
-               //              Deprecated.   Use get('value') instead.
-               // tags:
-               //              deprecated
-               dojo.deprecated("dijit.InlineEditBox.getValue() is deprecated.  Use get('value') instead.", "", "2.0");
-               return this.get("value");
-       },
-
-       cancel: function(/*Boolean*/ focus){
-               // summary:
-               //              Revert to display mode, discarding any changes made in the editor
-               // tags:
-               //              private
+               return "\\" + ch;
+       }); // String
+};
 
-               if(this.disabled || !this.editing){ return; }
-               this.editing = false;
+dojo.regexp.buildGroupRE = function(/*Object|Array*/arr, /*Function*/re, /*Boolean?*/nonCapture){
+       //      summary:
+       //              Builds a regular expression that groups subexpressions
+       //      description:
+       //              A utility function used by some of the RE generators. The
+       //              subexpressions are constructed by the function, re, in the second
+       //              parameter.  re builds one subexpression for each elem in the array
+       //              a, in the first parameter. Returns a string for a regular
+       //              expression that groups all the subexpressions.
+       // arr:
+       //              A single value or an array of values.
+       // re:
+       //              A function. Takes one parameter and converts it to a regular
+       //              expression.
+       // nonCapture:
+       //              If true, uses non-capturing match, otherwise matches are retained
+       //              by regular expression. Defaults to false
 
-               // tell the world that we have no changes
-               setTimeout(dojo.hitch(this, "onCancel"), 0); // setTimeout prevents browser freeze for long-running event handlers
+       // case 1: a is a single value.
+       if(!(arr instanceof Array)){
+               return re(arr); // String
+       }
 
-               this._showText(focus);
+       // case 2: a is an array
+       var b = [];
+       for(var i = 0; i < arr.length; i++){
+               // convert each elem to a RE
+               b.push(re(arr[i]));
        }
-});
 
-dojo.declare(
-       "dijit._InlineEditor",
-        [dijit._Widget, dijit._Templated],
-{
+        // join the REs as alternatives in a RE group.
+       return dojo.regexp.group(b.join("|"), nonCapture); // String
+};
+
+dojo.regexp.group = function(/*String*/expression, /*Boolean?*/nonCapture){
        // summary:
-       //              Internal widget used by InlineEditBox, displayed when in editing mode
-       //              to display the editor and maybe save/cancel buttons.  Calling code should
-       //              connect to save/cancel methods to detect when editing is finished
-       //
-       //              Has mainly the same parameters as InlineEditBox, plus these values:
-       //
-       // style: Object
-       //              Set of CSS attributes of display node, to replicate in editor
-       //
-       // value: String
-       //              Value as an HTML string or plain text string, depending on renderAsHTML flag
+       //              adds group match to expression
+       // nonCapture:
+       //              If true, uses non-capturing match, otherwise matches are retained
+       //              by regular expression.
+       return "(" + (nonCapture ? "?:":"") + expression + ")"; // String
+};
 
-       templateString: dojo.cache("dijit", "templates/InlineEditBox.html", "<span dojoAttachPoint=\"editNode\" waiRole=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdojoAttachEvent=\"onkeypress: _onKeyPress\"\n\t><span dojoAttachPoint=\"editorPlaceholder\"></span\n\t><span dojoAttachPoint=\"buttonContainer\"\n\t\t><button class='saveButton' dojoAttachPoint=\"saveButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:save\" label=\"${buttonSave}\"></button\n\t\t><button class='cancelButton' dojoAttachPoint=\"cancelButton\" dojoType=\"dijit.form.Button\" dojoAttachEvent=\"onClick:cancel\" label=\"${buttonCancel}\"></button\n\t></span\n></span>\n"),
-       widgetsInTemplate: true,
+return dojo.regexp;
+});
 
-       postMixInProperties: function(){
-               this.inherited(arguments);
-               this.messages = dojo.i18n.getLocalization("dijit", "common", this.lang);
-               dojo.forEach(["buttonSave", "buttonCancel"], function(prop){
-                       if(!this[prop]){ this[prop] = this.messages[prop]; }
-               }, this);
-       },
+},
+'dijit/form/_FormMixin':function(){
+define("dijit/form/_FormMixin", [
+       "dojo/_base/array", // array.every array.filter array.forEach array.indexOf array.map
+       "dojo/_base/declare", // declare
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.hitch lang.isArray
+       "dojo/window" // winUtils.scrollIntoView
+], function(array, declare, kernel, lang, winUtils){
+
+       // module:
+       //              dijit/form/_FormMixin
+       // summary:
+       //              Mixin for containers of form widgets (i.e. widgets that represent a single value
+       //              and can be children of a <form> node or dijit.form.Form widget)
 
-       postCreate: function(){
-               // Create edit widget in place in the template
-               var cls = dojo.getObject(this.editor);
+       return declare("dijit.form._FormMixin", null, {
+               // summary:
+               //              Mixin for containers of form widgets (i.e. widgets that represent a single value
+               //              and can be children of a <form> node or dijit.form.Form widget)
+               // description:
+               //              Can extract all the form widgets
+               //              values and combine them into a single javascript object, or alternately
+               //              take such an object and set the values for all the contained
+               //              form widgets
 
-               // Copy the style from the source
-               // Don't copy ALL properties though, just the necessary/applicable ones.
-               // wrapperStyle/destStyle code is to workaround IE bug where getComputedStyle().fontSize
-               // is a relative value like 200%, rather than an absolute value like 24px, and
-               // the 200% can refer *either* to a setting on the node or it's ancestor (see #11175)
-               var srcStyle = this.sourceStyle,
-                       editStyle = "line-height:" + srcStyle.lineHeight + ";",
-                       destStyle = dojo.getComputedStyle(this.domNode);
-               dojo.forEach(["Weight","Family","Size","Style"], function(prop){
-                       var textStyle = srcStyle["font"+prop],
-                               wrapperStyle = destStyle["font"+prop];
-                       if(wrapperStyle != textStyle){
-                               editStyle += "font-"+prop+":"+srcStyle["font"+prop]+";";
-                       }
-               }, this);
-               dojo.forEach(["marginTop","marginBottom","marginLeft", "marginRight"], function(prop){
-                       this.domNode.style[prop] = srcStyle[prop];
-               }, this);
-               var width = this.inlineEditBox.width;
-               if(width == "100%"){
-                       // block mode
-                       editStyle += "width:100%;";
-                       this.domNode.style.display = "block";
-               }else{
-                       // inline-block mode
-                       editStyle += "width:" + (width + (Number(width) == width ? "px" : "")) + ";";
-               }
-               var editorParams = dojo.delegate(this.inlineEditBox.editorParams, {
-                       style: editStyle,
-                       dir: this.dir,
-                       lang: this.lang
-               });
-               editorParams[ "displayedValue" in cls.prototype ? "displayedValue" : "value"] = this.value;
-               var ew = (this.editWidget = new cls(editorParams, this.editorPlaceholder));
+       /*=====
+               // value: Object
+               //              Name/value hash for each child widget with a name and value.
+               //              Child widgets without names are not part of the hash.
+               //
+               //              If there are multiple child widgets w/the same name, value is an array,
+               //              unless they are radio buttons in which case value is a scalar (since only
+               //              one radio button can be checked at a time).
+               //
+               //              If a child widget's name is a dot separated list (like a.b.c.d), it's a nested structure.
+               //
+               //              Example:
+               //      |       { name: "John Smith", interests: ["sports", "movies"] }
+       =====*/
 
-               if(this.inlineEditBox.autoSave){
-                       // Remove the save/cancel buttons since saving is done by simply tabbing away or
-                       // selecting a value from the drop down list
-                       dojo.destroy(this.buttonContainer);
+               // state: [readonly] String
+               //              Will be "Error" if one or more of the child widgets has an invalid value,
+               //              "Incomplete" if not all of the required child widgets are filled in.  Otherwise, "",
+               //              which indicates that the form is ready to be submitted.
+               state: "",
 
-                       // Selecting a value from a drop down list causes an onChange event and then we save
-                       this.connect(ew, "onChange", "_onChange");
+               //      TODO:
+               //      * Repeater
+               //      * better handling for arrays.  Often form elements have names with [] like
+               //      * people[3].sex (for a list of people [{name: Bill, sex: M}, ...])
+               //
+               //
 
-                       // ESC and TAB should cancel and save.  Note that edit widgets do a stopEvent() on ESC key (to
-                       // prevent Dialog from closing when the user just wants to revert the value in the edit widget),
-                       // so this is the only way we can see the key press event.
-                       this.connect(ew, "onKeyPress", "_onKeyPress");
-               }else{
-                       // If possible, enable/disable save button based on whether the user has changed the value
-                       if("intermediateChanges" in cls.prototype){
-                               ew.set("intermediateChanges", true);
-                               this.connect(ew, "onChange", "_onIntermediateChange");
-                               this.saveButton.set("disabled", true);
-                       }
-               }
-       },
+               _getDescendantFormWidgets: function(/*dijit._WidgetBase[]?*/ children){
+                       // summary:
+                       //              Returns all form widget descendants, searching through non-form child widgets like BorderContainer
+                       var res = [];
+                       array.forEach(children || this.getChildren(), function(child){
+                               if("value" in child){
+                                       res.push(child);
+                               }else{
+                                       res = res.concat(this._getDescendantFormWidgets(child.getChildren()));
+                               }
+                       }, this);
+                       return res;
+               },
 
-       _onIntermediateChange: function(val){
-               // summary:
-               //              Called for editor widgets that support the intermediateChanges=true flag as a way
-               //              to detect when to enable/disabled the save button
-               this.saveButton.set("disabled", (this.getValue() == this._resetValue) || !this.enableSave());
-       },
+               reset: function(){
+                       array.forEach(this._getDescendantFormWidgets(), function(widget){
+                               if(widget.reset){
+                                       widget.reset();
+                               }
+                       });
+               },
 
-       destroy: function(){
-               this.editWidget.destroy(true); // let the parent wrapper widget clean up the DOM
-               this.inherited(arguments);
-       },
+               validate: function(){
+                       // summary:
+                       //              returns if the form is valid - same as isValid - but
+                       //              provides a few additional (ui-specific) features.
+                       //              1 - it will highlight any sub-widgets that are not
+                       //                      valid
+                       //              2 - it will call focus() on the first invalid
+                       //                      sub-widget
+                       var didFocus = false;
+                       return array.every(array.map(this._getDescendantFormWidgets(), function(widget){
+                               // Need to set this so that "required" widgets get their
+                               // state set.
+                               widget._hasBeenBlurred = true;
+                               var valid = widget.disabled || !widget.validate || widget.validate();
+                               if(!valid && !didFocus){
+                                       // Set focus of the first non-valid widget
+                                       winUtils.scrollIntoView(widget.containerNode || widget.domNode);
+                                       widget.focus();
+                                       didFocus = true;
+                               }
+                               return valid;
+                       }), function(item){ return item; });
+               },
 
-       getValue: function(){
-               // summary:
-               //              Return the [display] value of the edit widget
-               var ew = this.editWidget;
-               return String(ew.get("displayedValue" in ew ? "displayedValue" : "value"));
-       },
+               setValues: function(val){
+                       kernel.deprecated(this.declaredClass+"::setValues() is deprecated. Use set('value', val) instead.", "", "2.0");
+                       return this.set('value', val);
+               },
+               _setValueAttr: function(/*Object*/ obj){
+                       // summary:
+                       //              Fill in form values from according to an Object (in the format returned by get('value'))
 
-       _onKeyPress: function(e){
-               // summary:
-               //              Handler for keypress in the edit box in autoSave mode.
-               // description:
-               //              For autoSave widgets, if Esc/Enter, call cancel/save.
-               // tags:
-               //              private
+                       // generate map from name --> [list of widgets with that name]
+                       var map = { };
+                       array.forEach(this._getDescendantFormWidgets(), function(widget){
+                               if(!widget.name){ return; }
+                               var entry = map[widget.name] || (map[widget.name] = [] );
+                               entry.push(widget);
+                       });
 
-               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
-                       if(e.altKey || e.ctrlKey){ return; }
-                       // If Enter/Esc pressed, treat as save/cancel.
-                       if(e.charOrCode == dojo.keys.ESCAPE){
-                               dojo.stopEvent(e);
-                               this.cancel(true); // sets editing=false which short-circuits _onBlur processing
-                       }else if(e.charOrCode == dojo.keys.ENTER && e.target.tagName == "INPUT"){
-                               dojo.stopEvent(e);
-                               this._onChange(); // fire _onBlur and then save
+                       for(var name in map){
+                               if(!map.hasOwnProperty(name)){
+                                       continue;
+                               }
+                               var widgets = map[name],                                                // array of widgets w/this name
+                                       values = lang.getObject(name, false, obj);      // list of values for those widgets
+
+                               if(values === undefined){
+                                       continue;
+                               }
+                               if(!lang.isArray(values)){
+                                       values = [ values ];
+                               }
+                               if(typeof widgets[0].checked == 'boolean'){
+                                       // for checkbox/radio, values is a list of which widgets should be checked
+                                       array.forEach(widgets, function(w){
+                                               w.set('value', array.indexOf(values, w.value) != -1);
+                                       });
+                               }else if(widgets[0].multiple){
+                                       // it takes an array (e.g. multi-select)
+                                       widgets[0].set('value', values);
+                               }else{
+                                       // otherwise, values is a list of values to be assigned sequentially to each widget
+                                       array.forEach(widgets, function(w, i){
+                                               w.set('value', values[i]);
+                                       });
+                               }
                        }
 
-                       // _onBlur will handle TAB automatically by allowing
-                       // the TAB to change focus before we mess with the DOM: #6227
-                       // Expounding by request:
-                       //      The current focus is on the edit widget input field.
-                       //      save() will hide and destroy this widget.
-                       //      We want the focus to jump from the currently hidden
-                       //      displayNode, but since it's hidden, it's impossible to
-                       //      unhide it, focus it, and then have the browser focus
-                       //      away from it to the next focusable element since each
-                       //      of these events is asynchronous and the focus-to-next-element
-                       //      is already queued.
-                       //      So we allow the browser time to unqueue the move-focus event
-                       //      before we do all the hide/show stuff.
-               }
-       },
+                       /***
+                        *      TODO: code for plain input boxes (this shouldn't run for inputs that are part of widgets)
 
-       _onBlur: function(){
-               // summary:
-               //              Called when focus moves outside the editor
-               // tags:
-               //              private
+                       array.forEach(this.containerNode.elements, function(element){
+                               if(element.name == ''){return}; // like "continue"
+                               var namePath = element.name.split(".");
+                               var myObj=obj;
+                               var name=namePath[namePath.length-1];
+                               for(var j=1,len2=namePath.length;j<len2;++j){
+                                       var p=namePath[j - 1];
+                                       // repeater support block
+                                       var nameA=p.split("[");
+                                       if(nameA.length > 1){
+                                               if(typeof(myObj[nameA[0]]) == "undefined"){
+                                                       myObj[nameA[0]]=[ ];
+                                               } // if
 
-               this.inherited(arguments);
-               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing){
-                       if(this.getValue() == this._resetValue){
-                               this.cancel(false);
-                       }else if(this.enableSave()){
-                               this.save(false);
-                       }
-               }
-       },
+                                               nameIndex=parseInt(nameA[1]);
+                                               if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+                                                       myObj[nameA[0]][nameIndex] = { };
+                                               }
+                                               myObj=myObj[nameA[0]][nameIndex];
+                                               continue;
+                                       } // repeater support ends
 
-       _onChange: function(){
-               // summary:
-               //              Called when the underlying widget fires an onChange event,
-               //              such as when the user selects a value from the drop down list of a ComboBox,
-               //              which means that the user has finished entering the value and we should save.
-               // tags:
-               //              private
-
-               if(this.inlineEditBox.autoSave && this.inlineEditBox.editing && this.enableSave()){
-                       dojo.style(this.inlineEditBox.displayNode, { display: "" });
-                       dijit.focus(this.inlineEditBox.displayNode); // fires _onBlur which will save the formatted value
-               }
-       },
-
-       enableSave: function(){
-               // summary:
-               //              User overridable function returning a Boolean to indicate
-               //              if the Save button should be enabled or not - usually due to invalid conditions
-               // tags:
-               //              extension
-               return (
-                       this.editWidget.isValid
-                       ? this.editWidget.isValid()
-                       : true
-               );
-       },
+                                       if(typeof(myObj[p]) == "undefined"){
+                                               myObj=undefined;
+                                               break;
+                                       };
+                                       myObj=myObj[p];
+                               }
 
-       focus: function(){
-               // summary:
-               //              Focus the edit widget.
-               // tags:
-               //              protected
+                               if(typeof(myObj) == "undefined"){
+                                       return;         // like "continue"
+                               }
+                               if(typeof(myObj[name]) == "undefined" && this.ignoreNullValues){
+                                       return;         // like "continue"
+                               }
 
-               this.editWidget.focus();
-               setTimeout(dojo.hitch(this, function(){
-                       if(this.editWidget.focusNode && this.editWidget.focusNode.tagName == "INPUT"){
-                               dijit.selectInputText(this.editWidget.focusNode);
-                       }
-               }), 0);
-       }
-});
+                               // TODO: widget values (just call set('value', ...) on the widget)
 
-}
+                               // TODO: maybe should call dojo.getNodeProp() instead
+                               switch(element.type){
+                                       case "checkbox":
+                                               element.checked = (name in myObj) &&
+                                                       array.some(myObj[name], function(val){ return val == element.value; });
+                                               break;
+                                       case "radio":
+                                               element.checked = (name in myObj) && myObj[name] == element.value;
+                                               break;
+                                       case "select-multiple":
+                                               element.selectedIndex=-1;
+                                               array.forEach(element.options, function(option){
+                                                       option.selected = array.some(myObj[name], function(val){ return option.value == val; });
+                                               });
+                                               break;
+                                       case "select-one":
+                                               element.selectedIndex="0";
+                                               array.forEach(element.options, function(option){
+                                                       option.selected = option.value == myObj[name];
+                                               });
+                                               break;
+                                       case "hidden":
+                                       case "text":
+                                       case "textarea":
+                                       case "password":
+                                               element.value = myObj[name] || "";
+                                               break;
+                               }
+                       });
+                       */
 
-if(!dojo._hasResource["dojo.cookie"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.cookie"] = true;
-dojo.provide("dojo.cookie");
+                       // Note: no need to call this._set("value", ...) as the child updates will trigger onChange events
+                       // which I am monitoring.
+               },
 
+               getValues: function(){
+                       kernel.deprecated(this.declaredClass+"::getValues() is deprecated. Use get('value') instead.", "", "2.0");
+                       return this.get('value');
+               },
+               _getValueAttr: function(){
+                       // summary:
+                       //              Returns Object representing form values.   See description of `value` for details.
+                       // description:
 
+                       // The value is updated into this.value every time a child has an onChange event,
+                       // so in the common case this function could just return this.value.   However,
+                       // that wouldn't work when:
+                       //
+                       // 1. User presses return key to submit a form.  That doesn't fire an onchange event,
+                       // and even if it did it would come too late due to the setTimeout(..., 0) in _handleOnChange()
+                       //
+                       // 2. app for some reason calls this.get("value") while the user is typing into a
+                       // form field.   Not sure if that case needs to be supported or not.
 
-/*=====
-dojo.__cookieProps = function(){
-       //      expires: Date|String|Number?
-       //              If a number, the number of days from today at which the cookie
-       //              will expire. If a date, the date past which the cookie will expire.
-       //              If expires is in the past, the cookie will be deleted.
-       //              If expires is omitted or is 0, the cookie will expire when the browser closes. << FIXME: 0 seems to disappear right away? FF3.
-       //      path: String?
-       //              The path to use for the cookie.
-       //      domain: String?
-       //              The domain to use for the cookie.
-       //      secure: Boolean?
-       //              Whether to only send the cookie on secure connections
-       this.expires = expires;
-       this.path = path;
-       this.domain = domain;
-       this.secure = secure;
-}
-=====*/
+                       // get widget values
+                       var obj = { };
+                       array.forEach(this._getDescendantFormWidgets(), function(widget){
+                               var name = widget.name;
+                               if(!name || widget.disabled){ return; }
 
+                               // Single value widget (checkbox, radio, or plain <input> type widget)
+                               var value = widget.get('value');
 
-dojo.cookie = function(/*String*/name, /*String?*/value, /*dojo.__cookieProps?*/props){
-       //      summary: 
-       //              Get or set a cookie.
-       //      description:
-       //              If one argument is passed, returns the value of the cookie
-       //              For two or more arguments, acts as a setter.
-       //      name:
-       //              Name of the cookie
-       //      value:
-       //              Value for the cookie
-       //      props: 
-       //              Properties for the cookie
-       //      example:
-       //              set a cookie with the JSON-serialized contents of an object which
-       //              will expire 5 days from now:
-       //      |       dojo.cookie("configObj", dojo.toJson(config), { expires: 5 });
-       //      
-       //      example:
-       //              de-serialize a cookie back into a JavaScript object:
-       //      |       var config = dojo.fromJson(dojo.cookie("configObj"));
-       //      
-       //      example:
-       //              delete a cookie:
-       //      |       dojo.cookie("configObj", null, {expires: -1});
-       var c = document.cookie;
-       if(arguments.length == 1){
-               var matches = c.match(new RegExp("(?:^|; )" + dojo.regexp.escapeString(name) + "=([^;]*)"));
-               return matches ? decodeURIComponent(matches[1]) : undefined; // String or undefined
-       }else{
-               props = props || {};
-// FIXME: expires=0 seems to disappear right away, not on close? (FF3)  Change docs?
-               var exp = props.expires;
-               if(typeof exp == "number"){ 
-                       var d = new Date();
-                       d.setTime(d.getTime() + exp*24*60*60*1000);
-                       exp = props.expires = d;
-               }
-               if(exp && exp.toUTCString){ props.expires = exp.toUTCString(); }
+                               // Store widget's value(s) as a scalar, except for checkboxes which are automatically arrays
+                               if(typeof widget.checked == 'boolean'){
+                                       if(/Radio/.test(widget.declaredClass)){
+                                               // radio button
+                                               if(value !== false){
+                                                       lang.setObject(name, value, obj);
+                                               }else{
+                                                       // give radio widgets a default of null
+                                                       value = lang.getObject(name, false, obj);
+                                                       if(value === undefined){
+                                                               lang.setObject(name, null, obj);
+                                                       }
+                                               }
+                                       }else{
+                                               // checkbox/toggle button
+                                               var ary=lang.getObject(name, false, obj);
+                                               if(!ary){
+                                                       ary=[];
+                                                       lang.setObject(name, ary, obj);
+                                               }
+                                               if(value !== false){
+                                                       ary.push(value);
+                                               }
+                                       }
+                               }else{
+                                       var prev=lang.getObject(name, false, obj);
+                                       if(typeof prev != "undefined"){
+                                               if(lang.isArray(prev)){
+                                                       prev.push(value);
+                                               }else{
+                                                       lang.setObject(name, [prev, value], obj);
+                                               }
+                                       }else{
+                                               // unique name
+                                               lang.setObject(name, value, obj);
+                                       }
+                               }
+                       });
 
-               value = encodeURIComponent(value);
-               var updatedCookie = name + "=" + value, propName;
-               for(propName in props){
-                       updatedCookie += "; " + propName;
-                       var propValue = props[propName];
-                       if(propValue !== true){ updatedCookie += "=" + propValue; }
-               }
-               document.cookie = updatedCookie;
-       }
-};
+                       /***
+                        * code for plain input boxes (see also domForm.formToObject, can we use that instead of this code?
+                        * but it doesn't understand [] notation, presumably)
+                       var obj = { };
+                       array.forEach(this.containerNode.elements, function(elm){
+                               if(!elm.name)   {
+                                       return;         // like "continue"
+                               }
+                               var namePath = elm.name.split(".");
+                               var myObj=obj;
+                               var name=namePath[namePath.length-1];
+                               for(var j=1,len2=namePath.length;j<len2;++j){
+                                       var nameIndex = null;
+                                       var p=namePath[j - 1];
+                                       var nameA=p.split("[");
+                                       if(nameA.length > 1){
+                                               if(typeof(myObj[nameA[0]]) == "undefined"){
+                                                       myObj[nameA[0]]=[ ];
+                                               } // if
+                                               nameIndex=parseInt(nameA[1]);
+                                               if(typeof(myObj[nameA[0]][nameIndex]) == "undefined"){
+                                                       myObj[nameA[0]][nameIndex] = { };
+                                               }
+                                       }else if(typeof(myObj[nameA[0]]) == "undefined"){
+                                               myObj[nameA[0]] = { }
+                                       } // if
 
-dojo.cookie.isSupported = function(){
-       //      summary:
-       //              Use to determine if the current browser supports cookies or not.
-       //              
-       //              Returns true if user allows cookies.
-       //              Returns false if user doesn't allow cookies.
+                                       if(nameA.length == 1){
+                                               myObj=myObj[nameA[0]];
+                                       }else{
+                                               myObj=myObj[nameA[0]][nameIndex];
+                                       } // if
+                               } // for
 
-       if(!("cookieEnabled" in navigator)){
-               this("__djCookieTest__", "CookiesAllowed");
-               navigator.cookieEnabled = this("__djCookieTest__") == "CookiesAllowed";
-               if(navigator.cookieEnabled){
-                       this("__djCookieTest__", "", {expires: -1});
-               }
-       }
-       return navigator.cookieEnabled;
-};
+                               if((elm.type != "select-multiple" && elm.type != "checkbox" && elm.type != "radio") || (elm.type == "radio" && elm.checked)){
+                                       if(name == name.split("[")[0]){
+                                               myObj[name]=elm.value;
+                                       }else{
+                                               // can not set value when there is no name
+                                       }
+                               }else if(elm.type == "checkbox" && elm.checked){
+                                       if(typeof(myObj[name]) == 'undefined'){
+                                               myObj[name]=[ ];
+                                       }
+                                       myObj[name].push(elm.value);
+                               }else if(elm.type == "select-multiple"){
+                                       if(typeof(myObj[name]) == 'undefined'){
+                                               myObj[name]=[ ];
+                                       }
+                                       for(var jdx=0,len3=elm.options.length; jdx<len3; ++jdx){
+                                               if(elm.options[jdx].selected){
+                                                       myObj[name].push(elm.options[jdx].value);
+                                               }
+                                       }
+                               } // if
+                               name=undefined;
+                       }); // forEach
+                       ***/
+                       return obj;
+               },
 
-}
+               isValid: function(){
+                       // summary:
+                       //              Returns true if all of the widgets are valid.
+                       //              Deprecated, will be removed in 2.0.  Use get("state") instead.
 
-if(!dojo._hasResource["dijit.layout.StackController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.StackController"] = true;
-dojo.provide("dijit.layout.StackController");
+                       return this.state == "";
+               },
 
+               onValidStateChange: function(/*Boolean*/ /*===== isValid =====*/){
+                       // summary:
+                       //              Stub function to connect to if you want to do something
+                       //              (like disable/enable a submit button) when the valid
+                       //              state changes on the form as a whole.
+                       //
+                       //              Deprecated.  Will be removed in 2.0.  Use watch("state", ...) instead.
+               },
 
+               _getState: function(){
+                       // summary:
+                       //              Compute what this.state should be based on state of children
+                       var states = array.map(this._descendants, function(w){
+                               return w.get("state") || "";
+                       });
 
+                       return array.indexOf(states, "Error") >= 0 ? "Error" :
+                               array.indexOf(states, "Incomplete") >= 0 ? "Incomplete" : "";
+               },
 
+               disconnectChildren: function(){
+                       // summary:
+                       //              Remove connections to monitor changes to children's value, error state, and disabled state,
+                       //              in order to update Form.value and Form.state.
+                       array.forEach(this._childConnections || [], lang.hitch(this, "disconnect"));
+                       array.forEach(this._childWatches || [], function(w){ w.unwatch(); });
+               },
 
-
-
-dojo.declare(
-               "dijit.layout.StackController",
-               [dijit._Widget, dijit._Templated, dijit._Container],
-               {
+               connectChildren: function(/*Boolean*/ inStartup){
                        // summary:
-                       //              Set of buttons to select a page in a page list.
-                       // description:
-                       //              Monitors the specified StackContainer, and whenever a page is
-                       //              added, deleted, or selected, updates itself accordingly.
-
-                       templateString: "<span wairole='tablist' dojoAttachEvent='onkeypress' class='dijitStackController'></span>",
-
-                       // containerId: [const] String
-                       //              The id of the page container that I point to
-                       containerId: "",
-
-                       // buttonWidget: [const] String
-                       //              The name of the button widget to create to correspond to each page
-                       buttonWidget: "dijit.layout._StackButton",
-
-                       postCreate: function(){
-                               dijit.setWaiRole(this.domNode, "tablist");
+                       //              Setup connections to monitor changes to children's value, error state, and disabled state,
+                       //              in order to update Form.value and Form.state.
+                       //
+                       //              You can call this function directly, ex. in the event that you
+                       //              programmatically add a widget to the form *after* the form has been
+                       //              initialized.
 
-                               this.pane2button = {};          // mapping from pane id to buttons
-                               this.pane2handles = {};         // mapping from pane id to this.connect() handles
+                       var _this = this;
 
-                               // Listen to notifications from StackContainer
-                               this.subscribe(this.containerId+"-startup", "onStartup");
-                               this.subscribe(this.containerId+"-addChild", "onAddChild");
-                               this.subscribe(this.containerId+"-removeChild", "onRemoveChild");
-                               this.subscribe(this.containerId+"-selectChild", "onSelectChild");
-                               this.subscribe(this.containerId+"-containerKeyPress", "onContainerKeyPress");
-                       },
+                       // Remove old connections, if any
+                       this.disconnectChildren();
 
-                       onStartup: function(/*Object*/ info){
-                               // summary:
-                               //              Called after StackContainer has finished initializing
-                               // tags:
-                               //              private
-                               dojo.forEach(info.children, this.onAddChild, this);
-                               if(info.selected){
-                                       // Show button corresponding to selected pane (unless selected
-                                       // is null because there are no panes)
-                                       this.onSelectChild(info.selected);
-                               }
-                       },
+                       this._descendants = this._getDescendantFormWidgets();
 
-                       destroy: function(){
-                               for(var pane in this.pane2button){
-                                       this.onRemoveChild(dijit.byId(pane));
-                               }
-                               this.inherited(arguments);
-                       },
+                       // (Re)set this.value and this.state.   Send watch() notifications but not on startup.
+                       var set = inStartup ? function(name, val){ _this[name] = val; } : lang.hitch(this, "_set");
+                       set("value", this.get("value"));
+                       set("state", this._getState());
 
-                       onAddChild: function(/*dijit._Widget*/ page, /*Integer?*/ insertIndex){
-                               // summary:
-                               //              Called whenever a page is added to the container.
-                               //              Create button corresponding to the page.
-                               // tags:
-                               //              private
-
-                               // create an instance of the button widget
-                               var cls = dojo.getObject(this.buttonWidget);
-                               var button = new cls({
-                                       id: this.id + "_" + page.id,
-                                       label: page.title,
-                                       dir: page.dir,
-                                       lang: page.lang,
-                                       showLabel: page.showTitle,
-                                       iconClass: page.iconClass,
-                                       closeButton: page.closable,
-                                       title: page.tooltip
+                       // Monitor changes to error state and disabled state in order to update
+                       // Form.state
+                       var conns = (this._childConnections = []),
+                               watches = (this._childWatches = []);
+                       array.forEach(array.filter(this._descendants,
+                               function(item){ return item.validate; }
+                       ),
+                       function(widget){
+                               // We are interested in whenever the widget changes validity state - or
+                               // whenever the disabled attribute on that widget is changed.
+                               array.forEach(["state", "disabled"], function(attr){
+                                       watches.push(widget.watch(attr, function(){
+                                               _this.set("state", _this._getState());
+                                       }));
                                });
-                               dijit.setWaiState(button.focusNode,"selected", "false");
-                               this.pane2handles[page.id] = [
-                                       this.connect(page, 'set', function(name, value){
-                                               var buttonAttr = {
-                                                       title: 'label',
-                                                       showTitle: 'showLabel',
-                                                       iconClass: 'iconClass',
-                                                       closable: 'closeButton',
-                                                       tooltip: 'title'
-                                               }[name];
-                                               if(buttonAttr){
-                                                       button.set(buttonAttr, value);
-                                               }
-                                       }),
-                                       this.connect(button, 'onClick', dojo.hitch(this,"onButtonClick", page)),
-                                       this.connect(button, 'onClickCloseButton', dojo.hitch(this,"onCloseButtonClick", page))
-                               ];
-                               this.addChild(button, insertIndex);
-                               this.pane2button[page.id] = button;
-                               page.controlButton = button;    // this value might be overwritten if two tabs point to same container
-                               if(!this._currentChild){ // put the first child into the tab order
-                                       button.focusNode.setAttribute("tabIndex", "0");
-                                       dijit.setWaiState(button.focusNode, "selected", "true");
-                                       this._currentChild = page;
-                               }
-                               // make sure all tabs have the same length
-                               if(!this.isLeftToRight() && dojo.isIE && this._rectifyRtlTabList){
-                                       this._rectifyRtlTabList();
-                               }
-                       },
-
-                       onRemoveChild: function(/*dijit._Widget*/ page){
-                               // summary:
-                               //              Called whenever a page is removed from the container.
-                               //              Remove the button corresponding to the page.
-                               // tags:
-                               //              private
-
-                               if(this._currentChild === page){ this._currentChild = null; }
-                               dojo.forEach(this.pane2handles[page.id], this.disconnect, this);
-                               delete this.pane2handles[page.id];
-                               var button = this.pane2button[page.id];
-                               if(button){
-                                       this.removeChild(button);
-                                       delete this.pane2button[page.id];
-                                       button.destroy();
-                               }
-                               delete page.controlButton;
-                       },
+                       });
 
-                       onSelectChild: function(/*dijit._Widget*/ page){
+                       // And monitor calls to child.onChange so we can update this.value
+                       var onChange = function(){
                                // summary:
-                               //              Called when a page has been selected in the StackContainer, either by me or by another StackController
-                               // tags:
-                               //              private
-
-                               if(!page){ return; }
-
-                               if(this._currentChild){
-                                       var oldButton=this.pane2button[this._currentChild.id];
-                                       oldButton.set('checked', false);
-                                       dijit.setWaiState(oldButton.focusNode, "selected", "false");
-                                       oldButton.focusNode.setAttribute("tabIndex", "-1");
+                               //              Called when child's value or disabled state changes
+
+                               // Use setTimeout() to collapse value changes in multiple children into a single
+                               // update to my value.   Multiple updates will occur on:
+                               //      1. Form.set()
+                               //      2. Form.reset()
+                               //      3. user selecting a radio button (which will de-select another radio button,
+                               //               causing two onChange events)
+                               if(_this._onChangeDelayTimer){
+                                       clearTimeout(_this._onChangeDelayTimer);
                                }
+                               _this._onChangeDelayTimer = setTimeout(function(){
+                                       delete _this._onChangeDelayTimer;
+                                       _this._set("value", _this.get("value"));
+                               }, 10);
+                       };
+                       array.forEach(
+                               array.filter(this._descendants, function(item){ return item.onChange; } ),
+                               function(widget){
+                                       // When a child widget's value changes,
+                                       // the efficient thing to do is to just update that one attribute in this.value,
+                                       // but that gets a little complicated when a checkbox is checked/unchecked
+                                       // since this.value["checkboxName"] contains an array of all the checkboxes w/the same name.
+                                       // Doing simple thing for now.
+                                       conns.push(_this.connect(widget, "onChange", onChange));
+
+                                       // Disabling/enabling a child widget should remove it's value from this.value.
+                                       // Again, this code could be more efficient, doing simple thing for now.
+                                       watches.push(widget.watch("disabled", onChange));
+                               }
+                       );
+               },
 
-                               var newButton=this.pane2button[page.id];
-                               newButton.set('checked', true);
-                               dijit.setWaiState(newButton.focusNode, "selected", "true");
-                               this._currentChild = page;
-                               newButton.focusNode.setAttribute("tabIndex", "0");
-                               var container = dijit.byId(this.containerId);
-                               dijit.setWaiState(container.containerNode, "labelledby", newButton.id);
-                       },
-
-                       onButtonClick: function(/*dijit._Widget*/ page){
-                               // summary:
-                               //              Called whenever one of my child buttons is pressed in an attempt to select a page
-                               // tags:
-                               //              private
+               startup: function(){
+                       this.inherited(arguments);
 
-                               var container = dijit.byId(this.containerId);
-                               container.selectChild(page);
-                       },
+                       // Initialize value and valid/invalid state tracking.  Needs to be done in startup()
+                       // so that children are initialized.
+                       this.connectChildren(true);
 
-                       onCloseButtonClick: function(/*dijit._Widget*/ page){
-                               // summary:
-                               //              Called whenever one of my child buttons [X] is pressed in an attempt to close a page
-                               // tags:
-                               //              private
-
-                               var container = dijit.byId(this.containerId);
-                               container.closeChild(page);
-                               if(this._currentChild){
-                                       var b = this.pane2button[this._currentChild.id];
-                                       if(b){
-                                               dijit.focus(b.focusNode || b.domNode);
-                                       }
-                               }
-                       },
+                       // Make state change call onValidStateChange(), will be removed in 2.0
+                       this.watch("state", function(attr, oldVal, newVal){ this.onValidStateChange(newVal == ""); });
+               },
 
-                       // TODO: this is a bit redundant with forward, back api in StackContainer
-                       adjacent: function(/*Boolean*/ forward){
-                               // summary:
-                               //              Helper for onkeypress to find next/previous button
-                               // tags:
-                               //              private
+               destroy: function(){
+                       this.disconnectChildren();
+                       this.inherited(arguments);
+               }
 
-                               if(!this.isLeftToRight() && (!this.tabPosition || /top|bottom/.test(this.tabPosition))){ forward = !forward; }
-                               // find currently focused button in children array
-                               var children = this.getChildren();
-                               var current = dojo.indexOf(children, this.pane2button[this._currentChild.id]);
-                               // pick next button to focus on
-                               var offset = forward ? 1 : children.length - 1;
-                               return children[ (current + offset) % children.length ]; // dijit._Widget
-                       },
+       });
+});
 
-                       onkeypress: function(/*Event*/ e){
-                               // summary:
-                               //              Handle keystrokes on the page list, for advancing to next/previous button
-                               //              and closing the current page if the page is closable.
-                               // tags:
-                               //              private
-
-                               if(this.disabled || e.altKey ){ return; }
-                               var forward = null;
-                               if(e.ctrlKey || !e._djpage){
-                                       var k = dojo.keys;
-                                       switch(e.charOrCode){
-                                               case k.LEFT_ARROW:
-                                               case k.UP_ARROW:
-                                                       if(!e._djpage){ forward = false; }
-                                                       break;
-                                               case k.PAGE_UP:
-                                                       if(e.ctrlKey){ forward = false; }
-                                                       break;
-                                               case k.RIGHT_ARROW:
-                                               case k.DOWN_ARROW:
-                                                       if(!e._djpage){ forward = true; }
-                                                       break;
-                                               case k.PAGE_DOWN:
-                                                       if(e.ctrlKey){ forward = true; }
-                                                       break;
-                                               case k.DELETE:
-                                                       if(this._currentChild.closable){
-                                                               this.onCloseButtonClick(this._currentChild);
-                                                       }
-                                                       dojo.stopEvent(e);
-                                                       break;
-                                               default:
-                                                       if(e.ctrlKey){
-                                                               if(e.charOrCode === k.TAB){
-                                                                       this.adjacent(!e.shiftKey).onClick();
-                                                                       dojo.stopEvent(e);
-                                                               }else if(e.charOrCode == "w"){
-                                                                       if(this._currentChild.closable){
-                                                                               this.onCloseButtonClick(this._currentChild);
-                                                                       }
-                                                                       dojo.stopEvent(e); // avoid browser tab closing.
-                                                               }
-                                                       }
-                                       }
-                                       // handle page navigation
-                                       if(forward !== null){
-                                               this.adjacent(forward).onClick();
-                                               dojo.stopEvent(e);
-                                       }
-                               }
-                       },
+},
+'dijit/DropDownMenu':function(){
+require({cache:{
+'url:dijit/templates/Menu.html':"<table class=\"dijit dijitMenu dijitMenuPassive dijitReset dijitMenuTable\" role=\"menu\" tabIndex=\"${tabIndex}\" data-dojo-attach-event=\"onkeypress:_onKeyPress\" cellspacing=\"0\">\n\t<tbody class=\"dijitReset\" data-dojo-attach-point=\"containerNode\"></tbody>\n</table>\n"}});
+define("dijit/DropDownMenu", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/keys", // keys
+       "dojo/text!./templates/Menu.html",
+       "./_OnDijitClickMixin",
+       "./_MenuBase"
+], function(declare, event, keys, template, _OnDijitClickMixin, _MenuBase){
 
-                       onContainerKeyPress: function(/*Object*/ info){
-                               // summary:
-                               //              Called when there was a keypress on the container
-                               // tags:
-                               //              private
-                               info.e._djpage = info.page;
-                               this.onkeypress(info.e);
-                       }
-       });
+/*=====
+       var _MenuBase = dijit._MenuBase;
+       var _OnDijitClickMixin = dijit._OnDijitClickMixin;
+=====*/
 
+       // module:
+       //              dijit/DropDownMenu
+       // summary:
+       //              dijit.DropDownMenu widget
 
-dojo.declare("dijit.layout._StackButton",
-               dijit.form.ToggleButton,
-               {
+       return declare("dijit.DropDownMenu", [_MenuBase, _OnDijitClickMixin], {
                // summary:
-               //              Internal widget used by StackContainer.
-               // description:
-               //              The button-like or tab-like object you click to select or delete a page
-               // tags:
-               //              private
+               //              A menu, without features for context menu (Meaning, drop down menu)
 
-               // Override _FormWidget.tabIndex.
-               // StackContainer buttons are not in the tab order by default.
-               // Probably we should be calling this.startupKeyNavChildren() instead.
-               tabIndex: "-1",
+               templateString: template,
 
-               postCreate: function(/*Event*/ evt){
-                       dijit.setWaiRole((this.focusNode || this.domNode), "tab");
-                       this.inherited(arguments);
+               baseClass: "dijitMenu",
+
+               postCreate: function(){
+                       var l = this.isLeftToRight();
+                       this._openSubMenuKey = l ? keys.RIGHT_ARROW : keys.LEFT_ARROW;
+                       this._closeSubMenuKey = l ? keys.LEFT_ARROW : keys.RIGHT_ARROW;
+                       this.connectKeyNavHandlers([keys.UP_ARROW], [keys.DOWN_ARROW]);
                },
 
-               onClick: function(/*Event*/ evt){
+               _onKeyPress: function(/*Event*/ evt){
                        // summary:
-                       //              This is for TabContainer where the tabs are <span> rather than button,
-                       //              so need to set focus explicitly (on some browsers)
-                       //              Note that you shouldn't override this method, but you can connect to it.
-                       dijit.focus(this.focusNode);
+                       //              Handle keyboard based menu navigation.
+                       // tags:
+                       //              protected
 
-                       // ... now let StackController catch the event and tell me what to do
-               },
+                       if(evt.ctrlKey || evt.altKey){ return; }
 
-               onClickCloseButton: function(/*Event*/ evt){
-                       // summary:
-                       //              StackContainer connects to this function; if your widget contains a close button
-                       //              then clicking it should call this function.
-                       //              Note that you shouldn't override this method, but you can connect to it.
-                       evt.stopPropagation();
+                       switch(evt.charOrCode){
+                               case this._openSubMenuKey:
+                                       this._moveToPopup(evt);
+                                       event.stop(evt);
+                                       break;
+                               case this._closeSubMenuKey:
+                                       if(this.parentMenu){
+                                               if(this.parentMenu._isMenuBar){
+                                                       this.parentMenu.focusPrev();
+                                               }else{
+                                                       this.onCancel(false);
+                                               }
+                                       }else{
+                                               event.stop(evt);
+                                       }
+                                       break;
+                       }
                }
        });
+});
 
+},
+'dojo/data/util/simpleFetch':function(){
+define("dojo/data/util/simpleFetch", ["dojo/_base/lang", "dojo/_base/window", "./sorter"], 
+  function(lang, winUtil, sorter) {
+       // module:
+       //              dojo/data/util/simpleFetch
+       // summary:
+       //              TODOC
 
-}
-
-if(!dojo._hasResource["dijit.layout.StackContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.StackContainer"] = true;
-dojo.provide("dijit.layout.StackContainer");
-
+var simpleFetch = lang.getObject("dojo.data.util.simpleFetch", true);
 
+simpleFetch.fetch = function(/* Object? */ request){
+       //      summary:
+       //              The simpleFetch mixin is designed to serve as a set of function(s) that can
+       //              be mixed into other datastore implementations to accelerate their development.
+       //              The simpleFetch mixin should work well for any datastore that can respond to a _fetchItems()
+       //              call by returning an array of all the found items that matched the query.  The simpleFetch mixin
+       //              is not designed to work for datastores that respond to a fetch() call by incrementally
+       //              loading items, or sequentially loading partial batches of the result
+       //              set.  For datastores that mixin simpleFetch, simpleFetch
+       //              implements a fetch method that automatically handles eight of the fetch()
+       //              arguments -- onBegin, onItem, onComplete, onError, start, count, sort and scope
+       //              The class mixing in simpleFetch should not implement fetch(),
+       //              but should instead implement a _fetchItems() method.  The _fetchItems()
+       //              method takes three arguments, the keywordArgs object that was passed
+       //              to fetch(), a callback function to be called when the result array is
+       //              available, and an error callback to be called if something goes wrong.
+       //              The _fetchItems() method should ignore any keywordArgs parameters for
+       //              start, count, onBegin, onItem, onComplete, onError, sort, and scope.
+       //              The _fetchItems() method needs to correctly handle any other keywordArgs
+       //              parameters, including the query parameter and any optional parameters
+       //              (such as includeChildren).  The _fetchItems() method should create an array of
+       //              result items and pass it to the fetchHandler along with the original request object
+       //              -- or, the _fetchItems() method may, if it wants to, create an new request object
+       //              with other specifics about the request that are specific to the datastore and pass
+       //              that as the request object to the handler.
+       //
+       //              For more information on this specific function, see dojo.data.api.Read.fetch()
+       request = request || {};
+       if(!request.store){
+               request.store = this;
+       }
+       var self = this;
 
+       var _errorHandler = function(errorData, requestObject){
+               if(requestObject.onError){
+                       var scope = requestObject.scope || winUtil.global;
+                       requestObject.onError.call(scope, errorData, requestObject);
+               }
+       };
 
+       var _fetchHandler = function(items, requestObject){
+               var oldAbortFunction = requestObject.abort || null;
+               var aborted = false;
 
+               var startIndex = requestObject.start?requestObject.start:0;
+               var endIndex = (requestObject.count && (requestObject.count !== Infinity))?(startIndex + requestObject.count):items.length;
 
-dojo.declare(
-       "dijit.layout.StackContainer",
-       dijit.layout._LayoutWidget,
-       {
-       // summary:
-       //              A container that has multiple children, but shows only
-       //              one child at a time
-       //
-       // description:
-       //              A container for widgets (ContentPanes, for example) That displays
-       //              only one Widget at a time.
-       //
-       //              Publishes topics [widgetId]-addChild, [widgetId]-removeChild, and [widgetId]-selectChild
-       //
-       //              Can be base class for container, Wizard, Show, etc.
+               requestObject.abort = function(){
+                       aborted = true;
+                       if(oldAbortFunction){
+                               oldAbortFunction.call(requestObject);
+                       }
+               };
 
-       // doLayout: Boolean
-       //              If true, change the size of my currently displayed child to match my size
-       doLayout: true,
+               var scope = requestObject.scope || winUtil.global;
+               if(!requestObject.store){
+                       requestObject.store = self;
+               }
+               if(requestObject.onBegin){
+                       requestObject.onBegin.call(scope, items.length, requestObject);
+               }
+               if(requestObject.sort){
+                       items.sort(sorter.createSortFunction(requestObject.sort, self));
+               }
+               if(requestObject.onItem){
+                       for(var i = startIndex; (i < items.length) && (i < endIndex); ++i){
+                               var item = items[i];
+                               if(!aborted){
+                                       requestObject.onItem.call(scope, item, requestObject);
+                               }
+                       }
+               }
+               if(requestObject.onComplete && !aborted){
+                       var subset = null;
+                       if(!requestObject.onItem){
+                               subset = items.slice(startIndex, endIndex);
+                       }
+                       requestObject.onComplete.call(scope, subset, requestObject);
+               }
+       };
+       this._fetchItems(request, _fetchHandler, _errorHandler);
+       return request; // Object
+};
 
-       // persist: Boolean
-       //              Remembers the selected child across sessions
-       persist: false,
+return simpleFetch;
+});
 
-       baseClass: "dijitStackContainer",
+},
+'dijit/Menu':function(){
+define("dijit/Menu", [
+       "require",
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/dom", // dom.byId dom.isDescendant
+       "dojo/dom-attr", // domAttr.get domAttr.set domAttr.has domAttr.remove
+       "dojo/dom-geometry", // domStyle.getComputedStyle domGeometry.position
+       "dojo/dom-style", // domStyle.getComputedStyle
+       "dojo/_base/kernel",
+       "dojo/keys",    // keys.F10
+       "dojo/_base/lang", // lang.hitch
+       "dojo/on",
+       "dojo/_base/sniff", // has("ie"), has("quirks")
+       "dojo/_base/window", // win.body win.doc.documentElement win.doc.frames win.withGlobal
+       "dojo/window", // winUtils.get
+       "./popup",
+       "./DropDownMenu",
+       "dojo/ready"
+], function(require, array, declare, event, dom, domAttr, domGeometry, domStyle, kernel, keys, lang, on,
+                       has, win, winUtils, pm, DropDownMenu, ready){
 
 /*=====
-       // selectedChildWidget: [readonly] dijit._Widget
-       //              References the currently selected child widget, if any.
-       //              Adjust selected child with selectChild() method.
-       selectedChildWidget: null,
+       var DropDownMenu = dijit.DropDownMenu;
 =====*/
 
-       postCreate: function(){
-               this.inherited(arguments);
-               dojo.addClass(this.domNode, "dijitLayoutContainer");
-               dijit.setWaiRole(this.containerNode, "tabpanel");
-               this.connect(this.domNode, "onkeypress", this._onKeyPress);
+// module:
+//             dijit/Menu
+// summary:
+//             Includes dijit.Menu widget and base class dijit._MenuBase
+
+// Back compat w/1.6, remove for 2.0
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/MenuItem", "dijit/PopupMenuItem", "dijit/CheckedMenuItem", "dijit/MenuSeparator"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
+
+return declare("dijit.Menu", DropDownMenu, {
+       // summary:
+       //              A context menu you can assign to multiple elements
+
+       constructor: function(){
+               this._bindings = [];
        },
 
-       startup: function(){
-               if(this._started){ return; }
+       // targetNodeIds: [const] String[]
+       //              Array of dom node ids of nodes to attach to.
+       //              Fill this with nodeIds upon widget creation and it becomes context menu for those nodes.
+       targetNodeIds: [],
 
-               var children = this.getChildren();
+       // contextMenuForWindow: [const] Boolean
+       //              If true, right clicking anywhere on the window will cause this context menu to open.
+       //              If false, must specify targetNodeIds.
+       contextMenuForWindow: false,
 
-               // Setup each page panel to be initially hidden
-               dojo.forEach(children, this._setupChild, this);
+       // leftClickToOpen: [const] Boolean
+       //              If true, menu will open on left click instead of right click, similar to a file menu.
+       leftClickToOpen: false,
 
-               // Figure out which child to initially display, defaulting to first one
-               if(this.persist){
-                       this.selectedChildWidget = dijit.byId(dojo.cookie(this.id + "_selectedChild"));
+       // refocus: Boolean
+       //              When this menu closes, re-focus the element which had focus before it was opened.
+       refocus: true,
+
+       postCreate: function(){
+               if(this.contextMenuForWindow){
+                       this.bindDomNode(win.body());
                }else{
-                       dojo.some(children, function(child){
-                               if(child.selected){
-                                       this.selectedChildWidget = child;
-                               }
-                               return child.selected;
-                       }, this);
+                       // TODO: should have _setTargetNodeIds() method to handle initialization and a possible
+                       // later set('targetNodeIds', ...) call.  There's also a problem that targetNodeIds[]
+                       // gets stale after calls to bindDomNode()/unBindDomNode() as it still is just the original list (see #9610)
+                       array.forEach(this.targetNodeIds, this.bindDomNode, this);
                }
-               var selected = this.selectedChildWidget;
-               if(!selected && children[0]){
-                       selected = this.selectedChildWidget = children[0];
-                       selected.selected = true;
-               }
-
-               // Publish information about myself so any StackControllers can initialize.
-               // This needs to happen before this.inherited(arguments) so that for
-               // TabContainer, this._contentBox doesn't include the space for the tab labels.
-               dojo.publish(this.id+"-startup", [{children: children, selected: selected}]);
-
-               // Startup each child widget, and do initial layout like setting this._contentBox,
-               // then calls this.resize() which does the initial sizing on the selected child.
                this.inherited(arguments);
        },
 
-       resize: function(){
-               // Resize is called when we are first made visible (it's called from startup()
-               // if we are initially visible).   If this is the first time we've been made
-               // visible then show our first child.
-               var selected = this.selectedChildWidget;
-               if(selected && !this._hasBeenShown){
-                       this._hasBeenShown = true;
-                       this._showChild(selected);
-               }
-               this.inherited(arguments);
+       // thanks burstlib!
+       _iframeContentWindow: function(/* HTMLIFrameElement */iframe_el){
+               // summary:
+               //              Returns the window reference of the passed iframe
+               // tags:
+               //              private
+               return winUtils.get(this._iframeContentDocument(iframe_el)) ||
+                       // Moz. TODO: is this available when defaultView isn't?
+                       this._iframeContentDocument(iframe_el)['__parent__'] ||
+                       (iframe_el.name && win.doc.frames[iframe_el.name]) || null;     //      Window
        },
 
-       _setupChild: function(/*dijit._Widget*/ child){
-               // Overrides _LayoutWidget._setupChild()
+       _iframeContentDocument: function(/* HTMLIFrameElement */iframe_el){
+               // summary:
+               //              Returns a reference to the document object inside iframe_el
+               // tags:
+               //              protected
+               return iframe_el.contentDocument // W3
+                       || (iframe_el.contentWindow && iframe_el.contentWindow.document) // IE
+                       || (iframe_el.name && win.doc.frames[iframe_el.name] && win.doc.frames[iframe_el.name].document)
+                       || null;        //      HTMLDocument
+       },
 
-               this.inherited(arguments);
+       bindDomNode: function(/*String|DomNode*/ node){
+               // summary:
+               //              Attach menu to given node
+               node = dom.byId(node);
 
-               dojo.removeClass(child.domNode, "dijitVisible");
-               dojo.addClass(child.domNode, "dijitHidden");
+               var cn; // Connect node
 
-               // remove the title attribute so it doesn't show up when i hover
-               // over a node
-               child.domNode.title = "";
-       },
+               // Support context menus on iframes.  Rather than binding to the iframe itself we need
+               // to bind to the <body> node inside the iframe.
+               if(node.tagName.toLowerCase() == "iframe"){
+                       var iframe = node,
+                               window = this._iframeContentWindow(iframe);
+                       cn = win.withGlobal(window, win.body);
+               }else{
 
-       addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-               // Overrides _Container.addChild() to do layout and publish events
+                       // To capture these events at the top level, attach to <html>, not <body>.
+                       // Otherwise right-click context menu just doesn't work.
+                       cn = (node == win.body() ? win.doc.documentElement : node);
+               }
 
-               this.inherited(arguments);
 
-               if(this._started){
-                       dojo.publish(this.id+"-addChild", [child, insertIndex]);
+               // "binding" is the object to track our connection to the node (ie, the parameter to bindDomNode())
+               var binding = {
+                       node: node,
+                       iframe: iframe
+               };
 
-                       // in case the tab titles have overflowed from one line to two lines
-                       // (or, if this if first child, from zero lines to one line)
-                       // TODO: w/ScrollingTabController this is no longer necessary, although
-                       // ScrollTabController.resize() does need to get called to show/hide
-                       // the navigation buttons as appropriate, but that's handled in ScrollingTabController.onAddChild()
-                       this.layout();
+               // Save info about binding in _bindings[], and make node itself record index(+1) into
+               // _bindings[] array.  Prefix w/_dijitMenu to avoid setting an attribute that may
+               // start with a number, which fails on FF/safari.
+               domAttr.set(node, "_dijitMenu" + this.id, this._bindings.push(binding));
 
-                       // if this is the first child, then select it
-                       if(!this.selectedChildWidget){
-                               this.selectChild(child);
+               // Setup the connections to monitor click etc., unless we are connecting to an iframe which hasn't finished
+               // loading yet, in which case we need to wait for the onload event first, and then connect
+               // On linux Shift-F10 produces the oncontextmenu event, but on Windows it doesn't, so
+               // we need to monitor keyboard events in addition to the oncontextmenu event.
+               var doConnects = lang.hitch(this, function(cn){
+                       return [
+                               // TODO: when leftClickToOpen is true then shouldn't space/enter key trigger the menu,
+                               // rather than shift-F10?
+                               on(cn, this.leftClickToOpen ? "click" : "contextmenu", lang.hitch(this, function(evt){
+                                       // Schedule context menu to be opened unless it's already been scheduled from onkeydown handler
+                                       event.stop(evt);
+                                       this._scheduleOpen(evt.target, iframe, {x: evt.pageX, y: evt.pageY});
+                               })),
+                               on(cn, "keydown", lang.hitch(this, function(evt){
+                                       if(evt.shiftKey && evt.keyCode == keys.F10){
+                                               event.stop(evt);
+                                               this._scheduleOpen(evt.target, iframe); // no coords - open near target node
+                                       }
+                               }))
+                       ];
+               });
+               binding.connects = cn ? doConnects(cn) : [];
+
+               if(iframe){
+                       // Setup handler to [re]bind to the iframe when the contents are initially loaded,
+                       // and every time the contents change.
+                       // Need to do this b/c we are actually binding to the iframe's <body> node.
+                       // Note: can't use connect.connect(), see #9609.
+
+                       binding.onloadHandler = lang.hitch(this, function(){
+                               // want to remove old connections, but IE throws exceptions when trying to
+                               // access the <body> node because it's already gone, or at least in a state of limbo
+
+                               var window = this._iframeContentWindow(iframe);
+                                       cn = win.withGlobal(window, win.body);
+                               binding.connects = doConnects(cn);
+                       });
+                       if(iframe.addEventListener){
+                               iframe.addEventListener("load", binding.onloadHandler, false);
+                       }else{
+                               iframe.attachEvent("onload", binding.onloadHandler);
                        }
                }
        },
 
-       removeChild: function(/*dijit._Widget*/ page){
-               // Overrides _Container.removeChild() to do layout and publish events
-
-               this.inherited(arguments);
+       unBindDomNode: function(/*String|DomNode*/ nodeName){
+               // summary:
+               //              Detach menu from given node
 
-               if(this._started){
-                       // this will notify any tablists to remove a button; do this first because it may affect sizing
-                       dojo.publish(this.id + "-removeChild", [page]);
+               var node;
+               try{
+                       node = dom.byId(nodeName);
+               }catch(e){
+                       // On IE the dom.byId() call will get an exception if the attach point was
+                       // the <body> node of an <iframe> that has since been reloaded (and thus the
+                       // <body> node is in a limbo state of destruction.
+                       return;
                }
 
-               // If we are being destroyed than don't run the code below (to select another page), because we are deleting
-               // every page one by one
-               if(this._beingDestroyed){ return; }
+               // node["_dijitMenu" + this.id] contains index(+1) into my _bindings[] array
+               var attrName = "_dijitMenu" + this.id;
+               if(node && domAttr.has(node, attrName)){
+                       var bid = domAttr.get(node, attrName)-1, b = this._bindings[bid], h;
+                       while(h = b.connects.pop()){
+                               h.remove();
+                       }
 
-               // Select new page to display, also updating TabController to show the respective tab.
-               // Do this before layout call because it can affect the height of the TabController.
-               if(this.selectedChildWidget === page){
-                       this.selectedChildWidget = undefined;
-                       if(this._started){
-                               var children = this.getChildren();
-                               if(children.length){
-                                       this.selectChild(children[0]);
+                       // Remove listener for iframe onload events
+                       var iframe = b.iframe;
+                       if(iframe){
+                               if(iframe.removeEventListener){
+                                       iframe.removeEventListener("load", b.onloadHandler, false);
+                               }else{
+                                       iframe.detachEvent("onload", b.onloadHandler);
                                }
                        }
+
+                       domAttr.remove(node, attrName);
+                       delete this._bindings[bid];
                }
+       },
 
-               if(this._started){
-                       // In case the tab titles now take up one line instead of two lines
-                       // (note though that ScrollingTabController never overflows to multiple lines),
-                       // or the height has changed slightly because of addition/removal of tab which close icon
-                       this.layout();
+       _scheduleOpen: function(/*DomNode?*/ target, /*DomNode?*/ iframe, /*Object?*/ coords){
+               // summary:
+               //              Set timer to display myself.  Using a timer rather than displaying immediately solves
+               //              two problems:
+               //
+               //              1. IE: without the delay, focus work in "open" causes the system
+               //              context menu to appear in spite of stopEvent.
+               //
+               //              2. Avoid double-shows on linux, where shift-F10 generates an oncontextmenu event
+               //              even after a event.stop(e).  (Shift-F10 on windows doesn't generate the
+               //              oncontextmenu event.)
+
+               if(!this._openTimer){
+                       this._openTimer = setTimeout(lang.hitch(this, function(){
+                               delete this._openTimer;
+                               this._openMyself({
+                                       target: target,
+                                       iframe: iframe,
+                                       coords: coords
+                               });
+                       }), 1);
                }
        },
 
-       selectChild: function(/*dijit._Widget|String*/ page, /*Boolean*/ animate){
+       _openMyself: function(args){
                // summary:
-               //              Show the given widget (which must be one of my children)
-               // page:
-               //              Reference to child widget or id of child widget
+               //              Internal function for opening myself when the user does a right-click or something similar.
+               // args:
+               //              This is an Object containing:
+               //              * target:
+               //                      The node that is being clicked
+               //              * iframe:
+               //                      If an <iframe> is being clicked, iframe points to that iframe
+               //              * coords:
+               //                      Put menu at specified x/y position in viewport, or if iframe is
+               //                      specified, then relative to iframe.
+               //
+               //              _openMyself() formerly took the event object, and since various code references
+               //              evt.target (after connecting to _openMyself()), using an Object for parameters
+               //              (so that old code still works).
+
+               var target = args.target,
+                       iframe = args.iframe,
+                       coords = args.coords;
 
-               page = dijit.byId(page);
+               // Get coordinates to open menu, either at specified (mouse) position or (if triggered via keyboard)
+               // then near the node the menu is assigned to.
+               if(coords){
+                       if(iframe){
+                               // Specified coordinates are on <body> node of an <iframe>, convert to match main document
+                               var ifc = domGeometry.position(iframe, true),
+                                       window = this._iframeContentWindow(iframe),
+                                       scroll = win.withGlobal(window, "_docScroll", dojo);
 
-               if(this.selectedChildWidget != page){
-                       // Deselect old page and select new one
-                       this._transition(page, this.selectedChildWidget, animate);
-                       this.selectedChildWidget = page;
-                       dojo.publish(this.id+"-selectChild", [page]);
+                               var cs = domStyle.getComputedStyle(iframe),
+                                       tp = domStyle.toPixelValue,
+                                       left = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingLeft)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderLeftWidth) : 0),
+                                       top = (has("ie") && has("quirks") ? 0 : tp(iframe, cs.paddingTop)) + (has("ie") && has("quirks") ? tp(iframe, cs.borderTopWidth) : 0);
 
-                       if(this.persist){
-                               dojo.cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
+                               coords.x += ifc.x + left - scroll.x;
+                               coords.y += ifc.y + top - scroll.y;
                        }
+               }else{
+                       coords = domGeometry.position(target, true);
+                       coords.x += 10;
+                       coords.y += 10;
                }
-       },
 
-       _transition: function(/*dijit._Widget*/newWidget, /*dijit._Widget*/oldWidget){
-               // summary:
-               //              Hide the old widget and display the new widget.
-               //              Subclasses should override this.
-               // tags:
-               //              protected extension
-               if(oldWidget){
-                       this._hideChild(oldWidget);
-               }
-               this._showChild(newWidget);
+               var self=this;
+               var prevFocusNode = this._focusManager.get("prevNode");
+               var curFocusNode = this._focusManager.get("curNode");
+               var savedFocusNode = !curFocusNode || (dom.isDescendant(curFocusNode, this.domNode)) ? prevFocusNode : curFocusNode;
 
-               // Size the new widget, in case this is the first time it's being shown,
-               // or I have been resized since the last time it was shown.
-               // Note that page must be visible for resizing to work.
-               if(newWidget.resize){
-                       if(this.doLayout){
-                               newWidget.resize(this._containerContentBox || this._contentBox);
-                       }else{
-                               // the child should pick it's own size but we still need to call resize()
-                               // (with no arguments) to let the widget lay itself out
-                               newWidget.resize();
+               function closeAndRestoreFocus(){
+                       // user has clicked on a menu or popup
+                       if(self.refocus && savedFocusNode){
+                               savedFocusNode.focus();
                        }
+                       pm.close(self);
                }
-       },
+               pm.open({
+                       popup: this,
+                       x: coords.x,
+                       y: coords.y,
+                       onExecute: closeAndRestoreFocus,
+                       onCancel: closeAndRestoreFocus,
+                       orient: this.isLeftToRight() ? 'L' : 'R'
+               });
+               this.focus();
 
-       _adjacent: function(/*Boolean*/ forward){
-               // summary:
-               //              Gets the next/previous child widget in this container from the current selection.
-               var children = this.getChildren();
-               var index = dojo.indexOf(children, this.selectedChildWidget);
-               index += forward ? 1 : children.length - 1;
-               return children[ index % children.length ]; // dijit._Widget
+               this._onBlur = function(){
+                       this.inherited('_onBlur', arguments);
+                       // Usually the parent closes the child widget but if this is a context
+                       // menu then there is no parent
+                       pm.close(this);
+                       // don't try to restore focus; user has clicked another part of the screen
+                       // and set focus there
+               };
        },
 
-       forward: function(){
-               // summary:
-               //              Advance to next page.
-               this.selectChild(this._adjacent(true), true);
-       },
+       uninitialize: function(){
+               array.forEach(this._bindings, function(b){ if(b){ this.unBindDomNode(b.node); } }, this);
+               this.inherited(arguments);
+       }
+});
 
-       back: function(){
-               // summary:
-               //              Go back to previous page.
-               this.selectChild(this._adjacent(false), true);
-       },
+});
 
-       _onKeyPress: function(e){
-               dojo.publish(this.id+"-containerKeyPress", [{ e: e, page: this}]);
-       },
+},
+'dijit/form/_CheckBoxMixin':function(){
+define("dijit/form/_CheckBoxMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/event" // event.stop
+], function(declare, domAttr, event){
+
+       // module:
+       //              dijit/form/_CheckBoxMixin
+       // summary:
+       //              Mixin to provide widget functionality corresponding to an HTML checkbox
 
-       layout: function(){
-               // Implement _LayoutWidget.layout() virtual method.
-               if(this.doLayout && this.selectedChildWidget && this.selectedChildWidget.resize){
-                       this.selectedChildWidget.resize(this._containerContentBox || this._contentBox);
-               }
-       },
-
-       _showChild: function(/*dijit._Widget*/ page){
+       return declare("dijit.form._CheckBoxMixin", null, {
                // summary:
-               //              Show the specified child by changing it's CSS, and call _onShow()/onShow() so
-               //              it can do any updates it needs regarding loading href's etc.
-               var children = this.getChildren();
-               page.isFirstChild = (page == children[0]);
-               page.isLastChild = (page == children[children.length-1]);
-               page.selected = true;
+               //              Mixin to provide widget functionality corresponding to an HTML checkbox
+               //
+               // description:
+               //              User interacts with real html inputs.
+               //              On onclick (which occurs by mouse click, space-bar, or
+               //              using the arrow keys to switch the selected radio button),
+               //              we update the state of the checkbox/radio.
+               //
 
-               dojo.removeClass(page.domNode, "dijitHidden");
-               dojo.addClass(page.domNode, "dijitVisible");
+               // type: [private] String
+               //              type attribute on <input> node.
+               //              Overrides `dijit.form.Button.type`.  Users should not change this value.
+               type: "checkbox",
 
-               page._onShow();
-       },
+               // value: String
+               //              As an initialization parameter, equivalent to value field on normal checkbox
+               //              (if checked, the value is passed as the value when form is submitted).
+               value: "on",
 
-       _hideChild: function(/*dijit._Widget*/ page){
-               // summary:
-               //              Hide the specified child by changing it's CSS, and call _onHide() so
-               //              it's notified.
-               page.selected=false;
-               dojo.removeClass(page.domNode, "dijitVisible");
-               dojo.addClass(page.domNode, "dijitHidden");
+               // readOnly: Boolean
+               //              Should this widget respond to user input?
+               //              In markup, this is specified as "readOnly".
+               //              Similar to disabled except readOnly form values are submitted.
+               readOnly: false,
+               
+               // aria-pressed for toggle buttons, and aria-checked for checkboxes
+               _aria_attr: "aria-checked",
 
-               page.onHide();
-       },
+               _setReadOnlyAttr: function(/*Boolean*/ value){
+                       this._set("readOnly", value);
+                       domAttr.set(this.focusNode, 'readOnly', value);
+                       this.focusNode.setAttribute("aria-readonly", value);
+               },
 
-       closeChild: function(/*dijit._Widget*/ page){
-               // summary:
-               //              Callback when user clicks the [X] to remove a page.
-               //              If onClose() returns true then remove and destroy the child.
-               // tags:
-               //              private
-               var remove = page.onClose(this, page);
-               if(remove){
-                       this.removeChild(page);
-                       // makes sure we can clean up executeScripts in ContentPane onUnLoad
-                       page.destroyRecursive();
-               }
-       },
+               // Override dijit.form.Button._setLabelAttr() since we don't even have a containerNode.
+               // Normally users won't try to set label, except when CheckBox or RadioButton is the child of a dojox.layout.TabContainer
+               _setLabelAttr: undefined,
 
-       destroyDescendants: function(/*Boolean*/preserveDom){
-               dojo.forEach(this.getChildren(), function(child){
-                       this.removeChild(child);
-                       child.destroyRecursive(preserveDom);
-               }, this);
-       }
-});
+               postMixInProperties: function(){
+                       if(this.value == ""){
+                               this.value = "on";
+                       }
+                       this.inherited(arguments);
+               },
 
-// For back-compat, remove for 2.0
+               reset: function(){
+                       this.inherited(arguments);
+                       // Handle unlikely event that the <input type=checkbox> value attribute has changed
+                       this._set("value", this.params.value || "on");
+                       domAttr.set(this.focusNode, 'value', this.value);
+               },
 
+               _onClick: function(/*Event*/ e){
+                       // summary:
+                       //              Internal function to handle click actions - need to check
+                       //              readOnly, since button no longer does that check.
+                       if(this.readOnly){
+                               event.stop(e);
+                               return false;
+                       }
+                       return this.inherited(arguments);
+               }
+       });
+});
 
+},
+'dijit/layout/ContentPane':function(){
+define("dijit/layout/ContentPane", [
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.mixin lang.delegate lang.hitch lang.isFunction lang.isObject
+       "../_Widget",
+       "./_ContentPaneResizeMixin",
+       "dojo/string", // string.substitute
+       "dojo/html", // html._ContentSetter html._emptyNode
+       "dojo/i18n!../nls/loading",
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred", // Deferred
+       "dojo/dom", // dom.byId
+       "dojo/dom-attr", // domAttr.attr
+       "dojo/_base/window", // win.body win.doc.createDocumentFragment
+       "dojo/_base/xhr", // xhr.get
+       "dojo/i18n" // i18n.getLocalization
+], function(kernel, lang, _Widget, _ContentPaneResizeMixin, string, html, nlsLoading,
+       array, declare, Deferred, dom, domAttr, win, xhr, i18n){
 
-// These arguments can be specified for the children of a StackContainer.
-// Since any widget can be specified as a StackContainer child, mix them
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-       // selected: Boolean
-       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
-       //              Specifies that this widget should be the initially displayed pane.
-       //              Note: to change the selected child use `dijit.layout.StackContainer.selectChild`
-       selected: false,
+/*=====
+       var _Widget = dijit._Widget;
+       var _ContentPaneResizeMixin = dijit.layout._ContentPaneResizeMixin;
+=====*/
 
-       // closable: Boolean
-       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
-       //              True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
-       closable: false,
+// module:
+//             dijit/layout/ContentPane
+// summary:
+//             A widget containing an HTML fragment, specified inline
+//             or by uri.  Fragment may include widgets.
 
-       // iconClass: String
-       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
-       //              CSS Class specifying icon to use in label associated with this pane.
-       iconClass: "",
 
-       // showTitle: Boolean
-       //              Parameter for children of `dijit.layout.StackContainer` or subclasses.
-       //              When true, display title of this widget as tab label etc., rather than just using
-       //              icon specified in iconClass
-       showTitle: true
-});
+return declare("dijit.layout.ContentPane", [_Widget, _ContentPaneResizeMixin], {
+       // summary:
+       //              A widget containing an HTML fragment, specified inline
+       //              or by uri.  Fragment may include widgets.
+       //
+       // description:
+       //              This widget embeds a document fragment in the page, specified
+       //              either by uri, javascript generated markup or DOM reference.
+       //              Any widgets within this content are instantiated and managed,
+       //              but laid out according to the HTML structure.  Unlike IFRAME,
+       //              ContentPane embeds a document fragment as would be found
+       //              inside the BODY tag of a full HTML document.  It should not
+       //              contain the HTML, HEAD, or BODY tags.
+       //              For more advanced functionality with scripts and
+       //              stylesheets, see dojox.layout.ContentPane.  This widget may be
+       //              used stand alone or as a base class for other widgets.
+       //              ContentPane is useful as a child of other layout containers
+       //              such as BorderContainer or TabContainer, but note that those
+       //              widgets can contain any widget as a child.
+       //
+       // example:
+       //              Some quick samples:
+       //              To change the innerHTML: cp.set('content', '<b>new content</b>')
+       //
+       //              Or you can send it a NodeList: cp.set('content', dojo.query('div [class=selected]', userSelection))
+       //
+       //              To do an ajax update: cp.set('href', url)
 
-}
+       // href: String
+       //              The href of the content that displays now.
+       //              Set this at construction if you want to load data externally when the
+       //              pane is shown.  (Set preload=true to load it immediately.)
+       //              Changing href after creation doesn't have any effect; Use set('href', ...);
+       href: "",
 
-if(!dojo._hasResource["dijit.layout.AccordionPane"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.AccordionPane"] = true;
-dojo.provide("dijit.layout.AccordionPane");
+       // content: String || DomNode || NodeList || dijit._Widget
+       //              The innerHTML of the ContentPane.
+       //              Note that the initialization parameter / argument to set("content", ...)
+       //              can be a String, DomNode, Nodelist, or _Widget.
+       content: "",
 
+       // extractContent: Boolean
+       //              Extract visible content from inside of <body> .... </body>.
+       //              I.e., strip <html> and <head> (and it's contents) from the href
+       extractContent: false,
 
+       // parseOnLoad: Boolean
+       //              Parse content and create the widgets, if any.
+       parseOnLoad: true,
 
-dojo.declare("dijit.layout.AccordionPane", dijit.layout.ContentPane, {
-       // summary:
-       //              Deprecated widget.   Use `dijit.layout.ContentPane` instead.
-       // tags:
-       //              deprecated
+       // parserScope: String
+       //              Flag passed to parser.  Root for attribute names to search for.   If scopeName is dojo,
+       //              will search for data-dojo-type (or dojoType).  For backwards compatibility
+       //              reasons defaults to dojo._scopeName (which is "dojo" except when
+       //              multi-version support is used, when it will be something like dojo16, dojo20, etc.)
+       parserScope: kernel._scopeName,
 
-       constructor: function(){
-               dojo.deprecated("dijit.layout.AccordionPane deprecated, use ContentPane instead", "", "2.0");
-       },
+       // preventCache: Boolean
+       //              Prevent caching of data from href's by appending a timestamp to the href.
+       preventCache: false,
 
-       onSelected: function(){
-               // summary:
-               //              called when this pane is selected
-       }
-});
+       // preload: Boolean
+       //              Force load of data on initialization even if pane is hidden.
+       preload: false,
 
-}
+       // refreshOnShow: Boolean
+       //              Refresh (re-download) content when pane goes from hidden to shown
+       refreshOnShow: false,
 
-if(!dojo._hasResource["dijit.layout.AccordionContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.AccordionContainer"] = true;
-dojo.provide("dijit.layout.AccordionContainer");
+       // loadingMessage: String
+       //              Message that shows while downloading
+       loadingMessage: "<span class='dijitContentPaneLoading'><span class='dijitInline dijitIconLoading'></span>${loadingState}</span>",
 
+       // errorMessage: String
+       //              Message that shows if an error occurs
+       errorMessage: "<span class='dijitContentPaneError'><span class='dijitInline dijitIconError'></span>${errorState}</span>",
 
+       // isLoaded: [readonly] Boolean
+       //              True if the ContentPane has data in it, either specified
+       //              during initialization (via href or inline content), or set
+       //              via set('content', ...) / set('href', ...)
+       //
+       //              False if it doesn't have any content, or if ContentPane is
+       //              still in the process of downloading href.
+       isLoaded: false,
 
+       baseClass: "dijitContentPane",
 
+       /*======
+       // ioMethod: dojo.xhrGet|dojo.xhrPost
+       //              Function that should grab the content specified via href.
+       ioMethod: dojo.xhrGet,
+       ======*/
 
+       // ioArgs: Object
+       //              Parameters to pass to xhrGet() request, for example:
+       // |    <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="href: './bar', ioArgs: {timeout: 500}">
+       ioArgs: {},
 
+       // onLoadDeferred: [readonly] dojo.Deferred
+       //              This is the `dojo.Deferred` returned by set('href', ...) and refresh().
+       //              Calling onLoadDeferred.addCallback() or addErrback() registers your
+       //              callback to be called only once, when the prior set('href', ...) call or
+       //              the initial href parameter to the constructor finishes loading.
+       //
+       //              This is different than an onLoad() handler which gets called any time any href
+       //              or content is loaded.
+       onLoadDeferred: null,
 
+       // Cancel _WidgetBase's _setTitleAttr because we don't want the title attribute (used to specify
+       // tab labels) to be copied to ContentPane.domNode... otherwise a tooltip shows up over the
+       // entire pane.
+       _setTitleAttr: null,
 
+       // Flag to parser that I'll parse my contents, so it shouldn't.
+       stopParser: true,
 
-       // for back compat, remove for 2.0
+       // template: [private] Boolean
+       //              Flag from the parser that this ContentPane is inside a template
+       //              so the contents are pre-parsed.
+       // (TODO: this declaration can be commented out in 2.0)
+       template: false,
 
-dojo.declare(
-       "dijit.layout.AccordionContainer",
-       dijit.layout.StackContainer,
-       {
-               // summary:
-               //              Holds a set of panes where every pane's title is visible, but only one pane's content is visible at a time,
-               //              and switching between panes is visualized by sliding the other panes up/down.
-               // example:
-               //      |       <div dojoType="dijit.layout.AccordionContainer">
-               //      |               <div dojoType="dijit.layout.ContentPane" title="pane 1">
-               //      |               </div>
-               //      |               <div dojoType="dijit.layout.ContentPane" title="pane 2">
-               //      |                       <p>This is some text</p>
-               //      |               </div>
-               //      |       </div>
+       create: function(params, srcNodeRef){
+               // Convert a srcNodeRef argument into a content parameter, so that the original contents are
+               // processed in the same way as contents set via set("content", ...), calling the parser etc.
+               // Avoid modifying original params object since that breaks NodeList instantiation, see #11906.
+               if((!params || !params.template) && srcNodeRef && !("href" in params) && !("content" in params)){
+                       var df = win.doc.createDocumentFragment();
+                       srcNodeRef = dom.byId(srcNodeRef);
+                       while(srcNodeRef.firstChild){
+                               df.appendChild(srcNodeRef.firstChild);
+                       }
+                       params = lang.delegate(params, {content: df});
+               }
+               this.inherited(arguments, [params, srcNodeRef]);
+       },
 
-               // duration: Integer
-               //              Amount of time (in ms) it takes to slide panes
-               duration: dijit.defaultDuration,
+       postMixInProperties: function(){
+               this.inherited(arguments);
+               var messages = i18n.getLocalization("dijit", "loading", this.lang);
+               this.loadingMessage = string.substitute(this.loadingMessage, messages);
+               this.errorMessage = string.substitute(this.errorMessage, messages);
+       },
 
-               // buttonWidget: [const] String
-               //              The name of the widget used to display the title of each pane
-               buttonWidget: "dijit.layout._AccordionButton",
+       buildRendering: function(){
+               this.inherited(arguments);
 
-               // _verticalSpace: Number
-               //              Pixels of space available for the open pane
-               //              (my content box size minus the cumulative size of all the title bars)
-               _verticalSpace: 0,
+               // Since we have no template we need to set this.containerNode ourselves, to make getChildren() work.
+               // For subclasses of ContentPane that do have a template, does nothing.
+               if(!this.containerNode){
+                       this.containerNode = this.domNode;
+               }
 
-               baseClass: "dijitAccordionContainer",
+               // remove the title attribute so it doesn't show up when hovering
+               // over a node  (TODO: remove in 2.0, no longer needed after #11490)
+               this.domNode.title = "";
 
-               postCreate: function(){
-                       this.domNode.style.overflow = "hidden";
-                       this.inherited(arguments);
-                       dijit.setWaiRole(this.domNode, "tablist");
-               },
+               if(!domAttr.get(this.domNode,"role")){
+                       this.domNode.setAttribute("role", "group");
+               }
+       },
 
-               startup: function(){
-                       if(this._started){ return; }
-                       this.inherited(arguments);
-                       if(this.selectedChildWidget){
-                               var style = this.selectedChildWidget.containerNode.style;
-                               style.display = "";
-                               style.overflow = "auto";
-                               this.selectedChildWidget._wrapperWidget.set("selected", true);
-                       }
-               },
+       startup: function(){
+               // summary:
+               //              Call startup() on all children including non _Widget ones like dojo.dnd.Source objects
 
-               _getTargetHeight: function(/* Node */ node){
-                       // summary:
-                       //              For the given node, returns the height that should be
-                       //              set to achieve our vertical space (subtract any padding
-                       //              we may have).
-                       //
-                       //              This is used by the animations.
-                       //
-                       //              TODO: I don't think this works correctly in IE quirks when an elements
-                       //              style.height including padding and borders
-                       var cs = dojo.getComputedStyle(node);
-                       return Math.max(this._verticalSpace - dojo._getPadBorderExtents(node, cs).h - dojo._getMarginExtents(node, cs).h, 0);
-               },
+               // This starts all the widgets
+               this.inherited(arguments);
 
-               layout: function(){
-                       // Implement _LayoutWidget.layout() virtual method.
-                       // Set the height of the open pane based on what room remains.
+               // And this catches stuff like dojo.dnd.Source
+               if(this._contentSetter){
+                       array.forEach(this._contentSetter.parseResults, function(obj){
+                               if(!obj._started && !obj._destroyed && lang.isFunction(obj.startup)){
+                                       obj.startup();
+                                       obj._started = true;
+                               }
+                       }, this);
+               }
+       },
 
-                       var openPane = this.selectedChildWidget;
-                       
-                       if(!openPane){ return;}
+       setHref: function(/*String|Uri*/ href){
+               // summary:
+               //              Deprecated.   Use set('href', ...) instead.
+               kernel.deprecated("dijit.layout.ContentPane.setHref() is deprecated. Use set('href', ...) instead.", "", "2.0");
+               return this.set("href", href);
+       },
+       _setHrefAttr: function(/*String|Uri*/ href){
+               // summary:
+               //              Hook so set("href", ...) works.
+               // description:
+               //              Reset the (external defined) content of this pane and replace with new url
+               //              Note: It delays the download until widget is shown if preload is false.
+               //      href:
+               //              url to the page you want to get, must be within the same domain as your mainpage
 
-                       var openPaneContainer = openPane._wrapperWidget.domNode,
-                               openPaneContainerMargin = dojo._getMarginExtents(openPaneContainer),
-                               openPaneContainerPadBorder = dojo._getPadBorderExtents(openPaneContainer),
-                               mySize = this._contentBox;
+               // Cancel any in-flight requests (a set('href', ...) will cancel any in-flight set('href', ...))
+               this.cancel();
 
-                       // get cumulative height of all the unselected title bars
-                       var totalCollapsedHeight = 0;
-                       dojo.forEach(this.getChildren(), function(child){
-                   if(child != openPane){
-                                       totalCollapsedHeight += dojo.marginBox(child._wrapperWidget.domNode).h;
-                               }
-                       });
-                       this._verticalSpace = mySize.h - totalCollapsedHeight - openPaneContainerMargin.h 
-                               - openPaneContainerPadBorder.h - openPane._buttonWidget.getTitleHeight();
+               this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
+               this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
 
-                       // Memo size to make displayed child
-                       this._containerContentBox = {
-                               h: this._verticalSpace,
-                               w: this._contentBox.w - openPaneContainerMargin.w - openPaneContainerPadBorder.w
-                       };
+               this._set("href", href);
 
-                       if(openPane){
-                               openPane.resize(this._containerContentBox);
-                       }
-               },
-
-               _setupChild: function(child){
-                       // Overrides _LayoutWidget._setupChild().
-                       // Put wrapper widget around the child widget, showing title
-
-                       child._wrapperWidget = new dijit.layout._AccordionInnerContainer({
-                               contentWidget: child,
-                               buttonWidget: this.buttonWidget,
-                               id: child.id + "_wrapper",
-                               dir: child.dir,
-                               lang: child.lang,
-                               parent: this
-                       });
-
-                       this.inherited(arguments);
-               },
+               // _setHrefAttr() is called during creation and by the user, after creation.
+               // Assuming preload == false, only in the second case do we actually load the URL;
+               // otherwise it's done in startup(), and only if this widget is shown.
+               if(this.preload || (this._created && this._isShown())){
+                       this._load();
+               }else{
+                       // Set flag to indicate that href needs to be loaded the next time the
+                       // ContentPane is made visible
+                       this._hrefChanged = true;
+               }
 
-               addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){  
-                       if(this._started){
-                               // Adding a child to a started Accordion is complicated because children have
-                               // wrapper widgets.  Default code path (calling this.inherited()) would add
-                               // the new child inside another child's wrapper.
+               return this.onLoadDeferred;             // Deferred
+       },
 
-                               // First add in child as a direct child of this AccordionContainer
-                               dojo.place(child.domNode, this.containerNode, insertIndex);
+       setContent: function(/*String|DomNode|Nodelist*/data){
+               // summary:
+               //              Deprecated.   Use set('content', ...) instead.
+               kernel.deprecated("dijit.layout.ContentPane.setContent() is deprecated.  Use set('content', ...) instead.", "", "2.0");
+               this.set("content", data);
+       },
+       _setContentAttr: function(/*String|DomNode|Nodelist*/data){
+               // summary:
+               //              Hook to make set("content", ...) work.
+               //              Replaces old content with data content, include style classes from old content
+               //      data:
+               //              the new Content may be String, DomNode or NodeList
+               //
+               //              if data is a NodeList (or an array of nodes) nodes are copied
+               //              so you can import nodes from another document implicitly
 
-                               if(!child._started){
-                                       child.startup();
-                               }
-                               
-                               // Then stick the wrapper widget around the child widget
-                               this._setupChild(child);
+               // clear href so we can't run refresh and clear content
+               // refresh should only work if we downloaded the content
+               this._set("href", "");
 
-                               // Code below copied from StackContainer        
-                               dojo.publish(this.id+"-addChild", [child, insertIndex]);
-                               this.layout();
-                               if(!this.selectedChildWidget){
-                                       this.selectChild(child);
-                               }
-                       }else{
-                               // We haven't been started yet so just add in the child widget directly,
-                               // and the wrapper will be created on startup()
-                               this.inherited(arguments);
-                       }
-               },
+               // Cancel any in-flight requests (a set('content', ...) will cancel any in-flight set('href', ...))
+               this.cancel();
 
-               removeChild: function(child){
-                       // Overrides _LayoutWidget.removeChild().
+               // Even though user is just setting content directly, still need to define an onLoadDeferred
+               // because the _onLoadHandler() handler is still getting called from setContent()
+               this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
+               if(this._created){
+                       // For back-compat reasons, call onLoad() for set('content', ...)
+                       // calls but not for content specified in srcNodeRef (ie: <div data-dojo-type=ContentPane>...</div>)
+                       // or as initialization parameter (ie: new ContentPane({content: ...})
+                       this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
+               }
 
-                       // destroy wrapper widget first, before StackContainer.getChildren() call
-                       child._wrapperWidget.destroy();
-                       delete child._wrapperWidget;
-                       dojo.removeClass(child.domNode, "dijitHidden");
+               this._setContent(data || "");
 
-                       this.inherited(arguments);
-               },
+               this._isDownloaded = false; // mark that content is from a set('content') not a set('href')
 
-               getChildren: function(){
-                       // Overrides _Container.getChildren() to return content panes rather than internal AccordionInnerContainer panes
-                       return dojo.map(this.inherited(arguments), function(child){
-                               return child.declaredClass == "dijit.layout._AccordionInnerContainer" ? child.contentWidget : child;
-                       }, this);
-               },
+               return this.onLoadDeferred;     // Deferred
+       },
+       _getContentAttr: function(){
+               // summary:
+               //              Hook to make get("content") work
+               return this.containerNode.innerHTML;
+       },
 
-               destroy: function(){
-                       dojo.forEach(this.getChildren(), function(child){
-                               child._wrapperWidget.destroy();
-                       });
-                       this.inherited(arguments);
-               },
+       cancel: function(){
+               // summary:
+               //              Cancels an in-flight download of content
+               if(this._xhrDfd && (this._xhrDfd.fired == -1)){
+                       this._xhrDfd.cancel();
+               }
+               delete this._xhrDfd; // garbage collect
 
-               _transition: function(/*dijit._Widget?*/newWidget, /*dijit._Widget?*/oldWidget, /*Boolean*/ animate){
-                       // Overrides StackContainer._transition() to provide sliding of title bars etc.
+               this.onLoadDeferred = null;
+       },
 
-//TODO: should be able to replace this with calls to slideIn/slideOut
-                       if(this._inTransition){ return; }
-                       var animations = [];
-                       var paneHeight = this._verticalSpace;
-                       if(newWidget){
-                               newWidget._wrapperWidget.set("selected", true);
+       uninitialize: function(){
+               if(this._beingDestroyed){
+                       this.cancel();
+               }
+               this.inherited(arguments);
+       },
 
-                               this._showChild(newWidget);     // prepare widget to be slid in
+       destroyRecursive: function(/*Boolean*/ preserveDom){
+               // summary:
+               //              Destroy the ContentPane and its contents
 
-                               // Size the new widget, in case this is the first time it's being shown,
-                               // or I have been resized since the last time it was shown.
-                               // Note that page must be visible for resizing to work.
-                               if(this.doLayout && newWidget.resize){
-                                       newWidget.resize(this._containerContentBox);
-                               }
+               // if we have multiple controllers destroying us, bail after the first
+               if(this._beingDestroyed){
+                       return;
+               }
+               this.inherited(arguments);
+       },
 
-                               var newContents = newWidget.domNode;
-                               dojo.addClass(newContents, "dijitVisible");
-                               dojo.removeClass(newContents, "dijitHidden");
-                               
-                               if(animate){
-                                       var newContentsOverflow = newContents.style.overflow;
-                                       newContents.style.overflow = "hidden";
-                                       animations.push(dojo.animateProperty({
-                                               node: newContents,
-                                               duration: this.duration,
-                                               properties: {
-                                                       height: { start: 1, end: this._getTargetHeight(newContents) }
-                                               },
-                                               onEnd: function(){
-                                                       newContents.style.overflow = newContentsOverflow;
-
-                                                       // Kick IE to workaround layout bug, see #11415
-                                                       if(dojo.isIE){
-                                                               setTimeout(function(){
-                                                                       dojo.removeClass(newContents.parentNode, "dijitAccordionInnerContainerFocused");
-                                                                       setTimeout(function(){
-                                                                               dojo.addClass(newContents.parentNode, "dijitAccordionInnerContainerFocused");
-                                                                       }, 0);
-                                                               }, 0);
-                                                       }
-                                               }
-                                       }));
-                               }
-                       }
-                       if(oldWidget){
-                               oldWidget._wrapperWidget.set("selected", false);
-                               var oldContents = oldWidget.domNode;
-                               if(animate){
-                                       var oldContentsOverflow = oldContents.style.overflow;
-                                       oldContents.style.overflow = "hidden";
-                                       animations.push(dojo.animateProperty({
-                                               node: oldContents,
-                                               duration: this.duration,
-                                               properties: {
-                                                       height: { start: this._getTargetHeight(oldContents), end: 1 }
-                                               },
-                                               onEnd: function(){
-                                                       dojo.addClass(oldContents, "dijitHidden");
-                                                       dojo.removeClass(oldContents, "dijitVisible");
-                                                       oldContents.style.overflow = oldContentsOverflow;
-                                                       if(oldWidget.onHide){
-                                                               oldWidget.onHide();
-                                                       }
-                                               }
-                                       }));
-                               }else{
-                                       dojo.addClass(oldContents, "dijitHidden");
-                                       dojo.removeClass(oldContents, "dijitVisible");
-                                       if(oldWidget.onHide){
-                                               oldWidget.onHide();
-                                       }
-                               }
-                       }
+       _onShow: function(){
+               // summary:
+               //              Called when the ContentPane is made visible
+               // description:
+               //              For a plain ContentPane, this is called on initialization, from startup().
+               //              If the ContentPane is a hidden pane of a TabContainer etc., then it's
+               //              called whenever the pane is made visible.
+               //
+               //              Does necessary processing, including href download and layout/resize of
+               //              child widget(s)
 
-                       if(animate){
-                               this._inTransition = true;
-                               var combined = dojo.fx.combine(animations);
-                               combined.onEnd = dojo.hitch(this, function(){
-                                       delete this._inTransition;
-                               });
-                               combined.play();
-                       }                       
-               },
+               this.inherited(arguments);
 
-               // note: we are treating the container as controller here
-               _onKeyPress: function(/*Event*/ e, /*dijit._Widget*/ fromTitle){
-                       // summary:
-                       //              Handle keypress events
-                       // description:
-                       //              This is called from a handler on AccordionContainer.domNode
-                       //              (setup in StackContainer), and is also called directly from
-                       //              the click handler for accordion labels
-                       if(this._inTransition || this.disabled || e.altKey || !(fromTitle || e.ctrlKey)){
-                               if(this._inTransition){
-                                       dojo.stopEvent(e);
-                               }
-                               return;
-                       }
-                       var k = dojo.keys,
-                               c = e.charOrCode;
-                       if((fromTitle && (c == k.LEFT_ARROW || c == k.UP_ARROW)) ||
-                                       (e.ctrlKey && c == k.PAGE_UP)){
-                               this._adjacent(false)._buttonWidget._onTitleClick();
-                               dojo.stopEvent(e);
-                       }else if((fromTitle && (c == k.RIGHT_ARROW || c == k.DOWN_ARROW)) ||
-                                       (e.ctrlKey && (c == k.PAGE_DOWN || c == k.TAB))){
-                               this._adjacent(true)._buttonWidget._onTitleClick();
-                               dojo.stopEvent(e);
+               if(this.href){
+                       if(!this._xhrDfd && // if there's an href that isn't already being loaded
+                               (!this.isLoaded || this._hrefChanged || this.refreshOnShow)
+                       ){
+                               return this.refresh();  // If child has an href, promise that fires when the load is complete
                        }
                }
-       }
-);
+       },
 
-dojo.declare("dijit.layout._AccordionInnerContainer",
-       [dijit._Widget, dijit._CssStateMixin], {
+       refresh: function(){
                // summary:
-               //              Internal widget placed as direct child of AccordionContainer.containerNode.
-               //              When other widgets are added as children to an AccordionContainer they are wrapped in
-               //              this widget.
-               
-               // buttonWidget: String
-               //              Name of class to use to instantiate title
-               //              (Wish we didn't have a separate widget for just the title but maintaining it
-               //              for backwards compatibility, is it worth it?)
-/*=====
-                buttonWidget: null,
-=====*/
-               // contentWidget: dijit._Widget
-               //              Pointer to the real child widget
-/*=====
-               contentWidget: null,
-=====*/
-
-               baseClass: "dijitAccordionInnerContainer",
-
-               // tell nested layout widget that we will take care of sizing
-               isContainer: true,
-               isLayoutContainer: true,
-
-               buildRendering: function(){                     
-                       // Create wrapper div, placed where the child is now
-                       this.domNode = dojo.place("<div class='" + this.baseClass + "'>", this.contentWidget.domNode, "after");
-                       
-                       // wrapper div's first child is the button widget (ie, the title bar)
-                       var child = this.contentWidget,
-                               cls = dojo.getObject(this.buttonWidget);
-                       this.button = child._buttonWidget = (new cls({
-                               contentWidget: child,
-                               label: child.title,
-                               title: child.tooltip,
-                               dir: child.dir,
-                               lang: child.lang,
-                               iconClass: child.iconClass,
-                               id: child.id + "_button",
-                               parent: this.parent
-                       })).placeAt(this.domNode);
-                       
-                       // and then the actual content widget (changing it from prior-sibling to last-child)
-                       dojo.place(this.contentWidget.domNode, this.domNode);
-               },
+               //              [Re]download contents of href and display
+               // description:
+               //              1. cancels any currently in-flight requests
+               //              2. posts "loading..." message
+               //              3. sends XHR to download new data
 
-               postCreate: function(){
-                       this.inherited(arguments);
-                       this.connect(this.contentWidget, 'set', function(name, value){
-                               var mappedName = {title: "label", tooltip: "title", iconClass: "iconClass"}[name];
-                               if(mappedName){
-                                       this.button.set(mappedName, value);
-                               }
-                       }, this);
-               },
+               // Cancel possible prior in-flight request
+               this.cancel();
 
-               _setSelectedAttr: function(/*Boolean*/ isSelected){
-                       this.selected = isSelected;
-                       this.button.set("selected", isSelected);
-                       if(isSelected){
-                               var cw = this.contentWidget;
-                               if(cw.onSelected){ cw.onSelected(); }
-                       }
-               },
+               this.onLoadDeferred = new Deferred(lang.hitch(this, "cancel"));
+               this.onLoadDeferred.addCallback(lang.hitch(this, "onLoad"));
+               this._load();
+               return this.onLoadDeferred;             // If child has an href, promise that fires when refresh is complete
+       },
 
-               startup: function(){
-                       // Called by _Container.addChild()
-                       this.contentWidget.startup();
-               },
+       _load: function(){
+               // summary:
+               //              Load/reload the href specified in this.href
 
-               destroy: function(){
-                       this.button.destroyRecursive();
-                       
-                       delete this.contentWidget._buttonWidget;
-                       delete this.contentWidget._wrapperWidget;
+               // display loading message
+               this._setContent(this.onDownloadStart(), true);
 
-                       this.inherited(arguments);
-               },
-               
-               destroyDescendants: function(){
-                       // since getChildren isn't working for me, have to code this manually
-                       this.contentWidget.destroyRecursive();
+               var self = this;
+               var getArgs = {
+                       preventCache: (this.preventCache || this.refreshOnShow),
+                       url: this.href,
+                       handleAs: "text"
+               };
+               if(lang.isObject(this.ioArgs)){
+                       lang.mixin(getArgs, this.ioArgs);
                }
-});
-
-dojo.declare("dijit.layout._AccordionButton",
-       [dijit._Widget, dijit._Templated, dijit._CssStateMixin],
-       {
-       // summary:
-       //              The title bar to click to open up an accordion pane.
-       //              Internal widget used by AccordionContainer.
-       // tags:
-       //              private
-
-       templateString: dojo.cache("dijit.layout", "templates/AccordionButton.html", "<div dojoAttachEvent='onclick:_onTitleClick' class='dijitAccordionTitle'>\n\t<div dojoAttachPoint='titleNode,focusNode' dojoAttachEvent='onkeypress:_onTitleKeyPress'\n\t\t\tclass='dijitAccordionTitleFocus' wairole=\"tab\" waiState=\"expanded-false\"\n\t\t><span class='dijitInline dijitAccordionArrow' waiRole=\"presentation\"></span\n\t\t><span class='arrowTextUp' waiRole=\"presentation\">+</span\n\t\t><span class='arrowTextDown' waiRole=\"presentation\">-</span\n\t\t><img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" dojoAttachPoint='iconNode' style=\"vertical-align: middle\" waiRole=\"presentation\"/>\n\t\t<span waiRole=\"presentation\" dojoAttachPoint='titleTextNode' class='dijitAccordionText'></span>\n\t</div>\n</div>\n"),
-       attributeMap: dojo.mixin(dojo.clone(dijit.layout.ContentPane.prototype.attributeMap), {
-               label: {node: "titleTextNode", type: "innerHTML" },
-               title: {node: "titleTextNode", type: "attribute", attribute: "title"},
-               iconClass: { node: "iconNode", type: "class" }
-       }),
 
-       baseClass: "dijitAccordionTitle",
+               var hand = (this._xhrDfd = (this.ioMethod || xhr.get)(getArgs));
 
-       getParent: function(){
-               // summary:
-               //              Returns the AccordionContainer parent.
-               // tags:
-               //              private
-               return this.parent;
-       },
+               hand.addCallback(function(html){
+                       try{
+                               self._isDownloaded = true;
+                               self._setContent(html, false);
+                               self.onDownloadEnd();
+                       }catch(err){
+                               self._onError('Content', err); // onContentError
+                       }
+                       delete self._xhrDfd;
+                       return html;
+               });
 
-       postCreate: function(){
-               this.inherited(arguments);
-               dojo.setSelectable(this.domNode, false);
-               var titleTextNodeId = dojo.attr(this.domNode,'id').replace(' ','_');
-               dojo.attr(this.titleTextNode, "id", titleTextNodeId+"_title");
-               dijit.setWaiState(this.focusNode, "labelledby", dojo.attr(this.titleTextNode, "id"));
-       },
+               hand.addErrback(function(err){
+                       if(!hand.canceled){
+                               // show error message in the pane
+                               self._onError('Download', err); // onDownloadError
+                       }
+                       delete self._xhrDfd;
+                       return err;
+               });
 
-       getTitleHeight: function(){
-               // summary:
-               //              Returns the height of the title dom node.
-               return dojo.marginBox(this.domNode).h;  // Integer
+               // Remove flag saying that a load is needed
+               delete this._hrefChanged;
        },
 
-       // TODO: maybe the parent should set these methods directly rather than forcing the code
-       // into the button widget?
-       _onTitleClick: function(){
+       _onLoadHandler: function(data){
                // summary:
-               //              Callback when someone clicks my title.
-               var parent = this.getParent();
-               if(!parent._inTransition){
-                       parent.selectChild(this.contentWidget, true);
-                       dijit.focus(this.focusNode);
+               //              This is called whenever new content is being loaded
+               this._set("isLoaded", true);
+               try{
+                       this.onLoadDeferred.callback(data);
+               }catch(e){
+                       console.error('Error '+this.widgetId+' running custom onLoad code: ' + e.message);
                }
        },
 
-       _onTitleKeyPress: function(/*Event*/ evt){
-               return this.getParent()._onKeyPress(evt, this.contentWidget);
+       _onUnloadHandler: function(){
+               // summary:
+               //              This is called whenever the content is being unloaded
+               this._set("isLoaded", false);
+               try{
+                       this.onUnload();
+               }catch(e){
+                       console.error('Error '+this.widgetId+' running custom onUnload code: ' + e.message);
+               }
        },
 
-       _setSelectedAttr: function(/*Boolean*/ isSelected){
-               this.selected = isSelected;
-               dijit.setWaiState(this.focusNode, "expanded", isSelected);
-               dijit.setWaiState(this.focusNode, "selected", isSelected);
-               this.focusNode.setAttribute("tabIndex", isSelected ? "0" : "-1");
-       }
-});
-
-}
-
-if(!dojo._hasResource["dijit.layout.BorderContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.BorderContainer"] = true;
-dojo.provide("dijit.layout.BorderContainer");
-
-
-
-
-dojo.declare(
-       "dijit.layout.BorderContainer",
-       dijit.layout._LayoutWidget,
-{
-       // summary:
-       //              Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
-       //
-       // description:
-       //              A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
-       //              that contains a child widget marked region="center" and optionally children widgets marked
-       //              region equal to "top", "bottom", "leading", "trailing", "left" or "right".
-       //              Children along the edges will be laid out according to width or height dimensions and may
-       //              include optional splitters (splitter="true") to make them resizable by the user.  The remaining
-       //              space is designated for the center region.
-       //
-       //              NOTE: Splitters must not be more than 50 pixels in width.
-       //
-       //              The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
-       //              and height for the top and bottom, respectively.  No dimensions should be specified on the center;
-       //              it will fill the remaining space.  Regions named "leading" and "trailing" may be used just like
-       //              "left" and "right" except that they will be reversed in right-to-left environments.
-       //
-       // example:
-       // |    <div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="false"
-       // |            style="width: 400px; height: 300px;">
-       // |            <div dojoType="ContentPane" region="top">header text</div>
-       // |            <div dojoType="ContentPane" region="right" splitter="true" style="width: 200px;">table of contents</div>
-       // |            <div dojoType="ContentPane" region="center">client area</div>
-       // |    </div>
-
-       // design: String
-       //              Which design is used for the layout:
-       //                      - "headline" (default) where the top and bottom extend
-       //                              the full width of the container
-       //                      - "sidebar" where the left and right sides extend from top to bottom.
-       design: "headline",
-
-       // gutters: Boolean
-       //              Give each pane a border and margin.
-       //              Margin determined by domNode.paddingLeft.
-       //              When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
-       gutters: true,
-
-       // liveSplitters: Boolean
-       //              Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
-       liveSplitters: true,
-
-       // persist: Boolean
-       //              Save splitter positions in a cookie.
-       persist: false,
+       destroyDescendants: function(/*Boolean*/ preserveDom){
+               // summary:
+               //              Destroy all the widgets inside the ContentPane and empty containerNode
 
-       baseClass: "dijitBorderContainer",
+               // Make sure we call onUnload (but only when the ContentPane has real content)
+               if(this.isLoaded){
+                       this._onUnloadHandler();
+               }
 
-       // _splitterClass: String
-       //              Optional hook to override the default Splitter widget used by BorderContainer
-       _splitterClass: "dijit.layout._Splitter",
+               // Even if this.isLoaded == false there might still be a "Loading..." message
+               // to erase, so continue...
 
-       postMixInProperties: function(){
-               // change class name to indicate that BorderContainer is being used purely for
-               // layout (like LayoutContainer) rather than for pretty formatting.
-               if(!this.gutters){
-                       this.baseClass += "NoGutter";
+               // For historical reasons we need to delete all widgets under this.containerNode,
+               // even ones that the user has created manually.
+               var setter = this._contentSetter;
+               array.forEach(this.getChildren(), function(widget){
+                       if(widget.destroyRecursive){
+                               widget.destroyRecursive(preserveDom);
+                       }
+               });
+               if(setter){
+                       // Most of the widgets in setter.parseResults have already been destroyed, but
+                       // things like Menu that have been moved to <body> haven't yet
+                       array.forEach(setter.parseResults, function(widget){
+                               if(widget.destroyRecursive && widget.domNode && widget.domNode.parentNode == win.body()){
+                                       widget.destroyRecursive(preserveDom);
+                               }
+                       });
+                       delete setter.parseResults;
                }
-               this.inherited(arguments);
-       },
 
-       postCreate: function(){
-               this.inherited(arguments);
-
-               this._splitters = {};
-               this._splitterThickness = {};
-       },
+               // And then clear away all the DOM nodes
+               if(!preserveDom){
+                       html._emptyNode(this.containerNode);
+               }
 
-       startup: function(){
-               if(this._started){ return; }
-               dojo.forEach(this.getChildren(), this._setupChild, this);
-               this.inherited(arguments);
+               // Delete any state information we have about current contents
+               delete this._singleChild;
        },
 
-       _setupChild: function(/*dijit._Widget*/ child){
-               // Override _LayoutWidget._setupChild().
+       _setContent: function(/*String|DocumentFragment*/ cont, /*Boolean*/ isFakeContent){
+               // summary:
+               //              Insert the content into the container node
 
-               var region = child.region;
-               if(region){
-                       this.inherited(arguments);
+               // first get rid of child widgets
+               this.destroyDescendants();
 
-                       dojo.addClass(child.domNode, this.baseClass+"Pane");
+               // html.set will take care of the rest of the details
+               // we provide an override for the error handling to ensure the widget gets the errors
+               // configure the setter instance with only the relevant widget instance properties
+               // NOTE: unless we hook into attr, or provide property setters for each property,
+               // we need to re-configure the ContentSetter with each use
+               var setter = this._contentSetter;
+               if(! (setter && setter instanceof html._ContentSetter)){
+                       setter = this._contentSetter = new html._ContentSetter({
+                               node: this.containerNode,
+                               _onError: lang.hitch(this, this._onError),
+                               onContentError: lang.hitch(this, function(e){
+                                       // fires if a domfault occurs when we are appending this.errorMessage
+                                       // like for instance if domNode is a UL and we try append a DIV
+                                       var errMess = this.onContentError(e);
+                                       try{
+                                               this.containerNode.innerHTML = errMess;
+                                       }catch(e){
+                                               console.error('Fatal '+this.id+' could not change content due to '+e.message, e);
+                                       }
+                               })/*,
+                               _onError */
+                       });
+               }
 
-                       var ltr = this.isLeftToRight();
-                       if(region == "leading"){ region = ltr ? "left" : "right"; }
-                       if(region == "trailing"){ region = ltr ? "right" : "left"; }
+               var setterParams = lang.mixin({
+                       cleanContent: this.cleanContent,
+                       extractContent: this.extractContent,
+                       parseContent: !cont.domNode && this.parseOnLoad,
+                       parserScope: this.parserScope,
+                       startup: false,
+                       dir: this.dir,
+                       lang: this.lang,
+                       textDir: this.textDir
+               }, this._contentSetterParams || {});
 
-                       //FIXME: redundant?
-                       this["_"+region] = child.domNode;
-                       this["_"+region+"Widget"] = child;
+               setter.set( (lang.isObject(cont) && cont.domNode) ? cont.domNode : cont, setterParams );
 
-                       // Create draggable splitter for resizing pane,
-                       // or alternately if splitter=false but BorderContainer.gutters=true then
-                       // insert dummy div just for spacing
-                       if((child.splitter || this.gutters) && !this._splitters[region]){
-                               var _Splitter = dojo.getObject(child.splitter ? this._splitterClass : "dijit.layout._Gutter");
-                               var splitter = new _Splitter({
-                                       id: child.id + "_splitter",
-                                       container: this,
-                                       child: child,
-                                       region: region,
-                                       live: this.liveSplitters
-                               });
-                               splitter.isSplitter = true;
-                               this._splitters[region] = splitter.domNode;
-                               dojo.place(this._splitters[region], child.domNode, "after");
+               // setter params must be pulled afresh from the ContentPane each time
+               delete this._contentSetterParams;
 
-                               // Splitters arent added as Contained children, so we need to call startup explicitly
-                               splitter.startup();
-                       }
-                       child.region = region;
+               if(this.doLayout){
+                       this._checkIfSingleChild();
                }
-       },
 
-       _computeSplitterThickness: function(region){
-               this._splitterThickness[region] = this._splitterThickness[region] ||
-                       dojo.marginBox(this._splitters[region])[(/top|bottom/.test(region) ? 'h' : 'w')];
-       },
+               if(!isFakeContent){
+                       if(this._started){
+                               // Startup each top level child widget (and they will start their children, recursively)
+                               delete this._started;
+                               this.startup();
 
-       layout: function(){
-               // Implement _LayoutWidget.layout() virtual method.
-               for(var region in this._splitters){ this._computeSplitterThickness(region); }
-               this._layoutChildren();
-       },
+                               // Call resize() on each of my child layout widgets,
+                               // or resize() on my single child layout widget...
+                               // either now (if I'm currently visible) or when I become visible
+                               this._scheduleLayout();
+                       }
 
-       addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
-               // Override _LayoutWidget.addChild().
-               this.inherited(arguments);
-               if(this._started){
-                       this.layout(); //OPT
+                       this._onLoadHandler(cont);
                }
        },
 
-       removeChild: function(/*dijit._Widget*/ child){
-               // Override _LayoutWidget.removeChild().
-               var region = child.region;
-               var splitter = this._splitters[region];
-               if(splitter){
-                       dijit.byNode(splitter).destroy();
-                       delete this._splitters[region];
-                       delete this._splitterThickness[region];
-               }
-               this.inherited(arguments);
-               delete this["_"+region];
-               delete this["_" +region+"Widget"];
-               if(this._started){
-                       this._layoutChildren();
+       _onError: function(type, err, consoleText){
+               this.onLoadDeferred.errback(err);
+
+               // shows user the string that is returned by on[type]Error
+               // override on[type]Error and return your own string to customize
+               var errText = this['on' + type + 'Error'].call(this, err);
+               if(consoleText){
+                       console.error(consoleText, err);
+               }else if(errText){// a empty string won't change current content
+                       this._setContent(errText, true);
                }
-               dojo.removeClass(child.domNode, this.baseClass+"Pane");
        },
 
-       getChildren: function(){
-               // Override _LayoutWidget.getChildren() to only return real children, not the splitters.
-               return dojo.filter(this.inherited(arguments), function(widget){
-                       return !widget.isSplitter;
-               });
+       // EVENT's, should be overide-able
+       onLoad: function(/*===== data =====*/){
+               // summary:
+               //              Event hook, is called after everything is loaded and widgetified
+               // tags:
+               //              callback
        },
 
-       getSplitter: function(/*String*/region){
+       onUnload: function(){
                // summary:
-               //              Returns the widget responsible for rendering the splitter associated with region
-               var splitter = this._splitters[region];
-               return splitter ? dijit.byNode(splitter) : null;
+               //              Event hook, is called before old content is cleared
+               // tags:
+               //              callback
        },
 
-       resize: function(newSize, currentSize){
-               // Overrides _LayoutWidget.resize().
-
-               // resetting potential padding to 0px to provide support for 100% width/height + padding
-               // TODO: this hack doesn't respect the box model and is a temporary fix
-               if(!this.cs || !this.pe){
-                       var node = this.domNode;
-                       this.cs = dojo.getComputedStyle(node);
-                       this.pe = dojo._getPadExtents(node, this.cs);
-                       this.pe.r = dojo._toPixelValue(node, this.cs.paddingRight);
-                       this.pe.b = dojo._toPixelValue(node, this.cs.paddingBottom);
-
-                       dojo.style(node, "padding", "0px");
-               }
-
-               this.inherited(arguments);
+       onDownloadStart: function(){
+               // summary:
+               //              Called before download starts.
+               // description:
+               //              The string returned by this function will be the html
+               //              that tells the user we are loading something.
+               //              Override with your own function if you want to change text.
+               // tags:
+               //              extension
+               return this.loadingMessage;
        },
 
-       _layoutChildren: function(/*String?*/changedRegion, /*Number?*/ changedRegionSize){
+       onContentError: function(/*Error*/ /*===== error =====*/){
                // summary:
-               //              This is the main routine for setting size/position of each child.
-               // description:
-               //              With no arguments, measures the height of top/bottom panes, the width
-               //              of left/right panes, and then sizes all panes accordingly.
+               //              Called on DOM faults, require faults etc. in content.
                //
-               //              With changedRegion specified (as "left", "top", "bottom", or "right"),
-               //              it changes that region's width/height to changedRegionSize and
-               //              then resizes other regions that were affected.
-               // changedRegion:
-               //              The region should be changed because splitter was dragged.
-               //              "left", "right", "top", or "bottom".
-               // changedRegionSize:
-               //              The new width/height (in pixels) to make changedRegion
-
-               if(!this._borderBox || !this._borderBox.h){
-                       // We are currently hidden, or we haven't been sized by our parent yet.
-                       // Abort.   Someone will resize us later.
-                       return;
-               }
-
-               var sidebarLayout = (this.design == "sidebar");
-               var topHeight = 0, bottomHeight = 0, leftWidth = 0, rightWidth = 0;
-               var topStyle = {}, leftStyle = {}, rightStyle = {}, bottomStyle = {},
-                       centerStyle = (this._center && this._center.style) || {};
-
-               var changedSide = /left|right/.test(changedRegion);
-
-               var layoutSides = !changedRegion || (!changedSide && !sidebarLayout);
-               var layoutTopBottom = !changedRegion || (changedSide && sidebarLayout);
+               //              In order to display an error message in the pane, return
+               //              the error message from this method, as an HTML string.
+               //
+               //              By default (if this method is not overriden), it returns
+               //              nothing, so the error message is just printed to the console.
+               // tags:
+               //              extension
+       },
 
-               // Ask browser for width/height of side panes.
-               // Would be nice to cache this but height can change according to width
-               // (because words wrap around).  I don't think width will ever change though
-               // (except when the user drags a splitter).
-               if(this._top){
-                       topStyle = (changedRegion == "top" || layoutTopBottom) && this._top.style;
-                       topHeight = changedRegion == "top" ? changedRegionSize : dojo.marginBox(this._top).h;
-               }
-               if(this._left){
-                       leftStyle = (changedRegion == "left" || layoutSides) && this._left.style;
-                       leftWidth = changedRegion == "left" ? changedRegionSize : dojo.marginBox(this._left).w;
-               }
-               if(this._right){
-                       rightStyle = (changedRegion == "right" || layoutSides) && this._right.style;
-                       rightWidth = changedRegion == "right" ? changedRegionSize : dojo.marginBox(this._right).w;
-               }
-               if(this._bottom){
-                       bottomStyle = (changedRegion == "bottom" || layoutTopBottom) && this._bottom.style;
-                       bottomHeight = changedRegion == "bottom" ? changedRegionSize : dojo.marginBox(this._bottom).h;
-               }
+       onDownloadError: function(/*Error*/ /*===== error =====*/){
+               // summary:
+               //              Called when download error occurs.
+               //
+               //              In order to display an error message in the pane, return
+               //              the error message from this method, as an HTML string.
+               //
+               //              Default behavior (if this method is not overriden) is to display
+               //              the error message inside the pane.
+               // tags:
+               //              extension
+               return this.errorMessage;
+       },
 
-               var splitters = this._splitters;
-               var topSplitter = splitters.top, bottomSplitter = splitters.bottom,
-                       leftSplitter = splitters.left, rightSplitter = splitters.right;
-               var splitterThickness = this._splitterThickness;
-               var topSplitterThickness = splitterThickness.top || 0,
-                       leftSplitterThickness = splitterThickness.left || 0,
-                       rightSplitterThickness = splitterThickness.right || 0,
-                       bottomSplitterThickness = splitterThickness.bottom || 0;
+       onDownloadEnd: function(){
+               // summary:
+               //              Called when download is finished.
+               // tags:
+               //              callback
+       }
+});
 
-               // Check for race condition where CSS hasn't finished loading, so
-               // the splitter width == the viewport width (#5824)
-               if(leftSplitterThickness > 50 || rightSplitterThickness > 50){
-                       setTimeout(dojo.hitch(this, function(){
-                               // Results are invalid.  Clear them out.
-                               this._splitterThickness = {};
+});
 
-                               for(var region in this._splitters){
-                                       this._computeSplitterThickness(region);
-                               }
-                               this._layoutChildren();
-                       }), 50);
-                       return false;
-               }
+},
+'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&#935; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n",
+'url:dijit/form/templates/TextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\" id=\"widget_${id}\" role=\"presentation\"\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n",
+'dijit/layout/utils':function(){
+define("dijit/layout/utils", [
+       "dojo/_base/array", // array.filter array.forEach
+       "dojo/dom-class", // domClass.add domClass.remove
+       "dojo/dom-geometry", // domGeometry.marginBox
+       "dojo/dom-style", // domStyle.getComputedStyle
+       "dojo/_base/lang", // lang.mixin
+       ".."    // for exporting symbols to dijit, remove in 2.0
+], function(array, domClass, domGeometry, domStyle, lang, dijit){
+
+       // module:
+       //              dijit/layout/utils
+       // summary:
+       //              marginBox2contentBox() and layoutChildren()
 
-               var pe = this.pe;
+       var layout = lang.getObject("layout", true, dijit);
+       /*===== layout = dijit.layout =====*/
 
-               var splitterBounds = {
-                       left: (sidebarLayout ? leftWidth + leftSplitterThickness: 0) + pe.l + "px",
-                       right: (sidebarLayout ? rightWidth + rightSplitterThickness: 0) + pe.r + "px"
+       layout.marginBox2contentBox = function(/*DomNode*/ node, /*Object*/ mb){
+               // summary:
+               //              Given the margin-box size of a node, return its content box size.
+               //              Functions like domGeometry.contentBox() but is more reliable since it doesn't have
+               //              to wait for the browser to compute sizes.
+               var cs = domStyle.getComputedStyle(node);
+               var me = domGeometry.getMarginExtents(node, cs);
+               var pb = domGeometry.getPadBorderExtents(node, cs);
+               return {
+                       l: domStyle.toPixelValue(node, cs.paddingLeft),
+                       t: domStyle.toPixelValue(node, cs.paddingTop),
+                       w: mb.w - (me.w + pb.w),
+                       h: mb.h - (me.h + pb.h)
                };
+       };
 
-               if(topSplitter){
-                       dojo.mixin(topSplitter.style, splitterBounds);
-                       topSplitter.style.top = topHeight + pe.t + "px";
-               }
+       function capitalize(word){
+               return word.substring(0,1).toUpperCase() + word.substring(1);
+       }
+
+       function size(widget, dim){
+               // size the child
+               var newSize = widget.resize ? widget.resize(dim) : domGeometry.setMarginBox(widget.domNode, dim);
 
-               if(bottomSplitter){
-                       dojo.mixin(bottomSplitter.style, splitterBounds);
-                       bottomSplitter.style.bottom = bottomHeight + pe.b + "px";
+               // record child's size
+               if(newSize){
+                       // if the child returned it's new size then use that
+                       lang.mixin(widget, newSize);
+               }else{
+                       // otherwise, call getMarginBox(), but favor our own numbers when we have them.
+                       // the browser lies sometimes
+                       lang.mixin(widget, domGeometry.getMarginBox(widget.domNode));
+                       lang.mixin(widget, dim);
                }
+       }
 
-               splitterBounds = {
-                       top: (sidebarLayout ? 0 : topHeight + topSplitterThickness) + pe.t + "px",
-                       bottom: (sidebarLayout ? 0 : bottomHeight + bottomSplitterThickness) + pe.b + "px"
-               };
+       layout.layoutChildren = function(/*DomNode*/ container, /*Object*/ dim, /*Widget[]*/ children,
+                       /*String?*/ changedRegionId, /*Number?*/ changedRegionSize){
+               // summary:
+               //              Layout a bunch of child dom nodes within a parent dom node
+               // container:
+               //              parent node
+               // dim:
+               //              {l, t, w, h} object specifying dimensions of container into which to place children
+               // children:
+               //              an array of Widgets or at least objects containing:
+               //                      * domNode: pointer to DOM node to position
+               //                      * region or layoutAlign: position to place DOM node
+               //                      * resize(): (optional) method to set size of node
+               //                      * id: (optional) Id of widgets, referenced from resize object, below.
+               // changedRegionId:
+               //              If specified, the slider for the region with the specified id has been dragged, and thus
+               //              the region's height or width should be adjusted according to changedRegionSize
+               // changedRegionSize:
+               //              See changedRegionId.
 
-               if(leftSplitter){
-                       dojo.mixin(leftSplitter.style, splitterBounds);
-                       leftSplitter.style.left = leftWidth + pe.l + "px";
-               }
+               // copy dim because we are going to modify it
+               dim = lang.mixin({}, dim);
 
-               if(rightSplitter){
-                       dojo.mixin(rightSplitter.style, splitterBounds);
-                       rightSplitter.style.right = rightWidth + pe.r + "px";
-               }
+               domClass.add(container, "dijitLayoutContainer");
 
-               dojo.mixin(centerStyle, {
-                       top: pe.t + topHeight + topSplitterThickness + "px",
-                       left: pe.l + leftWidth + leftSplitterThickness + "px",
-                       right: pe.r + rightWidth + rightSplitterThickness + "px",
-                       bottom: pe.b + bottomHeight + bottomSplitterThickness + "px"
-               });
+               // Move "client" elements to the end of the array for layout.  a11y dictates that the author
+               // needs to be able to put them in the document in tab-order, but this algorithm requires that
+               // client be last.    TODO: move these lines to LayoutContainer?   Unneeded other places I think.
+               children = array.filter(children, function(item){ return item.region != "center" && item.layoutAlign != "client"; })
+                       .concat(array.filter(children, function(item){ return item.region == "center" || item.layoutAlign == "client"; }));
 
-               var bounds = {
-                       top: sidebarLayout ? pe.t + "px" : centerStyle.top,
-                       bottom: sidebarLayout ? pe.b + "px" : centerStyle.bottom
-               };
-               dojo.mixin(leftStyle, bounds);
-               dojo.mixin(rightStyle, bounds);
-               leftStyle.left = pe.l + "px"; rightStyle.right = pe.r + "px"; topStyle.top = pe.t + "px"; bottomStyle.bottom = pe.b + "px";
-               if(sidebarLayout){
-                       topStyle.left = bottomStyle.left = leftWidth + leftSplitterThickness + pe.l + "px";
-                       topStyle.right = bottomStyle.right = rightWidth + rightSplitterThickness + pe.r + "px";
-               }else{
-                       topStyle.left = bottomStyle.left = pe.l + "px";
-                       topStyle.right = bottomStyle.right = pe.r + "px";
-               }
+               // set positions/sizes
+               array.forEach(children, function(child){
+                       var elm = child.domNode,
+                               pos = (child.region || child.layoutAlign);
+                       if(!pos){
+                               throw new Error("No region setting for " + child.id)
+                       }
 
-               // More calculations about sizes of panes
-               var containerHeight = this._borderBox.h - pe.t - pe.b,
-                       middleHeight = containerHeight - ( topHeight + topSplitterThickness + bottomHeight + bottomSplitterThickness),
-                       sidebarHeight = sidebarLayout ? containerHeight : middleHeight;
+                       // set elem to upper left corner of unused space; may move it later
+                       var elmStyle = elm.style;
+                       elmStyle.left = dim.l+"px";
+                       elmStyle.top = dim.t+"px";
+                       elmStyle.position = "absolute";
 
-               var containerWidth = this._borderBox.w - pe.l - pe.r,
-                       middleWidth = containerWidth - (leftWidth + leftSplitterThickness + rightWidth + rightSplitterThickness),
-                       sidebarWidth = sidebarLayout ? middleWidth : containerWidth;
+                       domClass.add(elm, "dijitAlign" + capitalize(pos));
 
-               // New margin-box size of each pane
-               var dim = {
-                       top:    { w: sidebarWidth, h: topHeight },
-                       bottom: { w: sidebarWidth, h: bottomHeight },
-                       left:   { w: leftWidth, h: sidebarHeight },
-                       right:  { w: rightWidth, h: sidebarHeight },
-                       center: { h: middleHeight, w: middleWidth }
-               };
+                       // Size adjustments to make to this child widget
+                       var sizeSetting = {};
 
-               if(changedRegion){
-                       // Respond to splitter drag event by changing changedRegion's width or height
-                       var child = this["_" + changedRegion + "Widget"],
-                               mb = {};
-                               mb[ /top|bottom/.test(changedRegion) ? "h" : "w"] = changedRegionSize;
-                       child.resize ? child.resize(mb, dim[child.region]) : dojo.marginBox(child.domNode, mb);
-               }
+                       // Check for optional size adjustment due to splitter drag (height adjustment for top/bottom align
+                       // panes and width adjustment for left/right align panes.
+                       if(changedRegionId && changedRegionId == child.id){
+                               sizeSetting[child.region == "top" || child.region == "bottom" ? "h" : "w"] = changedRegionSize;
+                       }
 
-               // Nodes in IE<8 don't respond to t/l/b/r, and TEXTAREA doesn't respond in any browser
-               var janky = dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.some(this.getChildren(), function(child){
-                       return child.domNode.tagName == "TEXTAREA" || child.domNode.tagName == "INPUT";
+                       // set size && adjust record of remaining space.
+                       // note that setting the width of a <div> may affect its height.
+                       if(pos == "top" || pos == "bottom"){
+                               sizeSetting.w = dim.w;
+                               size(child, sizeSetting);
+                               dim.h -= child.h;
+                               if(pos == "top"){
+                                       dim.t += child.h;
+                               }else{
+                                       elmStyle.top = dim.t + dim.h + "px";
+                               }
+                       }else if(pos == "left" || pos == "right"){
+                               sizeSetting.h = dim.h;
+                               size(child, sizeSetting);
+                               dim.w -= child.w;
+                               if(pos == "left"){
+                                       dim.l += child.w;
+                               }else{
+                                       elmStyle.left = dim.l + dim.w + "px";
+                               }
+                       }else if(pos == "client" || pos == "center"){
+                               size(child, dim);
+                       }
                });
-               if(janky){
-                       // Set the size of the children the old fashioned way, by setting
-                       // CSS width and height
+       };
 
-                       var resizeWidget = function(widget, changes, result){
-                               if(widget){
-                                       (widget.resize ? widget.resize(changes, result) : dojo.marginBox(widget.domNode, changes));
-                               }
-                       };
 
-                       if(leftSplitter){ leftSplitter.style.height = sidebarHeight; }
-                       if(rightSplitter){ rightSplitter.style.height = sidebarHeight; }
-                       resizeWidget(this._leftWidget, {h: sidebarHeight}, dim.left);
-                       resizeWidget(this._rightWidget, {h: sidebarHeight}, dim.right);
+       return {
+               marginBox2contentBox: layout.marginBox2contentBox,
+               layoutChildren: layout.layoutChildren
+       };
+});
 
-                       if(topSplitter){ topSplitter.style.width = sidebarWidth; }
-                       if(bottomSplitter){ bottomSplitter.style.width = sidebarWidth; }
-                       resizeWidget(this._topWidget, {w: sidebarWidth}, dim.top);
-                       resizeWidget(this._bottomWidget, {w: sidebarWidth}, dim.bottom);
+},
+'dijit/_Contained':function(){
+define("dijit/_Contained", [
+       "dojo/_base/declare", // declare
+       "./registry"    // registry.getEnclosingWidget(), registry.byNode()
+], function(declare, registry){
+
+       // module:
+       //              dijit/_Contained
+       // summary:
+       //              Mixin for widgets that are children of a container widget
 
-                       resizeWidget(this._centerWidget, dim.center);
-               }else{
-                       // Calculate which panes need a notification that their size has been changed
-                       // (we've already set style.top/bottom/left/right on those other panes).
-                       var notifySides = !changedRegion || (/top|bottom/.test(changedRegion) && this.design != "sidebar"),
-                               notifyTopBottom = !changedRegion || (/left|right/.test(changedRegion) && this.design == "sidebar"),
-                               notifyList = {
-                                       center: true,
-                                       left: notifySides,
-                                       right: notifySides,
-                                       top: notifyTopBottom,
-                                       bottom: notifyTopBottom
-                               };
-                       
-                       // Send notification to those panes that have changed size
-                       dojo.forEach(this.getChildren(), function(child){
-                               if(child.resize && notifyList[child.region]){
-                                       child.resize(null, dim[child.region]);
-                               }
-                       }, this);
-               }
-       },
+       return declare("dijit._Contained", null, {
+               // summary:
+               //              Mixin for widgets that are children of a container widget
+               //
+               // example:
+               // |    // make a basic custom widget that knows about it's parents
+               // |    declare("my.customClass",[dijit._Widget,dijit._Contained],{});
 
-       destroy: function(){
-               for(var region in this._splitters){
-                       var splitter = this._splitters[region];
-                       dijit.byNode(splitter).destroy();
-                       dojo.destroy(splitter);
-               }
-               delete this._splitters;
-               delete this._splitterThickness;
-               this.inherited(arguments);
-       }
-});
+               _getSibling: function(/*String*/ which){
+                       // summary:
+                       //      Returns next or previous sibling
+                       // which:
+                       //      Either "next" or "previous"
+                       // tags:
+                       //      private
+                       var node = this.domNode;
+                       do{
+                               node = node[which+"Sibling"];
+                       }while(node && node.nodeType != 1);
+                       return node && registry.byNode(node);   // dijit._Widget
+               },
 
-// This argument can be specified for the children of a BorderContainer.
-// Since any widget can be specified as a LayoutContainer child, mix it
-// into the base widget class.  (This is a hack, but it's effective.)
-dojo.extend(dijit._Widget, {
-       // region: [const] String
-       //              Parameter for children of `dijit.layout.BorderContainer`.
-       //              Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
-       //              See the `dijit.layout.BorderContainer` description for details.
-       region: '',
+               getPreviousSibling: function(){
+                       // summary:
+                       //              Returns null if this is the first child of the parent,
+                       //              otherwise returns the next element sibling to the "left".
 
-       // splitter: [const] Boolean
-       //              Parameter for child of `dijit.layout.BorderContainer` where region != "center".
-       //              If true, enables user to resize the widget by putting a draggable splitter between
-       //              this widget and the region=center widget.
-       splitter: false,
+                       return this._getSibling("previous"); // dijit._Widget
+               },
 
-       // minSize: [const] Number
-       //              Parameter for children of `dijit.layout.BorderContainer`.
-       //              Specifies a minimum size (in pixels) for this widget when resized by a splitter.
-       minSize: 0,
+               getNextSibling: function(){
+                       // summary:
+                       //              Returns null if this is the last child of the parent,
+                       //              otherwise returns the next element sibling to the "right".
 
-       // maxSize: [const] Number
-       //              Parameter for children of `dijit.layout.BorderContainer`.
-       //              Specifies a maximum size (in pixels) for this widget when resized by a splitter.
-       maxSize: Infinity
+                       return this._getSibling("next"); // dijit._Widget
+               },
+
+               getIndexInParent: function(){
+                       // summary:
+                       //              Returns the index of this widget within its container parent.
+                       //              It returns -1 if the parent does not exist, or if the parent
+                       //              is not a dijit._Container
+
+                       var p = this.getParent();
+                       if(!p || !p.getIndexOfChild){
+                               return -1; // int
+                       }
+                       return p.getIndexOfChild(this); // int
+               }
+       });
 });
 
+},
+'dijit/_KeyNavContainer':function(){
+define("dijit/_KeyNavContainer", [
+       "dojo/_base/kernel", // kernel.deprecated
+       "./_Container",
+       "./_FocusMixin",
+       "dojo/_base/array", // array.forEach
+       "dojo/keys", // keys.END keys.HOME
+       "dojo/_base/declare", // declare
+       "dojo/_base/event", // event.stop
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/lang" // lang.hitch
+], function(kernel, _Container, _FocusMixin, array, keys, declare, event, domAttr, lang){
 
+/*=====
+       var _FocusMixin = dijit._FocusMixin;
+       var _Container = dijit._Container;
+=====*/
 
-dojo.declare("dijit.layout._Splitter", [ dijit._Widget, dijit._Templated ],
-{
+       // module:
+       //              dijit/_KeyNavContainer
        // summary:
-       //              A draggable spacer between two items in a `dijit.layout.BorderContainer`.
-       // description:
-       //              This is instantiated by `dijit.layout.BorderContainer`.  Users should not
-       //              create it directly.
-       // tags:
-       //              private
+       //              A _Container with keyboard navigation of its children.
 
-/*=====
-       // container: [const] dijit.layout.BorderContainer
-       //              Pointer to the parent BorderContainer
-       container: null,
+       return declare("dijit._KeyNavContainer", [_FocusMixin, _Container], {
 
-       // child: [const] dijit.layout._LayoutWidget
-       //              Pointer to the pane associated with this splitter
-       child: null,
+               // summary:
+               //              A _Container with keyboard navigation of its children.
+               // description:
+               //              To use this mixin, call connectKeyNavHandlers() in
+               //              postCreate().
+               //              It provides normalized keyboard and focusing code for Container
+               //              widgets.
 
-       // region: String
-       //              Region of pane associated with this splitter.
-       //              "top", "bottom", "left", "right".
-       region: null,
+/*=====
+               // focusedChild: [protected] Widget
+               //              The currently focused child widget, or null if there isn't one
+               focusedChild: null,
 =====*/
 
-       // live: [const] Boolean
-       //              If true, the child's size changes and the child widget is redrawn as you drag the splitter;
-       //              otherwise, the size doesn't change until you drop the splitter (by mouse-up)
-       live: true,
+               // tabIndex: Integer
+               //              Tab index of the container; same as HTML tabIndex attribute.
+               //              Note then when user tabs into the container, focus is immediately
+               //              moved to the first item in the container.
+               tabIndex: "0",
 
-       templateString: '<div class="dijitSplitter" dojoAttachEvent="onkeypress:_onKeyPress,onmousedown:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" waiRole="separator"><div class="dijitSplitterThumb"></div></div>',
+               connectKeyNavHandlers: function(/*keys[]*/ prevKeyCodes, /*keys[]*/ nextKeyCodes){
+                       // summary:
+                       //              Call in postCreate() to attach the keyboard handlers
+                       //              to the container.
+                       // preKeyCodes: keys[]
+                       //              Key codes for navigating to the previous child.
+                       // nextKeyCodes: keys[]
+                       //              Key codes for navigating to the next child.
+                       // tags:
+                       //              protected
 
-       postCreate: function(){
-               this.inherited(arguments);
-               this.horizontal = /top|bottom/.test(this.region);
-               dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
-//             dojo.addClass(this.child.domNode, "dijitSplitterPane");
-//             dojo.setSelectable(this.domNode, false); //TODO is this necessary?
+                       // TODO: call this automatically from my own postCreate()
 
-               this._factor = /top|left/.test(this.region) ? 1 : -1;
+                       var keyCodes = (this._keyNavCodes = {});
+                       var prev = lang.hitch(this, "focusPrev");
+                       var next = lang.hitch(this, "focusNext");
+                       array.forEach(prevKeyCodes, function(code){ keyCodes[code] = prev; });
+                       array.forEach(nextKeyCodes, function(code){ keyCodes[code] = next; });
+                       keyCodes[keys.HOME] = lang.hitch(this, "focusFirstChild");
+                       keyCodes[keys.END] = lang.hitch(this, "focusLastChild");
+                       this.connect(this.domNode, "onkeypress", "_onContainerKeypress");
+                       this.connect(this.domNode, "onfocus", "_onContainerFocus");
+               },
 
-               this._cookieName = this.container.id + "_" + this.region;
-               if(this.container.persist){
-                       // restore old size
-                       var persistSize = dojo.cookie(this._cookieName);
-                       if(persistSize){
-                               this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
-                       }
-               }
-       },
+               startupKeyNavChildren: function(){
+                       kernel.deprecated("startupKeyNavChildren() call no longer needed", "", "2.0");
+               },
 
-       _computeMaxSize: function(){
-               // summary:
-               //              Compute the maximum size that my corresponding pane can be set to
+               startup: function(){
+                       this.inherited(arguments);
+                       array.forEach(this.getChildren(), lang.hitch(this, "_startupChild"));
+               },
 
-               var dim = this.horizontal ? 'h' : 'w',
-                       thickness = this.container._splitterThickness[this.region];
-                       
-               // Get DOMNode of opposite pane, if an opposite pane exists.
-               // Ex: if I am the _Splitter for the left pane, then get the right pane.
-               var flip = {left:'right', right:'left', top:'bottom', bottom:'top', leading:'trailing', trailing:'leading'},
-                       oppNode = this.container["_" + flip[this.region]];
-               
-               // I can expand up to the edge of the opposite pane, or if there's no opposite pane, then to
-               // edge of BorderContainer
-               var available = dojo.contentBox(this.container.domNode)[dim] -
-                               (oppNode ? dojo.marginBox(oppNode)[dim] : 0) -
-                               20 - thickness * 2;
+               addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
+                       this.inherited(arguments);
+                       this._startupChild(widget);
+               },
 
-               return Math.min(this.child.maxSize, available);
-       },
+               focus: function(){
+                       // summary:
+                       //              Default focus() implementation: focus the first child.
+                       this.focusFirstChild();
+               },
 
-       _startDrag: function(e){
-               if(!this.cover){
-                       this.cover = dojo.doc.createElement('div');
-                       dojo.addClass(this.cover, "dijitSplitterCover");
-                       dojo.place(this.cover, this.child.domNode, "after");
-               }
-               dojo.addClass(this.cover, "dijitSplitterCoverActive");
+               focusFirstChild: function(){
+                       // summary:
+                       //              Focus the first focusable child in the container.
+                       // tags:
+                       //              protected
+                       this.focusChild(this._getFirstFocusableChild());
+               },
 
-               // Safeguard in case the stop event was missed.  Shouldn't be necessary if we always get the mouse up.
-               if(this.fake){ dojo.destroy(this.fake); }
-               if(!(this._resize = this.live)){ //TODO: disable live for IE6?
-                       // create fake splitter to display at old position while we drag
-                       (this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
-                       dojo.addClass(this.domNode, "dijitSplitterShadow");
-                       dojo.place(this.fake, this.domNode, "after");
-               }
-               dojo.addClass(this.domNode, "dijitSplitterActive");
-               dojo.addClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
-               if(this.fake){
-                       dojo.removeClass(this.fake, "dijitSplitterHover");
-                       dojo.removeClass(this.fake, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
-               }
+               focusLastChild: function(){
+                       // summary:
+                       //              Focus the last focusable child in the container.
+                       // tags:
+                       //              protected
+                       this.focusChild(this._getLastFocusableChild());
+               },
 
-               //Performance: load data info local vars for onmousevent function closure
-               var factor = this._factor,
-                       max = this._computeMaxSize(),
-                       min = this.child.minSize || 20,
-                       isHorizontal = this.horizontal,
-                       axis = isHorizontal ? "pageY" : "pageX",
-                       pageStart = e[axis],
-                       splitterStyle = this.domNode.style,
-                       dim = isHorizontal ? 'h' : 'w',
-                       childStart = dojo.marginBox(this.child.domNode)[dim],
-                       region = this.region,
-                       splitterStart = parseInt(this.domNode.style[region], 10),
-                       resize = this._resize,
-                       childNode = this.child.domNode,
-                       layoutFunc = dojo.hitch(this.container, this.container._layoutChildren),
-                       de = dojo.doc;
+               focusNext: function(){
+                       // summary:
+                       //              Focus the next widget
+                       // tags:
+                       //              protected
+                       this.focusChild(this._getNextFocusableChild(this.focusedChild, 1));
+               },
 
-               this._handlers = (this._handlers || []).concat([
-                       dojo.connect(de, "onmousemove", this._drag = function(e, forceResize){
-                               var delta = e[axis] - pageStart,
-                                       childSize = factor * delta + childStart,
-                                       boundChildSize = Math.max(Math.min(childSize, max), min);
+               focusPrev: function(){
+                       // summary:
+                       //              Focus the last focusable node in the previous widget
+                       //              (ex: go to the ComboButton icon section rather than button section)
+                       // tags:
+                       //              protected
+                       this.focusChild(this._getNextFocusableChild(this.focusedChild, -1), true);
+               },
 
-                               if(resize || forceResize){
-                                       layoutFunc(region, boundChildSize);
-                               }
-                               splitterStyle[region] = factor * delta + splitterStart + (boundChildSize - childSize) + "px";
-                       }),
-                       dojo.connect(de, "ondragstart", dojo.stopEvent),
-                       dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent),
-                       dojo.connect(de, "onmouseup", this, "_stopDrag")
-               ]);
-               dojo.stopEvent(e);
-       },
+               focusChild: function(/*dijit._Widget*/ widget, /*Boolean*/ last){
+                       // summary:
+                       //              Focus specified child widget.
+                       // widget:
+                       //              Reference to container's child widget
+                       // last:
+                       //              If true and if widget has multiple focusable nodes, focus the
+                       //              last one instead of the first one
+                       // tags:
+                       //              protected
 
-       _onMouse: function(e){
-               var o = (e.type == "mouseover" || e.type == "mouseenter");
-               dojo.toggleClass(this.domNode, "dijitSplitterHover", o);
-               dojo.toggleClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
-       },
+                       if(!widget){ return; }
 
-       _stopDrag: function(e){
-               try{
-                       if(this.cover){
-                               dojo.removeClass(this.cover, "dijitSplitterCoverActive");
+                       if(this.focusedChild && widget !== this.focusedChild){
+                               this._onChildBlur(this.focusedChild);   // used by _MenuBase
                        }
-                       if(this.fake){ dojo.destroy(this.fake); }
-                       dojo.removeClass(this.domNode, "dijitSplitterActive");
-                       dojo.removeClass(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
-                       dojo.removeClass(this.domNode, "dijitSplitterShadow");
-                       this._drag(e); //TODO: redundant with onmousemove?
-                       this._drag(e, true);
-               }finally{
-                       this._cleanupHandlers();
-                       delete this._drag;
-               }
-
-               if(this.container.persist){
-                       dojo.cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
-               }
-       },
+                       widget.set("tabIndex", this.tabIndex);  // for IE focus outline to appear, must set tabIndex before focs
+                       widget.focus(last ? "end" : "start");
+                       this._set("focusedChild", widget);
+               },
 
-       _cleanupHandlers: function(){
-               dojo.forEach(this._handlers, dojo.disconnect);
-               delete this._handlers;
-       },
+               _startupChild: function(/*dijit._Widget*/ widget){
+                       // summary:
+                       //              Setup for each child widget
+                       // description:
+                       //              Sets tabIndex=-1 on each child, so that the tab key will
+                       //              leave the container rather than visiting each child.
+                       // tags:
+                       //              private
 
-       _onKeyPress: function(/*Event*/ e){
-               // should we apply typematic to this?
-               this._resize = true;
-               var horizontal = this.horizontal;
-               var tick = 1;
-               var dk = dojo.keys;
-               switch(e.charOrCode){
-                       case horizontal ? dk.UP_ARROW : dk.LEFT_ARROW:
-                               tick *= -1;
-//                             break;
-                       case horizontal ? dk.DOWN_ARROW : dk.RIGHT_ARROW:
-                               break;
-                       default:
-//                             this.inherited(arguments);
-                               return;
-               }
-               var childSize = dojo.marginBox(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
-               this.container._layoutChildren(this.region, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize));
-               dojo.stopEvent(e);
-       },
+                       widget.set("tabIndex", "-1");
 
-       destroy: function(){
-               this._cleanupHandlers();
-               delete this.child;
-               delete this.container;
-               delete this.cover;
-               delete this.fake;
-               this.inherited(arguments);
-       }
-});
+                       this.connect(widget, "_onFocus", function(){
+                               // Set valid tabIndex so tabbing away from widget goes to right place, see #10272
+                               widget.set("tabIndex", this.tabIndex);
+                       });
+                       this.connect(widget, "_onBlur", function(){
+                               widget.set("tabIndex", "-1");
+                       });
+               },
 
-dojo.declare("dijit.layout._Gutter", [dijit._Widget, dijit._Templated ],
-{
-       // summary:
-       //              Just a spacer div to separate side pane from center pane.
-       //              Basically a trick to lookup the gutter/splitter width from the theme.
-       // description:
-       //              Instantiated by `dijit.layout.BorderContainer`.  Users should not
-       //              create directly.
-       // tags:
-       //              private
+               _onContainerFocus: function(evt){
+                       // summary:
+                       //              Handler for when the container gets focus
+                       // description:
+                       //              Initially the container itself has a tabIndex, but when it gets
+                       //              focus, switch focus to first child...
+                       // tags:
+                       //              private
 
-       templateString: '<div class="dijitGutter" waiRole="presentation"></div>',
+                       // Note that we can't use _onFocus() because switching focus from the
+                       // _onFocus() handler confuses the focus.js code
+                       // (because it causes _onFocusNode() to be called recursively)
+                       // Also, _onFocus() would fire when focus went directly to a child widget due to mouse click.
 
-       postCreate: function(){
-               this.horizontal = /top|bottom/.test(this.region);
-               dojo.addClass(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
-       }
-});
+                       // Ignore spurious focus events:
+                       //      1. focus on a child widget bubbles on FF
+                       //      2. on IE, clicking the scrollbar of a select dropdown moves focus from the focused child item to me
+                       if(evt.target !== this.domNode || this.focusedChild){ return; }
 
-}
+                       this.focusFirstChild();
 
-if(!dojo._hasResource["dijit.layout._TabContainerBase"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout._TabContainerBase"] = true;
-dojo.provide("dijit.layout._TabContainerBase");
+                       // and then set the container's tabIndex to -1,
+                       // (don't remove as that breaks Safari 4)
+                       // so that tab or shift-tab will go to the fields after/before
+                       // the container, rather than the container itself
+                       domAttr.set(this.domNode, "tabIndex", "-1");
+               },
 
+               _onBlur: function(evt){
+                       // When focus is moved away the container, and its descendant (popup) widgets,
+                       // then restore the container's tabIndex so that user can tab to it again.
+                       // Note that using _onBlur() so that this doesn't happen when focus is shifted
+                       // to one of my child widgets (typically a popup)
+                       if(this.tabIndex){
+                               domAttr.set(this.domNode, "tabIndex", this.tabIndex);
+                       }
+                       this.focusedChild = null;
+                       this.inherited(arguments);
+               },
 
+               _onContainerKeypress: function(evt){
+                       // summary:
+                       //              When a key is pressed, if it's an arrow key etc. then
+                       //              it's handled here.
+                       // tags:
+                       //              private
+                       if(evt.ctrlKey || evt.altKey){ return; }
+                       var func = this._keyNavCodes[evt.charOrCode];
+                       if(func){
+                               func();
+                               event.stop(evt);
+                       }
+               },
 
+               _onChildBlur: function(/*dijit._Widget*/ /*===== widget =====*/){
+                       // summary:
+                       //              Called when focus leaves a child widget to go
+                       //              to a sibling widget.
+                       //              Used by MenuBase.js (TODO: move code there)
+                       // tags:
+                       //              protected
+               },
 
-dojo.declare("dijit.layout._TabContainerBase",
-       [dijit.layout.StackContainer, dijit._Templated],
-       {
-       // summary:
-       //              Abstract base class for TabContainer.   Must define _makeController() to instantiate
-       //              and return the widget that displays the tab labels
-       // description:
-       //              A TabContainer is a container that has multiple panes, but shows only
-       //              one pane at a time.  There are a set of tabs corresponding to each pane,
-       //              where each tab has the name (aka title) of the pane, and optionally a close button.
+               _getFirstFocusableChild: function(){
+                       // summary:
+                       //              Returns first child that can be focused
+                       return this._getNextFocusableChild(null, 1);    // dijit._Widget
+               },
 
-       // tabPosition: String
-       //              Defines where tabs go relative to tab content.
-       //              "top", "bottom", "left-h", "right-h"
-       tabPosition: "top",
+               _getLastFocusableChild: function(){
+                       // summary:
+                       //              Returns last child that can be focused
+                       return this._getNextFocusableChild(null, -1);   // dijit._Widget
+               },
 
-       baseClass: "dijitTabContainer",
+               _getNextFocusableChild: function(child, dir){
+                       // summary:
+                       //              Returns the next or previous focusable child, compared
+                       //              to "child"
+                       // child: Widget
+                       //              The current widget
+                       // dir: Integer
+                       //              * 1 = after
+                       //              * -1 = before
+                       if(child){
+                               child = this._getSiblingOfChild(child, dir);
+                       }
+                       var children = this.getChildren();
+                       for(var i=0; i < children.length; i++){
+                               if(!child){
+                                       child = children[(dir>0) ? 0 : (children.length-1)];
+                               }
+                               if(child.isFocusable()){
+                                       return child;   // dijit._Widget
+                               }
+                               child = this._getSiblingOfChild(child, dir);
+                       }
+                       // no focusable child found
+                       return null;    // dijit._Widget
+               }
+       });
+});
 
-       // tabStrip: Boolean
-       //              Defines whether the tablist gets an extra class for layouting, putting a border/shading
-       //              around the set of tabs.
-       tabStrip: false,
+},
+'dijit/form/DataList':function(){
+define("dijit/form/DataList", [
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.byId
+       "dojo/_base/lang", // lang.trim
+       "dojo/query", // query
+       "dojo/store/Memory", // dojo.store.Memory
+       "../registry"   // registry.add registry.remove
+], function(declare, dom, lang, query, MemoryStore, registry){
+
+       // module:
+       //              dijit/form/DataList
+       // summary:
+       //              Inefficient but small data store specialized for inlined data via OPTION tags
 
-       // nested: Boolean
-       //              If true, use styling for a TabContainer nested inside another TabContainer.
-       //              For tundra etc., makes tabs look like links, and hides the outer
-       //              border since the outer TabContainer already has a border.
-       nested: false,
+       function toItem(/*DOMNode*/ option){
+               // summary:
+               //              Convert <option> node to hash
+               return {
+                       id: option.value,
+                       value: option.value,
+                       name: lang.trim(option.innerText || option.textContent || '')
+               };
+       }
 
-       templateString: dojo.cache("dijit.layout", "templates/TabContainer.html", "<div class=\"dijitTabContainer\">\n\t<div class=\"dijitTabListWrapper\" dojoAttachPoint=\"tablistNode\"></div>\n\t<div dojoAttachPoint=\"tablistSpacer\" class=\"dijitTabSpacer ${baseClass}-spacer\"></div>\n\t<div class=\"dijitTabPaneWrapper ${baseClass}-container\" dojoAttachPoint=\"containerNode\"></div>\n</div>\n"),
+       return declare("dijit.form.DataList", MemoryStore, {
+               // summary:
+               //              Inefficient but small data store specialized for inlined data via OPTION tags
+               //
+               // description:
+               //              Provides a store for inlined data like:
+               //
+               //      |       <datalist>
+               //      |               <option value="AL">Alabama</option>
+               //      |               ...
 
-       postMixInProperties: function(){
-               // set class name according to tab position, ex: dijitTabContainerTop
-               this.baseClass += this.tabPosition.charAt(0).toUpperCase() + this.tabPosition.substr(1).replace(/-.*/, "");
+               constructor: function(/*Object?*/ params, /*DomNode|String*/ srcNodeRef){
+                       // store pointer to original DOM tree
+                       this.domNode = dom.byId(srcNodeRef);
 
-               this.srcNodeRef && dojo.style(this.srcNodeRef, "visibility", "hidden");
+                       lang.mixin(this, params);
+                       if(this.id){
+                               registry.add(this); // add to registry so it can be easily found by id
+                       }
+                       this.domNode.style.display = "none";
 
-               this.inherited(arguments);
-       },
+                       this.inherited(arguments, [{
+                               data: query("option", this.domNode).map(toItem)
+                       }]);
+               },
 
-       postCreate: function(){
-               this.inherited(arguments);
+               destroy: function(){
+                       registry.remove(this.id);
+               },
 
-               // Create the tab list that will have a tab (a.k.a. tab button) for each tab panel
-               this.tablist = this._makeController(this.tablistNode);
+               fetchSelectedItem: function(){
+                       // summary:
+                       //              Get the option marked as selected, like `<option selected>`.
+                       //              Not part of dojo.data API.
+                       var option = query("> option[selected]", this.domNode)[0] || query("> option", this.domNode)[0];
+                       return option && toItem(option);
+               }
+       });
+});
 
-               if(!this.doLayout){ dojo.addClass(this.domNode, "dijitTabContainerNoLayout"); }
+},
+'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"-1\">\n\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n",
+'dijit/form/CheckBox':function(){
+require({cache:{
+'url:dijit/form/templates/CheckBox.html':"<div class=\"dijit dijitReset dijitInline\" role=\"presentation\"\n\t><input\n\t \t${!nameAttrSetting} type=\"${type}\" ${checkedAttrSetting}\n\t\tclass=\"dijitReset dijitCheckBoxInput\"\n\t\tdata-dojo-attach-point=\"focusNode\"\n\t \tdata-dojo-attach-event=\"onclick:_onClick\"\n/></div>\n"}});
+define("dijit/form/CheckBox", [
+       "require",
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/_base/kernel",
+       "dojo/query", // query
+       "dojo/ready",
+       "./ToggleButton",
+       "./_CheckBoxMixin",
+       "dojo/text!./templates/CheckBox.html",
+       "dojo/NodeList-dom" // NodeList.addClass/removeClass
+], function(require, declare, domAttr, kernel, query, ready, ToggleButton, _CheckBoxMixin, template){
 
-               if(this.nested){
-                       /* workaround IE's lack of support for "a > b" selectors by
-                        * tagging each node in the template.
-                        */
-                       dojo.addClass(this.domNode, "dijitTabContainerNested");
-                       dojo.addClass(this.tablist.containerNode, "dijitTabContainerTabListNested");
-                       dojo.addClass(this.tablistSpacer, "dijitTabContainerSpacerNested");
-                       dojo.addClass(this.containerNode, "dijitTabPaneWrapperNested");
-               }else{
-                       dojo.addClass(this.domNode, "tabStrip-" + (this.tabStrip ? "enabled" : "disabled"));
-               }
-       },
+/*=====
+       var ToggleButton = dijit.form.ToggleButton;
+       var _CheckBoxMixin = dijit.form._CheckBoxMixin;
+=====*/
 
-       _setupChild: function(/*dijit._Widget*/ tab){
-               // Overrides StackContainer._setupChild().
-               dojo.addClass(tab.domNode, "dijitTabPane");
-               this.inherited(arguments);
-       },
+       // module:
+       //              dijit/form/CheckBox
+       // summary:
+       //              Checkbox widget
 
-       startup: function(){
-               if(this._started){ return; }
+       // Back compat w/1.6, remove for 2.0
+       if(!kernel.isAsync){
+               ready(0, function(){
+                       var requires = ["dijit/form/RadioButton"];
+                       require(requires);      // use indirection so modules not rolled into a build
+               });
+       }
 
-               // wire up the tablist and its tabs
-               this.tablist.startup();
+       return declare("dijit.form.CheckBox", [ToggleButton, _CheckBoxMixin], {
+               // summary:
+               //              Same as an HTML checkbox, but with fancy styling.
+               //
+               // description:
+               //              User interacts with real html inputs.
+               //              On onclick (which occurs by mouse click, space-bar, or
+               //              using the arrow keys to switch the selected radio button),
+               //              we update the state of the checkbox/radio.
+               //
+               //              There are two modes:
+               //                      1. High contrast mode
+               //                      2. Normal mode
+               //
+               //              In case 1, the regular html inputs are shown and used by the user.
+               //              In case 2, the regular html inputs are invisible but still used by
+               //              the user. They are turned quasi-invisible and overlay the background-image.
 
-               this.inherited(arguments);
-       },
+               templateString: template,
 
-       layout: function(){
-               // Overrides StackContainer.layout().
-               // Configure the content pane to take up all the space except for where the tabs are
+               baseClass: "dijitCheckBox",
 
-               if(!this._contentBox || typeof(this._contentBox.l) == "undefined"){return;}
+               _setValueAttr: function(/*String|Boolean*/ newValue, /*Boolean*/ priorityChange){
+                       // summary:
+                       //              Handler for value= attribute to constructor, and also calls to
+                       //              set('value', val).
+                       // description:
+                       //              During initialization, just saves as attribute to the <input type=checkbox>.
+                       //
+                       //              After initialization,
+                       //              when passed a boolean, controls whether or not the CheckBox is checked.
+                       //              If passed a string, changes the value attribute of the CheckBox (the one
+                       //              specified as "value" when the CheckBox was constructed (ex: <input
+                       //              data-dojo-type="dijit.CheckBox" value="chicken">)
+                       //              widget.set('value', string) will check the checkbox and change the value to the
+                       //              specified string
+                       //              widget.set('value', boolean) will change the checked state.
+                       if(typeof newValue == "string"){
+                               this._set("value", newValue);
+                               domAttr.set(this.focusNode, 'value', newValue);
+                               newValue = true;
+                       }
+                       if(this._created){
+                               this.set('checked', newValue, priorityChange);
+                       }
+               },
+               _getValueAttr: function(){
+                       // summary:
+                       //              Hook so get('value') works.
+                       // description:
+                       //              If the CheckBox is checked, returns the value attribute.
+                       //              Otherwise returns false.
+                       return (this.checked ? this.value : false);
+               },
 
-               var sc = this.selectedChildWidget;
+               // Override behavior from Button, since we don't have an iconNode
+               _setIconClassAttr: null,
 
-               if(this.doLayout){
-                       // position and size the titles and the container node
-                       var titleAlign = this.tabPosition.replace(/-h/, "");
-                       this.tablist.layoutAlign = titleAlign;
-                       var children = [this.tablist, {
-                               domNode: this.tablistSpacer,
-                               layoutAlign: titleAlign
-                       }, {
-                               domNode: this.containerNode,
-                               layoutAlign: "client"
-                       }];
-                       dijit.layout.layoutChildren(this.domNode, this._contentBox, children);
+               postMixInProperties: function(){
+                       this.inherited(arguments);
 
-                       // Compute size to make each of my children.
-                       // children[2] is the margin-box size of this.containerNode, set by layoutChildren() call above
-                       this._containerContentBox = dijit.layout.marginBox2contentBox(this.containerNode, children[2]);
+                       // Need to set initial checked state as part of template, so that form submit works.
+                       // domAttr.set(node, "checked", bool) doesn't work on IE until node has been attached
+                       // to <body>, see #8666
+                       this.checkedAttrSetting = this.checked ? "checked" : "";
+               },
 
-                       if(sc && sc.resize){
-                               sc.resize(this._containerContentBox);
-                       }
-               }else{
-                       // just layout the tab controller, so it can position left/right buttons etc.
-                       if(this.tablist.resize){
-                               this.tablist.resize({w: dojo.contentBox(this.domNode).w});
-                       }
+                _fillContent: function(){
+                       // Override Button::_fillContent() since it doesn't make sense for CheckBox,
+                       // since CheckBox doesn't even have a container
+               },
 
-                       // and call resize() on the selected pane just to tell it that it's been made visible
-                       if(sc && sc.resize){
-                               sc.resize();
+               _onFocus: function(){
+                       if(this.id){
+                               query("label[for='"+this.id+"']").addClass("dijitFocusedLabel");
                        }
-               }
-       },
+                       this.inherited(arguments);
+               },
 
-       destroy: function(){
-               if(this.tablist){
-                       this.tablist.destroy();
+               _onBlur: function(){
+                       if(this.id){
+                               query("label[for='"+this.id+"']").removeClass("dijitFocusedLabel");
+                       }
+                       this.inherited(arguments);
                }
-               this.inherited(arguments);
-       }
+       });
 });
 
+},
+'dijit/tree/_dndSelector':function(){
+define("dijit/tree/_dndSelector", [
+       "dojo/_base/array", // array.filter array.forEach array.map
+       "dojo/_base/connect", // connect.isCopyKey
+       "dojo/_base/declare", // declare
+       "dojo/_base/lang", // lang.hitch
+       "dojo/mouse", // mouse.isLeft
+       "dojo/on",
+       "dojo/touch",
+       "dojo/_base/window", // win.global
+       "./_dndContainer"
+], function(array, connect, declare, lang, mouse, on, touch, win, _dndContainer){
+
+       // module:
+       //              dijit/tree/_dndSelector
+       // summary:
+       //              This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
+       //              It's based on `dojo.dnd.Selector`.
 
-}
 
-if(!dojo._hasResource["dijit.layout.TabController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.TabController"] = true;
-dojo.provide("dijit.layout.TabController");
+       return declare("dijit.tree._dndSelector", _dndContainer, {
+               // summary:
+               //              This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
+               //              It's based on `dojo.dnd.Selector`.
+               // tags:
+               //              protected
 
+               /*=====
+               // selection: Hash<String, DomNode>
+               //              (id, DomNode) map for every TreeNode that's currently selected.
+               //              The DOMNode is the TreeNode.rowNode.
+               selection: {},
+               =====*/
 
+               constructor: function(){
+                       // summary:
+                       //              Initialization
+                       // tags:
+                       //              private
 
-// Menu is used for an accessible close button, would be nice to have a lighter-weight solution
+                       this.selection={};
+                       this.anchor = null;
 
+                       this.tree.domNode.setAttribute("aria-multiselect", !this.singular);
 
+                       this.events.push(
+                               on(this.tree.domNode, touch.press, lang.hitch(this,"onMouseDown")),
+                               on(this.tree.domNode, touch.release, lang.hitch(this,"onMouseUp")),
+                               on(this.tree.domNode, touch.move, lang.hitch(this,"onMouseMove"))
+                       );
+               },
 
+               //      singular: Boolean
+               //              Allows selection of only one element, if true.
+               //              Tree hasn't been tested in singular=true mode, unclear if it works.
+               singular: false,
 
+               // methods
+               getSelectedTreeNodes: function(){
+                       // summary:
+                       //              Returns a list of selected node(s).
+                       //              Used by dndSource on the start of a drag.
+                       // tags:
+                       //              protected
+                       var nodes=[], sel = this.selection;
+                       for(var i in sel){
+                               nodes.push(sel[i]);
+                       }
+                       return nodes;
+               },
 
-dojo.declare("dijit.layout.TabController",
-       dijit.layout.StackController,
-{
-       // summary:
-       //              Set of tabs (the things with titles and a close button, that you click to show a tab panel).
-       //              Used internally by `dijit.layout.TabContainer`.
-       // description:
-       //              Lets the user select the currently shown pane in a TabContainer or StackContainer.
-       //              TabController also monitors the TabContainer, and whenever a pane is
-       //              added or deleted updates itself accordingly.
-       // tags:
-       //              private
+               selectNone: function(){
+                       // summary:
+                       //              Unselects all items
+                       // tags:
+                       //              private
 
-       templateString: "<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'></div>",
+                       this.setSelection([]);
+                       return this;    // self
+               },
 
-       // tabPosition: String
-       //              Defines where tabs go relative to the content.
-       //              "top", "bottom", "left-h", "right-h"
-       tabPosition: "top",
+               destroy: function(){
+                       // summary:
+                       //              Prepares the object to be garbage-collected
+                       this.inherited(arguments);
+                       this.selection = this.anchor = null;
+               },
+               addTreeNode: function(/*dijit._TreeNode*/node, /*Boolean?*/isAnchor){
+                       // summary:
+                       //              add node to current selection
+                       // node: Node
+                       //              node to add
+                       // isAnchor: Boolean
+                       //              Whether the node should become anchor.
 
-       // buttonWidget: String
-       //              The name of the tab widget to create to correspond to each page
-       buttonWidget: "dijit.layout._TabButton",
+                       this.setSelection(this.getSelectedTreeNodes().concat( [node] ));
+                       if(isAnchor){ this.anchor = node; }
+                       return node;
+               },
+               removeTreeNode: function(/*dijit._TreeNode*/node){
+                       // summary:
+                       //              remove node from current selection
+                       // node: Node
+                       //              node to remove
+                       this.setSelection(this._setDifference(this.getSelectedTreeNodes(), [node]));
+                       return node;
+               },
+               isTreeNodeSelected: function(/*dijit._TreeNode*/node){
+                       // summary:
+                       //              return true if node is currently selected
+                       // node: Node
+                       //              the node to check whether it's in the current selection
 
-       _rectifyRtlTabList: function(){
-               // summary:
-               //              For left/right TabContainer when page is RTL mode, rectify the width of all tabs to be equal, otherwise the tab widths are different in IE
+                       return node.id && !!this.selection[node.id];
+               },
+               setSelection: function(/*dijit._treeNode[]*/ newSelection){
+                       // summary:
+                       //              set the list of selected nodes to be exactly newSelection. All changes to the
+                       //              selection should be passed through this function, which ensures that derived
+                       //              attributes are kept up to date. Anchor will be deleted if it has been removed
+                       //              from the selection, but no new anchor will be added by this function.
+                       // newSelection: Node[]
+                       //              list of tree nodes to make selected
+                       var oldSelection = this.getSelectedTreeNodes();
+                       array.forEach(this._setDifference(oldSelection, newSelection), lang.hitch(this, function(node){
+                               node.setSelected(false);
+                               if(this.anchor == node){
+                                       delete this.anchor;
+                               }
+                               delete this.selection[node.id];
+                       }));
+                       array.forEach(this._setDifference(newSelection, oldSelection), lang.hitch(this, function(node){
+                               node.setSelected(true);
+                               this.selection[node.id] = node;
+                       }));
+                       this._updateSelectionProperties();
+               },
+               _setDifference: function(xs,ys){
+                       // summary:
+                       //              Returns a copy of xs which lacks any objects
+                       //              occurring in ys. Checks for membership by
+                       //              modifying and then reading the object, so it will
+                       //              not properly handle sets of numbers or strings.
 
-               if(0 >= this.tabPosition.indexOf('-h')){ return; }
-               if(!this.pane2button){ return; }
+                       array.forEach(ys, function(y){ y.__exclude__ = true; });
+                       var ret = array.filter(xs, function(x){ return !x.__exclude__; });
 
-               var maxWidth = 0;
-               for(var pane in this.pane2button){
-                       var ow = this.pane2button[pane].innerDiv.scrollWidth;
-                       maxWidth = Math.max(maxWidth, ow);
-               }
-               //unify the length of all the tabs
-               for(pane in this.pane2button){
-                       this.pane2button[pane].innerDiv.style.width = maxWidth + 'px';
-               }
-       }
-});
+                       // clean up after ourselves.
+                       array.forEach(ys, function(y){ delete y['__exclude__'] });
+                       return ret;
+               },
+               _updateSelectionProperties: function(){
+                       // summary:
+                       //              Update the following tree properties from the current selection:
+                       //              path[s], selectedItem[s], selectedNode[s]
+
+                       var selected = this.getSelectedTreeNodes();
+                       var paths = [], nodes = [];
+                       array.forEach(selected, function(node){
+                               nodes.push(node);
+                               paths.push(node.getTreePath());
+                       });
+                       var items = array.map(nodes,function(node){ return node.item; });
+                       this.tree._set("paths", paths);
+                       this.tree._set("path", paths[0] || []);
+                       this.tree._set("selectedNodes", nodes);
+                       this.tree._set("selectedNode", nodes[0] || null);
+                       this.tree._set("selectedItems", items);
+                       this.tree._set("selectedItem", items[0] || null);
+               },
+               // mouse events
+               onMouseDown: function(e){
+                       // summary:
+                       //              Event processor for onmousedown/ontouchstart
+                       // e: Event
+                       //              onmousedown/ontouchstart event
+                       // tags:
+                       //              protected
 
-dojo.declare("dijit.layout._TabButton",
-       dijit.layout._StackButton,
-       {
-       // summary:
-       //              A tab (the thing you click to select a pane).
-       // description:
-       //              Contains the title of the pane, and optionally a close-button to destroy the pane.
-       //              This is an internal widget and should not be instantiated directly.
-       // tags:
-       //              private
+                       // ignore click on expando node
+                       if(!this.current || this.tree.isExpandoNode(e.target, this.current)){ return; }
 
-       // baseClass: String
-       //              The CSS class applied to the domNode.
-       baseClass: "dijitTab",
+                       if(!mouse.isLeft(e)){ return; } // ignore right-click
 
-       // Apply dijitTabCloseButtonHover when close button is hovered
-       cssStateNodes: {
-               closeNode: "dijitTabCloseButton"
-       },
+                       e.preventDefault();
 
-       templateString: dojo.cache("dijit.layout", "templates/_TabButton.html", "<div waiRole=\"presentation\" dojoAttachPoint=\"titleNode\" dojoAttachEvent='onclick:onClick'>\n    <div waiRole=\"presentation\" class='dijitTabInnerDiv' dojoAttachPoint='innerDiv'>\n        <div waiRole=\"presentation\" class='dijitTabContent' dojoAttachPoint='tabContent'>\n        \t<div waiRole=\"presentation\" dojoAttachPoint='focusNode'>\n\t\t        <img src=\"${_blankGif}\" alt=\"\" class=\"dijitIcon\" dojoAttachPoint='iconNode' />\n\t\t        <span dojoAttachPoint='containerNode' class='tabLabel'></span>\n\t\t        <span class=\"dijitInline dijitTabCloseButton dijitTabCloseIcon\" dojoAttachPoint='closeNode'\n\t\t        \t\tdojoAttachEvent='onclick: onClickCloseButton' waiRole=\"presentation\">\n\t\t            <span dojoAttachPoint='closeText' class='dijitTabCloseText'>x</span\n\t\t        ></span>\n\t\t\t</div>\n        </div>\n    </div>\n</div>\n"),
+                       var treeNode = this.current,
+                         copy = connect.isCopyKey(e), id = treeNode.id;
 
-       // Override _FormWidget.scrollOnFocus.
-       // Don't scroll the whole tab container into view when the button is focused.
-       scrollOnFocus: false,
+                       // if shift key is not pressed, and the node is already in the selection,
+                       // delay deselection until onmouseup so in the case of DND, deselection
+                       // will be canceled by onmousemove.
+                       if(!this.singular && !e.shiftKey && this.selection[id]){
+                               this._doDeselect = true;
+                               return;
+                       }else{
+                               this._doDeselect = false;
+                       }
+                       this.userSelect(treeNode, copy, e.shiftKey);
+               },
 
-       postMixInProperties: function(){
-               // Override blank iconClass from Button to do tab height adjustment on IE6,
-               // to make sure that tabs with and w/out close icons are same height
-               if(!this.iconClass){
-                       this.iconClass = "dijitTabButtonIcon";
-               }
-       },
+               onMouseUp: function(e){
+                       // summary:
+                       //              Event processor for onmouseup/ontouchend
+                       // e: Event
+                       //              onmouseup/ontouchend event
+                       // tags:
+                       //              protected
 
-       postCreate: function(){
-               this.inherited(arguments);
-               dojo.setSelectable(this.containerNode, false);
+                       // _doDeselect is the flag to indicate that the user wants to either ctrl+click on
+                       // a already selected item (to deselect the item), or click on a not-yet selected item
+                       // (which should remove all current selection, and add the clicked item). This can not
+                       // be done in onMouseDown, because the user may start a drag after mousedown. By moving
+                       // the deselection logic here, the user can drags an already selected item.
+                       if(!this._doDeselect){ return; }
+                       this._doDeselect = false;
+                       this.userSelect(this.current, connect.isCopyKey(e), e.shiftKey);
+               },
+               onMouseMove: function(/*===== e =====*/){
+                       // summary:
+                       //              event processor for onmousemove/ontouchmove
+                       // e: Event
+                       //              onmousemove/ontouchmove event
+                       this._doDeselect = false;
+               },
 
-               // If a custom icon class has not been set for the
-               // tab icon, set its width to one pixel. This ensures
-               // that the height styling of the tab is maintained,
-               // as it is based on the height of the icon.
-               // TODO: I still think we can just set dijitTabButtonIcon to 1px in CSS <Bill>
-               if(this.iconNode.className == "dijitTabButtonIcon"){
-                       dojo.style(this.iconNode, "width", "1px");
-               }
-       },
+               _compareNodes: function(n1, n2){
+                       if(n1 === n2){
+                               return 0;
+                       }
 
-       startup: function(){
-               this.inherited(arguments);
-               var n = this.domNode;
+                       if('sourceIndex' in document.documentElement){ //IE
+                               //TODO: does not yet work if n1 and/or n2 is a text node
+                               return n1.sourceIndex - n2.sourceIndex;
+                       }else if('compareDocumentPosition' in document.documentElement){ //FF, Opera
+                               return n1.compareDocumentPosition(n2) & 2 ? 1: -1;
+                       }else if(document.createRange){ //Webkit
+                               var r1 = doc.createRange();
+                               r1.setStartBefore(n1);
 
-               // Required to give IE6 a kick, as it initially hides the
-               // tabs until they are focused on.
-               setTimeout(function(){
-                       n.className = n.className;
-               }, 1);
-       },
-
-       _setCloseButtonAttr: function(disp){
-               this.closeButton = disp;
-               dojo.toggleClass(this.innerDiv, "dijitClosable", disp);
-               this.closeNode.style.display = disp ? "" : "none";
-               if(disp){
-                       var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-                       if(this.closeNode){
-                               dojo.attr(this.closeNode,"title", _nlsResources.itemClose);
-                       }
-                       // add context menu onto title button
-                       var _nlsResources = dojo.i18n.getLocalization("dijit", "common");
-                       this._closeMenu = new dijit.Menu({
-                               id: this.id+"_Menu",
-                               dir: this.dir,
-                               lang: this.lang,
-                               targetNodeIds: [this.domNode]
-                       });
+                               var r2 = doc.createRange();
+                               r2.setStartBefore(n2);
 
-                       this._closeMenu.addChild(new dijit.MenuItem({
-                               label: _nlsResources.itemClose,
-                               dir: this.dir,
-                               lang: this.lang,
-                               onClick: dojo.hitch(this, "onClickCloseButton")
-                       }));
-               }else{
-                       if(this._closeMenu){
-                               this._closeMenu.destroyRecursive();
-                               delete this._closeMenu;
-                       }
-               }
-       },
-       _setLabelAttr: function(/*String*/ content){
-               // summary:
-               //              Hook for attr('label', ...) to work.
-               // description:
-               //              takes an HTML string.
-               //              Inherited ToggleButton implementation will Set the label (text) of the button; 
-               //              Need to set the alt attribute of icon on tab buttons if no label displayed
-                       this.inherited(arguments);
-                       if(this.showLabel == false && !this.params.title){
-                               this.iconNode.alt = dojo.trim(this.containerNode.innerText || this.containerNode.textContent || '');
+                               return r1.compareBoundaryPoints(r1.END_TO_END, r2);
+                       }else{
+                               throw Error("dijit.tree._compareNodes don't know how to compare two different nodes in this browser");
                        }
                },
 
-       destroy: function(){
-               if(this._closeMenu){
-                       this._closeMenu.destroyRecursive();
-                       delete this._closeMenu;
-               }
-               this.inherited(arguments);
-       }
-});
+               userSelect: function(node, multi, range){
+                       // summary:
+                       //              Add or remove the given node from selection, responding
+                       //              to a user action such as a click or keypress.
+                       // multi: Boolean
+                       //              Indicates whether this is meant to be a multi-select action (e.g. ctrl-click)
+                       // range: Boolean
+                       //              Indicates whether this is meant to be a ranged action (e.g. shift-click)
+                       // tags:
+                       //              protected
 
-}
+                       if(this.singular){
+                               if(this.anchor == node && multi){
+                                       this.selectNone();
+                               }else{
+                                       this.setSelection([node]);
+                                       this.anchor = node;
+                               }
+                       }else{
+                               if(range && this.anchor){
+                                       var cr = this._compareNodes(this.anchor.rowNode, node.rowNode),
+                                       begin, end, anchor = this.anchor;
+
+                                       if(cr < 0){ //current is after anchor
+                                               begin = anchor;
+                                               end = node;
+                                       }else{ //current is before anchor
+                                               begin = node;
+                                               end = anchor;
+                                       }
+                                       var nodes = [];
+                                       //add everything betweeen begin and end inclusively
+                                       while(begin != end){
+                                               nodes.push(begin);
+                                               begin = this.tree._getNextNode(begin);
+                                       }
+                                       nodes.push(end);
 
-if(!dojo._hasResource["dijit.layout.ScrollingTabController"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.ScrollingTabController"] = true;
-dojo.provide("dijit.layout.ScrollingTabController");
+                                       this.setSelection(nodes);
+                               }else{
+                                       if( this.selection[ node.id ] && multi ){
+                                               this.removeTreeNode( node );
+                                       }else if(multi){
+                                               this.addTreeNode(node, true);
+                                       }else{
+                                               this.setSelection([node]);
+                                               this.anchor = node;
+                                       }
+                               }
+                       }
+               },
 
+               getItem: function(/*String*/ key){
+                       // summary:
+                       //              Returns the dojo.dnd.Item (representing a dragged node) by it's key (id).
+                       //              Called by dojo.dnd.Source.checkAcceptance().
+                       // tags:
+                       //              protected
 
+                       var widget = this.selection[key];
+                       return {
+                               data: widget,
+                               type: ["treeNode"]
+                       }; // dojo.dnd.Item
+               },
 
+               forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
+                       // summary:
+                       //              Iterates over selected items;
+                       //              see `dojo.dnd.Container.forInItems()` for details
+                       o = o || win.global;
+                       for(var id in this.selection){
+                               // console.log("selected item id: " + id);
+                               f.call(o, this.getItem(id), id, this);
+                       }
+               }
+       });
+});
 
-dojo.declare("dijit.layout.ScrollingTabController",
-       dijit.layout.TabController,
-       {
+},
+'dijit/_Container':function(){
+define("dijit/_Container", [
+       "dojo/_base/array", // array.forEach array.indexOf
+       "dojo/_base/declare", // declare
+       "dojo/dom-construct", // domConstruct.place
+       "./registry"    // registry.byNode()
+], function(array, declare, domConstruct, registry){
+
+       // module:
+       //              dijit/_Container
        // summary:
-       //              Set of tabs with left/right arrow keys and a menu to switch between tabs not
-       //              all fitting on a single row.
-       //              Works only for horizontal tabs (either above or below the content, not to the left
-       //              or right).
-       // tags:
-       //              private
+       //              Mixin for widgets that contain a set of widget children.
 
-       templateString: dojo.cache("dijit.layout", "templates/ScrollingTabController.html", "<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\" iconClass=\"dijitTabStripMenuIcon\"\n\t\t\tdojoAttachPoint=\"_menuBtn\" showLabel=false>&#9660;</div>\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\" iconClass=\"dijitTabStripSlideLeftIcon\"\n\t\t\tdojoAttachPoint=\"_leftBtn\" dojoAttachEvent=\"onClick: doSlideLeft\" showLabel=false>&#9664;</div>\n\t<div dojoType=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\" iconClass=\"dijitTabStripSlideRightIcon\"\n\t\t\tdojoAttachPoint=\"_rightBtn\" dojoAttachEvent=\"onClick: doSlideRight\" showLabel=false>&#9654;</div>\n\t<div class='dijitTabListWrapper' dojoAttachPoint='tablistWrapper'>\n\t\t<div wairole='tablist' dojoAttachEvent='onkeypress:onkeypress'\n\t\t\t\tdojoAttachPoint='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>\n"),
+       return declare("dijit._Container", null, {
+               // summary:
+               //              Mixin for widgets that contain a set of widget children.
+               // description:
+               //              Use this mixin for widgets that needs to know about and
+               //              keep track of their widget children. Suitable for widgets like BorderContainer
+               //              and TabContainer which contain (only) a set of child widgets.
+               //
+               //              It's not suitable for widgets like ContentPane
+               //              which contains mixed HTML (plain DOM nodes in addition to widgets),
+               //              and where contained widgets are not necessarily directly below
+               //              this.containerNode.   In that case calls like addChild(node, position)
+               //              wouldn't make sense.
 
-       // useMenu:[const] Boolean
-       //              True if a menu should be used to select tabs when they are too
-       //              wide to fit the TabContainer, false otherwise.
-       useMenu: true,
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       if(!this.containerNode){
+                               // all widgets with descendants must set containerNode
+                               this.containerNode = this.domNode;
+                       }
+               },
 
-       // useSlider: [const] Boolean
-       //              True if a slider should be used to select tabs when they are too
-       //              wide to fit the TabContainer, false otherwise.
-       useSlider: true,
+               addChild: function(/*dijit._Widget*/ widget, /*int?*/ insertIndex){
+                       // summary:
+                       //              Makes the given widget a child of this widget.
+                       // description:
+                       //              Inserts specified child widget's dom node as a child of this widget's
+                       //              container node, and possibly does other processing (such as layout).
 
-       // tabStripClass: String
-       //              The css class to apply to the tab strip, if it is visible.
-       tabStripClass: "",
+                       var refNode = this.containerNode;
+                       if(insertIndex && typeof insertIndex == "number"){
+                               var children = this.getChildren();
+                               if(children && children.length >= insertIndex){
+                                       refNode = children[insertIndex-1].domNode;
+                                       insertIndex = "after";
+                               }
+                       }
+                       domConstruct.place(widget.domNode, refNode, insertIndex);
 
-       widgetsInTemplate: true,
+                       // If I've been started but the child widget hasn't been started,
+                       // start it now.  Make sure to do this after widget has been
+                       // inserted into the DOM tree, so it can see that it's being controlled by me,
+                       // so it doesn't try to size itself.
+                       if(this._started && !widget._started){
+                               widget.startup();
+                       }
+               },
 
-       // _minScroll: Number
-       //              The distance in pixels from the edge of the tab strip which,
-       //              if a scroll animation is less than, forces the scroll to
-       //              go all the way to the left/right.
-       _minScroll: 5,
+               removeChild: function(/*Widget|int*/ widget){
+                       // summary:
+                       //              Removes the passed widget instance from this widget but does
+                       //              not destroy it.  You can also pass in an integer indicating
+                       //              the index within the container to remove
 
-       attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-               "class": "containerNode"
-       }),
+                       if(typeof widget == "number"){
+                               widget = this.getChildren()[widget];
+                       }
 
-       postCreate: function(){
-               this.inherited(arguments);
-               var n = this.domNode;
+                       if(widget){
+                               var node = widget.domNode;
+                               if(node && node.parentNode){
+                                       node.parentNode.removeChild(node); // detach but don't destroy
+                               }
+                       }
+               },
 
-               this.scrollNode = this.tablistWrapper;
-               this._initButtons();
+               hasChildren: function(){
+                       // summary:
+                       //              Returns true if widget has children, i.e. if this.containerNode contains something.
+                       return this.getChildren().length > 0;   // Boolean
+               },
 
-               if(!this.tabStripClass){
-                       this.tabStripClass = "dijitTabContainer" +
-                               this.tabPosition.charAt(0).toUpperCase() +
-                               this.tabPosition.substr(1).replace(/-.*/, "") +
-                               "None";
-                       dojo.addClass(n, "tabStrip-disabled")
+               _getSiblingOfChild: function(/*dijit._Widget*/ child, /*int*/ dir){
+                       // summary:
+                       //              Get the next or previous widget sibling of child
+                       // dir:
+                       //              if 1, get the next sibling
+                       //              if -1, get the previous sibling
+                       // tags:
+                       //      private
+                       var node = child.domNode,
+                               which = (dir>0 ? "nextSibling" : "previousSibling");
+                       do{
+                               node = node[which];
+                       }while(node && (node.nodeType != 1 || !registry.byNode(node)));
+                       return node && registry.byNode(node);   // dijit._Widget
+               },
+
+               getIndexOfChild: function(/*dijit._Widget*/ child){
+                       // summary:
+                       //              Gets the index of the child in this container or -1 if not found
+                       return array.indexOf(this.getChildren(), child);        // int
                }
+       });
+});
 
-               dojo.addClass(this.tablistWrapper, this.tabStripClass);
-       },
+},
+'dojo/data/ItemFileReadStore':function(){
+define("dojo/data/ItemFileReadStore", ["../_base/kernel", "../_base/lang", "../_base/declare", "../_base/array", "../_base/xhr", 
+       "../Evented", "../_base/window", "./util/filter", "./util/simpleFetch", "../date/stamp"
+], function(kernel, lang, declare, array, xhr, Evented, window, filterUtil, simpleFetch, dateStamp) {
+       // module:
+       //              dojo/data/ItemFileReadStore
+       // summary:
+       //              TODOC
 
-       onStartup: function(){
-               this.inherited(arguments);
 
-               // Do not show the TabController until the related
-               // StackController has added it's children.  This gives
-               // a less visually jumpy instantiation.
-               dojo.style(this.domNode, "visibility", "visible");
-               this._postStartup = true;
-       },
+var ItemFileReadStore = declare("dojo.data.ItemFileReadStore", [Evented],{
+       //      summary:
+       //              The ItemFileReadStore implements the dojo.data.api.Read API and reads
+       //              data from JSON files that have contents in this format --
+       //              { items: [
+       //                      { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]},
+       //                      { name:'Fozzie Bear', wears:['hat', 'tie']},
+       //                      { name:'Miss Piggy', pets:'Foo-Foo'}
+       //              ]}
+       //              Note that it can also contain an 'identifer' property that specified which attribute on the items
+       //              in the array of items that acts as the unique identifier for that item.
+       //
+       constructor: function(/* Object */ keywordParameters){
+               //      summary: constructor
+               //      keywordParameters: {url: String}
+               //      keywordParameters: {data: jsonObject}
+               //      keywordParameters: {typeMap: object)
+               //              The structure of the typeMap object is as follows:
+               //              {
+               //                      type0: function || object,
+               //                      type1: function || object,
+               //                      ...
+               //                      typeN: function || object
+               //              }
+               //              Where if it is a function, it is assumed to be an object constructor that takes the
+               //              value of _value as the initialization parameters.  If it is an object, then it is assumed
+               //              to be an object of general form:
+               //              {
+               //                      type: function, //constructor.
+               //                      deserialize:    function(value) //The function that parses the value and constructs the object defined by type appropriately.
+               //              }
 
-       onAddChild: function(page, insertIndex){
-               this.inherited(arguments);
-               var menuItem;
-               if(this.useMenu){
-                       var containerId = this.containerId;
-                       menuItem = new dijit.MenuItem({
-                               id: page.id + "_stcMi",
-                               label: page.title,
-                               dir: page.dir,
-                               lang: page.lang,
-                               onClick: dojo.hitch(this, function(){
-                                       var container = dijit.byId(containerId);
-                                       container.selectChild(page);
-                               })
-                       });
-                       this._menuChildren[page.id] = menuItem;
-                       this._menu.addChild(menuItem, insertIndex);
+               this._arrayOfAllItems = [];
+               this._arrayOfTopLevelItems = [];
+               this._loadFinished = false;
+               this._jsonFileUrl = keywordParameters.url;
+               this._ccUrl = keywordParameters.url;
+               this.url = keywordParameters.url;
+               this._jsonData = keywordParameters.data;
+               this.data = null;
+               this._datatypeMap = keywordParameters.typeMap || {};
+               if(!this._datatypeMap['Date']){
+                       //If no default mapping for dates, then set this as default.
+                       //We use the dojo.date.stamp here because the ISO format is the 'dojo way'
+                       //of generically representing dates.
+                       this._datatypeMap['Date'] = {
+                                                                                       type: Date,
+                                                                                       deserialize: function(value){
+                                                                                               return dateStamp.fromISOString(value);
+                                                                                       }
+                                                                               };
                }
-
-               // update the menuItem label when the button label is updated
-               this.pane2handles[page.id].push(
-                       this.connect(this.pane2button[page.id], "set", function(name, value){
-                               if(this._postStartup){
-                                       if(name == "label"){
-                                               if(menuItem){
-                                                       menuItem.set(name, value);
-                                               }
-       
-                                               // The changed label will have changed the width of the
-                                               // buttons, so do a resize
-                                               if(this._dim){
-                                                       this.resize(this._dim);
-                                               }
-                                       }
-                               }
-                       })
-               );
-
-               // Increment the width of the wrapper when a tab is added
-               // This makes sure that the buttons never wrap.
-               // The value 200 is chosen as it should be bigger than most
-               // Tab button widths.
-               dojo.style(this.containerNode, "width",
-                       (dojo.style(this.containerNode, "width") + 200) + "px");
-       },
-
-       onRemoveChild: function(page, insertIndex){
-               // null out _selectedTab because we are about to delete that dom node
-               var button = this.pane2button[page.id];
-               if(this._selectedTab === button.domNode){
-                       this._selectedTab = null;
+               this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true};
+               this._itemsByIdentity = null;
+               this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item.
+               this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item.
+               this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item.
+               this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity
+               this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset.
+               this._queuedFetches = [];
+               if(keywordParameters.urlPreventCache !== undefined){
+                       this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
                }
-
-               // delete menu entry corresponding to pane that was removed from TabContainer
-               if(this.useMenu && page && page.id && this._menuChildren[page.id]){
-                       this._menu.removeChild(this._menuChildren[page.id]);
-                       this._menuChildren[page.id].destroy();
-                       delete this._menuChildren[page.id];
+               if(keywordParameters.hierarchical !== undefined){
+                       this.hierarchical = keywordParameters.hierarchical?true:false;
+               }
+               if(keywordParameters.clearOnClose){
+                       this.clearOnClose = true;
+               }
+               if("failOk" in keywordParameters){
+                       this.failOk = keywordParameters.failOk?true:false;
                }
-
-               this.inherited(arguments);
        },
 
-       _initButtons: function(){
-               // summary:
-               //              Creates the buttons used to scroll to view tabs that
-               //              may not be visible if the TabContainer is too narrow.
-               this._menuChildren = {};
+       url: "",        // use "" rather than undefined for the benefit of the parser (#3539)
 
-               // Make a list of the buttons to display when the tab labels become
-               // wider than the TabContainer, and hide the other buttons.
-               // Also gets the total width of the displayed buttons.
-               this._btnWidth = 0;
-               this._buttons = dojo.query("> .tabStripButton", this.domNode).filter(function(btn){
-                       if((this.useMenu && btn == this._menuBtn.domNode) ||
-                               (this.useSlider && (btn == this._rightBtn.domNode || btn == this._leftBtn.domNode))){
-                               this._btnWidth += dojo.marginBox(btn).w;
-                               return true;
-                       }else{
-                               dojo.style(btn, "display", "none");
-                               return false;
-                       }
-               }, this);
+       //Internal var, crossCheckUrl.  Used so that setting either url or _jsonFileUrl, can still trigger a reload
+       //when clearOnClose and close is used.
+       _ccUrl: "",
 
-               if(this.useMenu){
-                       // Create the menu that is used to select tabs.
-                       this._menu = new dijit.Menu({
-                               id: this.id + "_menu",
-                               dir: this.dir,
-                               lang: this.lang,
-                               targetNodeIds: [this._menuBtn.domNode],
-                               leftClickToOpen: true,
-                               refocus: false  // selecting a menu item sets focus to a TabButton
-                       });
-                       this._supportingWidgets.push(this._menu);
-               }
-       },
+       data: null,     // define this so that the parser can populate it
 
-       _getTabsWidth: function(){
-               var children = this.getChildren();
-               if(children.length){
-                       var leftTab = children[this.isLeftToRight() ? 0 : children.length - 1].domNode,
-                               rightTab = children[this.isLeftToRight() ? children.length - 1 : 0].domNode;
-                       return rightTab.offsetLeft + dojo.style(rightTab, "width") - leftTab.offsetLeft;
-               }else{
-                       return 0;
-               }
-       },
+       typeMap: null, //Define so parser can populate.
 
-       _enableBtn: function(width){
-               // summary:
-               //              Determines if the tabs are wider than the width of the TabContainer, and
-               //              thus that we need to display left/right/menu navigation buttons.
-               var tabsWidth = this._getTabsWidth();
-               width = width || dojo.style(this.scrollNode, "width");
-               return tabsWidth > 0 && width < tabsWidth;
-       },
+       //Parameter to allow users to specify if a close call should force a reload or not.
+       //By default, it retains the old behavior of not clearing if close is called.  But
+       //if set true, the store will be reset to default state.  Note that by doing this,
+       //all item handles will become invalid and a new fetch must be issued.
+       clearOnClose: false,
 
-       resize: function(dim){
-               // summary:
-               //              Hides or displays the buttons used to scroll the tab list and launch the menu
-               //              that selects tabs.
+       //Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url.
+       //Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option.
+       //Added for tracker: #6072
+       urlPreventCache: false,
 
-               if(this.domNode.offsetWidth == 0){
-                       return;
+       //Parameter for specifying that it is OK for the xhrGet call to fail silently.
+       failOk: false,
+
+       //Parameter to indicate to process data from the url as hierarchical
+       //(data items can contain other data items in js form).  Default is true
+       //for backwards compatibility.  False means only root items are processed
+       //as items, all child objects outside of type-mapped objects and those in
+       //specific reference format, are left straight JS data objects.
+       hierarchical: true,
+
+       _assertIsItem: function(/* item */ item){
+               //      summary:
+               //              This function tests whether the item passed in is indeed an item in the store.
+               //      item:
+               //              The item to test for being contained by the store.
+               if(!this.isItem(item)){
+                       throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");
                }
+       },
 
-               // Save the dimensions to be used when a child is renamed.
-               this._dim = dim;
+       _assertIsAttribute: function(/* attribute-name-string */ attribute){
+               //      summary:
+               //              This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
+               //      attribute:
+               //              The attribute to test for being contained by the store.
+               if(typeof attribute !== "string"){
+                       throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");
+               }
+       },
 
-               // Set my height to be my natural height (tall enough for one row of tab labels),
-               // and my content-box width based on margin-box width specified in dim parameter.
-               // But first reset scrollNode.height in case it was set by layoutChildren() call
-               // in a previous run of this method.
-               this.scrollNode.style.height = "auto";
-               this._contentBox = dijit.layout.marginBox2contentBox(this.domNode, {h: 0, w: dim.w});
-               this._contentBox.h = this.scrollNode.offsetHeight;
-               dojo.contentBox(this.domNode, this._contentBox);
+       getValue: function(     /* item */ item,
+                                               /* attribute-name-string */ attribute,
+                                               /* value? */ defaultValue){
+               //      summary:
+               //              See dojo.data.api.Read.getValue()
+               var values = this.getValues(item, attribute);
+               return (values.length > 0)?values[0]:defaultValue; // mixed
+       },
 
-               // Show/hide the left/right/menu navigation buttons depending on whether or not they
-               // are needed.
-               var enable = this._enableBtn(this._contentBox.w);
-               this._buttons.style("display", enable ? "" : "none");
+       getValues: function(/* item */ item,
+                                               /* attribute-name-string */ attribute){
+               //      summary:
+               //              See dojo.data.api.Read.getValues()
 
-               // Position and size the navigation buttons and the tablist
-               this._leftBtn.layoutAlign = "left";
-               this._rightBtn.layoutAlign = "right";
-               this._menuBtn.layoutAlign = this.isLeftToRight() ? "right" : "left";
-               dijit.layout.layoutChildren(this.domNode, this._contentBox,
-                       [this._menuBtn, this._leftBtn, this._rightBtn, {domNode: this.scrollNode, layoutAlign: "client"}]);
+               this._assertIsItem(item);
+               this._assertIsAttribute(attribute);
+               // Clone it before returning.  refs: #10474
+               return (item[attribute] || []).slice(0); // Array
+       },
 
-               // set proper scroll so that selected tab is visible
-               if(this._selectedTab){
-                       if(this._anim && this._anim.status() == "playing"){
-                               this._anim.stop();
+       getAttributes: function(/* item */ item){
+               //      summary:
+               //              See dojo.data.api.Read.getAttributes()
+               this._assertIsItem(item);
+               var attributes = [];
+               for(var key in item){
+                       // Save off only the real item attributes, not the special id marks for O(1) isItem.
+                       if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){
+                               attributes.push(key);
                        }
-                       var w = this.scrollNode,
-                               sl = this._convertToScrollLeft(this._getScrollForSelectedTab());
-                       w.scrollLeft = sl;
                }
-
-               // Enable/disabled left right buttons depending on whether or not user can scroll to left or right
-               this._setButtonClass(this._getScroll());
-               
-               this._postResize = true;
+               return attributes; // Array
        },
 
-       _getScroll: function(){
-               // summary:
-               //              Returns the current scroll of the tabs where 0 means
-               //              "scrolled all the way to the left" and some positive number, based on #
-               //              of pixels of possible scroll (ex: 1000) means "scrolled all the way to the right"
-               var sl = (this.isLeftToRight() || dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.isWebKit) ? this.scrollNode.scrollLeft :
-                               dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width")
-                                        + (dojo.isIE == 8 ? -1 : 1) * this.scrollNode.scrollLeft;
-               return sl;
+       hasAttribute: function( /* item */ item,
+                                                       /* attribute-name-string */ attribute){
+               //      summary:
+               //              See dojo.data.api.Read.hasAttribute()
+               this._assertIsItem(item);
+               this._assertIsAttribute(attribute);
+               return (attribute in item);
        },
 
-       _convertToScrollLeft: function(val){
-               // summary:
-               //              Given a scroll value where 0 means "scrolled all the way to the left"
-               //              and some positive number, based on # of pixels of possible scroll (ex: 1000)
-               //              means "scrolled all the way to the right", return value to set this.scrollNode.scrollLeft
-               //              to achieve that scroll.
-               //
-               //              This method is to adjust for RTL funniness in various browsers and versions.
-               if(this.isLeftToRight() || dojo.isIE < 8 || (dojo.isIE && dojo.isQuirks) || dojo.isWebKit){
-                       return val;
-               }else{
-                       var maxScroll = dojo.style(this.containerNode, "width") - dojo.style(this.scrollNode, "width");
-                       return (dojo.isIE == 8 ? -1 : 1) * (val - maxScroll);
+       containsValue: function(/* item */ item,
+                                                       /* attribute-name-string */ attribute,
+                                                       /* anything */ value){
+               //      summary:
+               //              See dojo.data.api.Read.containsValue()
+               var regexp = undefined;
+               if(typeof value === "string"){
+                       regexp = filterUtil.patternToRegExp(value, false);
                }
+               return this._containsValue(item, attribute, value, regexp); //boolean.
        },
 
-       onSelectChild: function(/*dijit._Widget*/ page){
-               // summary:
-               //              Smoothly scrolls to a tab when it is selected.
-
-               var tab = this.pane2button[page.id];
-               if(!tab || !page){return;}
-
-               // Scroll to the selected tab, except on startup, when scrolling is handled in resize()
-               var node = tab.domNode;
-               if(this._postResize && node != this._selectedTab){
-                       this._selectedTab = node;
-
-                       var sl = this._getScroll();
+       _containsValue: function(       /* item */ item,
+                                                               /* attribute-name-string */ attribute,
+                                                               /* anything */ value,
+                                                               /* RegExp?*/ regexp){
+               //      summary:
+               //              Internal function for looking at the values contained by the item.
+               //      description:
+               //              Internal function for looking at the values contained by the item.  This
+               //              function allows for denoting if the comparison should be case sensitive for
+               //              strings or not (for handling filtering cases where string case should not matter)
+               //
+               //      item:
+               //              The data item to examine for attribute values.
+               //      attribute:
+               //              The attribute to inspect.
+               //      value:
+               //              The value to match.
+               //      regexp:
+               //              Optional regular expression generated off value if value was of string type to handle wildcarding.
+               //              If present and attribute values are string, then it can be used for comparison instead of 'value'
+               return array.some(this.getValues(item, attribute), function(possibleValue){
+                       if(possibleValue !== null && !lang.isObject(possibleValue) && regexp){
+                               if(possibleValue.toString().match(regexp)){
+                                       return true; // Boolean
+                               }
+                       }else if(value === possibleValue){
+                               return true; // Boolean
+                       }
+               });
+       },
 
-                       if(sl > node.offsetLeft ||
-                                       sl + dojo.style(this.scrollNode, "width") <
-                                       node.offsetLeft + dojo.style(node, "width")){
-                               this.createSmoothScroll().play();
+       isItem: function(/* anything */ something){
+               //      summary:
+               //              See dojo.data.api.Read.isItem()
+               if(something && something[this._storeRefPropName] === this){
+                       if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){
+                               return true;
                        }
                }
+               return false; // Boolean
+       },
 
-               this.inherited(arguments);
+       isItemLoaded: function(/* anything */ something){
+               //      summary:
+               //              See dojo.data.api.Read.isItemLoaded()
+               return this.isItem(something); //boolean
        },
 
-       _getScrollBounds: function(){
-               // summary:
-               //              Returns the minimum and maximum scroll setting to show the leftmost and rightmost
-               //              tabs (respectively)
-               var children = this.getChildren(),
-                       scrollNodeWidth = dojo.style(this.scrollNode, "width"),         // about 500px
-                       containerWidth = dojo.style(this.containerNode, "width"),       // 50,000px
-                       maxPossibleScroll = containerWidth - scrollNodeWidth,   // scrolling until right edge of containerNode visible
-                       tabsWidth = this._getTabsWidth();
+       loadItem: function(/* object */ keywordArgs){
+               //      summary:
+               //              See dojo.data.api.Read.loadItem()
+               this._assertIsItem(keywordArgs.item);
+       },
 
-               if(children.length && tabsWidth > scrollNodeWidth){
-                       // Scrolling should happen
-                       return {
-                               min: this.isLeftToRight() ? 0 : children[children.length-1].domNode.offsetLeft,
-                               max: this.isLeftToRight() ?
-                                       (children[children.length-1].domNode.offsetLeft + dojo.style(children[children.length-1].domNode, "width")) - scrollNodeWidth :
-                                       maxPossibleScroll
-                       };
-               }else{
-                       // No scrolling needed, all tabs visible, we stay either scrolled to far left or far right (depending on dir)
-                       var onlyScrollPosition = this.isLeftToRight() ? 0 : maxPossibleScroll;
-                       return {
-                               min: onlyScrollPosition,
-                               max: onlyScrollPosition
-                       };
+       getFeatures: function(){
+               //      summary:
+               //              See dojo.data.api.Read.getFeatures()
+               return this._features; //Object
+       },
+
+       getLabel: function(/* item */ item){
+               //      summary:
+               //              See dojo.data.api.Read.getLabel()
+               if(this._labelAttr && this.isItem(item)){
+                       return this.getValue(item,this._labelAttr); //String
                }
+               return undefined; //undefined
        },
 
-       _getScrollForSelectedTab: function(){
-               // summary:
-               //              Returns the scroll value setting so that the selected tab
-               //              will appear in the center
-               var w = this.scrollNode,
-                       n = this._selectedTab,
-                       scrollNodeWidth = dojo.style(this.scrollNode, "width"),
-                       scrollBounds = this._getScrollBounds();
+       getLabelAttributes: function(/* item */ item){
+               //      summary:
+               //              See dojo.data.api.Read.getLabelAttributes()
+               if(this._labelAttr){
+                       return [this._labelAttr]; //array
+               }
+               return null; //null
+       },
 
-               // TODO: scroll minimal amount (to either right or left) so that
-               // selected tab is fully visible, and just return if it's already visible?
-               var pos = (n.offsetLeft + dojo.style(n, "width")/2) - scrollNodeWidth/2;
-               pos = Math.min(Math.max(pos, scrollBounds.min), scrollBounds.max);
-
-               // TODO:
-               // If scrolling close to the left side or right side, scroll
-               // all the way to the left or right.  See this._minScroll.
-               // (But need to make sure that doesn't scroll the tab out of view...)
-               return pos;
-       },
+       _fetchItems: function(  /* Object */ keywordArgs,
+                                                       /* Function */ findCallback,
+                                                       /* Function */ errorCallback){
+               //      summary:
+               //              See dojo.data.util.simpleFetch.fetch()
+               var self = this,
+                   filter = function(requestArgs, arrayOfItems){
+                       var items = [],
+                           i, key;
+                       if(requestArgs.query){
+                               var value,
+                                   ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false;
 
-       createSmoothScroll : function(x){
-               // summary:
-               //              Creates a dojo._Animation object that smoothly scrolls the tab list
-               //              either to a fixed horizontal pixel value, or to the selected tab.
-               // description:
-               //              If an number argument is passed to the function, that horizontal
-               //              pixel position is scrolled to.  Otherwise the currently selected
-               //              tab is scrolled to.
-               // x: Integer?
-               //              An optional pixel value to scroll to, indicating distance from left.
+                               //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
+                               //same value for each item examined.  Much more efficient.
+                               var regexpList = {};
+                               for(key in requestArgs.query){
+                                       value = requestArgs.query[key];
+                                       if(typeof value === "string"){
+                                               regexpList[key] = filterUtil.patternToRegExp(value, ignoreCase);
+                                       }else if(value instanceof RegExp){
+                                               regexpList[key] = value;
+                                       }
+                               }
+                               for(i = 0; i < arrayOfItems.length; ++i){
+                                       var match = true;
+                                       var candidateItem = arrayOfItems[i];
+                                       if(candidateItem === null){
+                                               match = false;
+                                       }else{
+                                               for(key in requestArgs.query){
+                                                       value = requestArgs.query[key];
+                                                       if(!self._containsValue(candidateItem, key, value, regexpList[key])){
+                                                               match = false;
+                                                       }
+                                               }
+                                       }
+                                       if(match){
+                                               items.push(candidateItem);
+                                       }
+                               }
+                               findCallback(items, requestArgs);
+                       }else{
+                               // We want a copy to pass back in case the parent wishes to sort the array.
+                               // We shouldn't allow resort of the internal list, so that multiple callers
+                               // can get lists and sort without affecting each other.  We also need to
+                               // filter out any null values that have been left as a result of deleteItem()
+                               // calls in ItemFileWriteStore.
+                               for(i = 0; i < arrayOfItems.length; ++i){
+                                       var item = arrayOfItems[i];
+                                       if(item !== null){
+                                               items.push(item);
+                                       }
+                               }
+                               findCallback(items, requestArgs);
+                       }
+               };
 
-               // Calculate position to scroll to
-               if(arguments.length > 0){
-                       // position specified by caller, just make sure it's within bounds
-                       var scrollBounds = this._getScrollBounds();
-                       x = Math.min(Math.max(x, scrollBounds.min), scrollBounds.max);
+               if(this._loadFinished){
+                       filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
                }else{
-                       // scroll to center the current tab
-                       x = this._getScrollForSelectedTab();
-               }
+                       //Do a check on the JsonFileUrl and crosscheck it.
+                       //If it doesn't match the cross-check, it needs to be updated
+                       //This allows for either url or _jsonFileUrl to he changed to
+                       //reset the store load location.  Done this way for backwards
+                       //compatibility.  People use _jsonFileUrl (even though officially
+                       //private.
+                       if(this._jsonFileUrl !== this._ccUrl){
+                               kernel.deprecated("dojo.data.ItemFileReadStore: ",
+                                       "To change the url, set the url property of the store," +
+                                       " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+                               this._ccUrl = this._jsonFileUrl;
+                               this.url = this._jsonFileUrl;
+                       }else if(this.url !== this._ccUrl){
+                               this._jsonFileUrl = this.url;
+                               this._ccUrl = this.url;
+                       }
 
-               if(this._anim && this._anim.status() == "playing"){
-                       this._anim.stop();
-               }
+                       //See if there was any forced reset of data.
+                       if(this.data != null){
+                               this._jsonData = this.data;
+                               this.data = null;
+                       }
 
-               var self = this,
-                       w = this.scrollNode,
-                       anim = new dojo._Animation({
-                               beforeBegin: function(){
-                                       if(this.curve){ delete this.curve; }
-                                       var oldS = w.scrollLeft,
-                                               newS = self._convertToScrollLeft(x);
-                                       anim.curve = new dojo._Line(oldS, newS);
-                               },
-                               onAnimate: function(val){
-                                       w.scrollLeft = val;
-                               }
-                       });
-               this._anim = anim;
+                       if(this._jsonFileUrl){
+                               //If fetches come in before the loading has finished, but while
+                               //a load is in progress, we have to defer the fetching to be
+                               //invoked in the callback.
+                               if(this._loadInProgress){
+                                       this._queuedFetches.push({args: keywordArgs, filter: filter});
+                               }else{
+                                       this._loadInProgress = true;
+                                       var getArgs = {
+                                                       url: self._jsonFileUrl,
+                                                       handleAs: "json-comment-optional",
+                                                       preventCache: this.urlPreventCache,
+                                                       failOk: this.failOk
+                                               };
+                                       var getHandler = xhr.get(getArgs);
+                                       getHandler.addCallback(function(data){
+                                               try{
+                                                       self._getItemsFromLoadedData(data);
+                                                       self._loadFinished = true;
+                                                       self._loadInProgress = false;
 
-               // Disable/enable left/right buttons according to new scroll position
-               this._setButtonClass(x);
+                                                       filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));
+                                                       self._handleQueuedFetches();
+                                               }catch(e){
+                                                       self._loadFinished = true;
+                                                       self._loadInProgress = false;
+                                                       errorCallback(e, keywordArgs);
+                                               }
+                                       });
+                                       getHandler.addErrback(function(error){
+                                               self._loadInProgress = false;
+                                               errorCallback(error, keywordArgs);
+                                       });
 
-               return anim; // dojo._Animation
+                                       //Wire up the cancel to abort of the request
+                                       //This call cancel on the deferred if it hasn't been called
+                                       //yet and then will chain to the simple abort of the
+                                       //simpleFetch keywordArgs
+                                       var oldAbort = null;
+                                       if(keywordArgs.abort){
+                                               oldAbort = keywordArgs.abort;
+                                       }
+                                       keywordArgs.abort = function(){
+                                               var df = getHandler;
+                                               if(df && df.fired === -1){
+                                                       df.cancel();
+                                                       df = null;
+                                               }
+                                               if(oldAbort){
+                                                       oldAbort.call(keywordArgs);
+                                               }
+                                       };
+                               }
+                       }else if(this._jsonData){
+                               try{
+                                       this._loadFinished = true;
+                                       this._getItemsFromLoadedData(this._jsonData);
+                                       this._jsonData = null;
+                                       filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
+                               }catch(e){
+                                       errorCallback(e, keywordArgs);
+                               }
+                       }else{
+                               errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);
+                       }
+               }
        },
 
-       _getBtnNode: function(e){
-               // summary:
-               //              Gets a button DOM node from a mouse click event.
-               // e:
-               //              The mouse click event.
-               var n = e.target;
-               while(n && !dojo.hasClass(n, "tabStripButton")){
-                       n = n.parentNode;
+       _handleQueuedFetches: function(){
+               //      summary:
+               //              Internal function to execute delayed request in the store.
+               //Execute any deferred fetches now.
+               if(this._queuedFetches.length > 0){
+                       for(var i = 0; i < this._queuedFetches.length; i++){
+                               var fData = this._queuedFetches[i],
+                                   delayedQuery = fData.args,
+                                   delayedFilter = fData.filter;
+                               if(delayedFilter){
+                                       delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions));
+                               }else{
+                                       this.fetchItemByIdentity(delayedQuery);
+                               }
+                       }
+                       this._queuedFetches = [];
                }
-               return n;
        },
 
-       doSlideRight: function(e){
-               // summary:
-               //              Scrolls the menu to the right.
-               // e:
-               //              The mouse click event.
-               this.doSlide(1, this._getBtnNode(e));
+       _getItemsArray: function(/*object?*/queryOptions){
+               //      summary:
+               //              Internal function to determine which list of items to search over.
+               //      queryOptions: The query options parameter, if any.
+               if(queryOptions && queryOptions.deep){
+                       return this._arrayOfAllItems;
+               }
+               return this._arrayOfTopLevelItems;
        },
 
-       doSlideLeft: function(e){
-               // summary:
-               //              Scrolls the menu to the left.
-               // e:
-               //              The mouse click event.
-               this.doSlide(-1,this._getBtnNode(e));
+       close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
+                //     summary:
+                //             See dojo.data.api.Read.close()
+                if(this.clearOnClose &&
+                       this._loadFinished &&
+                       !this._loadInProgress){
+                        //Reset all internalsback to default state.  This will force a reload
+                        //on next fetch.  This also checks that the data or url param was set
+                        //so that the store knows it can get data.  Without one of those being set,
+                        //the next fetch will trigger an error.
+
+                        if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) &&
+                                (this.url == "" || this.url == null)
+                               ) && this.data == null){
+                                console.debug("dojo.data.ItemFileReadStore: WARNING!  Data reload " +
+                                       " information has not been provided." +
+                                       "  Please set 'url' or 'data' to the appropriate value before" +
+                                       " the next fetch");
+                        }
+                        this._arrayOfAllItems = [];
+                        this._arrayOfTopLevelItems = [];
+                        this._loadFinished = false;
+                        this._itemsByIdentity = null;
+                        this._loadInProgress = false;
+                        this._queuedFetches = [];
+                }
        },
 
-       doSlide: function(direction, node){
-               // summary:
-               //              Scrolls the tab list to the left or right by 75% of the widget width.
-               // direction:
-               //              If the direction is 1, the widget scrolls to the right, if it is
-               //              -1, it scrolls to the left.
+       _getItemsFromLoadedData: function(/* Object */ dataObject){
+               //      summary:
+               //              Function to parse the loaded data into item format and build the internal items array.
+               //      description:
+               //              Function to parse the loaded data into item format and build the internal items array.
+               //
+               //      dataObject:
+               //              The JS data object containing the raw data to convery into item format.
+               //
+               //      returns: array
+               //              Array of items in store item format.
 
-               if(node && dojo.hasClass(node, "dijitTabDisabled")){return;}
+               // First, we define a couple little utility functions...
+               var addingArrays = false,
+                   self = this;
 
-               var sWidth = dojo.style(this.scrollNode, "width");
-               var d = (sWidth * 0.75) * direction;
-
-               var to = this._getScroll() + d;
-
-               this._setButtonClass(to);
-
-               this.createSmoothScroll(to).play();
-       },
+               function valueIsAnItem(/* anything */ aValue){
+                       // summary:
+                       //              Given any sort of value that could be in the raw json data,
+                       //              return true if we should interpret the value as being an
+                       //              item itself, rather than a literal value or a reference.
+                       // example:
+                       //      |       false == valueIsAnItem("Kermit");
+                       //      |       false == valueIsAnItem(42);
+                       //      |       false == valueIsAnItem(new Date());
+                       //      |       false == valueIsAnItem({_type:'Date', _value:'1802-05-14'});
+                       //      |       false == valueIsAnItem({_reference:'Kermit'});
+                       //      |       true == valueIsAnItem({name:'Kermit', color:'green'});
+                       //      |       true == valueIsAnItem({iggy:'pop'});
+                       //      |       true == valueIsAnItem({foo:42});
+                       return (aValue !== null) &&
+                               (typeof aValue === "object") &&
+                               (!lang.isArray(aValue) || addingArrays) &&
+                               (!lang.isFunction(aValue)) &&
+                               (aValue.constructor == Object || lang.isArray(aValue)) &&
+                               (typeof aValue._reference === "undefined") &&
+                               (typeof aValue._type === "undefined") &&
+                               (typeof aValue._value === "undefined") &&
+                               self.hierarchical;
+               }
 
-       _setButtonClass: function(scroll){
-               // summary:
-               //              Disables the left scroll button if the tabs are scrolled all the way to the left,
-               //              or the right scroll button in the opposite case.
-               // scroll: Integer
-               //              amount of horizontal scroll
+               function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){
+                       self._arrayOfAllItems.push(anItem);
+                       for(var attribute in anItem){
+                               var valueForAttribute = anItem[attribute];
+                               if(valueForAttribute){
+                                       if(lang.isArray(valueForAttribute)){
+                                               var valueArray = valueForAttribute;
+                                               for(var k = 0; k < valueArray.length; ++k){
+                                                       var singleValue = valueArray[k];
+                                                       if(valueIsAnItem(singleValue)){
+                                                               addItemAndSubItemsToArrayOfAllItems(singleValue);
+                                                       }
+                                               }
+                                       }else{
+                                               if(valueIsAnItem(valueForAttribute)){
+                                                       addItemAndSubItemsToArrayOfAllItems(valueForAttribute);
+                                               }
+                                       }
+                               }
+                       }
+               }
 
-               var scrollBounds = this._getScrollBounds();
-               this._leftBtn.set("disabled", scroll <= scrollBounds.min);
-               this._rightBtn.set("disabled", scroll >= scrollBounds.max);
-       }
-});
+               this._labelAttr = dataObject.label;
 
-dojo.declare("dijit.layout._ScrollingTabControllerButton",
-       dijit.form.Button,
-       {
-               baseClass: "dijitTab tabStripButton",
+               // We need to do some transformations to convert the data structure
+               // that we read from the file into a format that will be convenient
+               // to work with in memory.
 
-               templateString: dojo.cache("dijit.layout", "templates/_ScrollingTabControllerButton.html", "<div dojoAttachEvent=\"onclick:_onButtonClick\">\n\t<div waiRole=\"presentation\" class=\"dijitTabInnerDiv\" dojoattachpoint=\"innerDiv,focusNode\">\n\t\t<div waiRole=\"presentation\" class=\"dijitTabContent dijitButtonContents\" dojoattachpoint=\"tabContent\">\n\t\t\t<img waiRole=\"presentation\" alt=\"\" src=\"${_blankGif}\" class=\"dijitTabStripIcon\" dojoAttachPoint=\"iconNode\"/>\n\t\t\t<span dojoAttachPoint=\"containerNode,titleNode\" class=\"dijitButtonText\"></span>\n\t\t</div>\n\t</div>\n</div>\n"),
+               // Step 1: Walk through the object hierarchy and build a list of all items
+               var i,
+                   item;
+               this._arrayOfAllItems = [];
+               this._arrayOfTopLevelItems = dataObject.items;
 
-               // Override inherited tabIndex: 0 from dijit.form.Button, because user shouldn't be
-               // able to tab to the left/right/menu buttons
-               tabIndex: "-1"
-       }
-);
+               for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){
+                       item = this._arrayOfTopLevelItems[i];
+                       if(lang.isArray(item)){
+                               addingArrays = true;
+                       }
+                       addItemAndSubItemsToArrayOfAllItems(item);
+                       item[this._rootItemPropName]=true;
+               }
 
-}
+               // Step 2: Walk through all the attribute values of all the items,
+               // and replace single values with arrays.  For example, we change this:
+               //              { name:'Miss Piggy', pets:'Foo-Foo'}
+               // into this:
+               //              { name:['Miss Piggy'], pets:['Foo-Foo']}
+               //
+               // We also store the attribute names so we can validate our store
+               // reference and item id special properties for the O(1) isItem
+               var allAttributeNames = {},
+                   key;
 
-if(!dojo._hasResource["dijit.layout.TabContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.layout.TabContainer"] = true;
-dojo.provide("dijit.layout.TabContainer");
+               for(i = 0; i < this._arrayOfAllItems.length; ++i){
+                       item = this._arrayOfAllItems[i];
+                       for(key in item){
+                               if(key !== this._rootItemPropName){
+                                       var value = item[key];
+                                       if(value !== null){
+                                               if(!lang.isArray(value)){
+                                                       item[key] = [value];
+                                               }
+                                       }else{
+                                               item[key] = [null];
+                                       }
+                               }
+                               allAttributeNames[key]=key;
+                       }
+               }
 
+               // Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName
+               // This should go really fast, it will generally never even run the loop.
+               while(allAttributeNames[this._storeRefPropName]){
+                       this._storeRefPropName += "_";
+               }
+               while(allAttributeNames[this._itemNumPropName]){
+                       this._itemNumPropName += "_";
+               }
+               while(allAttributeNames[this._reverseRefMap]){
+                       this._reverseRefMap += "_";
+               }
 
+               // Step 4: Some data files specify an optional 'identifier', which is
+               // the name of an attribute that holds the identity of each item.
+               // If this data file specified an identifier attribute, then build a
+               // hash table of items keyed by the identity of the items.
+               var arrayOfValues;
 
+               var identifier = dataObject.identifier;
+               if(identifier){
+                       this._itemsByIdentity = {};
+                       this._features['dojo.data.api.Identity'] = identifier;
+                       for(i = 0; i < this._arrayOfAllItems.length; ++i){
+                               item = this._arrayOfAllItems[i];
+                               arrayOfValues = item[identifier];
+                               var identity = arrayOfValues[0];
+                               if(!Object.hasOwnProperty.call(this._itemsByIdentity, identity)){
+                                       this._itemsByIdentity[identity] = item;
+                               }else{
+                                       if(this._jsonFileUrl){
+                                               throw new Error("dojo.data.ItemFileReadStore:  The json data as specified by: [" + this._jsonFileUrl + "] is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
+                                       }else if(this._jsonData){
+                                               throw new Error("dojo.data.ItemFileReadStore:  The json data provided by the creation arguments is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
+                                       }
+                               }
+                       }
+               }else{
+                       this._features['dojo.data.api.Identity'] = Number;
+               }
 
+               // Step 5: Walk through all the items, and set each item's properties
+               // for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true.
+               for(i = 0; i < this._arrayOfAllItems.length; ++i){
+                       item = this._arrayOfAllItems[i];
+                       item[this._storeRefPropName] = this;
+                       item[this._itemNumPropName] = i;
+               }
 
-dojo.declare("dijit.layout.TabContainer",
-       dijit.layout._TabContainerBase,
-       {
-               // summary:
-               //              A Container with tabs to select each child (only one of which is displayed at a time).
-               // description:
-               //              A TabContainer is a container that has multiple panes, but shows only
-               //              one pane at a time.  There are a set of tabs corresponding to each pane,
-               //              where each tab has the name (aka title) of the pane, and optionally a close button.
+               // Step 6: We walk through all the attribute values of all the items,
+               // looking for type/value literals and item-references.
+               //
+               // We replace item-references with pointers to items.  For example, we change:
+               //              { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+               // into this:
+               //              { name:['Kermit'], friends:[miss_piggy] }
+               // (where miss_piggy is the object representing the 'Miss Piggy' item).
+               //
+               // We replace type/value pairs with typed-literals.  For example, we change:
+               //              { name:['Nelson Mandela'], born:[{_type:'Date', _value:'1918-07-18'}] }
+               // into this:
+               //              { name:['Kermit'], born:(new Date(1918, 6, 18)) }
+               //
+               // We also generate the associate map for all items for the O(1) isItem function.
+               for(i = 0; i < this._arrayOfAllItems.length; ++i){
+                       item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+                       for(key in item){
+                               arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}]
+                               for(var j = 0; j < arrayOfValues.length; ++j){
+                                       value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}}
+                                       if(value !== null && typeof value == "object"){
+                                               if(("_type" in value) && ("_value" in value)){
+                                                       var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber'
+                                                       var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}}
+                                                       if(!mappingObj){
+                                                               throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'");
+                                                       }else if(lang.isFunction(mappingObj)){
+                                                               arrayOfValues[j] = new mappingObj(value._value);
+                                                       }else if(lang.isFunction(mappingObj.deserialize)){
+                                                               arrayOfValues[j] = mappingObj.deserialize(value._value);
+                                                       }else{
+                                                               throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");
+                                                       }
+                                               }
+                                               if(value._reference){
+                                                       var referenceDescription = value._reference; // example: {name:'Miss Piggy'}
+                                                       if(!lang.isObject(referenceDescription)){
+                                                               // example: 'Miss Piggy'
+                                                               // from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]}
+                                                               arrayOfValues[j] = this._getItemByIdentity(referenceDescription);
+                                                       }else{
+                                                               // example: {name:'Miss Piggy'}
+                                                               // from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
+                                                               for(var k = 0; k < this._arrayOfAllItems.length; ++k){
+                                                                       var candidateItem = this._arrayOfAllItems[k],
+                                                                           found = true;
+                                                                       for(var refKey in referenceDescription){
+                                                                               if(candidateItem[refKey] != referenceDescription[refKey]){
+                                                                                       found = false;
+                                                                               }
+                                                                       }
+                                                                       if(found){
+                                                                               arrayOfValues[j] = candidateItem;
+                                                                       }
+                                                               }
+                                                       }
+                                                       if(this.referenceIntegrity){
+                                                               var refItem = arrayOfValues[j];
+                                                               if(this.isItem(refItem)){
+                                                                       this._addReferenceToMap(refItem, item, key);
+                                                               }
+                                                       }
+                                               }else if(this.isItem(value)){
+                                                       //It's a child item (not one referenced through _reference).
+                                                       //We need to treat this as a referenced item, so it can be cleaned up
+                                                       //in a write store easily.
+                                                       if(this.referenceIntegrity){
+                                                               this._addReferenceToMap(value, item, key);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       },
 
-               // useMenu: [const] Boolean
-               //              True if a menu should be used to select tabs when they are too
-               //              wide to fit the TabContainer, false otherwise.
-               useMenu: true,
+       _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
+                //     summary:
+                //             Method to add an reference map entry for an item and attribute.
+                //     description:
+                //             Method to add an reference map entry for an item and attribute.                  //
+                //     refItem:
+                //             The item that is referenced.
+                //     parentItem:
+                //             The item that holds the new reference to refItem.
+                //     attribute:
+                //             The attribute on parentItem that contains the new reference.
 
-               // useSlider: [const] Boolean
-               //              True if a slider should be used to select tabs when they are too
-               //              wide to fit the TabContainer, false otherwise.
-               useSlider: true,
+                //Stub function, does nothing.  Real processing is in ItemFileWriteStore.
+       },
 
-               // controllerWidget: String
-               //              An optional parameter to override the widget used to display the tab labels
-               controllerWidget: "",
+       getIdentity: function(/* item */ item){
+               //      summary:
+               //              See dojo.data.api.Identity.getIdentity()
+               var identifier = this._features['dojo.data.api.Identity'];
+               if(identifier === Number){
+                       return item[this._itemNumPropName]; // Number
+               }else{
+                       var arrayOfValues = item[identifier];
+                       if(arrayOfValues){
+                               return arrayOfValues[0]; // Object || String
+                       }
+               }
+               return null; // null
+       },
 
-               _makeController: function(/*DomNode*/ srcNode){
-                       // summary:
-                       //              Instantiate tablist controller widget and return reference to it.
-                       //              Callback from _TabContainerBase.postCreate().
-                       // tags:
-                       //              protected extension
+       fetchItemByIdentity: function(/* Object */ keywordArgs){
+               //      summary:
+               //              See dojo.data.api.Identity.fetchItemByIdentity()
 
-                       var cls = this.baseClass + "-tabs" + (this.doLayout ? "" : " dijitTabNoLayout"),
-                               TabController = dojo.getObject(this.controllerWidget);
+               // Hasn't loaded yet, we have to trigger the load.
+               var item,
+                   scope;
+               if(!this._loadFinished){
+                       var self = this;
+                       //Do a check on the JsonFileUrl and crosscheck it.
+                       //If it doesn't match the cross-check, it needs to be updated
+                       //This allows for either url or _jsonFileUrl to he changed to
+                       //reset the store load location.  Done this way for backwards
+                       //compatibility.  People use _jsonFileUrl (even though officially
+                       //private.
+                       if(this._jsonFileUrl !== this._ccUrl){
+                               kernel.deprecated("dojo.data.ItemFileReadStore: ",
+                                       "To change the url, set the url property of the store," +
+                                       " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+                               this._ccUrl = this._jsonFileUrl;
+                               this.url = this._jsonFileUrl;
+                       }else if(this.url !== this._ccUrl){
+                               this._jsonFileUrl = this.url;
+                               this._ccUrl = this.url;
+                       }
 
-                       return new TabController({
-                               id: this.id + "_tablist",
-                               dir: this.dir,
-                               lang: this.lang,
-                               tabPosition: this.tabPosition,
-                               doLayout: this.doLayout,
-                               containerId: this.id,
-                               "class": cls,
-                               nested: this.nested,
-                               useMenu: this.useMenu,
-                               useSlider: this.useSlider,
-                               tabStripClass: this.tabStrip ? this.baseClass + (this.tabStrip ? "":"No") + "Strip": null
-                       }, srcNode);
-               },
+                       //See if there was any forced reset of data.
+                       if(this.data != null && this._jsonData == null){
+                               this._jsonData = this.data;
+                               this.data = null;
+                       }
 
-               postMixInProperties: function(){
-                       this.inherited(arguments);
+                       if(this._jsonFileUrl){
 
-                       // Scrolling controller only works for horizontal non-nested tabs
-                       if(!this.controllerWidget){
-                               this.controllerWidget = (this.tabPosition == "top" || this.tabPosition == "bottom") && !this.nested ?
-                                                       "dijit.layout.ScrollingTabController" : "dijit.layout.TabController";
+                               if(this._loadInProgress){
+                                       this._queuedFetches.push({args: keywordArgs});
+                               }else{
+                                       this._loadInProgress = true;
+                                       var getArgs = {
+                                                       url: self._jsonFileUrl,
+                                                       handleAs: "json-comment-optional",
+                                                       preventCache: this.urlPreventCache,
+                                                       failOk: this.failOk
+                                       };
+                                       var getHandler = xhr.get(getArgs);
+                                       getHandler.addCallback(function(data){
+                                               var scope = keywordArgs.scope?keywordArgs.scope:window.global;
+                                               try{
+                                                       self._getItemsFromLoadedData(data);
+                                                       self._loadFinished = true;
+                                                       self._loadInProgress = false;
+                                                       item = self._getItemByIdentity(keywordArgs.identity);
+                                                       if(keywordArgs.onItem){
+                                                               keywordArgs.onItem.call(scope, item);
+                                                       }
+                                                       self._handleQueuedFetches();
+                                               }catch(error){
+                                                       self._loadInProgress = false;
+                                                       if(keywordArgs.onError){
+                                                               keywordArgs.onError.call(scope, error);
+                                                       }
+                                               }
+                                       });
+                                       getHandler.addErrback(function(error){
+                                               self._loadInProgress = false;
+                                               if(keywordArgs.onError){
+                                                       var scope = keywordArgs.scope?keywordArgs.scope:window.global;
+                                                       keywordArgs.onError.call(scope, error);
+                                               }
+                                       });
+                               }
+
+                       }else if(this._jsonData){
+                               // Passed in data, no need to xhr.
+                               self._getItemsFromLoadedData(self._jsonData);
+                               self._jsonData = null;
+                               self._loadFinished = true;
+                               item = self._getItemByIdentity(keywordArgs.identity);
+                               if(keywordArgs.onItem){
+                                       scope = keywordArgs.scope?keywordArgs.scope:window.global;
+                                       keywordArgs.onItem.call(scope, item);
+                               }
+                       }
+               }else{
+                       // Already loaded.  We can just look it up and call back.
+                       item = this._getItemByIdentity(keywordArgs.identity);
+                       if(keywordArgs.onItem){
+                               scope = keywordArgs.scope?keywordArgs.scope:window.global;
+                               keywordArgs.onItem.call(scope, item);
                        }
                }
-});
-
+       },
 
-}
+       _getItemByIdentity: function(/* Object */ identity){
+               //      summary:
+               //              Internal function to look an item up by its identity map.
+               var item = null;
+               if(this._itemsByIdentity){
+                       // If this map is defined, we need to just try to get it.  If it fails
+                       // the item does not exist.
+                       if(Object.hasOwnProperty.call(this._itemsByIdentity, identity)){
+                               item = this._itemsByIdentity[identity];
+                       }
+               }else if (Object.hasOwnProperty.call(this._arrayOfAllItems, identity)){
+                       item = this._arrayOfAllItems[identity];
+               }
+               if(item === undefined){
+                       item = null;
+               }
+               return item; // Object
+       },
 
-if(!dojo._hasResource["dojo.number"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.number"] = true;
-dojo.provide("dojo.number");
+       getIdentityAttributes: function(/* item */ item){
+               //      summary:
+               //              See dojo.data.api.Identity.getIdentityAttributes()
 
+               var identifier = this._features['dojo.data.api.Identity'];
+               if(identifier === Number){
+                       // If (identifier === Number) it means getIdentity() just returns
+                       // an integer item-number for each item.  The dojo.data.api.Identity
+                       // spec says we need to return null if the identity is not composed
+                       // of attributes
+                       return null; // null
+               }else{
+                       return [identifier]; // Array
+               }
+       },
 
+       _forceLoad: function(){
+               //      summary:
+               //              Internal function to force a load of the store if it hasn't occurred yet.  This is required
+               //              for specific functions to work properly.
+               var self = this;
+               //Do a check on the JsonFileUrl and crosscheck it.
+               //If it doesn't match the cross-check, it needs to be updated
+               //This allows for either url or _jsonFileUrl to he changed to
+               //reset the store load location.  Done this way for backwards
+               //compatibility.  People use _jsonFileUrl (even though officially
+               //private.
+               if(this._jsonFileUrl !== this._ccUrl){
+                       kernel.deprecated("dojo.data.ItemFileReadStore: ",
+                               "To change the url, set the url property of the store," +
+                               " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
+                       this._ccUrl = this._jsonFileUrl;
+                       this.url = this._jsonFileUrl;
+               }else if(this.url !== this._ccUrl){
+                       this._jsonFileUrl = this.url;
+                       this._ccUrl = this.url;
+               }
 
+               //See if there was any forced reset of data.
+               if(this.data != null){
+                       this._jsonData = this.data;
+                       this.data = null;
+               }
 
+               if(this._jsonFileUrl){
+                               var getArgs = {
+                                       url: this._jsonFileUrl,
+                                       handleAs: "json-comment-optional",
+                                       preventCache: this.urlPreventCache,
+                                       failOk: this.failOk,
+                                       sync: true
+                               };
+                       var getHandler = xhr.get(getArgs);
+                       getHandler.addCallback(function(data){
+                               try{
+                                       //Check to be sure there wasn't another load going on concurrently
+                                       //So we don't clobber data that comes in on it.  If there is a load going on
+                                       //then do not save this data.  It will potentially clobber current data.
+                                       //We mainly wanted to sync/wait here.
+                                       //TODO:  Revisit the loading scheme of this store to improve multi-initial
+                                       //request handling.
+                                       if(self._loadInProgress !== true && !self._loadFinished){
+                                               self._getItemsFromLoadedData(data);
+                                               self._loadFinished = true;
+                                       }else if(self._loadInProgress){
+                                               //Okay, we hit an error state we can't recover from.  A forced load occurred
+                                               //while an async load was occurring.  Since we cannot block at this point, the best
+                                               //that can be managed is to throw an error.
+                                               throw new Error("dojo.data.ItemFileReadStore:  Unable to perform a synchronous load, an async load is in progress.");
+                                       }
+                               }catch(e){
+                                       console.log(e);
+                                       throw e;
+                               }
+                       });
+                       getHandler.addErrback(function(error){
+                               throw error;
+                       });
+               }else if(this._jsonData){
+                       self._getItemsFromLoadedData(self._jsonData);
+                       self._jsonData = null;
+                       self._loadFinished = true;
+               }
+       }
+});
+//Mix in the simple fetch implementation to this class.
+lang.extend(ItemFileReadStore,simpleFetch);
 
+return ItemFileReadStore;
+});
 
+},
+'dojo/html':function(){
+define("dojo/html", ["./_base/kernel", "./_base/lang", "./_base/array", "./_base/declare", "./dom", "./dom-construct", "./parser"], function(dojo, lang, darray, declare, dom, domConstruct, parser) {
+       // module:
+       //              dojo/html
+       // summary:
+       //              TODOC
 
-/*=====
-dojo.number = {
-       // summary: localized formatting and parsing routines for Number
-}
+       lang.getObject("html", true, dojo);
 
-dojo.number.__FormatOptions = function(){
-       //      pattern: String?
-       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-       //              with this string.  Default value is based on locale.  Overriding this property will defeat
-       //              localization.  Literal characters in patterns are not supported.
-       //      type: String?
-       //              choose a format type based on the locale from the following:
-       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
-       //      places: Number?
-       //              fixed number of decimal places to show.  This overrides any
-       //              information in the provided pattern.
-       //      round: Number?
-       //              5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
-       //              means do not round.
-       //      locale: String?
-       //              override the locale used to determine formatting rules
-       //      fractional: Boolean?
-       //              If false, show no decimal places, overriding places and pattern settings.
-       this.pattern = pattern;
-       this.type = type;
-       this.places = places;
-       this.round = round;
-       this.locale = locale;
-       this.fractional = fractional;
-}
-=====*/
+       // the parser might be needed..
 
-dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){
-       // summary:
-       //              Format a Number as a String, using locale-specific settings
-       // description:
-       //              Create a string from a Number using a known localized pattern.
-       //              Formatting patterns appropriate to the locale are chosen from the
-       //              [Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and
-       //              delimiters.
-       //              If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.
-       // value:
-       //              the number to be formatted
+       // idCounter is incremented with each instantiation to allow asignment of a unique id for tracking, logging purposes
+       var idCounter = 0;
 
-       options = dojo.mixin({}, options || {});
-       var locale = dojo.i18n.normalizeLocale(options.locale),
-               bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale);
-       options.customs = bundle;
-       var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
-       if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null
-       return dojo.number._applyPattern(value, pattern, options); // String
-};
+       dojo.html._secureForInnerHtml = function(/*String*/ cont){
+               // summary:
+               //              removes !DOCTYPE and title elements from the html string.
+               //
+               //              khtml is picky about dom faults, you can't attach a style or <title> node as child of body
+               //              must go into head, so we need to cut out those tags
+               //      cont:
+               //              An html string for insertion into the dom
+               //
+               return cont.replace(/(?:\s*<!DOCTYPE\s[^>]+>|<title[^>]*>[\s\S]*?<\/title>)/ig, ""); // String
+       };
 
-//dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough
-dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough
+/*====
+       dojo.html._emptyNode = function(node){
+               // summary:
+               //              removes all child nodes from the given node
+               //      node: DOMNode
+               //              the parent element
+       };
+=====*/
+       dojo.html._emptyNode = domConstruct.empty;
 
-dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){
-       // summary:
-       //              Apply pattern to format value as a string using options. Gives no
-       //              consideration to local customs.
-       // value:
-       //              the number to be formatted.
-       // pattern:
-       //              a pattern string as described by
-       //              [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-       // options: dojo.number.__FormatOptions?
-       //              _applyPattern is usually called via `dojo.number.format()` which
-       //              populates an extra property in the options parameter, "customs".
-       //              The customs object specifies group and decimal parameters if set.
-
-       //TODO: support escapes
-       options = options || {};
-       var group = options.customs.group,
-               decimal = options.customs.decimal,
-               patternList = pattern.split(';'),
-               positivePattern = patternList[0];
-       pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);
-
-       //TODO: only test against unescaped
-       if(pattern.indexOf('%') != -1){
-               value *= 100;
-       }else if(pattern.indexOf('\u2030') != -1){
-               value *= 1000; // per mille
-       }else if(pattern.indexOf('\u00a4') != -1){
-               group = options.customs.currencyGroup || group;//mixins instead?
-               decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?
-               pattern = pattern.replace(/\u00a4{1,3}/, function(match){
-                       var prop = ["symbol", "currency", "displayName"][match.length-1];
-                       return options[prop] || options.currency || "";
-               });
-       }else if(pattern.indexOf('E') != -1){
-               throw new Error("exponential notation not supported");
-       }
-       
-       //TODO: support @ sig figs?
-       var numberPatternRE = dojo.number._numberPatternRE;
-       var numberPattern = positivePattern.match(numberPatternRE);
-       if(!numberPattern){
-               throw new Error("unable to find a number expression in pattern: "+pattern);
-       }
-       if(options.fractional === false){ options.places = 0; }
-       return pattern.replace(numberPatternRE,
-               dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));
-}
+       dojo.html._setNodeContent = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont){
+               // summary:
+               //              inserts the given content into the given node
+               //      node:
+               //              the parent element
+               //      content:
+               //              the content to be set on the parent element.
+               //              This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
 
-dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
-       //      summary:
-       //              Rounds to the nearest value with the given number of decimal places, away from zero
-       //      description:
-       //              Rounds to the nearest value with the given number of decimal places, away from zero if equal.
-       //              Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by
-       //              fractional increments also, such as the nearest quarter.
-       //              NOTE: Subject to floating point errors.  See dojox.math.round for experimental workaround.
-       //      value:
-       //              The number to round
-       //      places:
-       //              The number of decimal places where rounding takes place.  Defaults to 0 for whole rounding.
-       //              Must be non-negative.
-       //      increment:
-       //              Rounds next place to nearest value of increment/10.  10 by default.
-       //      example:
-       //              >>> dojo.number.round(-0.5)
-       //              -1
-       //              >>> dojo.number.round(162.295, 2)
-       //              162.29  // note floating point error.  Should be 162.3
-       //              >>> dojo.number.round(10.71, 0, 2.5)
-       //              10.75
-       var factor = 10 / (increment || 10);
-       return (factor * +value).toFixed(places) / factor; // Number
-}
+               // always empty
+               domConstruct.empty(node);
 
-if((0.9).toFixed() == 0){
-       // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit
-       // is just after the rounding place and is >=5
-       (function(){
-               var round = dojo.number.round;
-               dojo.number.round = function(v, p, m){
-                       var d = Math.pow(10, -p || 0), a = Math.abs(v);
-                       if(!v || a >= d || a * Math.pow(10, p + 1) < 5){
-                               d = 0;
+               if(cont) {
+                       if(typeof cont == "string") {
+                               cont = domConstruct.toDom(cont, node.ownerDocument);
+                       }
+                       if(!cont.nodeType && lang.isArrayLike(cont)) {
+                               // handle as enumerable, but it may shrink as we enumerate it
+                               for(var startlen=cont.length, i=0; i<cont.length; i=startlen==cont.length ? i+1 : 0) {
+                                       domConstruct.place( cont[i], node, "last");
+                               }
+                       } else {
+                               // pass nodes, documentFragments and unknowns through to dojo.place
+                               domConstruct.place(cont, node, "last");
                        }
-                       return round(v, p, m) + (v > 0 ? d : -d);
                }
-       })();
-}
 
-/*=====
-dojo.number.__FormatAbsoluteOptions = function(){
-       //      decimal: String?
-       //              the decimal separator
-       //      group: String?
-       //              the group separator
-       //      places: Number?|String?
-       //              number of decimal places.  the range "n,m" will format to m places.
-       //      round: Number?
-       //              5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
-       //              means don't round.
-       this.decimal = decimal;
-       this.group = group;
-       this.places = places;
-       this.round = round;
-}
-=====*/
+               // return DomNode
+               return node;
+       };
 
-dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){
-       // summary: 
-       //              Apply numeric pattern to absolute value using options. Gives no
-       //              consideration to local customs.
-       // value:
-       //              the number to be formatted, ignores sign
-       // pattern:
-       //              the number portion of a pattern (e.g. `#,##0.00`)
-       options = options || {};
-       if(options.places === true){options.places=0;}
-       if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit
+       // we wrap up the content-setting operation in a object
+       declare("dojo.html._ContentSetter", null,
+               {
+                       // node: DomNode|String
+                       //              An node which will be the parent element that we set content into
+                       node: "",
 
-       var patternParts = pattern.split("."),
-               comma = typeof options.places == "string" && options.places.indexOf(","),
-               maxPlaces = options.places;
-       if(comma){
-               maxPlaces = options.places.substring(comma + 1);
-       }else if(!(maxPlaces >= 0)){
-               maxPlaces = (patternParts[1] || []).length;
-       }
-       if(!(options.round < 0)){
-               value = dojo.number.round(value, maxPlaces, options.round);
-       }
+                       // content: String|DomNode|DomNode[]
+                       //              The content to be placed in the node. Can be an HTML string, a node reference, or a enumerable list of nodes
+                       content: "",
 
-       var valueParts = String(Math.abs(value)).split("."),
-               fractional = valueParts[1] || "";
-       if(patternParts[1] || options.places){
-               if(comma){
-                       options.places = options.places.substring(0, comma);
-               }
-               // Pad fractional with trailing zeros
-               var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1);
-               if(pad > fractional.length){
-                       valueParts[1] = dojo.string.pad(fractional, pad, '0', true);
-               }
+                       // id: String?
+                       //              Usually only used internally, and auto-generated with each instance
+                       id: "",
 
-               // Truncate fractional
-               if(maxPlaces < fractional.length){
-                       valueParts[1] = fractional.substr(0, maxPlaces);
-               }
-       }else{
-               if(valueParts[1]){ valueParts.pop(); }
-       }
+                       // cleanContent: Boolean
+                       //              Should the content be treated as a full html document,
+                       //              and the real content stripped of <html>, <body> wrapper before injection
+                       cleanContent: false,
 
-       // Pad whole with leading zeros
-       var patternDigits = patternParts[0].replace(',', '');
-       pad = patternDigits.indexOf("0");
-       if(pad != -1){
-               pad = patternDigits.length - pad;
-               if(pad > valueParts[0].length){
-                       valueParts[0] = dojo.string.pad(valueParts[0], pad);
-               }
+                       // extractContent: Boolean
+                       //              Should the content be treated as a full html document, and the real content stripped of <html>, <body> wrapper before injection
+                       extractContent: false,
 
-               // Truncate whole
-               if(patternDigits.indexOf("#") == -1){
-                       valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);
-               }
-       }
+                       // parseContent: Boolean
+                       //              Should the node by passed to the parser after the new content is set
+                       parseContent: false,
 
-       // Add group separators
-       var index = patternParts[0].lastIndexOf(','),
-               groupSize, groupSize2;
-       if(index != -1){
-               groupSize = patternParts[0].length - index - 1;
-               var remainder = patternParts[0].substr(0, index);
-               index = remainder.lastIndexOf(',');
-               if(index != -1){
-                       groupSize2 = remainder.length - index - 1;
-               }
-       }
-       var pieces = [];
-       for(var whole = valueParts[0]; whole;){
-               var off = whole.length - groupSize;
-               pieces.push((off > 0) ? whole.substr(off) : whole);
-               whole = (off > 0) ? whole.slice(0, off) : "";
-               if(groupSize2){
-                       groupSize = groupSize2;
-                       delete groupSize2;
-               }
-       }
-       valueParts[0] = pieces.reverse().join(options.group || ",");
+                       // parserScope: String
+                       //              Flag passed to parser.  Root for attribute names to search for.   If scopeName is dojo,
+                       //              will search for data-dojo-type (or dojoType).  For backwards compatibility
+                       //              reasons defaults to dojo._scopeName (which is "dojo" except when
+                       //              multi-version support is used, when it will be something like dojo16, dojo20, etc.)
+                       parserScope: dojo._scopeName,
 
-       return valueParts.join(options.decimal || ".");
-};
+                       // startup: Boolean
+                       //              Start the child widgets after parsing them.       Only obeyed if parseContent is true.
+                       startup: true,
 
-/*=====
-dojo.number.__RegexpOptions = function(){
-       //      pattern: String?
-       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-       //              with this string.  Default value is based on locale.  Overriding this property will defeat
-       //              localization.
-       //      type: String?
-       //              choose a format type based on the locale from the following:
-       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
-       //      locale: String?
-       //              override the locale used to determine formatting rules
-       //      strict: Boolean?
-       //              strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
-       //              Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
-       //      places: Number|String?
-       //              number of decimal places to accept: Infinity, a positive number, or
-       //              a range "n,m".  Defined by pattern or Infinity if pattern not provided.
-       this.pattern = pattern;
-       this.type = type;
-       this.locale = locale;
-       this.strict = strict;
-       this.places = places;
-}
-=====*/
-dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){
-       //      summary:
-       //              Builds the regular needed to parse a number
-       //      description:
-       //              Returns regular expression with positive and negative match, group
-       //              and decimal separators
-       return dojo.number._parseInfo(options).regexp; // String
-}
+                       // lifecyle methods
+                       constructor: function(/* Object */params, /* String|DomNode */node){
+                               //      summary:
+                               //              Provides a configurable, extensible object to wrap the setting on content on a node
+                               //              call the set() method to actually set the content..
 
-dojo.number._parseInfo = function(/*Object?*/options){
-       options = options || {};
-       var locale = dojo.i18n.normalizeLocale(options.locale),
-               bundle = dojo.i18n.getLocalization("dojo.cldr", "number", locale),
-               pattern = options.pattern || bundle[(options.type || "decimal") + "Format"],
-//TODO: memoize?
-               group = bundle.group,
-               decimal = bundle.decimal,
-               factor = 1;
+                               // the original params are mixed directly into the instance "this"
+                               lang.mixin(this, params || {});
 
-       if(pattern.indexOf('%') != -1){
-               factor /= 100;
-       }else if(pattern.indexOf('\u2030') != -1){
-               factor /= 1000; // per mille
-       }else{
-               var isCurrency = pattern.indexOf('\u00a4') != -1;
-               if(isCurrency){
-                       group = bundle.currencyGroup || group;
-                       decimal = bundle.currencyDecimal || decimal;
-               }
-       }
+                               // give precedence to params.node vs. the node argument
+                               // and ensure its a node, not an id string
+                               node = this.node = dom.byId( this.node || node );
 
-       //TODO: handle quoted escapes
-       var patternList = pattern.split(';');
-       if(patternList.length == 1){
-               patternList.push("-" + patternList[0]);
-       }
+                               if(!this.id){
+                                       this.id = [
+                                               "Setter",
+                                               (node) ? node.id || node.tagName : "",
+                                               idCounter++
+                                       ].join("_");
+                               }
+                       },
+                       set: function(/* String|DomNode|NodeList? */ cont, /* Object? */ params){
+                               // summary:
+                               //              front-end to the set-content sequence
+                               //      cont:
+                               //              An html string, node or enumerable list of nodes for insertion into the dom
+                               //              If not provided, the object's content property will be used
+                               if(undefined !== cont){
+                                       this.content = cont;
+                               }
+                               // in the re-use scenario, set needs to be able to mixin new configuration
+                               if(params){
+                                       this._mixin(params);
+                               }
 
-       var re = dojo.regexp.buildGroupRE(patternList, function(pattern){
-               pattern = "(?:"+dojo.regexp.escapeString(pattern, '.')+")";
-               return pattern.replace(dojo.number._numberPatternRE, function(format){
-                       var flags = {
-                               signed: false,
-                               separator: options.strict ? group : [group,""],
-                               fractional: options.fractional,
-                               decimal: decimal,
-                               exponent: false
-                               },
+                               this.onBegin();
+                               this.setContent();
+                               this.onEnd();
 
-                               parts = format.split('.'),
-                               places = options.places;
+                               return this.node;
+                       },
+                       setContent: function(){
+                               // summary:
+                               //              sets the content on the node
 
-                       // special condition for percent (factor != 1)
-                       // allow decimal places even if not specified in pattern
-                       if(parts.length == 1 && factor != 1){
-                           parts[1] = "###";
-                       }
-                       if(parts.length == 1 || places === 0){
-                               flags.fractional = false;
-                       }else{
-                               if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0') + 1 : Infinity; }
-                               if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified
-                               if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }
-                               flags.places = places;
-                       }
-                       var groups = parts[0].split(',');
-                       if(groups.length > 1){
-                               flags.groupSize = groups.pop().length;
-                               if(groups.length > 1){
-                                       flags.groupSize2 = groups.pop().length;
+                               var node = this.node;
+                               if(!node) {
+                                       // can't proceed
+                                       throw new Error(this.declaredClass + ": setContent given no node");
                                }
-                       }
-                       return "("+dojo.number._realNumberRegexp(flags)+")";
-               });
-       }, true);
+                               try{
+                                       node = dojo.html._setNodeContent(node, this.content);
+                               }catch(e){
+                                       // check if a domfault occurs when we are appending this.errorMessage
+                                       // like for instance if domNode is a UL and we try append a DIV
 
-       if(isCurrency){
-               // substitute the currency symbol for the placeholder in the pattern
-               re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){
-                       var prop = ["symbol", "currency", "displayName"][target.length-1],
-                               symbol = dojo.regexp.escapeString(options[prop] || options.currency || "");
-                       before = before ? "[\\s\\xa0]" : "";
-                       after = after ? "[\\s\\xa0]" : "";
-                       if(!options.strict){
-                               if(before){before += "*";}
-                               if(after){after += "*";}
-                               return "(?:"+before+symbol+after+")?";
-                       }
-                       return before+symbol+after;
-               });
-       }
+                                       // FIXME: need to allow the user to provide a content error message string
+                                       var errMess = this.onContentError(e);
+                                       try{
+                                               node.innerHTML = errMess;
+                                       }catch(e){
+                                               console.error('Fatal ' + this.declaredClass + '.setContent could not change content due to '+e.message, e);
+                                       }
+                               }
+                               // always put back the node for the next method
+                               this.node = node; // DomNode
+                       },
 
-//TODO: substitute localized sign/percent/permille/etc.?
+                       empty: function() {
+                               // summary
+                               //      cleanly empty out existing content
 
-       // normalize whitespace and return
-       return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object
-}
+                               // destroy any widgets from a previous run
+                               // NOTE: if you dont want this you'll need to empty
+                               // the parseResults array property yourself to avoid bad things happenning
+                               if(this.parseResults && this.parseResults.length) {
+                                       darray.forEach(this.parseResults, function(w) {
+                                               if(w.destroy){
+                                                       w.destroy();
+                                               }
+                                       });
+                                       delete this.parseResults;
+                               }
+                               // this is fast, but if you know its already empty or safe, you could
+                               // override empty to skip this step
+                               dojo.html._emptyNode(this.node);
+                       },
 
-/*=====
-dojo.number.__ParseOptions = function(){
-       //      pattern: String?
-       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-       //              with this string.  Default value is based on locale.  Overriding this property will defeat
-       //              localization.  Literal characters in patterns are not supported.
-       //      type: String?
-       //              choose a format type based on the locale from the following:
-       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
-       //      locale: String?
-       //              override the locale used to determine formatting rules
-       //      strict: Boolean?
-       //              strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
-       //              Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
-       //      fractional: Boolean?|Array?
-       //              Whether to include the fractional portion, where the number of decimal places are implied by pattern
-       //              or explicit 'places' parameter.  The value [true,false] makes the fractional portion optional.
-       this.pattern = pattern;
-       this.type = type;
-       this.locale = locale;
-       this.strict = strict;
-       this.fractional = fractional;
-}
-=====*/
-dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){
-       // summary:
-       //              Convert a properly formatted string to a primitive Number, using
-       //              locale-specific settings.
-       // description:
-       //              Create a Number from a string using a known localized pattern.
-       //              Formatting patterns are chosen appropriate to the locale
-       //              and follow the syntax described by
-       //              [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
-       //              Note that literal characters in patterns are not supported.
-       // expression:
-       //              A string representation of a Number
-       var info = dojo.number._parseInfo(options),
-               results = (new RegExp("^"+info.regexp+"$")).exec(expression);
-       if(!results){
-               return NaN; //NaN
-       }
-       var absoluteMatch = results[1]; // match for the positive expression
-       if(!results[1]){
-               if(!results[2]){
-                       return NaN; //NaN
-               }
-               // matched the negative pattern
-               absoluteMatch =results[2];
-               info.factor *= -1;
-       }
+                       onBegin: function(){
+                               // summary
+                               //              Called after instantiation, but before set();
+                               //              It allows modification of any of the object properties
+                               //              - including the node and content provided - before the set operation actually takes place
+                               //              This default implementation checks for cleanContent and extractContent flags to
+                               //              optionally pre-process html string content
+                               var cont = this.content;
 
-       // Transform it to something Javascript can parse as a number.  Normalize
-       // decimal point and strip out group separators or alternate forms of whitespace
-       absoluteMatch = absoluteMatch.
-               replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").
-               replace(info.decimal, ".");
-       // Adjust for negative sign, percent, etc. as necessary
-       return absoluteMatch * info.factor; //Number
-};
+                               if(lang.isString(cont)){
+                                       if(this.cleanContent){
+                                               cont = dojo.html._secureForInnerHtml(cont);
+                                       }
 
-/*=====
-dojo.number.__RealNumberRegexpFlags = function(){
-       //      places: Number?
-       //              The integer number of decimal places or a range given as "n,m".  If
-       //              not given, the decimal part is optional and the number of places is
-       //              unlimited.
-       //      decimal: String?
-       //              A string for the character used as the decimal point.  Default
-       //              is ".".
-       //      fractional: Boolean?|Array?
-       //              Whether decimal places are used.  Can be true, false, or [true,
-       //              false].  Default is [true, false] which means optional.
-       //      exponent: Boolean?|Array?
-       //              Express in exponential notation.  Can be true, false, or [true,
-       //              false]. Default is [true, false], (i.e. will match if the
-       //              exponential part is present are not).
-       //      eSigned: Boolean?|Array?
-       //              The leading plus-or-minus sign on the exponent.  Can be true,
-       //              false, or [true, false].  Default is [true, false], (i.e. will
-       //              match if it is signed or unsigned).  flags in regexp.integer can be
-       //              applied.
-       this.places = places;
-       this.decimal = decimal;
-       this.fractional = fractional;
-       this.exponent = exponent;
-       this.eSigned = eSigned;
-}
-=====*/
+                                       if(this.extractContent){
+                                               var match = cont.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);
+                                               if(match){ cont = match[1]; }
+                                       }
+                               }
 
-dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){
-       // summary:
-       //              Builds a regular expression to match a real number in exponential
-       //              notation
+                               // clean out the node and any cruft associated with it - like widgets
+                               this.empty();
 
-       // assign default values to missing parameters
-       flags = flags || {};
-       //TODO: use mixin instead?
-       if(!("places" in flags)){ flags.places = Infinity; }
-       if(typeof flags.decimal != "string"){ flags.decimal = "."; }
-       if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; }
-       if(!("exponent" in flags)){ flags.exponent = [true, false]; }
-       if(!("eSigned" in flags)){ flags.eSigned = [true, false]; }
+                               this.content = cont;
+                               return this.node; /* DomNode */
+                       },
 
-       var integerRE = dojo.number._integerRegexp(flags),
-               decimalRE = dojo.regexp.buildGroupRE(flags.fractional,
-               function(q){
-                       var re = "";
-                       if(q && (flags.places!==0)){
-                               re = "\\" + flags.decimal;
-                               if(flags.places == Infinity){ 
-                                       re = "(?:" + re + "\\d+)?"; 
-                               }else{
-                                       re += "\\d{" + flags.places + "}"; 
+                       onEnd: function(){
+                               // summary
+                               //              Called after set(), when the new content has been pushed into the node
+                               //              It provides an opportunity for post-processing before handing back the node to the caller
+                               //              This default implementation checks a parseContent flag to optionally run the dojo parser over the new content
+                               if(this.parseContent){
+                                       // populates this.parseResults if you need those..
+                                       this._parse();
                                }
-                       }
-                       return re;
-               },
-               true
-       );
-
-       var exponentRE = dojo.regexp.buildGroupRE(flags.exponent,
-               function(q){ 
-                       if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
-                       return ""; 
-               }
-       );
-
-       var realRE = integerRE + decimalRE;
-       // allow for decimals without integers, e.g. .25
-       if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}
-       return realRE + exponentRE; // String
-};
-
-/*=====
-dojo.number.__IntegerRegexpFlags = function(){
-       //      signed: Boolean?
-       //              The leading plus-or-minus sign. Can be true, false, or `[true,false]`.
-       //              Default is `[true, false]`, (i.e. will match if it is signed
-       //              or unsigned).
-       //      separator: String?
-       //              The character used as the thousands separator. Default is no
-       //              separator. For more than one symbol use an array, e.g. `[",", ""]`,
-       //              makes ',' optional.
-       //      groupSize: Number?
-       //              group size between separators
-       //      groupSize2: Number?
-       //              second grouping, where separators 2..n have a different interval than the first separator (for India)
-       this.signed = signed;
-       this.separator = separator;
-       this.groupSize = groupSize;
-       this.groupSize2 = groupSize2;
-}
-=====*/
-
-dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){
-       // summary: 
-       //              Builds a regular expression that matches an integer
+                               return this.node; /* DomNode */
+                       },
 
-       // assign default values to missing parameters
-       flags = flags || {};
-       if(!("signed" in flags)){ flags.signed = [true, false]; }
-       if(!("separator" in flags)){
-               flags.separator = "";
-       }else if(!("groupSize" in flags)){
-               flags.groupSize = 3;
-       }
+                       tearDown: function(){
+                               // summary
+                               //              manually reset the Setter instance if its being re-used for example for another set()
+                               // description
+                               //              tearDown() is not called automatically.
+                               //              In normal use, the Setter instance properties are simply allowed to fall out of scope
+                               //              but the tearDown method can be called to explicitly reset this instance.
+                               delete this.parseResults;
+                               delete this.node;
+                               delete this.content;
+                       },
 
-       var signRE = dojo.regexp.buildGroupRE(flags.signed,
-               function(q){ return q ? "[-+]" : ""; },
-               true
-       );
+                       onContentError: function(err){
+                               return "Error occured setting content: " + err;
+                       },
 
-       var numberRE = dojo.regexp.buildGroupRE(flags.separator,
-               function(sep){
-                       if(!sep){
-                               return "(?:\\d+)";
-                       }
+                       _mixin: function(params){
+                               // mix properties/methods into the instance
+                               // TODO: the intention with tearDown is to put the Setter's state
+                               // back to that of the original constructor (vs. deleting/resetting everything regardless of ctor params)
+                               // so we could do something here to move the original properties aside for later restoration
+                               var empty = {}, key;
+                               for(key in params){
+                                       if(key in empty){ continue; }
+                                       // TODO: here's our opportunity to mask the properties we dont consider configurable/overridable
+                                       // .. but history shows we'll almost always guess wrong
+                                       this[key] = params[key];
+                               }
+                       },
+                       _parse: function(){
+                               // summary:
+                               //              runs the dojo parser over the node contents, storing any results in this.parseResults
+                               //              Any errors resulting from parsing are passed to _onError for handling
 
-                       sep = dojo.regexp.escapeString(sep);
-                       if(sep == " "){ sep = "\\s"; }
-                       else if(sep == "\xa0"){ sep = "\\s\\xa0"; }
+                               var rootNode = this.node;
+                               try{
+                                       // store the results (widgets, whatever) for potential retrieval
+                                       var inherited = {};
+                                       darray.forEach(["dir", "lang", "textDir"], function(name){
+                                               if(this[name]){
+                                                       inherited[name] = this[name];
+                                               }
+                                       }, this);
+                                       this.parseResults = parser.parse({
+                                               rootNode: rootNode,
+                                               noStart: !this.startup,
+                                               inherited: inherited,
+                                               scope: this.parserScope
+                                       });
+                               }catch(e){
+                                       this._onError('Content', e, "Error parsing in _ContentSetter#"+this.id);
+                               }
+                       },
 
-                       var grp = flags.groupSize, grp2 = flags.groupSize2;
-                       //TODO: should we continue to enforce that numbers with separators begin with 1-9?  See #6933
-                       if(grp2){
-                               var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";
-                               return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;
+                       _onError: function(type, err, consoleText){
+                               // summary:
+                               //              shows user the string that is returned by on[type]Error
+                               //              overide/implement on[type]Error and return your own string to customize
+                               var errText = this['on' + type + 'Error'].call(this, err);
+                               if(consoleText){
+                                       console.error(consoleText, err);
+                               }else if(errText){ // a empty string won't change current content
+                                       dojo.html._setNodeContent(this.node, errText, true);
+                               }
                        }
-                       return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";
-               },
-               true
-       );
-
-       return signRE + numberRE; // String
-}
+       }); // end dojo.declare()
 
-}
+       dojo.html.set = function(/* DomNode */ node, /* String|DomNode|NodeList */ cont, /* Object? */ params){
+                       // summary:
+                       //              inserts (replaces) the given content into the given node. dojo.place(cont, node, "only")
+                       //              may be a better choice for simple HTML insertion.
+                       // description:
+                       //              Unless you need to use the params capabilities of this method, you should use
+                       //              dojo.place(cont, node, "only"). dojo.place() has more robust support for injecting
+                       //              an HTML string into the DOM, but it only handles inserting an HTML string as DOM
+                       //              elements, or inserting a DOM node. dojo.place does not handle NodeList insertions
+                       //              or the other capabilities as defined by the params object for this method.
+                       //      node:
+                       //              the parent element that will receive the content
+                       //      cont:
+                       //              the content to be set on the parent element.
+                       //              This can be an html string, a node reference or a NodeList, dojo.NodeList, Array or other enumerable list of nodes
+                       //      params:
+                       //              Optional flags/properties to configure the content-setting. See dojo.html._ContentSetter
+                       //      example:
+                       //              A safe string/node/nodelist content replacement/injection with hooks for extension
+                       //              Example Usage:
+                       //              dojo.html.set(node, "some string");
+                       //              dojo.html.set(node, contentNode, {options});
+                       //              dojo.html.set(node, myNode.childNodes, {options});
+               if(undefined == cont){
+                       console.warn("dojo.html.set: no cont argument provided, using empty string");
+                       cont = "";
+               }
+               if(!params){
+                       // simple and fast
+                       return dojo.html._setNodeContent(node, cont, true);
+               }else{
+                       // more options but slower
+                       // note the arguments are reversed in order, to match the convention for instantiation via the parser
+                       var op = new dojo.html._ContentSetter(lang.mixin(
+                                       params,
+                                       { content: cont, node: node }
+                       ));
+                       return op.set();
+               }
+       };
 
-if(!dojo._hasResource["dijit.ProgressBar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.ProgressBar"] = true;
-dojo.provide("dijit.ProgressBar");
+       return dojo.html;
+});
 
+},
+'dijit/_PaletteMixin':function(){
+define("dijit/_PaletteMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-class", // domClass.add domClass.remove
+       "dojo/dom-construct", // domConstruct.create domConstruct.place
+       "dojo/_base/event", // event.stop
+       "dojo/keys", // keys
+       "dojo/_base/lang", // lang.getObject
+       "./_CssStateMixin",
+       "./focus",
+       "./typematic"
+], function(declare, domAttr, domClass, domConstruct, event, keys, lang, _CssStateMixin, focus, typematic){
 
+/*=====
+       var _CssStateMixin = dijit._CssStateMixin;
+=====*/
 
+// module:
+//             dijit/_PaletteMixin
+// summary:
+//             A keyboard accessible palette, for picking a color/emoticon/etc.
 
+return declare("dijit._PaletteMixin", [_CssStateMixin], {
+       // summary:
+       //              A keyboard accessible palette, for picking a color/emoticon/etc.
+       // description:
+       //              A mixin for a grid showing various entities, so the user can pick a certain entity.
 
+       // defaultTimeout: Number
+       //              Number of milliseconds before a held key or button becomes typematic
+       defaultTimeout: 500,
 
+       // timeoutChangeRate: Number
+       //              Fraction of time used to change the typematic timer between events
+       //              1.0 means that each typematic event fires at defaultTimeout intervals
+       //              < 1.0 means that each typematic event fires at an increasing faster rate
+       timeoutChangeRate: 0.90,
 
-dojo.declare("dijit.ProgressBar", [dijit._Widget, dijit._Templated], {
-       // summary:
-       //              A progress indication widget, showing the amount completed
-       //              (often the percentage completed) of a task.
-       //
-       // example:
-       // |    <div dojoType="ProgressBar"
-       // |             places="0"
-       // |             progress="..." maximum="...">
-       // |    </div>
-       //
-       // description:
-       //              Note that the progress bar is updated via (a non-standard)
-       //              update() method, rather than via attr() like other widgets.
+       // value: String
+       //              Currently selected color/emoticon/etc.
+       value: "",
 
-       // progress: [const] String (Percentage or Number)
-       //              Number or percentage indicating amount of task completed.
-       //              With "%": percentage value, 0% <= progress <= 100%, or
-       //              without "%": absolute value, 0 <= progress <= maximum
-       // TODO: rename to value for 2.0
-       progress: "0",
+       // _selectedCell: [private] Integer
+       //              Index of the currently selected cell. Initially, none selected
+       _selectedCell: -1,
 
-       // maximum: [const] Float
-       //              Max sample number
-       maximum: 100,
+/*=====
+       // _currentFocus: [private] DomNode
+       //              The currently focused cell (if the palette itself has focus), or otherwise
+       //              the cell to be focused when the palette itself gets focus.
+       //              Different from value, which represents the selected (i.e. clicked) cell.
+       _currentFocus: null,
+=====*/
 
-       // places: [const] Number
-       //              Number of places to show in values; 0 by default
-       places: 0,
+/*=====
+       // _xDim: [protected] Integer
+       //              This is the number of cells horizontally across.
+       _xDim: null,
+=====*/
 
-       // indeterminate: [const] Boolean
-       //              If false: show progress value (number or percentage).
-       //              If true: show that a process is underway but that the amount completed is unknown.
-       indeterminate: false,
+/*=====
+       // _yDim: [protected] Integer
+       //              This is the number of cells vertically down.
+       _yDim: null,
+=====*/
 
-       // name: String
-       //              this is the field name (for a form) if set. This needs to be set if you want to use
-       //              this widget in a dijit.form.Form widget (such as dijit.Dialog)
-       name: '',
+       // tabIndex: String
+       //              Widget tab index.
+       tabIndex: "0",
 
-       templateString: dojo.cache("dijit", "templates/ProgressBar.html", "<div class=\"dijitProgressBar dijitProgressBarEmpty\"\n\t><div waiRole=\"progressbar\" dojoAttachPoint=\"internalProgress\" class=\"dijitProgressBarFull\"\n\t\t><div class=\"dijitProgressBarTile\"></div\n\t\t><span style=\"visibility:hidden\">&nbsp;</span\n\t></div\n\t><div dojoAttachPoint=\"label\" class=\"dijitProgressBarLabel\" id=\"${id}_label\">&nbsp;</div\n\t><img dojoAttachPoint=\"indeterminateHighContrastImage\" class=\"dijitProgressBarIndeterminateHighContrastImage\" alt=\"\"\n/></div>\n"),
+       // cellClass: [protected] String
+       //              CSS class applied to each cell in the palette
+       cellClass: "dijitPaletteCell",
 
-       // _indeterminateHighContrastImagePath: [private] dojo._URL
-       //              URL to image to use for indeterminate progress bar when display is in high contrast mode
-       _indeterminateHighContrastImagePath:
-               dojo.moduleUrl("dijit", "themes/a11y/indeterminate_progress.gif"),
+       // dyeClass: [protected] String
+       //       Name of javascript class for Object created for each cell of the palette.
+       //       dyeClass should implements dijit.Dye interface
+       dyeClass: '',
+       
+       // summary: String
+       //              Localized summary for the palette table
+       summary: '',
+       _setSummaryAttr: "paletteTableNode",
 
-       // public functions
-       postCreate: function(){
-               this.inherited(arguments);
-               this.indeterminateHighContrastImage.setAttribute("src",
-                       this._indeterminateHighContrastImagePath.toString());
-               this.update();
+       _dyeFactory: function(value /*===== , row, col =====*/){
+               // summary:
+               //              Return instance of dijit.Dye for specified cell of palette
+               // tags:
+               //              extension
+               var dyeClassObj = lang.getObject(this.dyeClass);
+               return new dyeClassObj(value);
        },
 
-       update: function(/*Object?*/attributes){
+       _preparePalette: function(choices, titles) {
                // summary:
-               //              Change attributes of ProgressBar, similar to attr(hash).
-               //
-               // attributes:
-               //              May provide progress and/or maximum properties on this parameter;
-               //              see attribute specs for details.
-               //
-               // example:
-               //      |       myProgressBar.update({'indeterminate': true});
-               //      |       myProgressBar.update({'progress': 80});
+               //              Subclass must call _preparePalette() from postCreate(), passing in the tooltip
+               //              for each cell
+               // choices: String[][]
+               //              id's for each cell of the palette, used to create Dye JS object for each cell
+               // titles: String[]
+               //              Localized tooltip for each cell
 
-               // TODO: deprecate this method and use set() instead
+               this._cells = [];
+               var url = this._blankGif;
 
-               dojo.mixin(this, attributes || {});
-               var tip = this.internalProgress;
-               var percent = 1, classFunc;
-               if(this.indeterminate){
-                       classFunc = "addClass";
-                       dijit.removeWaiState(tip, "valuenow");
-                       dijit.removeWaiState(tip, "valuemin");
-                       dijit.removeWaiState(tip, "valuemax");
-               }else{
-                       classFunc = "removeClass";
-                       if(String(this.progress).indexOf("%") != -1){
-                               percent = Math.min(parseFloat(this.progress)/100, 1);
-                               this.progress = percent * this.maximum;
-                       }else{
-                               this.progress = Math.min(this.progress, this.maximum);
-                               percent = this.progress / this.maximum;
+               this.connect(this.gridNode, "ondijitclick", "_onCellClick");
+
+               for(var row=0; row < choices.length; row++){
+                       var rowNode = domConstruct.create("tr", {tabIndex: "-1"}, this.gridNode);
+                       for(var col=0; col < choices[row].length; col++){
+                               var value = choices[row][col];
+                               if(value){
+                                       var cellObject = this._dyeFactory(value, row, col);
+
+                                       var cellNode = domConstruct.create("td", {
+                                               "class": this.cellClass,
+                                               tabIndex: "-1",
+                                               title: titles[value],
+                                               role: "gridcell"
+                                       });
+
+                                       // prepare cell inner structure
+                                       cellObject.fillCell(cellNode, url);
+
+                                       domConstruct.place(cellNode, rowNode);
+
+                                       cellNode.index = this._cells.length;
+
+                                       // save cell info into _cells
+                                       this._cells.push({node:cellNode, dye:cellObject});
+                               }
                        }
-                       var text = this.report(percent);
-                       this.label.firstChild.nodeValue = text;
-                       dijit.setWaiState(tip, "describedby", this.label.id);
-                       dijit.setWaiState(tip, "valuenow", this.progress);
-                       dijit.setWaiState(tip, "valuemin", 0);
-                       dijit.setWaiState(tip, "valuemax", this.maximum);
                }
-               dojo[classFunc](this.domNode, "dijitProgressBarIndeterminate");
-               tip.style.width = (percent * 100) + "%";
-               this.onChange();
-       },
+               this._xDim = choices[0].length;
+               this._yDim = choices.length;
 
-       _setValueAttr: function(v){
-               if(v == Infinity){
-                       this.update({indeterminate:true});
-               }else{
-                       this.update({indeterminate:false, progress:v});
+               // Now set all events
+               // The palette itself is navigated to with the tab key on the keyboard
+               // Keyboard navigation within the Palette is with the arrow keys
+               // Spacebar selects the cell.
+               // For the up key the index is changed by negative the x dimension.
+
+               var keyIncrementMap = {
+                       UP_ARROW: -this._xDim,
+                       // The down key the index is increase by the x dimension.
+                       DOWN_ARROW: this._xDim,
+                       // Right and left move the index by 1.
+                       RIGHT_ARROW: this.isLeftToRight() ? 1 : -1,
+                       LEFT_ARROW: this.isLeftToRight() ? -1 : 1
+               };
+               for(var key in keyIncrementMap){
+                       this._connects.push(
+                               typematic.addKeyListener(
+                                       this.domNode,
+                                       {charOrCode:keys[key], ctrlKey:false, altKey:false, shiftKey:false},
+                                       this,
+                                       function(){
+                                               var increment = keyIncrementMap[key];
+                                               return function(count){ this._navigateByKey(increment, count); };
+                                       }(),
+                                       this.timeoutChangeRate,
+                                       this.defaultTimeout
+                               )
+                       );
                }
        },
 
-       _getValueAttr: function(){
-               return this.progress;
+       postCreate: function(){
+               this.inherited(arguments);
+
+               // Set initial navigable node.
+               this._setCurrent(this._cells[0].node);
        },
 
-       report: function(/*float*/percent){
+       focus: function(){
                // summary:
-               //              Generates message to show inside progress bar (normally indicating amount of task completed).
-               //              May be overridden.
-               // tags:
-               //              extension
+               //              Focus this widget.  Puts focus on the most recently focused cell.
 
-               return dojo.number.format(percent, { type: "percent", places: this.places, locale: this.lang });
+               // The cell already has tabIndex set, just need to set CSS and focus it
+               focus.focus(this._currentFocus);
        },
 
-       onChange: function(){
+       _onCellClick: function(/*Event*/ evt){
                // summary:
-               //              Callback fired when progress updates.
+               //              Handler for click, enter key & space key. Selects the cell.
+               // evt:
+               //              The event.
                // tags:
-               //              progress
-       }
-});
+               //              private
 
-}
+               var target = evt.target;
 
-if(!dojo._hasResource["dijit.ToolbarSeparator"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.ToolbarSeparator"] = true;
-dojo.provide("dijit.ToolbarSeparator");
+               // Find TD associated with click event.   For ColorPalette user likely clicked IMG inside of TD
+               while(target.tagName != "TD"){
+                       if(!target.parentNode || target == this.gridNode){      // probably can never happen, but just in case
+                               return;
+                       }
+                       target = target.parentNode;
+               }
 
+               var value = this._getDye(target).getValue();
 
+               // First focus the clicked cell, and then send onChange() notification.
+               // onChange() (via _setValueAttr) must be after the focus call, because
+               // it may trigger a refocus to somewhere else (like the Editor content area), and that
+               // second focus should win.
+               this._setCurrent(target);
+               focus.focus(target);
+               this._setValueAttr(value, true);
 
+               event.stop(evt);
+       },
 
-dojo.declare("dijit.ToolbarSeparator",
-               [ dijit._Widget, dijit._Templated ],
-               {
+       _setCurrent: function(/*DomNode*/ node){
                // summary:
-               //              A spacer between two `dijit.Toolbar` items
-               templateString: '<div class="dijitToolbarSeparator dijitInline" waiRole="presentation"></div>',
-               postCreate: function(){ dojo.setSelectable(this.domNode, false); },
-               isFocusable: function(){
-                       // summary:
-                       //              This widget isn't focusable, so pass along that fact.
-                       // tags:
-                       //              protected
-                       return false;
+               //              Sets which node is the focused cell.
+               // description:
+               //              At any point in time there's exactly one
+               //              cell with tabIndex != -1.   If focus is inside the palette then
+               //              focus is on that cell.
+               //
+               //              After calling this method, arrow key handlers and mouse click handlers
+               //              should focus the cell in a setTimeout().
+               // tags:
+               //              protected
+               if("_currentFocus" in this){
+                       // Remove tabIndex on old cell
+                       domAttr.set(this._currentFocus, "tabIndex", "-1");
                }
 
-       });
+               // Set tabIndex of new cell
+               this._currentFocus = node;
+               if(node){
+                       domAttr.set(node, "tabIndex", this.tabIndex);
+               }
+       },
 
+       _setValueAttr: function(value, priorityChange){
+               // summary:
+               //              This selects a cell. It triggers the onChange event.
+               // value: String value of the cell to select
+               // tags:
+               //              protected
+               // priorityChange:
+               //              Optional parameter used to tell the select whether or not to fire
+               //              onChange event.
 
+               // clear old selected cell
+               if(this._selectedCell >= 0){
+                       domClass.remove(this._cells[this._selectedCell].node, this.cellClass + "Selected");
+               }
+               this._selectedCell = -1;
 
-}
+               // search for cell matching specified value
+               if(value){
+                       for(var i = 0; i < this._cells.length; i++){
+                               if(value == this._cells[i].dye.getValue()){
+                                       this._selectedCell = i;
+                                       domClass.add(this._cells[i].node, this.cellClass + "Selected");
+                                       break;
+                               }
+                       }
+               }
 
-if(!dojo._hasResource["dijit.Toolbar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Toolbar"] = true;
-dojo.provide("dijit.Toolbar");
+               // record new value, or null if no matching cell
+               this._set("value", this._selectedCell >= 0 ? value : null);
 
+               if(priorityChange || priorityChange === undefined){
+                       this.onChange(value);
+               }
+       },
 
+       onChange: function(/*===== value =====*/){
+               // summary:
+               //              Callback when a cell is selected.
+               // value: String
+               //              Value corresponding to cell.
+       },
 
+       _navigateByKey: function(increment, typeCount){
+               // summary:
+               //              This is the callback for typematic.
+               //              It changes the focus and the highlighed cell.
+               // increment:
+               //              How much the key is navigated.
+               // typeCount:
+               //              How many times typematic has fired.
+               // tags:
+               //              private
 
+               // typecount == -1 means the key is released.
+               if(typeCount == -1){ return; }
 
-dojo.declare("dijit.Toolbar",
-       [dijit._Widget, dijit._Templated, dijit._KeyNavContainer],
-       {
-       // summary:
-       //              A Toolbar widget, used to hold things like `dijit.Editor` buttons
+               var newFocusIndex = this._currentFocus.index + increment;
+               if(newFocusIndex < this._cells.length && newFocusIndex > -1){
+                       var focusNode = this._cells[newFocusIndex].node;
+                       this._setCurrent(focusNode);
 
-       templateString:
-               '<div class="dijit" waiRole="toolbar" tabIndex="${tabIndex}" dojoAttachPoint="containerNode">' +
-               //      '<table style="table-layout: fixed" class="dijitReset dijitToolbarTable">' + // factor out style
-               //              '<tr class="dijitReset" dojoAttachPoint="containerNode"></tr>'+
-               //      '</table>' +
-               '</div>',
+                       // Actually focus the node, for the benefit of screen readers.
+                       // Use setTimeout because IE doesn't like changing focus inside of an event handler
+                       setTimeout(lang.hitch(dijit, "focus", focusNode), 0);
+               }
+       },
 
-       baseClass: "dijitToolbar",
+       _getDye: function(/*DomNode*/ cell){
+               // summary:
+               //              Get JS object for given cell DOMNode
 
-       postCreate: function(){
-               this.connectKeyNavHandlers(
-                       this.isLeftToRight() ? [dojo.keys.LEFT_ARROW] : [dojo.keys.RIGHT_ARROW],
-                       this.isLeftToRight() ? [dojo.keys.RIGHT_ARROW] : [dojo.keys.LEFT_ARROW]
-               );
-               this.inherited(arguments);
-       },
+               return this._cells[cell.index].dye;
+       }
+});
 
-       startup: function(){
-               if(this._started){ return; }
+/*=====
+declare("dijit.Dye",
+       null,
+       {
+               // summary:
+               //              Interface for the JS Object associated with a palette cell (i.e. DOMNode)
 
-               this.startupKeyNavChildren();
+               constructor: function(alias, row, col){
+                       // summary:
+                       //              Initialize according to value or alias like "white"
+                       // alias: String
+               },
 
-               this.inherited(arguments);
+               getValue: function(){
+                       // summary:
+                       //              Return "value" of cell; meaning of "value" varies by subclass.
+                       // description:
+                       //              For example color hex value, emoticon ascii value etc, entity hex value.
+               },
+
+               fillCell: function(cell, blankGif){
+                       // summary:
+                       //              Add cell DOMNode inner structure
+                       //      cell: DomNode
+                       //              The surrounding cell
+                       //      blankGif: String
+                       //              URL for blank cell image
+               }
        }
-}
 );
+=====*/
 
-// For back-compat, remove for 2.0
+});
 
+},
+'dijit/form/ValidationTextBox':function(){
+require({cache:{
+'url:dijit/form/templates/ValidationTextBox.html':"<div class=\"dijit dijitReset dijitInline dijitLeft\"\n\tid=\"widget_${id}\" role=\"presentation\"\n\t><div class='dijitReset dijitValidationContainer'\n\t\t><input class=\"dijitReset dijitInputField dijitValidationIcon dijitValidationInner\" value=\"&#935; \" type=\"text\" tabIndex=\"-1\" readonly=\"readonly\" role=\"presentation\"\n\t/></div\n\t><div class=\"dijitReset dijitInputField dijitInputContainer\"\n\t\t><input class=\"dijitReset dijitInputInner\" data-dojo-attach-point='textbox,focusNode' autocomplete=\"off\"\n\t\t\t${!nameAttrSetting} type='${type}'\n\t/></div\n></div>\n"}});
+define("dijit/form/ValidationTextBox", [
+       "dojo/_base/declare", // declare
+       "dojo/i18n", // i18n.getLocalization
+       "./TextBox",
+       "../Tooltip",
+       "dojo/text!./templates/ValidationTextBox.html",
+       "dojo/i18n!./nls/validate"
+], function(declare, i18n, TextBox, Tooltip, template){
 
-}
+/*=====
+       var Tooltip = dijit.Tooltip;
+       var TextBox = dijit.form.TextBox;
+=====*/
 
-if(!dojo._hasResource["dojo.DeferredList"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.DeferredList"] = true;
-dojo.provide("dojo.DeferredList");
-dojo.DeferredList = function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){
+       // module:
+       //              dijit/form/ValidationTextBox
        // summary:
-       //              Provides event handling for a group of Deferred objects.
-       // description:
-       //              DeferredList takes an array of existing deferreds and returns a new deferred of its own
-       //              this new deferred will typically have its callback fired when all of the deferreds in
-       //              the given list have fired their own deferreds.  The parameters `fireOnOneCallback` and
-       //              fireOnOneErrback, will fire before all the deferreds as appropriate
-       //
-       //      list:
-       //              The list of deferreds to be synchronizied with this DeferredList
-       //      fireOnOneCallback:
-       //              Will cause the DeferredLists callback to be fired as soon as any
-       //              of the deferreds in its list have been fired instead of waiting until
-       //              the entire list has finished
-       //      fireonOneErrback:
-       //              Will cause the errback to fire upon any of the deferreds errback
-       //      canceller:
-       //              A deferred canceller function, see dojo.Deferred
-       var resultList = [];
-       dojo.Deferred.call(this);
-       var self = this;
-       if(list.length === 0 && !fireOnOneCallback){
-               this.resolve([0, []]);
-       }
-       var finished = 0;
-       dojo.forEach(list, function(item, i){
-               item.then(function(result){
-                       if(fireOnOneCallback){
-                               self.resolve([i, result]);
-                       }else{
-                               addResult(true, result);
-                       }
-               },function(error){
-                       if(fireOnOneErrback){
-                               self.reject(error);
-                       }else{
-                               addResult(false, error);
-                       }
-                       if(consumeErrors){
-                               return null;
-                       }
-                       throw error;
-               });
-               function addResult(succeeded, result){
-                       resultList[i] = [succeeded, result];
-                       finished++;
-                       if(finished === list.length){
-                               self.resolve(resultList);
-                       }
-                       
-               }
-       });
-};
-dojo.DeferredList.prototype = new dojo.Deferred();
-
-dojo.DeferredList.prototype.gatherResults= function(deferredList){
-       // summary:     
-       //      Gathers the results of the deferreds for packaging
-       //      as the parameters to the Deferred Lists' callback
-
-       var d = new dojo.DeferredList(deferredList, false, true, false);
-       d.addCallback(function(results){
-               var ret = [];
-               dojo.forEach(results, function(result){
-                       ret.push(result[1]);
-               });
-               return ret;
-       });
-       return d;
-};
+       //              Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
 
-}
 
-if(!dojo._hasResource["dijit.tree.TreeStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree.TreeStoreModel"] = true;
-dojo.provide("dijit.tree.TreeStoreModel");
+       /*=====
+               dijit.form.ValidationTextBox.__Constraints = function(){
+                       // locale: String
+                       //              locale used for validation, picks up value from this widget's lang attribute
+                       // _flags_: anything
+                       //              various flags passed to regExpGen function
+                       this.locale = "";
+                       this._flags_ = "";
+               }
+       =====*/
 
-dojo.declare(
-               "dijit.tree.TreeStoreModel",
-               null,
-       {
+       return declare("dijit.form.ValidationTextBox", TextBox, {
                // summary:
-               //              Implements dijit.Tree.model connecting to a store with a single
-               //              root item.  Any methods passed into the constructor will override
-               //              the ones defined here.
+               //              Base class for textbox widgets with the ability to validate content of various types and provide user feedback.
+               // tags:
+               //              protected
 
-               // store: dojo.data.Store
-               //              Underlying store
-               store: null,
+               templateString: template,
+               baseClass: "dijitTextBox dijitValidationTextBox",
 
-               // childrenAttrs: String[]
-               //              One or more attribute names (attributes in the dojo.data item) that specify that item's children
-               childrenAttrs: ["children"],
+               // required: Boolean
+               //              User is required to enter data into this field.
+               required: false,
 
-               // newItemIdAttr: String
-               //              Name of attribute in the Object passed to newItem() that specifies the id.
-               //
-               //              If newItemIdAttr is set then it's used when newItem() is called to see if an
-               //              item with the same id already exists, and if so just links to the old item
-               //              (so that the old item ends up with two parents).
+               // promptMessage: String
+               //              If defined, display this hint string immediately on focus to the textbox, if empty.
+               //              Also displays if the textbox value is Incomplete (not yet valid but will be with additional input).
+               //              Think of this like a tooltip that tells the user what to do, not an error message
+               //              that tells the user what they've done wrong.
                //
-               //              Setting this to null or "" will make every drop create a new item.
-               newItemIdAttr: "id",
+               //              Message disappears when user starts typing.
+               promptMessage: "",
 
-               // labelAttr: String
-               //              If specified, get label for tree node from this attribute, rather
-               //              than by calling store.getLabel()
-               labelAttr: "",
+               // invalidMessage: String
+               //              The message to display if value is invalid.
+               //              The translated string value is read from the message file by default.
+               //              Set to "" to use the promptMessage instead.
+               invalidMessage: "$_unset_$",
 
-               // root: [readonly] dojo.data.Item
-               //              Pointer to the root item (read only, not a parameter)
-               root: null,
+               // missingMessage: String
+               //              The message to display if value is empty and the field is required.
+               //              The translated string value is read from the message file by default.
+               //              Set to "" to use the invalidMessage instead.
+               missingMessage: "$_unset_$",
 
-               // query: anything
-               //              Specifies datastore query to return the root item for the tree.
-               //              Must only return a single item.   Alternately can just pass in pointer
-               //              to root item.
-               // example:
-               //      |       {id:'ROOT'}
-               query: null,
+               // message: String
+               //              Currently error/prompt message.
+               //              When using the default tooltip implementation, this will only be
+               //              displayed when the field is focused.
+               message: "",
 
-               // deferItemLoadingUntilExpand: Boolean
-               //              Setting this to true will cause the TreeStoreModel to defer calling loadItem on nodes
-               //              until they are expanded. This allows for lazying loading where only one
-               //              loadItem (and generally one network call, consequently) per expansion
-               //              (rather than one for each child).
-               //              This relies on partial loading of the children items; each children item of a
-               //              fully loaded item should contain the label and info about having children.
-               deferItemLoadingUntilExpand: false,
+               // constraints: dijit.form.ValidationTextBox.__Constraints
+               //              user-defined object needed to pass parameters to the validator functions
+               constraints: {},
 
-               constructor: function(/* Object */ args){
+               // regExp: [extension protected] String
+               //              regular expression string used to validate the input
+               //              Do not specify both regExp and regExpGen
+               regExp: ".*",
+
+               regExpGen: function(/*dijit.form.ValidationTextBox.__Constraints*/ /*===== constraints =====*/){
                        // summary:
-                       //              Passed the arguments listed above (store, etc)
+                       //              Overridable function used to generate regExp when dependent on constraints.
+                       //              Do not specify both regExp and regExpGen.
                        // tags:
-                       //              private
+                       //              extension protected
+                       return this.regExp; // String
+               },
 
-                       dojo.mixin(this, args);
+               // state: [readonly] String
+               //              Shows current state (ie, validation result) of input (""=Normal, Incomplete, or Error)
+               state: "",
 
-                       this.connects = [];
+               // tooltipPosition: String[]
+               //              See description of `dijit.Tooltip.defaultPosition` for details on this parameter.
+               tooltipPosition: [],
 
-                       var store = this.store;
-                       if(!store.getFeatures()['dojo.data.api.Identity']){
-                               throw new Error("dijit.Tree: store must support dojo.data.Identity");
-                       }
+               _setValueAttr: function(){
+                       // summary:
+                       //              Hook so set('value', ...) works.
+                       this.inherited(arguments);
+                       this.validate(this.focused);
+               },
 
-                       // if the store supports Notification, subscribe to the notification events
-                       if(store.getFeatures()['dojo.data.api.Notification']){
-                               this.connects = this.connects.concat([
-                                       dojo.connect(store, "onNew", this, "onNewItem"),
-                                       dojo.connect(store, "onDelete", this, "onDeleteItem"),
-                                       dojo.connect(store, "onSet", this, "onSetItem")
-                               ]);
-                       }
+               validator: function(/*anything*/ value, /*dijit.form.ValidationTextBox.__Constraints*/ constraints){
+                       // summary:
+                       //              Overridable function used to validate the text input against the regular expression.
+                       // tags:
+                       //              protected
+                       return (new RegExp("^(?:" + this.regExpGen(constraints) + ")"+(this.required?"":"?")+"$")).test(value) &&
+                               (!this.required || !this._isEmpty(value)) &&
+                               (this._isEmpty(value) || this.parse(value, constraints) !== undefined); // Boolean
                },
 
-               destroy: function(){
-                       dojo.forEach(this.connects, dojo.disconnect);
-                       // TODO: should cancel any in-progress processing of getRoot(), getChildren()
+               _isValidSubset: function(){
+                       // summary:
+                       //              Returns true if the value is either already valid or could be made valid by appending characters.
+                       //              This is used for validation while the user [may be] still typing.
+                       return this.textbox.value.search(this._partialre) == 0;
                },
 
-               // =======================================================================
-               // Methods for traversing hierarchy
+               isValid: function(/*Boolean*/ /*===== isFocused =====*/){
+                       // summary:
+                       //              Tests if value is valid.
+                       //              Can override with your own routine in a subclass.
+                       // tags:
+                       //              protected
+                       return this.validator(this.textbox.value, this.constraints);
+               },
 
-               getRoot: function(onItem, onError){
+               _isEmpty: function(value){
                        // summary:
-                       //              Calls onItem with the root item for the tree, possibly a fabricated item.
-                       //              Calls onError on error.
-                       if(this.root){
-                               onItem(this.root);
-                       }else{
-                               this.store.fetch({
-                                       query: this.query,
-                                       onComplete: dojo.hitch(this, function(items){
-                                               if(items.length != 1){
-                                                       throw new Error(this.declaredClass + ": query " + dojo.toJson(this.query) + " returned " + items.length +
-                                                               " items, but must return exactly one item");
-                                               }
-                                               this.root = items[0];
-                                               onItem(this.root);
-                                       }),
-                                       onError: onError
-                               });
-                       }
+                       //              Checks for whitespace
+                       return (this.trim ? /^\s*$/ : /^$/).test(value); // Boolean
                },
 
-               mayHaveChildren: function(/*dojo.data.Item*/ item){
+               getErrorMessage: function(/*Boolean*/ /*===== isFocused =====*/){
                        // summary:
-                       //              Tells if an item has or may have children.  Implementing logic here
-                       //              avoids showing +/- expando icon for nodes that we know don't have children.
-                       //              (For efficiency reasons we may not want to check if an element actually
-                       //              has children until user clicks the expando node)
-                       return dojo.some(this.childrenAttrs, function(attr){
-                               return this.store.hasAttribute(item, attr);
-                       }, this);
+                       //              Return an error message to show if appropriate
+                       // tags:
+                       //              protected
+                       return (this.required && this._isEmpty(this.textbox.value)) ? this.missingMessage : this.invalidMessage; // String
                },
 
-               getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete, /*function*/ onError){
+               getPromptMessage: function(/*Boolean*/ /*===== isFocused =====*/){
                        // summary:
-                       //              Calls onComplete() with array of child items of given parent item, all loaded.
+                       //              Return a hint message to show when widget is first focused
+                       // tags:
+                       //              protected
+                       return this.promptMessage; // String
+               },
 
-                       var store = this.store;
-                       if(!store.isItemLoaded(parentItem)){
-                               // The parent is not loaded yet, we must be in deferItemLoadingUntilExpand
-                               // mode, so we will load it and just return the children (without loading each
-                               // child item)
-                               var getChildren = dojo.hitch(this, arguments.callee);
-                               store.loadItem({
-                                       item: parentItem,
-                                       onItem: function(parentItem){
-                                               getChildren(parentItem, onComplete, onError);
-                                       },
-                                       onError: onError
-                               });
-                               return;
-                       }
-                       // get children of specified item
-                       var childItems = [];
-                       for(var i=0; i<this.childrenAttrs.length; i++){
-                               var vals = store.getValues(parentItem, this.childrenAttrs[i]);
-                               childItems = childItems.concat(vals);
-                       }
+               _maskValidSubsetError: true,
+               validate: function(/*Boolean*/ isFocused){
+                       // summary:
+                       //              Called by oninit, onblur, and onkeypress.
+                       // description:
+                       //              Show missing or invalid messages if appropriate, and highlight textbox field.
+                       // tags:
+                       //              protected
+                       var message = "";
+                       var isValid = this.disabled || this.isValid(isFocused);
+                       if(isValid){ this._maskValidSubsetError = true; }
+                       var isEmpty = this._isEmpty(this.textbox.value);
+                       var isValidSubset = !isValid && isFocused && this._isValidSubset();
+                       this._set("state", isValid ? "" : (((((!this._hasBeenBlurred || isFocused) && isEmpty) || isValidSubset) && this._maskValidSubsetError) ? "Incomplete" : "Error"));
+                       this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
 
-                       // count how many items need to be loaded
-                       var _waitCount = 0;
-                       if(!this.deferItemLoadingUntilExpand){
-                               dojo.forEach(childItems, function(item){ if(!store.isItemLoaded(item)){ _waitCount++; } });
+                       if(this.state == "Error"){
+                               this._maskValidSubsetError = isFocused && isValidSubset; // we want the error to show up after a blur and refocus
+                               message = this.getErrorMessage(isFocused);
+                       }else if(this.state == "Incomplete"){
+                               message = this.getPromptMessage(isFocused); // show the prompt whenever the value is not yet complete
+                               this._maskValidSubsetError = !this._hasBeenBlurred || isFocused; // no Incomplete warnings while focused
+                       }else if(isEmpty){
+                               message = this.getPromptMessage(isFocused); // show the prompt whenever there's no error and no text
                        }
+                       this.set("message", message);
 
-                       if(_waitCount == 0){
-                               // all items are already loaded (or we aren't loading them).  proceed...
-                               onComplete(childItems);
+                       return isValid;
+               },
+
+               displayMessage: function(/*String*/ message){
+                       // summary:
+                       //              Overridable method to display validation errors/hints.
+                       //              By default uses a tooltip.
+                       // tags:
+                       //              extension
+                       if(message && this.focused){
+                               Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
                        }else{
-                               // still waiting for some or all of the items to load
-                               dojo.forEach(childItems, function(item, idx){
-                                       if(!store.isItemLoaded(item)){
-                                               store.loadItem({
-                                                       item: item,
-                                                       onItem: function(item){
-                                                               childItems[idx] = item;
-                                                               if(--_waitCount == 0){
-                                                                       // all nodes have been loaded, send them to the tree
-                                                                       onComplete(childItems);
-                                                               }
-                                                       },
-                                                       onError: onError
-                                               });
-                                       }
-                               });
+                               Tooltip.hide(this.domNode);
                        }
                },
 
-               // =======================================================================
-               // Inspecting items
-
-               isItem: function(/* anything */ something){
-                       return this.store.isItem(something);    // Boolean
+               _refreshState: function(){
+                       // Overrides TextBox._refreshState()
+                       this.validate(this.focused);
+                       this.inherited(arguments);
                },
 
-               fetchItemByIdentity: function(/* object */ keywordArgs){
-                       this.store.fetchItemByIdentity(keywordArgs);
+               //////////// INITIALIZATION METHODS ///////////////////////////////////////
+
+               constructor: function(){
+                       this.constraints = {};
                },
 
-               getIdentity: function(/* item */ item){
-                       return this.store.getIdentity(item);    // Object
+               _setConstraintsAttr: function(/*Object*/ constraints){
+                       if(!constraints.locale && this.lang){
+                               constraints.locale = this.lang;
+                       }
+                       this._set("constraints", constraints);
+                       this._computePartialRE();
                },
 
-               getLabel: function(/*dojo.data.Item*/ item){
-                       // summary:
-                       //              Get the label for an item
-                       if(this.labelAttr){
-                               return this.store.getValue(item,this.labelAttr);        // String
-                       }else{
-                               return this.store.getLabel(item);       // String
-                       }
-               },
-
-               // =======================================================================
-               // Write interface
-
-               newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
-                       // summary:
-                       //              Creates a new item.   See `dojo.data.api.Write` for details on args.
-                       //              Used in drag & drop when item from external source dropped onto tree.
-                       // description:
-                       //              Developers will need to override this method if new items get added
-                       //              to parents with multiple children attributes, in order to define which
-                       //              children attribute points to the new item.
-
-                       var pInfo = {parent: parent, attribute: this.childrenAttrs[0], insertIndex: insertIndex};
-
-                       if(this.newItemIdAttr && args[this.newItemIdAttr]){
-                               // Maybe there's already a corresponding item in the store; if so, reuse it.
-                               this.fetchItemByIdentity({identity: args[this.newItemIdAttr], scope: this, onItem: function(item){
-                                       if(item){
-                                               // There's already a matching item in store, use it
-                                               this.pasteItem(item, null, parent, true, insertIndex);
-                                       }else{
-                                               // Create new item in the tree, based on the drag source.
-                                               this.store.newItem(args, pInfo);
-                                       }
-                               }});
-                       }else{
-                               // [as far as we know] there is no id so we must assume this is a new item
-                               this.store.newItem(args, pInfo);
-                       }
-               },
-
-               pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
-                       // summary:
-                       //              Move or copy an item from one parent item to another.
-                       //              Used in drag & drop
-                       var store = this.store,
-                               parentAttr = this.childrenAttrs[0];     // name of "children" attr in parent item
-
-                       // remove child from source item, and record the attribute that child occurred in
-                       if(oldParentItem){
-                               dojo.forEach(this.childrenAttrs, function(attr){
-                                       if(store.containsValue(oldParentItem, attr, childItem)){
-                                               if(!bCopy){
-                                                       var values = dojo.filter(store.getValues(oldParentItem, attr), function(x){
-                                                               return x != childItem;
-                                                       });
-                                                       store.setValues(oldParentItem, attr, values);
-                                               }
-                                               parentAttr = attr;
+               _computePartialRE: function(){
+                       var p = this.regExpGen(this.constraints);
+                       this.regExp = p;
+                       var partialre = "";
+                       // parse the regexp and produce a new regexp that matches valid subsets
+                       // if the regexp is .* then there's no use in matching subsets since everything is valid
+                       if(p != ".*"){ this.regExp.replace(/\\.|\[\]|\[.*?[^\\]{1}\]|\{.*?\}|\(\?[=:!]|./g,
+                               function(re){
+                                       switch(re.charAt(0)){
+                                               case '{':
+                                               case '+':
+                                               case '?':
+                                               case '*':
+                                               case '^':
+                                               case '$':
+                                               case '|':
+                                               case '(':
+                                                       partialre += re;
+                                                       break;
+                                               case ")":
+                                                       partialre += "|$)";
+                                                       break;
+                                                default:
+                                                       partialre += "(?:"+re+"|$)";
+                                                       break;
                                        }
-                               });
-                       }
-
-                       // modify target item's children attribute to include this item
-                       if(newParentItem){
-                               if(typeof insertIndex == "number"){
-                                       // call slice() to avoid modifying the original array, confusing the data store
-                                       var childItems = store.getValues(newParentItem, parentAttr).slice();
-                                       childItems.splice(insertIndex, 0, childItem);
-                                       store.setValues(newParentItem, parentAttr, childItems);
-                               }else{
-                                       store.setValues(newParentItem, parentAttr,
-                                               store.getValues(newParentItem, parentAttr).concat(childItem));
                                }
-                       }
+                       );}
+                       try{ // this is needed for now since the above regexp parsing needs more test verification
+                               "".search(partialre);
+                       }catch(e){ // should never be here unless the original RE is bad or the parsing is bad
+                               partialre = this.regExp;
+                               console.warn('RegExp error in ' + this.declaredClass + ': ' + this.regExp);
+                       } // should never be here unless the original RE is bad or the parsing is bad
+                       this._partialre = "^(?:" + partialre + ")$";
                },
 
-               // =======================================================================
-               // Callbacks
-
-               onChange: function(/*dojo.data.Item*/ item){
-                       // summary:
-                       //              Callback whenever an item has changed, so that Tree
-                       //              can update the label, icon, etc.   Note that changes
-                       //              to an item's children or parent(s) will trigger an
-                       //              onChildrenChange() so you can ignore those changes here.
-                       // tags:
-                       //              callback
+               postMixInProperties: function(){
+                       this.inherited(arguments);
+                       this.messages = i18n.getLocalization("dijit.form", "validate", this.lang);
+                       if(this.invalidMessage == "$_unset_$"){ this.invalidMessage = this.messages.invalidMessage; }
+                       if(!this.invalidMessage){ this.invalidMessage = this.promptMessage; }
+                       if(this.missingMessage == "$_unset_$"){ this.missingMessage = this.messages.missingMessage; }
+                       if(!this.missingMessage){ this.missingMessage = this.invalidMessage; }
+                       this._setConstraintsAttr(this.constraints); // this needs to happen now (and later) due to codependency on _set*Attr calls attachPoints
                },
 
-               onChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-                       // summary:
-                       //              Callback to do notifications about new, updated, or deleted items.
-                       // tags:
-                       //              callback
+               _setDisabledAttr: function(/*Boolean*/ value){
+                       this.inherited(arguments);      // call FormValueWidget._setDisabledAttr()
+                       this._refreshState();
                },
 
-               onDelete: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-                       // summary:
-                       //              Callback when an item has been deleted.
-                       // description:
-                       //              Note that there will also be an onChildrenChange() callback for the parent
-                       //              of this item.
-                       // tags:
-                       //              callback
+               _setRequiredAttr: function(/*Boolean*/ value){
+                       this._set("required", value);
+                       this.focusNode.setAttribute("aria-required", value);
+                       this._refreshState();
                },
 
-               // =======================================================================
-               // Events from data store
-
-               onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
-                       // summary:
-                       //              Handler for when new items appear in the store, either from a drop operation
-                       //              or some other way.   Updates the tree view (if necessary).
-                       // description:
-                       //              If the new item is a child of an existing item,
-                       //              calls onChildrenChange() with the new list of children
-                       //              for that existing item.
-                       //
-                       // tags:
-                       //              extension
-
-                       // We only care about the new item if it has a parent that corresponds to a TreeNode
-                       // we are currently displaying
-                       if(!parentInfo){
-                               return;
-                       }
-
-                       // Call onChildrenChange() on parent (ie, existing) item with new list of children
-                       // In the common case, the new list of children is simply parentInfo.newValue or
-                       // [ parentInfo.newValue ], although if items in the store has multiple
-                       // child attributes (see `childrenAttr`), then it's a superset of parentInfo.newValue,
-                       // so call getChildren() to be sure to get right answer.
-                       this.getChildren(parentInfo.item, dojo.hitch(this, function(children){
-                               this.onChildrenChange(parentInfo.item, children);
-                       }));
+               _setMessageAttr: function(/*String*/ message){
+                       this._set("message", message);
+                       this.displayMessage(message);
                },
 
-               onDeleteItem: function(/*Object*/ item){
-                       // summary:
-                       //              Handler for delete notifications from underlying store
-                       this.onDelete(item);
+               reset:function(){
+                       // Overrides dijit.form.TextBox.reset() by also
+                       // hiding errors about partial matches
+                       this._maskValidSubsetError = true;
+                       this.inherited(arguments);
                },
 
-               onSetItem: function(/* item */ item,
-                                               /* attribute-name-string */ attribute,
-                                               /* object | array */ oldValue,
-                                               /* object | array */ newValue){
-                       // summary:
-                       //              Updates the tree view according to changes in the data store.
-                       // description:
-                       //              Handles updates to an item's children by calling onChildrenChange(), and
-                       //              other updates to an item by calling onChange().
-                       //
-                       //              See `onNewItem` for more details on handling updates to an item's children.
-                       // tags:
-                       //              extension
+               _onBlur: function(){
+                       // the message still exists but for back-compat, and to erase the tooltip
+                       // (if the message is being displayed as a tooltip), call displayMessage('')
+                       this.displayMessage('');
 
-                       if(dojo.indexOf(this.childrenAttrs, attribute) != -1){
-                               // item's children list changed
-                               this.getChildren(item, dojo.hitch(this, function(children){
-                                       // See comments in onNewItem() about calling getChildren()
-                                       this.onChildrenChange(item, children);
-                               }));
-                       }else{
-                               // item's label/icon/etc. changed.
-                               this.onChange(item);
-                       }
+                       this.inherited(arguments);
                }
        });
+});
 
+},
+'dijit/_base/typematic':function(){
+define("dijit/_base/typematic", ["../typematic"], function(){
+       // for back-compat, just loads top level module
+});
 
+},
+'dijit/_base':function(){
+define("dijit/_base", [
+       ".",
+       "./a11y",       // used to be in dijit/_base/manager
+       "./WidgetSet",  // used to be in dijit/_base/manager
+       "./_base/focus",
+       "./_base/manager",
+       "./_base/place",
+       "./_base/popup",
+       "./_base/scroll",
+       "./_base/sniff",
+       "./_base/typematic",
+       "./_base/wai",
+       "./_base/window"
+], function(dijit){
+
+       // module:
+       //              dijit/_base
+       // summary:
+       //              Includes all the modules in dijit/_base
 
-}
+       return dijit._base;
+});
 
-if(!dojo._hasResource["dijit.tree.ForestStoreModel"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree.ForestStoreModel"] = true;
-dojo.provide("dijit.tree.ForestStoreModel");
+},
+'dijit/layout/BorderContainer':function(){
+define("dijit/layout/BorderContainer", [
+       "dojo/_base/array", // array.filter array.forEach array.map
+       "dojo/cookie", // cookie
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.remove domClass.toggle
+       "dojo/dom-construct", // domConstruct.destroy domConstruct.place
+       "dojo/dom-geometry", // domGeometry.marginBox
+       "dojo/dom-style", // domStyle.style
+       "dojo/_base/event", // event.stop
+       "dojo/keys",
+       "dojo/_base/lang", // lang.getObject lang.hitch
+       "dojo/on",
+       "dojo/touch",
+       "dojo/_base/window", // win.body win.doc win.doc.createElement
+       "../_WidgetBase",
+       "../_Widget",
+       "../_TemplatedMixin",
+       "./_LayoutWidget",
+       "./utils"               // layoutUtils.layoutChildren
+], function(array, cookie, declare, domClass, domConstruct, domGeometry, domStyle, event, keys, lang, on, touch, win,
+                       _WidgetBase, _Widget, _TemplatedMixin, _LayoutWidget, layoutUtils){
 
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _LayoutWidget = dijit.layout._LayoutWidget;
+=====*/
 
+// module:
+//             dijit/layout/BorderContainer
+// summary:
+//             Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
 
-dojo.declare("dijit.tree.ForestStoreModel", dijit.tree.TreeStoreModel, {
+var _Splitter = declare("dijit.layout._Splitter", [_Widget, _TemplatedMixin ],
+{
        // summary:
-       //              Interface between Tree and a dojo.store that doesn't have a root item,
-       //              i.e. has multiple "top level" items.
-       //
-       // description
-       //              Use this class to wrap a dojo.store, making all the items matching the specified query
-       //              appear as children of a fabricated "root item".  If no query is specified then all the
-       //              items returned by fetch() on the underlying store become children of the root item.
-       //              It allows dijit.Tree to assume a single root item, even if the store doesn't have one.
+       //              A draggable spacer between two items in a `dijit.layout.BorderContainer`.
+       // description:
+       //              This is instantiated by `dijit.layout.BorderContainer`.  Users should not
+       //              create it directly.
+       // tags:
+       //              private
 
-       // Parameters to constructor
+/*=====
+       // container: [const] dijit.layout.BorderContainer
+       //              Pointer to the parent BorderContainer
+       container: null,
 
-       // rootId: String
-       //              ID of fabricated root item
-       rootId: "$root$",
+       // child: [const] dijit.layout._LayoutWidget
+       //              Pointer to the pane associated with this splitter
+       child: null,
 
-       // rootLabel: String
-       //              Label of fabricated root item
-       rootLabel: "ROOT",
+       // region: [const] String
+       //              Region of pane associated with this splitter.
+       //              "top", "bottom", "left", "right".
+       region: null,
+=====*/
 
-       // query: String
-       //              Specifies the set of children of the root item.
-       // example:
-       //      |       {type:'continent'}
-       query: null,
+       // live: [const] Boolean
+       //              If true, the child's size changes and the child widget is redrawn as you drag the splitter;
+       //              otherwise, the size doesn't change until you drop the splitter (by mouse-up)
+       live: true,
 
-       // End of parameters to constructor
+       templateString: '<div class="dijitSplitter" data-dojo-attach-event="onkeypress:_onKeyPress,press:_startDrag,onmouseenter:_onMouse,onmouseleave:_onMouse" tabIndex="0" role="separator"><div class="dijitSplitterThumb"></div></div>',
 
-       constructor: function(params){
-               // summary:
-               //              Sets up variables, etc.
-               // tags:
-               //              private
+       constructor: function(){
+               this._handlers = [];
+       },
 
-               // Make dummy root item
-               this.root = {
-                       store: this,
-                       root: true,
-                       id: params.rootId,
-                       label: params.rootLabel,
-                       children: params.rootChildren   // optional param
-               };
-       },
-
-       // =======================================================================
-       // Methods for traversing hierarchy
-
-       mayHaveChildren: function(/*dojo.data.Item*/ item){
-               // summary:
-               //              Tells if an item has or may have children.  Implementing logic here
-               //              avoids showing +/- expando icon for nodes that we know don't have children.
-               //              (For efficiency reasons we may not want to check if an element actually
-               //              has children until user clicks the expando node)
-               // tags:
-               //              extension
-               return item === this.root || this.inherited(arguments);
-       },
+       postMixInProperties: function(){
+               this.inherited(arguments);
 
-       getChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ callback, /*function*/ onError){
-               // summary:
-               //              Calls onComplete() with array of child items of given parent item, all loaded.
-               if(parentItem === this.root){
-                       if(this.root.children){
-                               // already loaded, just return
-                               callback(this.root.children);
-                       }else{
-                               this.store.fetch({
-                                       query: this.query,
-                                       onComplete: dojo.hitch(this, function(items){
-                                               this.root.children = items;
-                                               callback(items);
-                                       }),
-                                       onError: onError
-                               });
-                       }
-               }else{
-                       this.inherited(arguments);
-               }
+               this.horizontal = /top|bottom/.test(this.region);
+               this._factor = /top|left/.test(this.region) ? 1 : -1;
+               this._cookieName = this.container.id + "_" + this.region;
        },
 
-       // =======================================================================
-       // Inspecting items
+       buildRendering: function(){
+               this.inherited(arguments);
 
-       isItem: function(/* anything */ something){
-               return (something === this.root) ? true : this.inherited(arguments);
-       },
+               domClass.add(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V"));
 
-       fetchItemByIdentity: function(/* object */ keywordArgs){
-               if(keywordArgs.identity == this.root.id){
-                       var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-                       if(keywordArgs.onItem){
-                               keywordArgs.onItem.call(scope, this.root);
+               if(this.container.persist){
+                       // restore old size
+                       var persistSize = cookie(this._cookieName);
+                       if(persistSize){
+                               this.child.domNode.style[this.horizontal ? "height" : "width"] = persistSize;
                        }
-               }else{
-                       this.inherited(arguments);
                }
        },
 
-       getIdentity: function(/* item */ item){
-               return (item === this.root) ? this.root.id : this.inherited(arguments);
-       },
-
-       getLabel: function(/* item */ item){
-               return  (item === this.root) ? this.root.label : this.inherited(arguments);
-       },
+       _computeMaxSize: function(){
+               // summary:
+               //              Return the maximum size that my corresponding pane can be set to
 
-       // =======================================================================
-       // Write interface
+               var dim = this.horizontal ? 'h' : 'w',
+                       childSize = domGeometry.getMarginBox(this.child.domNode)[dim],
+                       center = array.filter(this.container.getChildren(), function(child){ return child.region == "center";})[0],
+                       spaceAvailable = domGeometry.getMarginBox(center.domNode)[dim]; // can expand until center is crushed to 0
 
-       newItem: function(/* dojo.dnd.Item */ args, /*Item*/ parent, /*int?*/ insertIndex){
-               // summary:
-               //              Creates a new item.   See dojo.data.api.Write for details on args.
-               //              Used in drag & drop when item from external source dropped onto tree.
-               if(parent === this.root){
-                       this.onNewRootItem(args);
-                       return this.store.newItem(args);
-               }else{
-                       return this.inherited(arguments);
-               }
+               return Math.min(this.child.maxSize, childSize + spaceAvailable);
        },
 
-       onNewRootItem: function(args){
-               // summary:
-               //              User can override this method to modify a new element that's being
-               //              added to the root of the tree, for example to add a flag like root=true
-       },
+       _startDrag: function(e){
+               if(!this.cover){
+                       this.cover = win.doc.createElement('div');
+                       domClass.add(this.cover, "dijitSplitterCover");
+                       domConstruct.place(this.cover, this.child.domNode, "after");
+               }
+               domClass.add(this.cover, "dijitSplitterCoverActive");
 
-       pasteItem: function(/*Item*/ childItem, /*Item*/ oldParentItem, /*Item*/ newParentItem, /*Boolean*/ bCopy, /*int?*/ insertIndex){
-               // summary:
-               //              Move or copy an item from one parent item to another.
-               //              Used in drag & drop
-               if(oldParentItem === this.root){
-                       if(!bCopy){
-                               // It's onLeaveRoot()'s responsibility to modify the item so it no longer matches
-                               // this.query... thus triggering an onChildrenChange() event to notify the Tree
-                               // that this element is no longer a child of the root node
-                               this.onLeaveRoot(childItem);
-                       }
+               // Safeguard in case the stop event was missed.  Shouldn't be necessary if we always get the mouse up.
+               if(this.fake){ domConstruct.destroy(this.fake); }
+               if(!(this._resize = this.live)){ //TODO: disable live for IE6?
+                       // create fake splitter to display at old position while we drag
+                       (this.fake = this.domNode.cloneNode(true)).removeAttribute("id");
+                       domClass.add(this.domNode, "dijitSplitterShadow");
+                       domConstruct.place(this.fake, this.domNode, "after");
                }
-               dijit.tree.TreeStoreModel.prototype.pasteItem.call(this, childItem,
-                       oldParentItem === this.root ? null : oldParentItem,
-                       newParentItem === this.root ? null : newParentItem,
-                       bCopy,
-                       insertIndex
-               );
-               if(newParentItem === this.root){
-                       // It's onAddToRoot()'s responsibility to modify the item so it matches
-                       // this.query... thus triggering an onChildrenChange() event to notify the Tree
-                       // that this element is now a child of the root node
-                       this.onAddToRoot(childItem);
+               domClass.add(this.domNode, "dijitSplitterActive dijitSplitter" + (this.horizontal ? "H" : "V") + "Active");
+               if(this.fake){
+                       domClass.remove(this.fake, "dijitSplitterHover dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover");
                }
-       },
 
-       // =======================================================================
-       // Handling for top level children
+               //Performance: load data info local vars for onmousevent function closure
+               var factor = this._factor,
+                       isHorizontal = this.horizontal,
+                       axis = isHorizontal ? "pageY" : "pageX",
+                       pageStart = e[axis],
+                       splitterStyle = this.domNode.style,
+                       dim = isHorizontal ? 'h' : 'w',
+                       childStart = domGeometry.getMarginBox(this.child.domNode)[dim],
+                       max = this._computeMaxSize(),
+                       min = this.child.minSize || 20,
+                       region = this.region,
+                       splitterAttr = region == "top" || region == "bottom" ? "top" : "left",  // style attribute of splitter to adjust
+                       splitterStart = parseInt(splitterStyle[splitterAttr], 10),
+                       resize = this._resize,
+                       layoutFunc = lang.hitch(this.container, "_layoutChildren", this.child.id),
+                       de = win.doc;
 
-       onAddToRoot: function(/* item */ item){
-               // summary:
-               //              Called when item added to root of tree; user must override this method
-               //              to modify the item so that it matches the query for top level items
-               // example:
-               //      |       store.setValue(item, "root", true);
-               // tags:
-               //              extension
-               console.log(this, ": item ", item, " added to root");
+               this._handlers = this._handlers.concat([
+                       on(de, touch.move, this._drag = function(e, forceResize){
+                               var delta = e[axis] - pageStart,
+                                       childSize = factor * delta + childStart,
+                                       boundChildSize = Math.max(Math.min(childSize, max), min);
+
+                               if(resize || forceResize){
+                                       layoutFunc(boundChildSize);
+                               }
+                               // TODO: setting style directly (usually) sets content box size, need to set margin box size
+                               splitterStyle[splitterAttr] = delta + splitterStart + factor*(boundChildSize - childSize) + "px";
+                       }),
+                       on(de, "dragstart", event.stop),
+                       on(win.body(), "selectstart", event.stop),
+                       on(de, touch.release, lang.hitch(this, "_stopDrag"))
+               ]);
+               event.stop(e);
        },
 
-       onLeaveRoot: function(/* item */ item){
+       _onMouse: function(e){
                // summary:
-               //              Called when item removed from root of tree; user must override this method
-               //              to modify the item so it doesn't match the query for top level items
-               // example:
-               //      |       store.unsetAttribute(item, "root");
-               // tags:
-               //              extension
-               console.log(this, ": item ", item, " removed from root");
+               //              Handler for onmouseenter / onmouseleave events
+               var o = (e.type == "mouseover" || e.type == "mouseenter");
+               domClass.toggle(this.domNode, "dijitSplitterHover", o);
+               domClass.toggle(this.domNode, "dijitSplitter" + (this.horizontal ? "H" : "V") + "Hover", o);
        },
 
-       // =======================================================================
-       // Events from data store
-
-       _requeryTop: function(){
-               // reruns the query for the children of the root node,
-               // sending out an onSet notification if those children have changed
-               var oldChildren = this.root.children || [];
-               this.store.fetch({
-                       query: this.query,
-                       onComplete: dojo.hitch(this, function(newChildren){
-                               this.root.children = newChildren;
+       _stopDrag: function(e){
+               try{
+                       if(this.cover){
+                               domClass.remove(this.cover, "dijitSplitterCoverActive");
+                       }
+                       if(this.fake){ domConstruct.destroy(this.fake); }
+                       domClass.remove(this.domNode, "dijitSplitterActive dijitSplitter"
+                               + (this.horizontal ? "H" : "V") + "Active dijitSplitterShadow");
+                       this._drag(e); //TODO: redundant with onmousemove?
+                       this._drag(e, true);
+               }finally{
+                       this._cleanupHandlers();
+                       delete this._drag;
+               }
 
-                               // If the list of children or the order of children has changed...
-                               if(oldChildren.length != newChildren.length ||
-                                       dojo.some(oldChildren, function(item, idx){ return newChildren[idx] != item;})){
-                                       this.onChildrenChange(this.root, newChildren);
-                               }
-                       })
-               });
+               if(this.container.persist){
+                       cookie(this._cookieName, this.child.domNode.style[this.horizontal ? "height" : "width"], {expires:365});
+               }
        },
 
-       onNewItem: function(/* dojo.data.Item */ item, /* Object */ parentInfo){
-               // summary:
-               //              Handler for when new items appear in the store.  Developers should override this
-               //              method to be more efficient based on their app/data.
-               // description:
-               //              Note that the default implementation requeries the top level items every time
-               //              a new item is created, since any new item could be a top level item (even in
-               //              addition to being a child of another item, since items can have multiple parents).
-               //
-               //              Developers can override this function to do something more efficient if they can
-               //              detect which items are possible top level items (based on the item and the
-               //              parentInfo parameters).  Often all top level items have parentInfo==null, but
-               //              that will depend on which store you use and what your data is like.
-               // tags:
-               //              extension
-               this._requeryTop();
-
-               this.inherited(arguments);
+       _cleanupHandlers: function(){
+               var h;
+               while(h = this._handlers.pop()){ h.remove(); }
        },
 
-       onDeleteItem: function(/*Object*/ item){
-               // summary:
-               //              Handler for delete notifications from underlying store
-
-               // check if this was a child of root, and if so send notification that root's children
-               // have changed
-               if(dojo.indexOf(this.root.children, item) != -1){
-                       this._requeryTop();
+       _onKeyPress: function(/*Event*/ e){
+               // should we apply typematic to this?
+               this._resize = true;
+               var horizontal = this.horizontal;
+               var tick = 1;
+               switch(e.charOrCode){
+                       case horizontal ? keys.UP_ARROW : keys.LEFT_ARROW:
+                               tick *= -1;
+//                             break;
+                       case horizontal ? keys.DOWN_ARROW : keys.RIGHT_ARROW:
+                               break;
+                       default:
+//                             this.inherited(arguments);
+                               return;
                }
+               var childSize = domGeometry.getMarginSize(this.child.domNode)[ horizontal ? 'h' : 'w' ] + this._factor * tick;
+               this.container._layoutChildren(this.child.id, Math.max(Math.min(childSize, this._computeMaxSize()), this.child.minSize));
+               event.stop(e);
+       },
 
+       destroy: function(){
+               this._cleanupHandlers();
+               delete this.child;
+               delete this.container;
+               delete this.cover;
+               delete this.fake;
                this.inherited(arguments);
        }
 });
 
-
-
-}
-
-if(!dojo._hasResource["dijit.Tree"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.Tree"] = true;
-dojo.provide("dijit.Tree");
-
-
-
-
-
-
-
-
-
-
-
-dojo.declare(
-       "dijit._TreeNode",
-       [dijit._Widget, dijit._Templated, dijit._Container, dijit._Contained, dijit._CssStateMixin],
+var _Gutter = declare("dijit.layout._Gutter", [_Widget, _TemplatedMixin],
 {
        // summary:
-       //              Single node within a tree.   This class is used internally
-       //              by Tree and should not be accessed directly.
+       //              Just a spacer div to separate side pane from center pane.
+       //              Basically a trick to lookup the gutter/splitter width from the theme.
+       // description:
+       //              Instantiated by `dijit.layout.BorderContainer`.  Users should not
+       //              create directly.
        // tags:
        //              private
 
-       // item: dojo.data.Item
-       //              the dojo.data entry this tree represents
-       item: null,
+       templateString: '<div class="dijitGutter" role="presentation"></div>',
 
-       // isTreeNode: [protected] Boolean
-       //              Indicates that this is a TreeNode.   Used by `dijit.Tree` only,
-       //              should not be accessed directly.
-       isTreeNode: true,
+       postMixInProperties: function(){
+               this.inherited(arguments);
+               this.horizontal = /top|bottom/.test(this.region);
+       },
 
-       // label: String
-       //              Text of this tree node
-       label: "",
+       buildRendering: function(){
+               this.inherited(arguments);
+               domClass.add(this.domNode, "dijitGutter" + (this.horizontal ? "H" : "V"));
+       }
+});
 
-       // isExpandable: [private] Boolean
-       //              This node has children, so show the expando node (+ sign)
-       isExpandable: null,
+var BorderContainer = declare("dijit.layout.BorderContainer", _LayoutWidget, {
+       // summary:
+       //              Provides layout in up to 5 regions, a mandatory center with optional borders along its 4 sides.
+       //
+       // description:
+       //              A BorderContainer is a box with a specified size, such as style="width: 500px; height: 500px;",
+       //              that contains a child widget marked region="center" and optionally children widgets marked
+       //              region equal to "top", "bottom", "leading", "trailing", "left" or "right".
+       //              Children along the edges will be laid out according to width or height dimensions and may
+       //              include optional splitters (splitter="true") to make them resizable by the user.  The remaining
+       //              space is designated for the center region.
+       //
+       //              The outer size must be specified on the BorderContainer node.  Width must be specified for the sides
+       //              and height for the top and bottom, respectively.  No dimensions should be specified on the center;
+       //              it will fill the remaining space.  Regions named "leading" and "trailing" may be used just like
+       //              "left" and "right" except that they will be reversed in right-to-left environments.
+       //
+       //              For complex layouts, multiple children can be specified for a single region.   In this case, the
+       //              layoutPriority flag on the children determines which child is closer to the edge (low layoutPriority)
+       //              and which child is closer to the center (high layoutPriority).   layoutPriority can also be used
+       //              instead of the design attribute to control layout precedence of horizontal vs. vertical panes.
+       // example:
+       // |    <div data-dojo-type="dijit.layout.BorderContainer" data-dojo-props="design: 'sidebar', gutters: false"
+       // |            style="width: 400px; height: 300px;">
+       // |            <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'top'">header text</div>
+       // |            <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'right', splitter: true" style="width: 200px;">table of contents</div>
+       // |            <div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region: 'center'">client area</div>
+       // |    </div>
 
-       // isExpanded: [readonly] Boolean
-       //              This node is currently expanded (ie, opened)
-       isExpanded: false,
+       // design: String
+       //              Which design is used for the layout:
+       //                      - "headline" (default) where the top and bottom extend
+       //                              the full width of the container
+       //                      - "sidebar" where the left and right sides extend from top to bottom.
+       design: "headline",
 
-       // state: [private] String
-       //              Dynamic loading-related stuff.
-       //              When an empty folder node appears, it is "UNCHECKED" first,
-       //              then after dojo.data query it becomes "LOADING" and, finally "LOADED"
-       state: "UNCHECKED",
+       // gutters: [const] Boolean
+       //              Give each pane a border and margin.
+       //              Margin determined by domNode.paddingLeft.
+       //              When false, only resizable panes have a gutter (i.e. draggable splitter) for resizing.
+       gutters: true,
 
-       templateString: dojo.cache("dijit", "templates/TreeNode.html", "<div class=\"dijitTreeNode\" waiRole=\"presentation\"\n\t><div dojoAttachPoint=\"rowNode\" class=\"dijitTreeRow\" waiRole=\"presentation\" dojoAttachEvent=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint=\"expandoNode\" class=\"dijitTreeExpando\" waiRole=\"presentation\"\n\t\t/><span dojoAttachPoint=\"expandoNodeText\" class=\"dijitExpandoText\" waiRole=\"presentation\"\n\t\t></span\n\t\t><span dojoAttachPoint=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" waiRole=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" dojoAttachPoint=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" waiRole=\"presentation\"\n\t\t\t/><span dojoAttachPoint=\"labelNode\" class=\"dijitTreeLabel\" wairole=\"treeitem\" tabindex=\"-1\" waiState=\"selected-false\" dojoAttachEvent=\"onfocus:_onLabelFocus\"></span>\n\t\t</span\n\t></div>\n\t<div dojoAttachPoint=\"containerNode\" class=\"dijitTreeContainer\" waiRole=\"presentation\" style=\"display: none;\"></div>\n</div>\n"),
+       // liveSplitters: [const] Boolean
+       //              Specifies whether splitters resize as you drag (true) or only upon mouseup (false)
+       liveSplitters: true,
 
-       baseClass: "dijitTreeNode",
+       // persist: Boolean
+       //              Save splitter positions in a cookie.
+       persist: false,
 
-       // For hover effect for tree node, and focus effect for label
-       cssStateNodes: {
-               rowNode: "dijitTreeRow",
-               labelNode: "dijitTreeLabel"
-       },
+       baseClass: "dijitBorderContainer",
 
-       attributeMap: dojo.delegate(dijit._Widget.prototype.attributeMap, {
-               label: {node: "labelNode", type: "innerText"},
-               tooltip: {node: "rowNode", type: "attribute", attribute: "title"}
-       }),
+       // _splitterClass: Function||String
+       //              Optional hook to override the default Splitter widget used by BorderContainer
+       _splitterClass: _Splitter,
 
-       postCreate: function(){
+       postMixInProperties: function(){
+               // change class name to indicate that BorderContainer is being used purely for
+               // layout (like LayoutContainer) rather than for pretty formatting.
+               if(!this.gutters){
+                       this.baseClass += "NoGutter";
+               }
                this.inherited(arguments);
+       },
 
-               // set expand icon for leaf
-               this._setExpando();
+       startup: function(){
+               if(this._started){ return; }
+               array.forEach(this.getChildren(), this._setupChild, this);
+               this.inherited(arguments);
+       },
 
-               // set icon and label class based on item
-               this._updateItemClasses(this.item);
+       _setupChild: function(/*dijit._Widget*/ child){
+               // Override _LayoutWidget._setupChild().
 
-               if(this.isExpandable){
-                       dijit.setWaiState(this.labelNode, "expanded", this.isExpanded);
-               }
-       },
+               var region = child.region;
+               if(region){
+                       this.inherited(arguments);
 
-       _setIndentAttr: function(indent){
-               // summary:
-               //              Tell this node how many levels it should be indented
-               // description:
-               //              0 for top level nodes, 1 for their children, 2 for their
-               //              grandchildren, etc.
-               this.indent = indent;
+                       domClass.add(child.domNode, this.baseClass+"Pane");
 
-               // Math.max() is to prevent negative padding on hidden root node (when indent == -1)
-               var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px";
+                       var ltr = this.isLeftToRight();
+                       if(region == "leading"){ region = ltr ? "left" : "right"; }
+                       if(region == "trailing"){ region = ltr ? "right" : "left"; }
 
-               dojo.style(this.domNode, "backgroundPosition",  pixels + " 0px");
-               dojo.style(this.rowNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels);
+                       // Create draggable splitter for resizing pane,
+                       // or alternately if splitter=false but BorderContainer.gutters=true then
+                       // insert dummy div just for spacing
+                       if(region != "center" && (child.splitter || this.gutters) && !child._splitterWidget){
+                               var _Splitter = child.splitter ? this._splitterClass : _Gutter;
+                               if(lang.isString(_Splitter)){
+                                       _Splitter = lang.getObject(_Splitter);  // for back-compat, remove in 2.0
+                               }
+                               var splitter = new _Splitter({
+                                       id: child.id + "_splitter",
+                                       container: this,
+                                       child: child,
+                                       region: region,
+                                       live: this.liveSplitters
+                               });
+                               splitter.isSplitter = true;
+                               child._splitterWidget = splitter;
 
-               dojo.forEach(this.getChildren(), function(child){
-                       child.set("indent", indent+1);
-               });
-       },
+                               domConstruct.place(splitter.domNode, child.domNode, "after");
 
-       markProcessing: function(){
-               // summary:
-               //              Visually denote that tree is loading data, etc.
-               // tags:
-               //              private
-               this.state = "LOADING";
-               this._setExpando(true);
+                               // Splitters aren't added as Contained children, so we need to call startup explicitly
+                               splitter.startup();
+                       }
+                       child.region = region;  // TODO: technically wrong since it overwrites "trailing" with "left" etc.
+               }
        },
 
-       unmarkProcessing: function(){
-               // summary:
-               //              Clear markup from markProcessing() call
-               // tags:
-               //              private
-               this._setExpando(false);
+       layout: function(){
+               // Implement _LayoutWidget.layout() virtual method.
+               this._layoutChildren();
        },
 
-       _updateItemClasses: function(item){
-               // summary:
-               //              Set appropriate CSS classes for icon and label dom node
-               //              (used to allow for item updates to change respective CSS)
-               // tags:
-               //              private
-               var tree = this.tree, model = tree.model;
-               if(tree._v10Compat && item === model.root){
-                       // For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0)
-                       item = null;
+       addChild: function(/*dijit._Widget*/ child, /*Integer?*/ insertIndex){
+               // Override _LayoutWidget.addChild().
+               this.inherited(arguments);
+               if(this._started){
+                       this.layout(); //OPT
                }
-               this._applyClassAndStyle(item, "icon", "Icon");
-               this._applyClassAndStyle(item, "label", "Label");
-               this._applyClassAndStyle(item, "row", "Row");
        },
 
-       _applyClassAndStyle: function(item, lower, upper){
-               // summary:
-               //              Set the appropriate CSS classes and styles for labels, icons and rows.
-               //
-               // item:
-               //              The data item.
-               //
-               // lower:
-               //              The lower case attribute to use, e.g. 'icon', 'label' or 'row'.
-               //
-               // upper:
-               //              The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'.
-               //
-               // tags:
-               //              private
-
-               var clsName = "_" + lower + "Class";
-               var nodeName = lower + "Node";
+       removeChild: function(/*dijit._Widget*/ child){
+               // Override _LayoutWidget.removeChild().
 
-               if(this[clsName]){
-                       dojo.removeClass(this[nodeName], this[clsName]);
-               }
-               this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded);
-               if(this[clsName]){
-                       dojo.addClass(this[nodeName], this[clsName]);
-               }
-               dojo.style(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {});
-       },
+               var region = child.region;
+               var splitter = child._splitterWidget;
+               if(splitter){
+                       splitter.destroy();
+                       delete child._splitterWidget;
+               }
+               this.inherited(arguments);
 
-       _updateLayout: function(){
-               // summary:
-               //              Set appropriate CSS classes for this.domNode
-               // tags:
-               //              private
-               var parent = this.getParent();
-               if(!parent || parent.rowNode.style.display == "none"){
-                       /* if we are hiding the root node then make every first level child look like a root node */
-                       dojo.addClass(this.domNode, "dijitTreeIsRoot");
-               }else{
-                       dojo.toggleClass(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
+               if(this._started){
+                       this._layoutChildren();
                }
+               // Clean up whatever style changes we made to the child pane.
+               // Unclear how height and width should be handled.
+               domClass.remove(child.domNode, this.baseClass+"Pane");
+               domStyle.set(child.domNode, {
+                       top: "auto",
+                       bottom: "auto",
+                       left: "auto",
+                       right: "auto",
+                       position: "static"
+               });
+               domStyle.set(child.domNode, region == "top" || region == "bottom" ? "width" : "height", "auto");
        },
 
-       _setExpando: function(/*Boolean*/ processing){
+       getChildren: function(){
+               // Override _LayoutWidget.getChildren() to only return real children, not the splitters.
+               return array.filter(this.inherited(arguments), function(widget){
+                       return !widget.isSplitter;
+               });
+       },
+
+       // TODO: remove in 2.0
+       getSplitter: function(/*String*/region){
                // summary:
-               //              Set the right image for the expando node
+               //              Returns the widget responsible for rendering the splitter associated with region
                // tags:
-               //              private
+               //              deprecated
+               return array.filter(this.getChildren(), function(child){
+                       return child.region == region;
+               })[0]._splitterWidget;
+       },
 
-               var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
-                                               "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"],
-                       _a11yStates = ["*","-","+","*"],
-                       idx = processing ? 0 : (this.isExpandable ?     (this.isExpanded ? 1 : 2) : 3);
+       resize: function(newSize, currentSize){
+               // Overrides _LayoutWidget.resize().
 
-               // apply the appropriate class to the expando node
-               dojo.removeClass(this.expandoNode, styles);
-               dojo.addClass(this.expandoNode, styles[idx]);
+               // resetting potential padding to 0px to provide support for 100% width/height + padding
+               // TODO: this hack doesn't respect the box model and is a temporary fix
+               if(!this.cs || !this.pe){
+                       var node = this.domNode;
+                       this.cs = domStyle.getComputedStyle(node);
+                       this.pe = domGeometry.getPadExtents(node, this.cs);
+                       this.pe.r = domStyle.toPixelValue(node, this.cs.paddingRight);
+                       this.pe.b = domStyle.toPixelValue(node, this.cs.paddingBottom);
 
-               // provide a non-image based indicator for images-off mode
-               this.expandoNodeText.innerHTML = _a11yStates[idx];
+                       domStyle.set(node, "padding", "0px");
+               }
 
+               this.inherited(arguments);
        },
 
-       expand: function(){
+       _layoutChildren: function(/*String?*/ changedChildId, /*Number?*/ changedChildSize){
                // summary:
-               //              Show my children
-               // returns:
-               //              Deferred that fires when expansion is complete
+               //              This is the main routine for setting size/position of each child.
+               // description:
+               //              With no arguments, measures the height of top/bottom panes, the width
+               //              of left/right panes, and then sizes all panes accordingly.
+               //
+               //              With changedRegion specified (as "left", "top", "bottom", or "right"),
+               //              it changes that region's width/height to changedRegionSize and
+               //              then resizes other regions that were affected.
+               // changedChildId:
+               //              Id of the child which should be resized because splitter was dragged.
+               // changedChildSize:
+               //              The new width/height (in pixels) to make specified child
 
-               // If there's already an expand in progress or we are already expanded, just return
-               if(this._expandDeferred){
-                       return this._expandDeferred;            // dojo.Deferred
+               if(!this._borderBox || !this._borderBox.h){
+                       // We are currently hidden, or we haven't been sized by our parent yet.
+                       // Abort.   Someone will resize us later.
+                       return;
                }
 
-               // cancel in progress collapse operation
-               this._wipeOut && this._wipeOut.stop();
+               // Generate list of wrappers of my children in the order that I want layoutChildren()
+               // to process them (i.e. from the outside to the inside)
+               var wrappers = array.map(this.getChildren(), function(child, idx){
+                       return {
+                               pane: child,
+                               weight: [
+                                       child.region == "center" ? Infinity : 0,
+                                       child.layoutPriority,
+                                       (this.design == "sidebar" ? 1 : -1) * (/top|bottom/.test(child.region) ? 1 : -1),
+                                       idx
+                               ]
+                       };
+               }, this);
+               wrappers.sort(function(a, b){
+                       var aw = a.weight, bw = b.weight;
+                       for(var i=0; i<aw.length; i++){
+                               if(aw[i] != bw[i]){
+                                       return aw[i] - bw[i];
+                               }
+                       }
+                       return 0;
+               });
 
-               // All the state information for when a node is expanded, maybe this should be
-               // set when the animation completes instead
-               this.isExpanded = true;
-               dijit.setWaiState(this.labelNode, "expanded", "true");
-               dijit.setWaiRole(this.containerNode, "group");
-               dojo.addClass(this.contentNode,'dijitTreeContentExpanded');
-               this._setExpando();
-               this._updateItemClasses(this.item);
-               if(this == this.tree.rootNode){
-                       dijit.setWaiState(this.tree.domNode, "expanded", "true");
-               }
+               // Make new list, combining the externally specified children with splitters and gutters
+               var childrenAndSplitters = [];
+               array.forEach(wrappers, function(wrapper){
+                       var pane = wrapper.pane;
+                       childrenAndSplitters.push(pane);
+                       if(pane._splitterWidget){
+                               childrenAndSplitters.push(pane._splitterWidget);
+                       }
+               });
 
-               var def,
-                       wipeIn = dojo.fx.wipeIn({
-                               node: this.containerNode, duration: dijit.defaultDuration,
-                               onEnd: function(){
-                                       def.callback(true);
-                               }
-                       });
+               // Compute the box in which to lay out my children
+               var dim = {
+                       l: this.pe.l,
+                       t: this.pe.t,
+                       w: this._borderBox.w - this.pe.w,
+                       h: this._borderBox.h - this.pe.h
+               };
 
-               // Deferred that fires when expand is complete
-               def = (this._expandDeferred = new dojo.Deferred(function(){
-                       // Canceller
-                       wipeIn.stop();
-               }));
+               // Layout the children, possibly changing size due to a splitter drag
+               layoutUtils.layoutChildren(this.domNode, dim, childrenAndSplitters,
+                       changedChildId, changedChildSize);
+       },
 
-               wipeIn.play();
+       destroyRecursive: function(){
+               // Destroy splitters first, while getChildren() still works
+               array.forEach(this.getChildren(), function(child){
+                       var splitter = child._splitterWidget;
+                       if(splitter){
+                               splitter.destroy();
+                       }
+                       delete child._splitterWidget;
+               });
 
-               return def;             // dojo.Deferred
-       },
+               // Then destroy the real children, and myself
+               this.inherited(arguments);
+       }
+});
 
-       collapse: function(){
-               // summary:
-               //              Collapse this node (if it's expanded)
+// This argument can be specified for the children of a BorderContainer.
+// Since any widget can be specified as a LayoutContainer child, mix it
+// into the base widget class.  (This is a hack, but it's effective.)
+lang.extend(_WidgetBase, {
+       // region: [const] String
+       //              Parameter for children of `dijit.layout.BorderContainer`.
+       //              Values: "top", "bottom", "leading", "trailing", "left", "right", "center".
+       //              See the `dijit.layout.BorderContainer` description for details.
+       region: '',
 
-               if(!this.isExpanded){ return; }
+       // layoutPriority: [const] Number
+       //              Parameter for children of `dijit.layout.BorderContainer`.
+       //              Children with a higher layoutPriority will be placed closer to the BorderContainer center,
+       //              between children with a lower layoutPriority.
+       layoutPriority: 0,
 
-               // cancel in progress expand operation
-               if(this._expandDeferred){
-                       this._expandDeferred.cancel();
-                       delete this._expandDeferred;
-               }
+       // splitter: [const] Boolean
+       //              Parameter for child of `dijit.layout.BorderContainer` where region != "center".
+       //              If true, enables user to resize the widget by putting a draggable splitter between
+       //              this widget and the region=center widget.
+       splitter: false,
 
-               this.isExpanded = false;
-               dijit.setWaiState(this.labelNode, "expanded", "false");
-               if(this == this.tree.rootNode){
-                       dijit.setWaiState(this.tree.domNode, "expanded", "false");
-               }
-               dojo.removeClass(this.contentNode,'dijitTreeContentExpanded');
-               this._setExpando();
-               this._updateItemClasses(this.item);
+       // minSize: [const] Number
+       //              Parameter for children of `dijit.layout.BorderContainer`.
+       //              Specifies a minimum size (in pixels) for this widget when resized by a splitter.
+       minSize: 0,
 
-               if(!this._wipeOut){
-                       this._wipeOut = dojo.fx.wipeOut({
-                               node: this.containerNode, duration: dijit.defaultDuration
-                       });
-               }
-               this._wipeOut.play();
-       },
+       // maxSize: [const] Number
+       //              Parameter for children of `dijit.layout.BorderContainer`.
+       //              Specifies a maximum size (in pixels) for this widget when resized by a splitter.
+       maxSize: Infinity
+});
 
-       // indent: Integer
-       //              Levels from this node to the root node
-       indent: 0,
+// For monkey patching
+BorderContainer._Splitter = _Splitter;
+BorderContainer._Gutter = _Gutter;
 
-       setChildItems: function(/* Object[] */ items){
-               // summary:
-               //              Sets the child items of this node, removing/adding nodes
-               //              from current children to match specified items[] array.
-               //              Also, if this.persist == true, expands any children that were previously
-               //              opened.
-               // returns:
-               //              Deferred object that fires after all previously opened children
-               //              have been expanded again (or fires instantly if there are no such children).
+return BorderContainer;
+});
 
-               var tree = this.tree,
-                       model = tree.model,
-                       defs = [];      // list of deferreds that need to fire before I am complete
+},
+'dojo/window':function(){
+define("dojo/window", ["./_base/lang", "./_base/sniff", "./_base/window", "./dom", "./dom-geometry", "./dom-style"],
+       function(lang, has, baseWindow, dom, geom, style) {
 
+// module:
+//             dojo/window
+// summary:
+//             TODOC
 
-               // Orphan all my existing children.
-               // If items contains some of the same items as before then we will reattach them.
-               // Don't call this.removeChild() because that will collapse the tree etc.
-               dojo.forEach(this.getChildren(), function(child){
-                       dijit._Container.prototype.removeChild.call(this, child);
-               }, this);
+var window = lang.getObject("dojo.window", true);
 
-               this.state = "LOADED";
+/*=====
+dojo.window = {
+       // summary:
+       //              TODO
+};
+window = dojo.window;
+=====*/
 
-               if(items && items.length > 0){
-                       this.isExpandable = true;
+window.getBox = function(){
+       // summary:
+       //              Returns the dimensions and scroll position of the viewable area of a browser window
 
-                       // Create _TreeNode widget for each specified tree node, unless one already
-                       // exists and isn't being used (presumably it's from a DnD move and was recently
-                       // released
-                       dojo.forEach(items, function(item){
-                               var id = model.getIdentity(item),
-                                       existingNodes = tree._itemNodesMap[id],
-                                       node;
-                               if(existingNodes){
-                                       for(var i=0;i<existingNodes.length;i++){
-                                               if(existingNodes[i] && !existingNodes[i].getParent()){
-                                                       node = existingNodes[i];
-                                                       node.set('indent', this.indent+1);
-                                                       break;
-                                               }
-                                       }
-                               }
-                               if(!node){
-                                       node = this.tree._createTreeNode({
-                                                       item: item,
-                                                       tree: tree,
-                                                       isExpandable: model.mayHaveChildren(item),
-                                                       label: tree.getLabel(item),
-                                                       tooltip: tree.getTooltip(item),
-                                                       dir: tree.dir,
-                                                       lang: tree.lang,
-                                                       indent: this.indent + 1
-                                               });
-                                       if(existingNodes){
-                                               existingNodes.push(node);
-                                       }else{
-                                               tree._itemNodesMap[id] = [node];
-                                       }
-                               }
-                               this.addChild(node);
+       var
+               scrollRoot = (baseWindow.doc.compatMode == 'BackCompat') ? baseWindow.body() : baseWindow.doc.documentElement,
+               // get scroll position
+               scroll = geom.docScroll(), // scrollRoot.scrollTop/Left should work
+               w, h;
+
+       if(has("touch")){ // if(scrollbars not supported)
+               var uiWindow = baseWindow.doc.parentWindow || baseWindow.doc.defaultView;   // use UI window, not dojo.global window. baseWindow.doc.parentWindow probably not needed since it's not defined for webkit
+               // on mobile, scrollRoot.clientHeight <= uiWindow.innerHeight <= scrollRoot.offsetHeight, return uiWindow.innerHeight
+               w = uiWindow.innerWidth || scrollRoot.clientWidth; // || scrollRoot.clientXXX probably never evaluated
+               h = uiWindow.innerHeight || scrollRoot.clientHeight;
+       }else{
+               // on desktops, scrollRoot.clientHeight <= scrollRoot.offsetHeight <= uiWindow.innerHeight, return scrollRoot.clientHeight
+               // uiWindow.innerWidth/Height includes the scrollbar and cannot be used
+               w = scrollRoot.clientWidth;
+               h = scrollRoot.clientHeight;
+       }
+       return {
+               l: scroll.x,
+               t: scroll.y,
+               w: w,
+               h: h
+       };
+};
 
-                               // If node was previously opened then open it again now (this may trigger
-                               // more data store accesses, recursively)
-                               if(this.tree.autoExpand || this.tree._state(item)){
-                                       defs.push(tree._expandNode(node));
-                               }
-                       }, this);
+window.get = function(doc){
+       // summary:
+       //              Get window object associated with document doc
 
-                       // note that updateLayout() needs to be called on each child after
-                       // _all_ the children exist
-                       dojo.forEach(this.getChildren(), function(child, idx){
-                               child._updateLayout();
-                       });
-               }else{
-                       this.isExpandable=false;
-               }
+       // In some IE versions (at least 6.0), document.parentWindow does not return a
+       // reference to the real window object (maybe a copy), so we must fix it as well
+       // We use IE specific execScript to attach the real window reference to
+       // document._parentWindow for later use
+       if(has("ie") && window !== document.parentWindow){
+               /*
+               In IE 6, only the variable "window" can be used to connect events (others
+               may be only copies).
+               */
+               doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
+               //to prevent memory leak, unset it after use
+               //another possibility is to add an onUnload handler which seems overkill to me (liucougar)
+               var win = doc._parentWindow;
+               doc._parentWindow = null;
+               return win;     //      Window
+       }
 
-               if(this._setExpando){
-                       // change expando to/from dot or + icon, as appropriate
-                       this._setExpando(false);
+       return doc.parentWindow || doc.defaultView;     //      Window
+};
+
+window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
+       // summary:
+       //              Scroll the passed node into view, if it is not already.
+
+       // don't rely on node.scrollIntoView working just because the function is there
+
+       try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
+               node = dom.byId(node);
+               var doc = node.ownerDocument || baseWindow.doc,
+                       body = doc.body || baseWindow.body(),
+                       html = doc.documentElement || body.parentNode,
+                       isIE = has("ie"), isWK = has("webkit");
+               // if an untested browser, then use the native method
+               if((!(has("mozilla") || isIE || isWK || has("opera")) || node == body || node == html) && (typeof node.scrollIntoView != "undefined")){
+                       node.scrollIntoView(false); // short-circuit to native if possible
+                       return;
                }
+               var backCompat = doc.compatMode == 'BackCompat',
+                       clientAreaRoot = (isIE >= 9 && node.ownerDocument.parentWindow.frameElement)
+                               ? ((html.clientHeight > 0 && html.clientWidth > 0 && (body.clientHeight == 0 || body.clientWidth == 0 || body.clientHeight > html.clientHeight || body.clientWidth > html.clientWidth)) ? html : body)
+                               : (backCompat ? body : html),
+                       scrollRoot = isWK ? body : clientAreaRoot,
+                       rootWidth = clientAreaRoot.clientWidth,
+                       rootHeight = clientAreaRoot.clientHeight,
+                       rtl = !geom.isBodyLtr(),
+                       nodePos = pos || geom.position(node),
+                       el = node.parentNode,
+                       isFixed = function(el){
+                               return ((isIE <= 6 || (isIE && backCompat))? false : (style.get(el, 'position').toLowerCase() == "fixed"));
+                       };
+               if(isFixed(node)){ return; } // nothing to do
 
-               // Set leaf icon or folder icon, as appropriate
-               this._updateItemClasses(this.item);
+               while(el){
+                       if(el == body){ el = scrollRoot; }
+                       var elPos = geom.position(el),
+                               fixedPos = isFixed(el);
 
-               // On initial tree show, make the selected TreeNode as either the root node of the tree,
-               // or the first child, if the root node is hidden
-               if(this == tree.rootNode){
-                       var fc = this.tree.showRoot ? this : this.getChildren()[0];
-                       if(fc){
-                               fc.setFocusable(true);
-                               tree.lastFocused = fc;
+                       if(el == scrollRoot){
+                               elPos.w = rootWidth; elPos.h = rootHeight;
+                               if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
+                               if(elPos.x < 0 || !isIE){ elPos.x = 0; } // IE can have values > 0
+                               if(elPos.y < 0 || !isIE){ elPos.y = 0; }
                        }else{
-                               // fallback: no nodes in tree so focus on Tree <div> itself
-                               tree.domNode.setAttribute("tabIndex", "0");
+                               var pb = geom.getPadBorderExtents(el);
+                               elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
+                               var clientSize = el.clientWidth,
+                                       scrollBarSize = elPos.w - clientSize;
+                               if(clientSize > 0 && scrollBarSize > 0){
+                                       elPos.w = clientSize;
+                                       elPos.x += (rtl && (isIE || el.clientLeft > pb.l/*Chrome*/)) ? scrollBarSize : 0;
+                               }
+                               clientSize = el.clientHeight;
+                               scrollBarSize = elPos.h - clientSize;
+                               if(clientSize > 0 && scrollBarSize > 0){
+                                       elPos.h = clientSize;
+                               }
+                       }
+                       if(fixedPos){ // bounded by viewport, not parents
+                               if(elPos.y < 0){
+                                       elPos.h += elPos.y; elPos.y = 0;
+                               }
+                               if(elPos.x < 0){
+                                       elPos.w += elPos.x; elPos.x = 0;
+                               }
+                               if(elPos.y + elPos.h > rootHeight){
+                                       elPos.h = rootHeight - elPos.y;
+                               }
+                               if(elPos.x + elPos.w > rootWidth){
+                                       elPos.w = rootWidth - elPos.x;
+                               }
+                       }
+                       // calculate overflow in all 4 directions
+                       var l = nodePos.x - elPos.x, // beyond left: < 0
+                               t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
+                               r = l + nodePos.w - elPos.w, // beyond right: > 0
+                               bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
+                       if(r * l > 0){
+                               var s = Math[l < 0? "max" : "min"](l, r);
+                               if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; }
+                               nodePos.x += el.scrollLeft;
+                               el.scrollLeft += s;
+                               nodePos.x -= el.scrollLeft;
                        }
+                       if(bot * t > 0){
+                               nodePos.y += el.scrollTop;
+                               el.scrollTop += Math[t < 0? "max" : "min"](t, bot);
+                               nodePos.y -= el.scrollTop;
+                       }
+                       el = (el != scrollRoot) && !fixedPos && el.parentNode;
                }
+       }catch(error){
+               console.error('scrollIntoView: ' + error);
+               node.scrollIntoView(false);
+       }
+};
 
-               return new dojo.DeferredList(defs);     // dojo.Deferred
-       },
+return window;
+});
 
-       removeChild: function(/* treeNode */ node){
-               this.inherited(arguments);
+},
+'dojo/number':function(){
+define("dojo/number", ["./_base/kernel", "./_base/lang", "./i18n", "./i18n!./cldr/nls/number", "./string", "./regexp"],
+       function(dojo, lang, i18n, nlsNumber, dstring, dregexp) {
 
-               var children = this.getChildren();
-               if(children.length == 0){
-                       this.isExpandable = false;
-                       this.collapse();
-               }
+       // module:
+       //              dojo/number
+       // summary:
+       //              TODOC
 
-               dojo.forEach(children, function(child){
-                               child._updateLayout();
-               });
-       },
-
-       makeExpandable: function(){
-               // summary:
-               //              if this node wasn't already showing the expando node,
-               //              turn it into one and call _setExpando()
-
-               // TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0
+lang.getObject("number", true, dojo);
 
-               this.isExpandable = true;
-               this._setExpando(false);
-       },
+/*=====
+dojo.number = {
+       // summary: localized formatting and parsing routines for Number
+}
 
-       _onLabelFocus: function(evt){
-               // summary:
-               //              Called when this row is focused (possibly programatically)
-               //              Note that we aren't using _onFocus() builtin to dijit
-               //              because it's called when focus is moved to a descendant TreeNode.
-               // tags:
-               //              private
-               this.tree._onNodeFocus(this);
-       },
+dojo.number.__FormatOptions = function(){
+       //      pattern: String?
+       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+       //              with this string.  Default value is based on locale.  Overriding this property will defeat
+       //              localization.  Literal characters in patterns are not supported.
+       //      type: String?
+       //              choose a format type based on the locale from the following:
+       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
+       //      places: Number?
+       //              fixed number of decimal places to show.  This overrides any
+       //              information in the provided pattern.
+       //      round: Number?
+       //              5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
+       //              means do not round.
+       //      locale: String?
+       //              override the locale used to determine formatting rules
+       //      fractional: Boolean?
+       //              If false, show no decimal places, overriding places and pattern settings.
+       this.pattern = pattern;
+       this.type = type;
+       this.places = places;
+       this.round = round;
+       this.locale = locale;
+       this.fractional = fractional;
+}
+=====*/
 
-       setSelected: function(/*Boolean*/ selected){
-               // summary:
-               //              A Tree has a (single) currently selected node.
-               //              Mark that this node is/isn't that currently selected node.
-               // description:
-               //              In particular, setting a node as selected involves setting tabIndex
-               //              so that when user tabs to the tree, focus will go to that node (only).
-               dijit.setWaiState(this.labelNode, "selected", selected);
-               dojo.toggleClass(this.rowNode, "dijitTreeRowSelected", selected);
-       },
+dojo.number.format = function(/*Number*/value, /*dojo.number.__FormatOptions?*/options){
+       // summary:
+       //              Format a Number as a String, using locale-specific settings
+       // description:
+       //              Create a string from a Number using a known localized pattern.
+       //              Formatting patterns appropriate to the locale are chosen from the
+       //              [Common Locale Data Repository](http://unicode.org/cldr) as well as the appropriate symbols and
+       //              delimiters.
+       //              If value is Infinity, -Infinity, or is not a valid JavaScript number, return null.
+       // value:
+       //              the number to be formatted
 
-       setFocusable: function(/*Boolean*/ selected){
-               // summary:
-               //              A Tree has a (single) node that's focusable.
-               //              Mark that this node is/isn't that currently focsuable node.
-               // description:
-               //              In particular, setting a node as selected involves setting tabIndex
-               //              so that when user tabs to the tree, focus will go to that node (only).
+       options = lang.mixin({}, options || {});
+       var locale = i18n.normalizeLocale(options.locale),
+               bundle = i18n.getLocalization("dojo.cldr", "number", locale);
+       options.customs = bundle;
+       var pattern = options.pattern || bundle[(options.type || "decimal") + "Format"];
+       if(isNaN(value) || Math.abs(value) == Infinity){ return null; } // null
+       return dojo.number._applyPattern(value, pattern, options); // String
+};
 
-               this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
-       },
+//dojo.number._numberPatternRE = /(?:[#0]*,?)*[#0](?:\.0*#*)?/; // not precise, but good enough
+dojo.number._numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/; // not precise, but good enough
 
-       _onClick: function(evt){
-               // summary:
-               //              Handler for onclick event on a node
-               // tags:
-               //              private
-               this.tree._onClick(this, evt);
-       },
-       _onDblClick: function(evt){
-               // summary:
-               //              Handler for ondblclick event on a node
-               // tags:
-               //              private
-               this.tree._onDblClick(this, evt);
-       },
+dojo.number._applyPattern = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatOptions?*/options){
+       // summary:
+       //              Apply pattern to format value as a string using options. Gives no
+       //              consideration to local customs.
+       // value:
+       //              the number to be formatted.
+       // pattern:
+       //              a pattern string as described by
+       //              [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+       // options: dojo.number.__FormatOptions?
+       //              _applyPattern is usually called via `dojo.number.format()` which
+       //              populates an extra property in the options parameter, "customs".
+       //              The customs object specifies group and decimal parameters if set.
 
-       _onMouseEnter: function(evt){
-               // summary:
-               //              Handler for onmouseenter event on a node
-               // tags:
-               //              private
-               this.tree._onNodeMouseEnter(this, evt);
-       },
+       //TODO: support escapes
+       options = options || {};
+       var group = options.customs.group,
+               decimal = options.customs.decimal,
+               patternList = pattern.split(';'),
+               positivePattern = patternList[0];
+       pattern = patternList[(value < 0) ? 1 : 0] || ("-" + positivePattern);
 
-       _onMouseLeave: function(evt){
-               // summary:
-               //              Handler for onmouseenter event on a node
-               // tags:
-               //              private
-               this.tree._onNodeMouseLeave(this, evt);
+       //TODO: only test against unescaped
+       if(pattern.indexOf('%') != -1){
+               value *= 100;
+       }else if(pattern.indexOf('\u2030') != -1){
+               value *= 1000; // per mille
+       }else if(pattern.indexOf('\u00a4') != -1){
+               group = options.customs.currencyGroup || group;//mixins instead?
+               decimal = options.customs.currencyDecimal || decimal;// Should these be mixins instead?
+               pattern = pattern.replace(/\u00a4{1,3}/, function(match){
+                       var prop = ["symbol", "currency", "displayName"][match.length-1];
+                       return options[prop] || options.currency || "";
+               });
+       }else if(pattern.indexOf('E') != -1){
+               throw new Error("exponential notation not supported");
        }
-});
-
-dojo.declare(
-       "dijit.Tree",
-       [dijit._Widget, dijit._Templated],
-{
-       // summary:
-       //              This widget displays hierarchical data from a store.
 
-       // store: [deprecated] String||dojo.data.Store
-       //              Deprecated.  Use "model" parameter instead.
-       //              The store to get data to display in the tree.
-       store: null,
+       //TODO: support @ sig figs?
+       var numberPatternRE = dojo.number._numberPatternRE;
+       var numberPattern = positivePattern.match(numberPatternRE);
+       if(!numberPattern){
+               throw new Error("unable to find a number expression in pattern: "+pattern);
+       }
+       if(options.fractional === false){ options.places = 0; }
+       return pattern.replace(numberPatternRE,
+               dojo.number._formatAbsolute(value, numberPattern[0], {decimal: decimal, group: group, places: options.places, round: options.round}));
+};
 
-       // model: dijit.Tree.model
-       //              Interface to read tree data, get notifications of changes to tree data,
-       //              and for handling drop operations (i.e drag and drop onto the tree)
-       model: null,
+dojo.number.round = function(/*Number*/value, /*Number?*/places, /*Number?*/increment){
+       //      summary:
+       //              Rounds to the nearest value with the given number of decimal places, away from zero
+       //      description:
+       //              Rounds to the nearest value with the given number of decimal places, away from zero if equal.
+       //              Similar to Number.toFixed(), but compensates for browser quirks. Rounding can be done by
+       //              fractional increments also, such as the nearest quarter.
+       //              NOTE: Subject to floating point errors.  See dojox.math.round for experimental workaround.
+       //      value:
+       //              The number to round
+       //      places:
+       //              The number of decimal places where rounding takes place.  Defaults to 0 for whole rounding.
+       //              Must be non-negative.
+       //      increment:
+       //              Rounds next place to nearest value of increment/10.  10 by default.
+       //      example:
+       //              >>> dojo.number.round(-0.5)
+       //              -1
+       //              >>> dojo.number.round(162.295, 2)
+       //              162.29  // note floating point error.  Should be 162.3
+       //              >>> dojo.number.round(10.71, 0, 2.5)
+       //              10.75
+       var factor = 10 / (increment || 10);
+       return (factor * +value).toFixed(places) / factor; // Number
+};
 
-       // query: [deprecated] anything
-       //              Deprecated.  User should specify query to the model directly instead.
-       //              Specifies datastore query to return the root item or top items for the tree.
-       query: null,
+if((0.9).toFixed() == 0){
+       // (isIE) toFixed() bug workaround: Rounding fails on IE when most significant digit
+       // is just after the rounding place and is >=5
+       var round = dojo.number.round;
+       dojo.number.round = function(v, p, m){
+               var d = Math.pow(10, -p || 0), a = Math.abs(v);
+               if(!v || a >= d || a * Math.pow(10, p + 1) < 5){
+                       d = 0;
+               }
+               return round(v, p, m) + (v > 0 ? d : -d);
+       };
+}
 
-       // label: [deprecated] String
-       //              Deprecated.  Use dijit.tree.ForestStoreModel directly instead.
-       //              Used in conjunction with query parameter.
-       //              If a query is specified (rather than a root node id), and a label is also specified,
-       //              then a fake root node is created and displayed, with this label.
-       label: "",
+/*=====
+dojo.number.__FormatAbsoluteOptions = function(){
+       //      decimal: String?
+       //              the decimal separator
+       //      group: String?
+       //              the group separator
+       //      places: Number?|String?
+       //              number of decimal places.  the range "n,m" will format to m places.
+       //      round: Number?
+       //              5 rounds to nearest .5; 0 rounds to nearest whole (default). -1
+       //              means don't round.
+       this.decimal = decimal;
+       this.group = group;
+       this.places = places;
+       this.round = round;
+}
+=====*/
 
-       // showRoot: [const] Boolean
-       //              Should the root node be displayed, or hidden?
-       showRoot: true,
+dojo.number._formatAbsolute = function(/*Number*/value, /*String*/pattern, /*dojo.number.__FormatAbsoluteOptions?*/options){
+       // summary:
+       //              Apply numeric pattern to absolute value using options. Gives no
+       //              consideration to local customs.
+       // value:
+       //              the number to be formatted, ignores sign
+       // pattern:
+       //              the number portion of a pattern (e.g. `#,##0.00`)
+       options = options || {};
+       if(options.places === true){options.places=0;}
+       if(options.places === Infinity){options.places=6;} // avoid a loop; pick a limit
 
-       // childrenAttr: [deprecated] String[]
-       //              Deprecated.   This information should be specified in the model.
-       //              One ore more attributes that holds children of a tree node
-       childrenAttr: ["children"],
+       var patternParts = pattern.split("."),
+               comma = typeof options.places == "string" && options.places.indexOf(","),
+               maxPlaces = options.places;
+       if(comma){
+               maxPlaces = options.places.substring(comma + 1);
+       }else if(!(maxPlaces >= 0)){
+               maxPlaces = (patternParts[1] || []).length;
+       }
+       if(!(options.round < 0)){
+               value = dojo.number.round(value, maxPlaces, options.round);
+       }
 
-       // path: String[] or Item[]
-       //              Full path from rootNode to selected node expressed as array of items or array of ids.
-       //              Since setting the path may be asynchronous (because ofwaiting on dojo.data), set("path", ...)
-       //              returns a Deferred to indicate when the set is complete.
-       path: [],
+       var valueParts = String(Math.abs(value)).split("."),
+               fractional = valueParts[1] || "";
+       if(patternParts[1] || options.places){
+               if(comma){
+                       options.places = options.places.substring(0, comma);
+               }
+               // Pad fractional with trailing zeros
+               var pad = options.places !== undefined ? options.places : (patternParts[1] && patternParts[1].lastIndexOf("0") + 1);
+               if(pad > fractional.length){
+                       valueParts[1] = dstring.pad(fractional, pad, '0', true);
+               }
 
-       // selectedItem: [readonly] Item
-       //              The currently selected item in this tree.
-       //              This property can only be set (via set('selectedItem', ...)) when that item is already
-       //              visible in the tree.   (I.e. the tree has already been expanded to show that node.)
-       //              Should generally use `path` attribute to set the selected item instead.
-       selectedItem: null,
+               // Truncate fractional
+               if(maxPlaces < fractional.length){
+                       valueParts[1] = fractional.substr(0, maxPlaces);
+               }
+       }else{
+               if(valueParts[1]){ valueParts.pop(); }
+       }
 
-       // openOnClick: Boolean
-       //              If true, clicking a folder node's label will open it, rather than calling onClick()
-       openOnClick: false,
+       // Pad whole with leading zeros
+       var patternDigits = patternParts[0].replace(',', '');
+       pad = patternDigits.indexOf("0");
+       if(pad != -1){
+               pad = patternDigits.length - pad;
+               if(pad > valueParts[0].length){
+                       valueParts[0] = dstring.pad(valueParts[0], pad);
+               }
 
-       // openOnDblClick: Boolean
-       //              If true, double-clicking a folder node's label will open it, rather than calling onDblClick()
-       openOnDblClick: false,
+               // Truncate whole
+               if(patternDigits.indexOf("#") == -1){
+                       valueParts[0] = valueParts[0].substr(valueParts[0].length - pad);
+               }
+       }
 
-       templateString: dojo.cache("dijit", "templates/Tree.html", "<div class=\"dijitTree dijitTreeContainer\" waiRole=\"tree\"\n\tdojoAttachEvent=\"onkeypress:_onKeyPress\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" dojoAttachPoint=\"indentDetector\"></div>\n</div>\n"),
+       // Add group separators
+       var index = patternParts[0].lastIndexOf(','),
+               groupSize, groupSize2;
+       if(index != -1){
+               groupSize = patternParts[0].length - index - 1;
+               var remainder = patternParts[0].substr(0, index);
+               index = remainder.lastIndexOf(',');
+               if(index != -1){
+                       groupSize2 = remainder.length - index - 1;
+               }
+       }
+       var pieces = [];
+       for(var whole = valueParts[0]; whole;){
+               var off = whole.length - groupSize;
+               pieces.push((off > 0) ? whole.substr(off) : whole);
+               whole = (off > 0) ? whole.slice(0, off) : "";
+               if(groupSize2){
+                       groupSize = groupSize2;
+                       delete groupSize2;
+               }
+       }
+       valueParts[0] = pieces.reverse().join(options.group || ",");
 
-       // persist: Boolean
-       //              Enables/disables use of cookies for state saving.
-       persist: true,
+       return valueParts.join(options.decimal || ".");
+};
 
-       // autoExpand: Boolean
-       //              Fully expand the tree on load.   Overrides `persist`
-       autoExpand: false,
+/*=====
+dojo.number.__RegexpOptions = function(){
+       //      pattern: String?
+       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+       //              with this string.  Default value is based on locale.  Overriding this property will defeat
+       //              localization.
+       //      type: String?
+       //              choose a format type based on the locale from the following:
+       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
+       //      locale: String?
+       //              override the locale used to determine formatting rules
+       //      strict: Boolean?
+       //              strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
+       //              Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
+       //      places: Number|String?
+       //              number of decimal places to accept: Infinity, a positive number, or
+       //              a range "n,m".  Defined by pattern or Infinity if pattern not provided.
+       this.pattern = pattern;
+       this.type = type;
+       this.locale = locale;
+       this.strict = strict;
+       this.places = places;
+}
+=====*/
+dojo.number.regexp = function(/*dojo.number.__RegexpOptions?*/options){
+       //      summary:
+       //              Builds the regular needed to parse a number
+       //      description:
+       //              Returns regular expression with positive and negative match, group
+       //              and decimal separators
+       return dojo.number._parseInfo(options).regexp; // String
+};
 
-       // dndController: [protected] String
-       //              Class name to use as as the dnd controller.  Specifying this class enables DnD.
-       //              Generally you should specify this as "dijit.tree.dndSource".
-       dndController: null,
+dojo.number._parseInfo = function(/*Object?*/options){
+       options = options || {};
+       var locale = i18n.normalizeLocale(options.locale),
+               bundle = i18n.getLocalization("dojo.cldr", "number", locale),
+               pattern = options.pattern || bundle[(options.type || "decimal") + "Format"],
+//TODO: memoize?
+               group = bundle.group,
+               decimal = bundle.decimal,
+               factor = 1;
 
-       // parameters to pull off of the tree and pass on to the dndController as its params
-       dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"],
+       if(pattern.indexOf('%') != -1){
+               factor /= 100;
+       }else if(pattern.indexOf('\u2030') != -1){
+               factor /= 1000; // per mille
+       }else{
+               var isCurrency = pattern.indexOf('\u00a4') != -1;
+               if(isCurrency){
+                       group = bundle.currencyGroup || group;
+                       decimal = bundle.currencyDecimal || decimal;
+               }
+       }
 
-       //declare the above items so they can be pulled from the tree's markup
+       //TODO: handle quoted escapes
+       var patternList = pattern.split(';');
+       if(patternList.length == 1){
+               patternList.push("-" + patternList[0]);
+       }
 
-       // onDndDrop: [protected] Function
-       //              Parameter to dndController, see `dijit.tree.dndSource.onDndDrop`.
-       //              Generally this doesn't need to be set.
-       onDndDrop: null,
+       var re = dregexp.buildGroupRE(patternList, function(pattern){
+               pattern = "(?:"+dregexp.escapeString(pattern, '.')+")";
+               return pattern.replace(dojo.number._numberPatternRE, function(format){
+                       var flags = {
+                               signed: false,
+                               separator: options.strict ? group : [group,""],
+                               fractional: options.fractional,
+                               decimal: decimal,
+                               exponent: false
+                               },
 
-       /*=====
-       itemCreator: function(nodes, target, source){
-               // summary:
-               //              Returns objects passed to `Tree.model.newItem()` based on DnD nodes
-               //              dropped onto the tree.   Developer must override this method to enable
-               //              dropping from external sources onto this Tree, unless the Tree.model's items
-               //              happen to look like {id: 123, name: "Apple" } with no other attributes.
-               // description:
-               //              For each node in nodes[], which came from source, create a hash of name/value
-               //              pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
-               // nodes: DomNode[]
-               //              The DOMNodes dragged from the source container
-               // target: DomNode
-               //              The target TreeNode.rowNode
-               // source: dojo.dnd.Source
-               //              The source container the nodes were dragged from, perhaps another Tree or a plain dojo.dnd.Source
-               // returns: Object[]
-               //              Array of name/value hashes for each new item to be added to the Tree, like:
-               // |    [
-               // |            { id: 123, label: "apple", foo: "bar" },
-               // |            { id: 456, label: "pear", zaz: "bam" }
-               // |    ]
-               // tags:
-               //              extension
-               return [{}];
-       },
-       =====*/
-       itemCreator: null,
+                               parts = format.split('.'),
+                               places = options.places;
 
-       // onDndCancel: [protected] Function
-       //              Parameter to dndController, see `dijit.tree.dndSource.onDndCancel`.
-       //              Generally this doesn't need to be set.
-       onDndCancel: null,
+                       // special condition for percent (factor != 1)
+                       // allow decimal places even if not specified in pattern
+                       if(parts.length == 1 && factor != 1){
+                           parts[1] = "###";
+                       }
+                       if(parts.length == 1 || places === 0){
+                               flags.fractional = false;
+                       }else{
+                               if(places === undefined){ places = options.pattern ? parts[1].lastIndexOf('0') + 1 : Infinity; }
+                               if(places && options.fractional == undefined){flags.fractional = true;} // required fractional, unless otherwise specified
+                               if(!options.places && (places < parts[1].length)){ places += "," + parts[1].length; }
+                               flags.places = places;
+                       }
+                       var groups = parts[0].split(',');
+                       if(groups.length > 1){
+                               flags.groupSize = groups.pop().length;
+                               if(groups.length > 1){
+                                       flags.groupSize2 = groups.pop().length;
+                               }
+                       }
+                       return "("+dojo.number._realNumberRegexp(flags)+")";
+               });
+       }, true);
 
-/*=====
-       checkAcceptance: function(source, nodes){
-               // summary:
-               //              Checks if the Tree itself can accept nodes from this source
-               // source: dijit.tree._dndSource
-               //              The source which provides items
-               // nodes: DOMNode[]
-               //              Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
-               //              source is a dijit.Tree.
-               // tags:
-               //              extension
-               return true;    // Boolean
-       },
-=====*/
-       checkAcceptance: null,
+       if(isCurrency){
+               // substitute the currency symbol for the placeholder in the pattern
+               re = re.replace(/([\s\xa0]*)(\u00a4{1,3})([\s\xa0]*)/g, function(match, before, target, after){
+                       var prop = ["symbol", "currency", "displayName"][target.length-1],
+                               symbol = dregexp.escapeString(options[prop] || options.currency || "");
+                       before = before ? "[\\s\\xa0]" : "";
+                       after = after ? "[\\s\\xa0]" : "";
+                       if(!options.strict){
+                               if(before){before += "*";}
+                               if(after){after += "*";}
+                               return "(?:"+before+symbol+after+")?";
+                       }
+                       return before+symbol+after;
+               });
+       }
 
-/*=====
-       checkItemAcceptance: function(target, source, position){
-               // summary:
-               //              Stub function to be overridden if one wants to check for the ability to drop at the node/item level
-               // description:
-               //              In the base case, this is called to check if target can become a child of source.
-               //              When betweenThreshold is set, position="before" or "after" means that we
-               //              are asking if the source node can be dropped before/after the target node.
-               // target: DOMNode
-               //              The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
-               //              Use dijit.getEnclosingWidget(target) to get the TreeNode.
-               // source: dijit.tree.dndSource
-               //              The (set of) nodes we are dropping
-               // position: String
-               //              "over", "before", or "after"
-               // tags:
-               //              extension
-               return true;    // Boolean
-       },
-=====*/
-       checkItemAcceptance: null,
+//TODO: substitute localized sign/percent/permille/etc.?
 
-       // dragThreshold: Integer
-       //              Number of pixels mouse moves before it's considered the start of a drag operation
-       dragThreshold: 5,
+       // normalize whitespace and return
+       return {regexp: re.replace(/[\xa0 ]/g, "[\\s\\xa0]"), group: group, decimal: decimal, factor: factor}; // Object
+};
 
-       // betweenThreshold: Integer
-       //              Set to a positive value to allow drag and drop "between" nodes.
-       //
-       //              If during DnD mouse is over a (target) node but less than betweenThreshold
-       //              pixels from the bottom edge, dropping the the dragged node will make it
-       //              the next sibling of the target node, rather than the child.
-       //
-       //              Similarly, if mouse is over a target node but less that betweenThreshold
-       //              pixels from the top edge, dropping the dragged node will make it
-       //              the target node's previous sibling rather than the target node's child.
-       betweenThreshold: 0,
+/*=====
+dojo.number.__ParseOptions = function(){
+       //      pattern: String?
+       //              override [formatting pattern](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+       //              with this string.  Default value is based on locale.  Overriding this property will defeat
+       //              localization.  Literal characters in patterns are not supported.
+       //      type: String?
+       //              choose a format type based on the locale from the following:
+       //              decimal, scientific (not yet supported), percent, currency. decimal by default.
+       //      locale: String?
+       //              override the locale used to determine formatting rules
+       //      strict: Boolean?
+       //              strict parsing, false by default.  Strict parsing requires input as produced by the format() method.
+       //              Non-strict is more permissive, e.g. flexible on white space, omitting thousands separators
+       //      fractional: Boolean?|Array?
+       //              Whether to include the fractional portion, where the number of decimal places are implied by pattern
+       //              or explicit 'places' parameter.  The value [true,false] makes the fractional portion optional.
+       this.pattern = pattern;
+       this.type = type;
+       this.locale = locale;
+       this.strict = strict;
+       this.fractional = fractional;
+}
+=====*/
+dojo.number.parse = function(/*String*/expression, /*dojo.number.__ParseOptions?*/options){
+       // summary:
+       //              Convert a properly formatted string to a primitive Number, using
+       //              locale-specific settings.
+       // description:
+       //              Create a Number from a string using a known localized pattern.
+       //              Formatting patterns are chosen appropriate to the locale
+       //              and follow the syntax described by
+       //              [unicode.org TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns)
+       //              Note that literal characters in patterns are not supported.
+       // expression:
+       //              A string representation of a Number
+       var info = dojo.number._parseInfo(options),
+               results = (new RegExp("^"+info.regexp+"$")).exec(expression);
+       if(!results){
+               return NaN; //NaN
+       }
+       var absoluteMatch = results[1]; // match for the positive expression
+       if(!results[1]){
+               if(!results[2]){
+                       return NaN; //NaN
+               }
+               // matched the negative pattern
+               absoluteMatch =results[2];
+               info.factor *= -1;
+       }
 
-       // _nodePixelIndent: Integer
-       //              Number of pixels to indent tree nodes (relative to parent node).
-       //              Default is 19 but can be overridden by setting CSS class dijitTreeIndent
-       //              and calling resize() or startup() on tree after it's in the DOM.
-       _nodePixelIndent: 19,
+       // Transform it to something Javascript can parse as a number.  Normalize
+       // decimal point and strip out group separators or alternate forms of whitespace
+       absoluteMatch = absoluteMatch.
+               replace(new RegExp("["+info.group + "\\s\\xa0"+"]", "g"), "").
+               replace(info.decimal, ".");
+       // Adjust for negative sign, percent, etc. as necessary
+       return absoluteMatch * info.factor; //Number
+};
 
-       _publish: function(/*String*/ topicName, /*Object*/ message){
-               // summary:
-               //              Publish a message for this widget/topic
-               dojo.publish(this.id, [dojo.mixin({tree: this, event: topicName}, message || {})]);
-       },
+/*=====
+dojo.number.__RealNumberRegexpFlags = function(){
+       //      places: Number?
+       //              The integer number of decimal places or a range given as "n,m".  If
+       //              not given, the decimal part is optional and the number of places is
+       //              unlimited.
+       //      decimal: String?
+       //              A string for the character used as the decimal point.  Default
+       //              is ".".
+       //      fractional: Boolean?|Array?
+       //              Whether decimal places are used.  Can be true, false, or [true,
+       //              false].  Default is [true, false] which means optional.
+       //      exponent: Boolean?|Array?
+       //              Express in exponential notation.  Can be true, false, or [true,
+       //              false]. Default is [true, false], (i.e. will match if the
+       //              exponential part is present are not).
+       //      eSigned: Boolean?|Array?
+       //              The leading plus-or-minus sign on the exponent.  Can be true,
+       //              false, or [true, false].  Default is [true, false], (i.e. will
+       //              match if it is signed or unsigned).  flags in regexp.integer can be
+       //              applied.
+       this.places = places;
+       this.decimal = decimal;
+       this.fractional = fractional;
+       this.exponent = exponent;
+       this.eSigned = eSigned;
+}
+=====*/
 
-       postMixInProperties: function(){
-               this.tree = this;
+dojo.number._realNumberRegexp = function(/*dojo.number.__RealNumberRegexpFlags?*/flags){
+       // summary:
+       //              Builds a regular expression to match a real number in exponential
+       //              notation
 
-               if(this.autoExpand){
-                       // There's little point in saving opened/closed state of nodes for a Tree
-                       // that initially opens all it's nodes.
-                       this.persist = false;
-               }
+       // assign default values to missing parameters
+       flags = flags || {};
+       //TODO: use mixin instead?
+       if(!("places" in flags)){ flags.places = Infinity; }
+       if(typeof flags.decimal != "string"){ flags.decimal = "."; }
+       if(!("fractional" in flags) || /^0/.test(flags.places)){ flags.fractional = [true, false]; }
+       if(!("exponent" in flags)){ flags.exponent = [true, false]; }
+       if(!("eSigned" in flags)){ flags.eSigned = [true, false]; }
 
-               this._itemNodesMap={};
+       var integerRE = dojo.number._integerRegexp(flags),
+               decimalRE = dregexp.buildGroupRE(flags.fractional,
+               function(q){
+                       var re = "";
+                       if(q && (flags.places!==0)){
+                               re = "\\" + flags.decimal;
+                               if(flags.places == Infinity){
+                                       re = "(?:" + re + "\\d+)?";
+                               }else{
+                                       re += "\\d{" + flags.places + "}";
+                               }
+                       }
+                       return re;
+               },
+               true
+       );
 
-               if(!this.cookieName){
-                       this.cookieName = this.id + "SaveStateCookie";
+       var exponentRE = dregexp.buildGroupRE(flags.exponent,
+               function(q){
+                       if(q){ return "([eE]" + dojo.number._integerRegexp({ signed: flags.eSigned}) + ")"; }
+                       return "";
                }
+       );
 
-               this._loadDeferred = new dojo.Deferred();
+       var realRE = integerRE + decimalRE;
+       // allow for decimals without integers, e.g. .25
+       if(decimalRE){realRE = "(?:(?:"+ realRE + ")|(?:" + decimalRE + "))";}
+       return realRE + exponentRE; // String
+};
 
-               this.inherited(arguments);
-       },
+/*=====
+dojo.number.__IntegerRegexpFlags = function(){
+       //      signed: Boolean?
+       //              The leading plus-or-minus sign. Can be true, false, or `[true,false]`.
+       //              Default is `[true, false]`, (i.e. will match if it is signed
+       //              or unsigned).
+       //      separator: String?
+       //              The character used as the thousands separator. Default is no
+       //              separator. For more than one symbol use an array, e.g. `[",", ""]`,
+       //              makes ',' optional.
+       //      groupSize: Number?
+       //              group size between separators
+       //      groupSize2: Number?
+       //              second grouping, where separators 2..n have a different interval than the first separator (for India)
+       this.signed = signed;
+       this.separator = separator;
+       this.groupSize = groupSize;
+       this.groupSize2 = groupSize2;
+}
+=====*/
 
-       postCreate: function(){
-               this._initState();
+dojo.number._integerRegexp = function(/*dojo.number.__IntegerRegexpFlags?*/flags){
+       // summary:
+       //              Builds a regular expression that matches an integer
 
-               // Create glue between store and Tree, if not specified directly by user
-               if(!this.model){
-                       this._store2model();
-               }
+       // assign default values to missing parameters
+       flags = flags || {};
+       if(!("signed" in flags)){ flags.signed = [true, false]; }
+       if(!("separator" in flags)){
+               flags.separator = "";
+       }else if(!("groupSize" in flags)){
+               flags.groupSize = 3;
+       }
 
-               // monitor changes to items
-               this.connect(this.model, "onChange", "_onItemChange");
-               this.connect(this.model, "onChildrenChange", "_onItemChildrenChange");
-               this.connect(this.model, "onDelete", "_onItemDelete");
+       var signRE = dregexp.buildGroupRE(flags.signed,
+               function(q){ return q ? "[-+]" : ""; },
+               true
+       );
 
-               this._load();
+       var numberRE = dregexp.buildGroupRE(flags.separator,
+               function(sep){
+                       if(!sep){
+                               return "(?:\\d+)";
+                       }
 
-               this.inherited(arguments);
+                       sep = dregexp.escapeString(sep);
+                       if(sep == " "){ sep = "\\s"; }
+                       else if(sep == "\xa0"){ sep = "\\s\\xa0"; }
 
-               if(this.dndController){
-                       if(dojo.isString(this.dndController)){
-                               this.dndController = dojo.getObject(this.dndController);
-                       }
-                       var params={};
-                       for(var i=0; i<this.dndParams.length;i++){
-                               if(this[this.dndParams[i]]){
-                                       params[this.dndParams[i]] = this[this.dndParams[i]];
-                               }
+                       var grp = flags.groupSize, grp2 = flags.groupSize2;
+                       //TODO: should we continue to enforce that numbers with separators begin with 1-9?  See #6933
+                       if(grp2){
+                               var grp2RE = "(?:0|[1-9]\\d{0," + (grp2-1) + "}(?:[" + sep + "]\\d{" + grp2 + "})*[" + sep + "]\\d{" + grp + "})";
+                               return ((grp-grp2) > 0) ? "(?:" + grp2RE + "|(?:0|[1-9]\\d{0," + (grp-1) + "}))" : grp2RE;
                        }
-                       this.dndController = new this.dndController(this, params);
-               }
-       },
+                       return "(?:0|[1-9]\\d{0," + (grp-1) + "}(?:[" + sep + "]\\d{" + grp + "})*)";
+               },
+               true
+       );
 
-       _store2model: function(){
-               // summary:
-               //              User specified a store&query rather than model, so create model from store/query
-               this._v10Compat = true;
-               dojo.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
+       return signRE + numberRE; // String
+};
 
-               var modelParams = {
-                       id: this.id + "_ForestStoreModel",
-                       store: this.store,
-                       query: this.query,
-                       childrenAttrs: this.childrenAttr
-               };
+return dojo.number;
+});
 
-               // Only override the model's mayHaveChildren() method if the user has specified an override
-               if(this.params.mayHaveChildren){
-                       modelParams.mayHaveChildren = dojo.hitch(this, "mayHaveChildren");
-               }
+},
+'dijit/_FocusMixin':function(){
+define("dijit/_FocusMixin", [
+       "./focus",
+       "./_WidgetBase",
+       "dojo/_base/declare", // declare
+       "dojo/_base/lang" // lang.extend
+], function(focus, _WidgetBase, declare, lang){
 
-               if(this.params.getItemChildren){
-                       modelParams.getChildren = dojo.hitch(this, function(item, onComplete, onError){
-                               this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError);
-                       });
-               }
-               this.model = new dijit.tree.ForestStoreModel(modelParams);
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+=====*/
 
-               // For backwards compatibility, the visibility of the root node is controlled by
-               // whether or not the user has specified a label
-               this.showRoot = Boolean(this.label);
-       },
+       // module:
+       //              dijit/_FocusMixin
+       // summary:
+       //              Mixin to widget to provide _onFocus() and _onBlur() methods that
+       //              fire when a widget or it's descendants get/lose focus
+
+       // We don't know where _FocusMixin will occur in the inheritance chain, but we need the _onFocus()/_onBlur() below
+       // to be last in the inheritance chain, so mixin to _WidgetBase.
+       lang.extend(_WidgetBase, {
+               // focused: [readonly] Boolean
+               //              This widget or a widget it contains has focus, or is "active" because
+               //              it was recently clicked.
+               focused: false,
+
+               onFocus: function(){
+                       // summary:
+                       //              Called when the widget becomes "active" because
+                       //              it or a widget inside of it either has focus, or has recently
+                       //              been clicked.
+                       // tags:
+                       //              callback
+               },
 
-       onLoad: function(){
-               // summary:
-               //              Called when tree finishes loading and expanding.
-               // description:
-               //              If persist == true the loading may encompass many levels of fetches
-               //              from the data store, each asynchronous.   Waits for all to finish.
-               // tags:
-               //              callback
-       },
+               onBlur: function(){
+                       // summary:
+                       //              Called when the widget stops being "active" because
+                       //              focus moved to something outside of it, or the user
+                       //              clicked somewhere outside of it, or the widget was
+                       //              hidden.
+                       // tags:
+                       //              callback
+               },
 
-       _load: function(){
+               _onFocus: function(){
+                       // summary:
+                       //              This is where widgets do processing for when they are active,
+                       //              such as changing CSS classes.  See onFocus() for more details.
+                       // tags:
+                       //              protected
+                       this.onFocus();
+               },
+
+               _onBlur: function(){
+                       // summary:
+                       //              This is where widgets do processing for when they stop being active,
+                       //              such as changing CSS classes.  See onBlur() for more details.
+                       // tags:
+                       //              protected
+                       this.onBlur();
+               }
+       });
+
+       return declare("dijit._FocusMixin", null, {
                // summary:
-               //              Initial load of the tree.
-               //              Load root node (possibly hidden) and it's children.
-               this.model.getRoot(
-                       dojo.hitch(this, function(item){
-                               var rn = (this.rootNode = this.tree._createTreeNode({
-                                       item: item,
-                                       tree: this,
-                                       isExpandable: true,
-                                       label: this.label || this.getLabel(item),
-                                       indent: this.showRoot ? 0 : -1
-                               }));
-                               if(!this.showRoot){
-                                       rn.rowNode.style.display="none";
-                               }
-                               this.domNode.appendChild(rn.domNode);
-                               var identity = this.model.getIdentity(item);
-                               if(this._itemNodesMap[identity]){
-                                       this._itemNodesMap[identity].push(rn);
-                               }else{
-                                       this._itemNodesMap[identity] = [rn];
-                               }
+               //              Mixin to widget to provide _onFocus() and _onBlur() methods that
+               //              fire when a widget or it's descendants get/lose focus
 
-                               rn._updateLayout();             // sets "dijitTreeIsRoot" CSS classname
+               // flag that I want _onFocus()/_onBlur() notifications from focus manager
+               _focusManager: focus
+       });
 
-                               // load top level children and then fire onLoad() event
-                               this._expandNode(rn).addCallback(dojo.hitch(this, function(){
-                                       this._loadDeferred.callback(true);
-                                       this.onLoad();
-                               }));
-                       }),
-                       function(err){
-                               console.error(this, ": error loading root: ", err);
-                       }
-               );
-       },
+});
 
-       getNodesByItem: function(/*dojo.data.Item or id*/ item){
-               // summary:
-               //              Returns all tree nodes that refer to an item
-               // returns:
-               //              Array of tree nodes that refer to passed item
+},
+'dojo/data/util/filter':function(){
+define("dojo/data/util/filter", ["dojo/_base/lang"], function(lang) {
+       // module:
+       //              dojo/data/util/filter
+       // summary:
+       //              TODOC
 
-               if(!item){ return []; }
-               var identity = dojo.isString(item) ? item : this.model.getIdentity(item);
-               // return a copy so widget don't get messed up by changes to returned array
-               return [].concat(this._itemNodesMap[identity]);
-       },
+var filter = lang.getObject("dojo.data.util.filter", true);
 
-       _setSelectedItemAttr: function(/*dojo.data.Item or id*/ item){
-               // summary:
-               //              Select a tree node related to passed item.
-               //              WARNING: if model use multi-parented items or desired tree node isn't already loaded
-               //              behavior is undefined. Use set('path', ...) instead.
+filter.patternToRegExp = function(/*String*/pattern, /*boolean?*/ ignoreCase){
+       //      summary:
+       //              Helper function to convert a simple pattern to a regular expression for matching.
+       //      description:
+       //              Returns a regular expression object that conforms to the defined conversion rules.
+       //              For example:
+       //                      ca*   -> /^ca.*$/
+       //                      *ca*  -> /^.*ca.*$/
+       //                      *c\*a*  -> /^.*c\*a.*$/
+       //                      *c\*a?*  -> /^.*c\*a..*$/
+       //                      and so on.
+       //
+       //      pattern: string
+       //              A simple matching pattern to convert that follows basic rules:
+       //                      * Means match anything, so ca* means match anything starting with ca
+       //                      ? Means match single character.  So, b?b will match to bob and bab, and so on.
+       //              \ is an escape character.  So for example, \* means do not treat * as a match, but literal character *.
+       //                              To use a \ as a character in the string, it must be escaped.  So in the pattern it should be
+       //                              represented by \\ to be treated as an ordinary \ character instead of an escape.
+       //
+       //      ignoreCase:
+       //              An optional flag to indicate if the pattern matching should be treated as case-sensitive or not when comparing
+       //              By default, it is assumed case sensitive.
 
-               var oldValue = this.get("selectedItem");
-               var identity = (!item || dojo.isString(item)) ? item : this.model.getIdentity(item);
-               if(identity == oldValue ? this.model.getIdentity(oldValue) : null){ return; }
-               var nodes = this._itemNodesMap[identity];
-               this._selectNode((nodes && nodes[0]) || null);  //select the first item
-       },
+       var rxp = "^";
+       var c = null;
+       for(var i = 0; i < pattern.length; i++){
+               c = pattern.charAt(i);
+               switch(c){
+                       case '\\':
+                               rxp += c;
+                               i++;
+                               rxp += pattern.charAt(i);
+                               break;
+                       case '*':
+                               rxp += ".*"; break;
+                       case '?':
+                               rxp += "."; break;
+                       case '$':
+                       case '^':
+                       case '/':
+                       case '+':
+                       case '.':
+                       case '|':
+                       case '(':
+                       case ')':
+                       case '{':
+                       case '}':
+                       case '[':
+                       case ']':
+                               rxp += "\\"; //fallthrough
+                       default:
+                               rxp += c;
+               }
+       }
+       rxp += "$";
+       if(ignoreCase){
+               return new RegExp(rxp,"mi"); //RegExp
+       }else{
+               return new RegExp(rxp,"m"); //RegExp
+       }
 
-       _getSelectedItemAttr: function(){
-               // summary:
-               //              Return item related to selected tree node.
-               return this.selectedNode && this.selectedNode.item;
-       },
+};
 
-       _setPathAttr: function(/*Item[] || String[]*/ path){
+return filter;
+});
+
+},
+'dijit/_WidgetsInTemplateMixin':function(){
+define("dijit/_WidgetsInTemplateMixin", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/parser", // parser.parse
+       "dijit/registry"        // registry.findWidgets
+], function(array, declare, parser, registry){
+
+       // module:
+       //              dijit/_WidgetsInTemplateMixin
+       // summary:
+       //              Mixin to supplement _TemplatedMixin when template contains widgets
+
+       return declare("dijit._WidgetsInTemplateMixin", null, {
                // summary:
-               //              Select the tree node identified by passed path.
-               // path:
-               //              Array of items or item id's
-               // returns:
-               //              Deferred to indicate when the set is complete
+               //              Mixin to supplement _TemplatedMixin when template contains widgets
 
-               var d = new dojo.Deferred();
+               // _earlyTemplatedStartup: Boolean
+               //              A fallback to preserve the 1.0 - 1.3 behavior of children in
+               //              templates having their startup called before the parent widget
+               //              fires postCreate. Defaults to 'false', causing child widgets to
+               //              have their .startup() called immediately before a parent widget
+               //              .startup(), but always after the parent .postCreate(). Set to
+               //              'true' to re-enable to previous, arguably broken, behavior.
+               _earlyTemplatedStartup: false,
 
-               this._selectNode(null);
-               if(!path || !path.length){
-                       d.resolve(true);
-                       return d;
-               }
+               // widgetsInTemplate: [protected] Boolean
+               //              Should we parse the template to find widgets that might be
+               //              declared in markup inside it?  (Remove for 2.0 and assume true)
+               widgetsInTemplate: true,
 
-               // If this is called during initialization, defer running until Tree has finished loading
-               this._loadDeferred.addCallback(dojo.hitch(this, function(){
-                       if(!this.rootNode){
-                               d.reject(new Error("!this.rootNode"));
-                               return;
-                       }
-                       if(path[0] !== this.rootNode.item && (dojo.isString(path[0]) && path[0] != this.model.getIdentity(this.rootNode.item))){
-                               d.reject(new Error(this.id + ":path[0] doesn't match this.rootNode.item.  Maybe you are using the wrong tree."));
-                               return;
-                       }
-                       path.shift();
+               _beforeFillContent: function(){
+                       if(this.widgetsInTemplate){
+                               // Before copying over content, instantiate widgets in template
+                               var node = this.domNode;
 
-                       var node = this.rootNode;
+                               var cw = (this._startupWidgets = parser.parse(node, {
+                                       noStart: !this._earlyTemplatedStartup,
+                                       template: true,
+                                       inherited: {dir: this.dir, lang: this.lang, textDir: this.textDir},
+                                       propsThis: this,        // so data-dojo-props of widgets in the template can reference "this" to refer to me
+                                       scope: "dojo"   // even in multi-version mode templates use dojoType/data-dojo-type
+                               }));
 
-                       function advance(){
-                               // summary:
-                               //              Called when "node" has completed loading and expanding.   Pop the next item from the path
-                               //              (which must be a child of "node") and advance to it, and then recurse.
-
-                               // Set item and identity to next item in path (node is pointing to the item that was popped
-                               // from the path _last_ time.
-                               var item = path.shift(),
-                                       identity = dojo.isString(item) ? item : this.model.getIdentity(item);
-
-                               // Change "node" from previous item in path to the item we just popped from path
-                               dojo.some(this._itemNodesMap[identity], function(n){
-                                       if(n.getParent() == node){
-                                               node = n;
-                                               return true;
-                                       }
-                                       return false;
-                               });
+                               this._supportingWidgets = registry.findWidgets(node);
 
-                               if(path.length){
-                                       // Need to do more expanding
-                                       this._expandNode(node).addCallback(dojo.hitch(this, advance));
-                               }else{
-                                       // Final destination node, select it
-                                       this._selectNode(node);
-                                       
-                                       // signal that path setting is finished
-                                       d.resolve(true);
-                               }
+                               this._attachTemplateNodes(cw, function(n,p){
+                                       return n[p];
+                               });
                        }
+               },
 
-                       this._expandNode(node).addCallback(dojo.hitch(this, advance));
-               }));
-                       
-               return d;
-       },
-
-       _getPathAttr: function(){
-               // summary:
-               //              Return an array of items that is the path to selected tree node.
-               if(!this.selectedNode){ return; }
-               var res = [];
-               var treeNode = this.selectedNode;
-               while(treeNode && treeNode !== this.rootNode){
-                       res.unshift(treeNode.item);
-                       treeNode = treeNode.getParent();
+               startup: function(){
+                       array.forEach(this._startupWidgets, function(w){
+                               if(w && !w._started && w.startup){
+                                       w.startup();
+                               }
+                       });
+                       this.inherited(arguments);
                }
-               res.unshift(this.rootNode.item);
-               return res;
-       },
-
-       ////////////// Data store related functions //////////////////////
-       // These just get passed to the model; they are here for back-compat
+       });
+});
 
-       mayHaveChildren: function(/*dojo.data.Item*/ item){
-               // summary:
-               //              Deprecated.   This should be specified on the model itself.
-               //
-               //              Overridable function to tell if an item has or may have children.
-               //              Controls whether or not +/- expando icon is shown.
-               //              (For efficiency reasons we may not want to check if an element actually
-               //              has children until user clicks the expando node)
-               // tags:
-               //              deprecated
-       },
+},
+'dojo/fx/Toggler':function(){
+define("dojo/fx/Toggler", ["../_base/lang","../_base/declare","../_base/fx", "../_base/connect"], 
+  function(lang, declare, baseFx, connectUtil) {
+       // module:
+       //              dojo/fx/Toggler
+       // summary:
+       //              TODOC
 
-       getItemChildren: function(/*dojo.data.Item*/ parentItem, /*function(items)*/ onComplete){
-               // summary:
-               //              Deprecated.   This should be specified on the model itself.
-               //
-               //              Overridable function that return array of child items of given parent item,
-               //              or if parentItem==null then return top items in tree
-               // tags:
-               //              deprecated
-       },
+return declare("dojo.fx.Toggler", null, {
+       // summary:
+       //              A simple `dojo.Animation` toggler API.
+       //
+       // description:
+       //              class constructor for an animation toggler. It accepts a packed
+       //              set of arguments about what type of animation to use in each
+       //              direction, duration, etc. All available members are mixed into
+       //              these animations from the constructor (for example, `node`,
+       //              `showDuration`, `hideDuration`).
+       //
+       // example:
+       //      |       var t = new dojo.fx.Toggler({
+       //      |               node: "nodeId",
+       //      |               showDuration: 500,
+       //      |               // hideDuration will default to "200"
+       //      |               showFunc: dojo.fx.wipeIn,
+       //      |               // hideFunc will default to "fadeOut"
+       //      |       });
+       //      |       t.show(100); // delay showing for 100ms
+       //      |       // ...time passes...
+       //      |       t.hide();
 
-       ///////////////////////////////////////////////////////
-       // Functions for converting an item to a TreeNode
-       getLabel: function(/*dojo.data.Item*/ item){
-               // summary:
-               //              Overridable function to get the label for a tree node (given the item)
-               // tags:
-               //              extension
-               return this.model.getLabel(item);       // String
-       },
+       // node: DomNode
+       //              the node to target for the showing and hiding animations
+       node: null,
 
-       getIconClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS class name to display icon
-               // tags:
-               //              extension
-               return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
-       },
+       // showFunc: Function
+       //              The function that returns the `dojo.Animation` to show the node
+       showFunc: baseFx.fadeIn,
 
-       getLabelClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS class name to display label
-               // tags:
-               //              extension
-       },
+       // hideFunc: Function
+       //              The function that returns the `dojo.Animation` to hide the node
+       hideFunc: baseFx.fadeOut,
 
-       getRowClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS class name to display row
-               // tags:
-               //              extension
-       },
+       // showDuration:
+       //              Time in milliseconds to run the show Animation
+       showDuration: 200,
 
-       getIconStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS styles to display icon
-               // returns:
-               //              Object suitable for input to dojo.style() like {backgroundImage: "url(...)"}
-               // tags:
-               //              extension
-       },
+       // hideDuration:
+       //              Time in milliseconds to run the hide Animation
+       hideDuration: 200,
 
-       getLabelStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS styles to display label
-               // returns:
-               //              Object suitable for input to dojo.style() like {color: "red", background: "green"}
-               // tags:
-               //              extension
-       },
+       // FIXME: need a policy for where the toggler should "be" the next
+       // time show/hide are called if we're stopped somewhere in the
+       // middle.
+       // FIXME: also would be nice to specify individual showArgs/hideArgs mixed into
+       // each animation individually.
+       // FIXME: also would be nice to have events from the animations exposed/bridged
 
-       getRowStyle: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
-               // summary:
-               //              Overridable function to return CSS styles to display row
-               // returns:
-               //              Object suitable for input to dojo.style() like {background-color: "#bbb"}
-               // tags:
-               //              extension
-       },
+       /*=====
+       _showArgs: null,
+       _showAnim: null,
 
-       getTooltip: function(/*dojo.data.Item*/ item){
-               // summary:
-               //              Overridable function to get the tooltip for a tree node (given the item)
-               // tags:
-               //              extension
-               return "";      // String
-       },
+       _hideArgs: null,
+       _hideAnim: null,
 
-       /////////// Keyboard and Mouse handlers ////////////////////
+       _isShowing: false,
+       _isHiding: false,
+       =====*/
 
-       _onKeyPress: function(/*Event*/ e){
-               // summary:
-               //              Translates keypress events into commands for the controller
-               if(e.altKey){ return; }
-               var dk = dojo.keys;
-               var treeNode = dijit.getEnclosingWidget(e.target);
-               if(!treeNode){ return; }
+       constructor: function(args){
+               var _t = this;
 
-               var key = e.charOrCode;
-               if(typeof key == "string"){     // handle printables (letter navigation)
-                       // Check for key navigation.
-                       if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
-                               this._onLetterKeyNav( { node: treeNode, key: key.toLowerCase() } );
-                               dojo.stopEvent(e);
-                       }
-               }else{  // handle non-printables (arrow keys)
-                       // clear record of recent printables (being saved for multi-char letter navigation),
-                       // because "a", down-arrow, "b" shouldn't search for "ab"
-                       if(this._curSearch){
-                               clearTimeout(this._curSearch.timer);
-                               delete this._curSearch;
-                       }
+               lang.mixin(_t, args);
+               _t.node = args.node;
+               _t._showArgs = lang.mixin({}, args);
+               _t._showArgs.node = _t.node;
+               _t._showArgs.duration = _t.showDuration;
+               _t.showAnim = _t.showFunc(_t._showArgs);
 
-                       var map = this._keyHandlerMap;
-                       if(!map){
-                               // setup table mapping keys to events
-                               map = {};
-                               map[dk.ENTER]="_onEnterKey";
-                               map[this.isLeftToRight() ? dk.LEFT_ARROW : dk.RIGHT_ARROW]="_onLeftArrow";
-                               map[this.isLeftToRight() ? dk.RIGHT_ARROW : dk.LEFT_ARROW]="_onRightArrow";
-                               map[dk.UP_ARROW]="_onUpArrow";
-                               map[dk.DOWN_ARROW]="_onDownArrow";
-                               map[dk.HOME]="_onHomeKey";
-                               map[dk.END]="_onEndKey";
-                               this._keyHandlerMap = map;
-                       }
-                       if(this._keyHandlerMap[key]){
-                               this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } );
-                               dojo.stopEvent(e);
-                       }
-               }
-       },
+               _t._hideArgs = lang.mixin({}, args);
+               _t._hideArgs.node = _t.node;
+               _t._hideArgs.duration = _t.hideDuration;
+               _t.hideAnim = _t.hideFunc(_t._hideArgs);
 
-       _onEnterKey: function(/*Object*/ message, /*Event*/ evt){
-               this._publish("execute", { item: message.item, node: message.node } );
-               this._selectNode(message.node);
-               this.onClick(message.item, message.node, evt);
+               connectUtil.connect(_t.showAnim, "beforeBegin", lang.hitch(_t.hideAnim, "stop", true));
+               connectUtil.connect(_t.hideAnim, "beforeBegin", lang.hitch(_t.showAnim, "stop", true));
        },
 
-       _onDownArrow: function(/*Object*/ message){
-               // summary:
-               //              down arrow pressed; get next visible node, set focus there
-               var node = this._getNextNode(message.node);
-               if(node && node.isTreeNode){
-                       this.focusNode(node);
-               }
+       show: function(delay){
+               // summary: Toggle the node to showing
+               // delay: Integer?
+               //              Ammount of time to stall playing the show animation
+               return this.showAnim.play(delay || 0);
        },
 
-       _onUpArrow: function(/*Object*/ message){
-               // summary:
-               //              Up arrow pressed; move to previous visible node
+       hide: function(delay){
+               // summary: Toggle the node to hidden
+               // delay: Integer?
+               //              Ammount of time to stall playing the hide animation
+               return this.hideAnim.play(delay || 0);
+       }
+});
 
-               var node = message.node;
+});
 
-               // if younger siblings
-               var previousSibling = node.getPreviousSibling();
-               if(previousSibling){
-                       node = previousSibling;
-                       // if the previous node is expanded, dive in deep
-                       while(node.isExpandable && node.isExpanded && node.hasChildren()){
-                               // move to the last child
-                               var children = node.getChildren();
-                               node = children[children.length-1];
-                       }
-               }else{
-                       // if this is the first child, return the parent
-                       // unless the parent is the root of a tree with a hidden root
-                       var parent = node.getParent();
-                       if(!(!this.showRoot && parent === this.rootNode)){
-                               node = parent;
-                       }
-               }
+},
+'dijit/form/FilteringSelect':function(){
+define("dijit/form/FilteringSelect", [
+       "dojo/data/util/filter", // filter.patternToRegExp
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred", // Deferred.when
+       "dojo/_base/lang", // lang.mixin
+       "./MappedTextBox",
+       "./ComboBoxMixin"
+], function(filter, declare, Deferred, lang, MappedTextBox, ComboBoxMixin){
 
-               if(node && node.isTreeNode){
-                       this.focusNode(node);
-               }
-       },
+/*=====
+       var MappedTextBox = dijit.form.MappedTextBox;
+       var ComboBoxMixin = dijit.form.ComboBoxMixin;
+=====*/
 
-       _onRightArrow: function(/*Object*/ message){
-               // summary:
-               //              Right arrow pressed; go to child node
-               var node = message.node;
+       // module:
+       //              dijit/form/FilteringSelect
+       // summary:
+       //              An enhanced version of the HTML SELECT tag, populated dynamically
 
-               // if not expanded, expand, else move to 1st child
-               if(node.isExpandable && !node.isExpanded){
-                       this._expandNode(node);
-               }else if(node.hasChildren()){
-                       node = node.getChildren()[0];
-                       if(node && node.isTreeNode){
-                               this.focusNode(node);
-                       }
-               }
-       },
 
-       _onLeftArrow: function(/*Object*/ message){
+       return declare("dijit.form.FilteringSelect", [MappedTextBox, ComboBoxMixin], {
                // summary:
-               //              Left arrow pressed.
-               //              If not collapsed, collapse, else move to parent.
+               //              An enhanced version of the HTML SELECT tag, populated dynamically
+               //
+               // description:
+               //              An enhanced version of the HTML SELECT tag, populated dynamically. It works
+               //              very nicely with very large data sets because it can load and page data as needed.
+               //              It also resembles ComboBox, but does not allow values outside of the provided ones.
+               //              If OPTION tags are used as the data provider via markup, then the
+               //              OPTION tag's child text node is used as the displayed value when selected
+               //              while the OPTION tag's value attribute is used as the widget value on form submit.
+               //              To set the default value when using OPTION tags, specify the selected
+               //              attribute on 1 of the child OPTION tags.
+               //
+               //              Similar features:
+               //                      - There is a drop down list of possible values.
+               //                      - You can only enter a value from the drop down list.  (You can't
+               //                              enter an arbitrary value.)
+               //                      - The value submitted with the form is the hidden value (ex: CA),
+               //                              not the displayed value a.k.a. label (ex: California)
+               //
+               //              Enhancements over plain HTML version:
+               //                      - If you type in some text then it will filter down the list of
+               //                              possible values in the drop down list.
+               //                      - List can be specified either as a static list or via a javascript
+               //                              function (that can get the list from a server)
 
-               var node = message.node;
+               // required: Boolean
+               //              True (default) if user is required to enter a value into this field.
+               required: true,
 
-               if(node.isExpandable && node.isExpanded){
-                       this._collapseNode(node);
-               }else{
-                       var parent = node.getParent();
-                       if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){
-                               this.focusNode(parent);
+               _lastDisplayedValue: "",
+
+               _isValidSubset: function(){
+                       return this._opened;
+               },
+
+               isValid: function(){
+                       // Overrides ValidationTextBox.isValid()
+                       return !!this.item || (!this.required && this.get('displayedValue') == ""); // #5974
+               },
+
+               _refreshState: function(){
+                       if(!this.searchTimer){ // state will be refreshed after results are returned
+                               this.inherited(arguments);
                        }
-               }
-       },
+               },
 
-       _onHomeKey: function(){
-               // summary:
-               //              Home key pressed; get first visible node, and set focus there
-               var node = this._getRootOrFirstNode();
-               if(node){
-                       this.focusNode(node);
-               }
-       },
+               _callbackSetLabel: function(
+                                               /*Array*/ result,
+                                               /*Object*/ query,
+                                               /*Object*/ options,
+                                               /*Boolean?*/ priorityChange){
+                       // summary:
+                       //              Callback from dojo.store after lookup of user entered value finishes
 
-       _onEndKey: function(/*Object*/ message){
-               // summary:
-               //              End key pressed; go to last visible node.
+                       // setValue does a synchronous lookup,
+                       // so it calls _callbackSetLabel directly,
+                       // and so does not pass dataObject
+                       // still need to test against _lastQuery in case it came too late
+                       if((query && query[this.searchAttr] !== this._lastQuery) || (!query && result.length && this.store.getIdentity(result[0]) != this._lastQuery)){
+                               return;
+                       }
+                       if(!result.length){
+                               //#3268: don't modify display value on bad input
+                               //#3285: change CSS to indicate error
+                               this.set("value", '', priorityChange || (priorityChange === undefined && !this.focused), this.textbox.value, null);
+                       }else{
+                               this.set('item', result[0], priorityChange);
+                       }
+               },
 
-               var node = this.rootNode;
-               while(node.isExpanded){
-                       var c = node.getChildren();
-                       node = c[c.length - 1];
-               }
+               _openResultList: function(/*Object*/ results, /*Object*/ query, /*Object*/ options){
+                       // Callback when a data store query completes.
+                       // Overrides ComboBox._openResultList()
 
-               if(node && node.isTreeNode){
-                       this.focusNode(node);
-               }
-       },
+                       // #3285: tap into search callback to see if user's query resembles a match
+                       if(query[this.searchAttr] !== this._lastQuery){
+                               return;
+                       }
+                       this.inherited(arguments);
 
-       // multiCharSearchDuration: Number
-       //              If multiple characters are typed where each keystroke happens within
-       //              multiCharSearchDuration of the previous keystroke,
-       //              search for nodes matching all the keystrokes.
-       //
-       //              For example, typing "ab" will search for entries starting with
-       //              "ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration.
-       multiCharSearchDuration: 250,
+                       if(this.item === undefined){ // item == undefined for keyboard search
+                               // If the search returned no items that means that the user typed
+                               // in something invalid (and they can't make it valid by typing more characters),
+                               // so flag the FilteringSelect as being in an invalid state
+                               this.validate(true);
+                       }
+               },
 
-       _onLetterKeyNav: function(message){
-               // summary:
-               //              Called when user presses a prinatable key; search for node starting with recently typed letters.
-               // message: Object
-               //              Like { node: TreeNode, key: 'a' } where key is the key the user pressed.
+               _getValueAttr: function(){
+                       // summary:
+                       //              Hook for get('value') to work.
 
-               // Branch depending on whether this key starts a new search, or modifies an existing search
-               var cs = this._curSearch;
-               if(cs){
-                       // We are continuing a search.  Ex: user has pressed 'a', and now has pressed
-                       // 'b', so we want to search for nodes starting w/"ab".
-                       cs.pattern = cs.pattern + message.key;
-                       clearTimeout(cs.timer);
-               }else{
-                       // We are starting a new search
-                       cs = this._curSearch = {
-                                       pattern: message.key,
-                                       startNode: message.node
-                       };
-               }
-
-               // set/reset timer to forget recent keystrokes
-               var self = this;
-               cs.timer = setTimeout(function(){
-                       delete self._curSearch;
-               }, this.multiCharSearchDuration);
-
-               // Navigate to TreeNode matching keystrokes [entered so far].
-               var node = cs.startNode;
-               do{
-                       node = this._getNextNode(node);
-                       //check for last node, jump to first node if necessary
-                       if(!node){
-                               node = this._getRootOrFirstNode();
-                       }
-               }while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern));
-               if(node && node.isTreeNode){
-                       // no need to set focus if back where we started
-                       if(node !== cs.startNode){
-                               this.focusNode(node);
-                       }
-               }
-       },
-
-       _onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
-               // summary:
-               //              Translates click events into commands for the controller to process
+                       // don't get the textbox value but rather the previously set hidden value.
+                       // Use this.valueNode.value which isn't always set for other MappedTextBox widgets until blur
+                       return this.valueNode.value;
+               },
 
-               var domElement = e.target,
-                       isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
+               _getValueField: function(){
+                       // Overrides ComboBox._getValueField()
+                       return "value";
+               },
 
-               if( (this.openOnClick && nodeWidget.isExpandable) || isExpandoClick ){
-                       // expando node was clicked, or label of a folder node was clicked; open it
-                       if(nodeWidget.isExpandable){
-                               this._onExpandoClick({node:nodeWidget});
-                       }
-               }else{
-                       this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
-                       this.onClick(nodeWidget.item, nodeWidget, e);
-                       this.focusNode(nodeWidget);
-               }
-               if(!isExpandoClick){
-                       this._selectNode(nodeWidget);
-               }
-               dojo.stopEvent(e);
-       },
-       _onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
-               // summary:
-               //              Translates double-click events into commands for the controller to process
+               _setValueAttr: function(/*String*/ value, /*Boolean?*/ priorityChange, /*String?*/ displayedValue, /*item?*/ item){
+                       // summary:
+                       //              Hook so set('value', value) works.
+                       // description:
+                       //              Sets the value of the select.
+                       //              Also sets the label to the corresponding value by reverse lookup.
+                       if(!this._onChangeActive){ priorityChange = null; }
 
-               var domElement = e.target,
-                       isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
+                       if(item === undefined){
+                               if(value === null || value === ''){
+                                       value = '';
+                                       if(!lang.isString(displayedValue)){
+                                               this._setDisplayedValueAttr(displayedValue||'', priorityChange);
+                                               return;
+                                       }
+                               }
 
-               if( (this.openOnDblClick && nodeWidget.isExpandable) ||isExpandoClick ){
-                       // expando node was clicked, or label of a folder node was clicked; open it
-                       if(nodeWidget.isExpandable){
-                               this._onExpandoClick({node:nodeWidget});
+                               var self = this;
+                               this._lastQuery = value;
+                               Deferred.when(this.store.get(value), function(item){
+                                       self._callbackSetLabel(item? [item] : [], undefined, undefined, priorityChange);
+                               });
+                       }else{
+                               this.valueNode.value = value;
+                               this.inherited(arguments);
                        }
-               }else{
-                       this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
-                       this.onDblClick(nodeWidget.item, nodeWidget, e);
-                       this.focusNode(nodeWidget);
-               }
-               if(!isExpandoClick){
-                       this._selectNode(nodeWidget);
-               }
-               dojo.stopEvent(e);
-       },
-
-       _onExpandoClick: function(/*Object*/ message){
-               // summary:
-               //              User clicked the +/- icon; expand or collapse my children.
-               var node = message.node;
+               },
 
-               // If we are collapsing, we might be hiding the currently focused node.
-               // Also, clicking the expando node might have erased focus from the current node.
-               // For simplicity's sake just focus on the node with the expando.
-               this.focusNode(node);
+               _setItemAttr: function(/*item*/ item, /*Boolean?*/ priorityChange, /*String?*/ displayedValue){
+                       // summary:
+                       //              Set the displayed valued in the input box, and the hidden value
+                       //              that gets submitted, based on a dojo.data store item.
+                       // description:
+                       //              Users shouldn't call this function; they should be calling
+                       //              set('item', value)
+                       // tags:
+                       //              private
+                       this.inherited(arguments);
+                       this._lastDisplayedValue = this.textbox.value;
+               },
 
-               if(node.isExpanded){
-                       this._collapseNode(node);
-               }else{
-                       this._expandNode(node);
-               }
-       },
+               _getDisplayQueryString: function(/*String*/ text){
+                       return text.replace(/([\\\*\?])/g, "\\$1");
+               },
 
-       onClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
-               // summary:
-               //              Callback when a tree node is clicked
-               // tags:
-               //              callback
-       },
-       onDblClick: function(/* dojo.data */ item, /*TreeNode*/ node, /*Event*/ evt){
-               // summary:
-               //              Callback when a tree node is double-clicked
-               // tags:
-               //              callback
-       },
-       onOpen: function(/* dojo.data */ item, /*TreeNode*/ node){
-               // summary:
-               //              Callback when a node is opened
-               // tags:
-               //              callback
-       },
-       onClose: function(/* dojo.data */ item, /*TreeNode*/ node){
-               // summary:
-               //              Callback when a node is closed
-               // tags:
-               //              callback
-       },
+               _setDisplayedValueAttr: function(/*String*/ label, /*Boolean?*/ priorityChange){
+                       // summary:
+                       //              Hook so set('displayedValue', label) works.
+                       // description:
+                       //              Sets textbox to display label. Also performs reverse lookup
+                       //              to set the hidden value.  label should corresponding to item.searchAttr.
 
-       _getNextNode: function(node){
-               // summary:
-               //              Get next visible node
+                       if(label == null){ label = ''; }
 
-               if(node.isExpandable && node.isExpanded && node.hasChildren()){
-                       // if this is an expanded node, get the first child
-                       return node.getChildren()[0];           // _TreeNode
-               }else{
-                       // find a parent node with a sibling
-                       while(node && node.isTreeNode){
-                               var returnNode = node.getNextSibling();
-                               if(returnNode){
-                                       return returnNode;              // _TreeNode
+                       // This is called at initialization along with every custom setter.
+                       // Usually (or always?) the call can be ignored.   If it needs to be
+                       // processed then at least make sure that the XHR request doesn't trigger an onChange()
+                       // event, even if it returns after creation has finished
+                       if(!this._created){
+                               if(!("displayedValue" in this.params)){
+                                       return;
                                }
-                               node = node.getParent();
+                               priorityChange = false;
                        }
-                       return null;
-               }
-       },
-
-       _getRootOrFirstNode: function(){
-               // summary:
-               //              Get first visible node
-               return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0];
-       },
-
-       _collapseNode: function(/*_TreeNode*/ node){
-               // summary:
-               //              Called when the user has requested to collapse the node
-
-               if(node._expandNodeDeferred){
-                       delete node._expandNodeDeferred;
-               }
 
-               if(node.isExpandable){
-                       if(node.state == "LOADING"){
-                               // ignore clicks while we are in the process of loading data
-                               return;
-                       }
+                       // Do a reverse lookup to map the specified displayedValue to the hidden value.
+                       // Note that if there's a custom labelFunc() this code
+                       if(this.store){
+                               this.closeDropDown();
+                               var query = lang.clone(this.query); // #6196: populate query with user-specifics
 
-                       node.collapse();
-                       this.onClose(node.item, node);
+                               // Generate query
+                               var qs = this._getDisplayQueryString(label), q;
+                               if(this.store._oldAPI){
+                                       // remove this branch for 2.0
+                                       q = qs;
+                               }else{
+                                       // Query on searchAttr is a regex for benefit of dojo.store.Memory,
+                                       // but with a toString() method to help dojo.store.JsonRest.
+                                       // Search string like "Co*" converted to regex like /^Co.*$/i.
+                                       q = filter.patternToRegExp(qs, this.ignoreCase);
+                                       q.toString = function(){ return qs; };
+                               }
+                               this._lastQuery = query[this.searchAttr] = q;
 
-                       if(node.item){
-                               this._state(node.item,false);
-                               this._saveState();
+                               // If the label is not valid, the callback will never set it,
+                               // so the last valid value will get the warning textbox.   Set the
+                               // textbox value now so that the impending warning will make
+                               // sense to the user
+                               this.textbox.value = label;
+                               this._lastDisplayedValue = label;
+                               this._set("displayedValue", label);     // for watch("displayedValue") notification
+                               var _this = this;
+                               var options = {
+                                       ignoreCase: this.ignoreCase,
+                                       deep: true
+                               };
+                               lang.mixin(options, this.fetchProperties);
+                               this._fetchHandle = this.store.query(query, options);
+                               Deferred.when(this._fetchHandle, function(result){
+                                       _this._fetchHandle = null;
+                                       _this._callbackSetLabel(result || [], query, options, priorityChange);
+                               }, function(err){
+                                       _this._fetchHandle = null;
+                                       if(!_this._cancelingQuery){     // don't treat canceled query as an error
+                                               console.error('dijit.form.FilteringSelect: ' + err.toString());
+                                       }
+                               });
                        }
-               }
-       },
-
-       _expandNode: function(/*_TreeNode*/ node, /*Boolean?*/ recursive){
-               // summary:
-               //              Called when the user has requested to expand the node
-               // recursive:
-               //              Internal flag used when _expandNode() calls itself, don't set.
-               // returns:
-               //              Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants
-               //              that were previously opened too
+               },
 
-               if(node._expandNodeDeferred && !recursive){
-                       // there's already an expand in progress (or completed), so just return
-                       return node._expandNodeDeferred;        // dojo.Deferred
+               undo: function(){
+                       this.set('displayedValue', this._lastDisplayedValue);
                }
+       });
+});
 
-               var model = this.model,
-                       item = node.item,
-                       _this = this;
+},
+'dojo/data/util/sorter':function(){
+define("dojo/data/util/sorter", ["dojo/_base/lang"], function(lang) {
+       // module:
+       //              dojo/data/util/sorter
+       // summary:
+       //              TODOC
 
-               switch(node.state){
-                       case "UNCHECKED":
-                               // need to load all the children, and then expand
-                               node.markProcessing();
+var sorter = lang.getObject("dojo.data.util.sorter", true);
 
-                               // Setup deferred to signal when the load and expand are finished.
-                               // Save that deferred in this._expandDeferred as a flag that operation is in progress.
-                               var def = (node._expandNodeDeferred = new dojo.Deferred());
+sorter.basicComparator = function(     /*anything*/ a,
+                                                                                                       /*anything*/ b){
+       //      summary:
+       //              Basic comparision function that compares if an item is greater or less than another item
+       //      description:
+       //              returns 1 if a > b, -1 if a < b, 0 if equal.
+       //              'null' values (null, undefined) are treated as larger values so that they're pushed to the end of the list.
+       //              And compared to each other, null is equivalent to undefined.
 
-                               // Get the children
-                               model.getChildren(
-                                       item,
-                                       function(items){
-                                               node.unmarkProcessing();
+       //null is a problematic compare, so if null, we set to undefined.
+       //Makes the check logic simple, compact, and consistent
+       //And (null == undefined) === true, so the check later against null
+       //works for undefined and is less bytes.
+       var r = -1;
+       if(a === null){
+               a = undefined;
+       }
+       if(b === null){
+               b = undefined;
+       }
+       if(a == b){
+               r = 0;
+       }else if(a > b || a == null){
+               r = 1;
+       }
+       return r; //int {-1,0,1}
+};
 
-                                               // Display the children and also start expanding any children that were previously expanded
-                                               // (if this.persist == true).   The returned Deferred will fire when those expansions finish.
-                                               var scid = node.setChildItems(items);
-
-                                               // Call _expandNode() again but this time it will just to do the animation (default branch).
-                                               // The returned Deferred will fire when the animation completes.
-                                               // TODO: seems like I can avoid recursion and just use a deferred to sequence the events?
-                                               var ed = _this._expandNode(node, true);
-
-                                               // After the above two tasks (setChildItems() and recursive _expandNode()) finish,
-                                               // signal that I am done.
-                                               scid.addCallback(function(){
-                                                       ed.addCallback(function(){
-                                                               def.callback();
-                                                       })
-                                               });
-                                       },
-                                       function(err){
-                                               console.error(_this, ": error loading root children: ", err);
-                                       }
-                               );
-                               break;
-
-                       default:        // "LOADED"
-                               // data is already loaded; just expand node
-                               def = (node._expandNodeDeferred = node.expand());
-
-                               this.onOpen(node.item, node);
+sorter.createSortFunction = function(  /* attributes array */sortSpec, /*dojo.data.core.Read*/ store){
+       //      summary:
+       //              Helper function to generate the sorting function based off the list of sort attributes.
+       //      description:
+       //              The sort function creation will look for a property on the store called 'comparatorMap'.  If it exists
+       //              it will look in the mapping for comparisons function for the attributes.  If one is found, it will
+       //              use it instead of the basic comparator, which is typically used for strings, ints, booleans, and dates.
+       //              Returns the sorting function for this particular list of attributes and sorting directions.
+       //
+       //      sortSpec: array
+       //              A JS object that array that defines out what attribute names to sort on and whether it should be descenting or asending.
+       //              The objects should be formatted as follows:
+       //              {
+       //                      attribute: "attributeName-string" || attribute,
+       //                      descending: true|false;   // Default is false.
+       //              }
+       //      store: object
+       //              The datastore object to look up item values from.
+       //
+       var sortFunctions=[];
 
-                               if(item){
-                                       this._state(item, true);
-                                       this._saveState();
+       function createSortFunction(attr, dir, comp, s){
+               //Passing in comp and s (comparator and store), makes this
+               //function much faster.
+               return function(itemA, itemB){
+                       var a = s.getValue(itemA, attr);
+                       var b = s.getValue(itemB, attr);
+                       return dir * comp(a,b); //int
+               };
+       }
+       var sortAttribute;
+       var map = store.comparatorMap;
+       var bc = sorter.basicComparator;
+       for(var i = 0; i < sortSpec.length; i++){
+               sortAttribute = sortSpec[i];
+               var attr = sortAttribute.attribute;
+               if(attr){
+                       var dir = (sortAttribute.descending) ? -1 : 1;
+                       var comp = bc;
+                       if(map){
+                               if(typeof attr !== "string" && ("toString" in attr)){
+                                        attr = attr.toString();
                                }
+                               comp = map[attr] || bc;
+                       }
+                       sortFunctions.push(createSortFunction(attr,
+                               dir, comp, store));
                }
+       }
+       return function(rowA, rowB){
+               var i=0;
+               while(i < sortFunctions.length){
+                       var ret = sortFunctions[i++](rowA, rowB);
+                       if(ret !== 0){
+                               return ret;//int
+                       }
+               }
+               return 0; //int
+       }; // Function
+};
 
-               return def;     // dojo.Deferred
-       },
-
-       ////////////////// Miscellaneous functions ////////////////
+return sorter;
+});
 
-       focusNode: function(/* _tree.Node */ node){
-               // summary:
-               //              Focus on the specified node (which must be visible)
-               // tags:
-               //              protected
+},
+'dijit/form/_ButtonMixin':function(){
+define("dijit/form/_ButtonMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.setSelectable
+       "dojo/_base/event", // event.stop
+       "../registry"           // registry.byNode
+], function(declare, dom, event, registry){
+
+// module:
+//             dijit/form/_ButtonMixin
+// summary:
+//             A mixin to add a thin standard API wrapper to a normal HTML button
 
-               // set focus so that the label will be voiced using screen readers
-               dijit.focus(node.labelNode);
-       },
+return declare("dijit.form._ButtonMixin", null, {
+       // summary:
+       //              A mixin to add a thin standard API wrapper to a normal HTML button
+       // description:
+       //              A label should always be specified (through innerHTML) or the label attribute.
+       //              Attach points:
+       //                      focusNode (required): this node receives focus
+       //                      valueNode (optional): this node's value gets submitted with FORM elements
+       //                      containerNode (optional): this node gets the innerHTML assignment for label
+       // example:
+       // |    <button data-dojo-type="dijit.form.Button" onClick="...">Hello world</button>
+       //
+       // example:
+       // |    var button1 = new dijit.form.Button({label: "hello world", onClick: foo});
+       // |    dojo.body().appendChild(button1.domNode);
 
-       _selectNode: function(/*_tree.Node*/ node){
-               // summary:
-               //              Mark specified node as select, and unmark currently selected node.
-               // tags:
-               //              protected
+       // label: HTML String
+       //              Content to display in button.
+       label: "",
 
-               if(this.selectedNode && !this.selectedNode._destroyed){
-                       this.selectedNode.setSelected(false);
-               }
-               if(node){
-                       node.setSelected(true);
-               }
-               this.selectedNode = node;
-       },
+       // type: [const] String
+       //              Type of button (submit, reset, button, checkbox, radio)
+       type: "button",
 
-       _onNodeFocus: function(/*dijit._Widget*/ node){
+       _onClick: function(/*Event*/ e){
                // summary:
-               //              Called when a TreeNode gets focus, either by user clicking
-               //              it, or programatically by arrow key handling code.
-               // description:
-               //              It marks that the current node is the selected one, and the previously
-               //              selected node no longer is.
-
-               if(node && node != this.lastFocused){
-                       if(this.lastFocused && !this.lastFocused._destroyed){
-                               // mark that the previously focsable node is no longer focusable
-                               this.lastFocused.setFocusable(false);
+               //              Internal function to handle click actions
+               if(this.disabled){
+                       event.stop(e);
+                       return false;
+               }
+               var preventDefault = this.onClick(e) === false; // user click actions
+               if(!preventDefault && this.type == "submit" && !(this.valueNode||this.focusNode).form){ // see if a non-form widget needs to be signalled
+                       for(var node=this.domNode; node.parentNode; node=node.parentNode){
+                               var widget=registry.byNode(node);
+                               if(widget && typeof widget._onSubmit == "function"){
+                                       widget._onSubmit(e);
+                                       preventDefault = true;
+                                       break;
+                               }
                        }
-
-                       // mark that the new node is the currently selected one
-                       node.setFocusable(true);
-                       this.lastFocused = node;
                }
+               if(preventDefault){
+                       e.preventDefault();
+               }
+               return !preventDefault;
        },
 
-       _onNodeMouseEnter: function(/*dijit._Widget*/ node){
-               // summary:
-               //              Called when mouse is over a node (onmouseenter event),
-               //              this is monitored by the DND code
+       postCreate: function(){
+               this.inherited(arguments);
+               dom.setSelectable(this.focusNode, false);
        },
 
-       _onNodeMouseLeave: function(/*dijit._Widget*/ node){
+       onClick: function(/*Event*/ /*===== e =====*/){
                // summary:
-               //              Called when mouse leaves a node (onmouseleave event),
-               //              this is monitored by the DND code
+               //              Callback for when button is clicked.
+               //              If type="submit", return true to perform submit, or false to cancel it.
+               // type:
+               //              callback
+               return true;            // Boolean
        },
 
-       //////////////// Events from the model //////////////////////////
-
-       _onItemChange: function(/*Item*/ item){
+       _setLabelAttr: function(/*String*/ content){
                // summary:
-               //              Processes notification of a change to an item's scalar values like label
-               var model = this.model,
-                       identity = model.getIdentity(item),
-                       nodes = this._itemNodesMap[identity];
+               //              Hook for set('label', ...) to work.
+               // description:
+               //              Set the label (text) of the button; takes an HTML string.
+               this._set("label", content);
+               (this.containerNode||this.focusNode).innerHTML = content;
+       }
+});
 
-               if(nodes){
-                       var label = this.getLabel(item),
-                               tooltip = this.getTooltip(item);
-                       dojo.forEach(nodes, function(node){
-                               node.set({
-                                       item: item,             // theoretically could be new JS Object representing same item
-                                       label: label,
-                                       tooltip: tooltip
-                               });
-                               node._updateItemClasses(item);
-                       });
-               }
-       },
+});
 
-       _onItemChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
-               // summary:
-               //              Processes notification of a change to an item's children
-               var model = this.model,
-                       identity = model.getIdentity(parent),
-                       parentNodes = this._itemNodesMap[identity];
+},
+'dojo/colors':function(){
+define("dojo/colors", ["./_base/kernel", "./_base/lang", "./_base/Color", "./_base/array"], function(dojo, lang, Color, ArrayUtil) {
+       // module:
+       //              dojo/colors
+       // summary:
+       //              TODOC
 
-               if(parentNodes){
-                       dojo.forEach(parentNodes,function(parentNode){
-                               parentNode.setChildItems(newChildrenList);
-                       });
-               }
-       },
+       var ColorExt = lang.getObject("dojo.colors", true);
 
-       _onItemDelete: function(/*Item*/ item){
-               // summary:
-               //              Processes notification of a deletion of an item
-               var model = this.model,
-                       identity = model.getIdentity(item),
-                       nodes = this._itemNodesMap[identity];
+//TODO: this module appears to break naming conventions
 
-               if(nodes){
-                       dojo.forEach(nodes,function(node){
-                               var parent = node.getParent();
-                               if(parent){
-                                       // if node has not already been orphaned from a _onSetItem(parent, "children", ..) call...
-                                       parent.removeChild(node);
-                               }
-                               node.destroyRecursive();
-                       });
-                       delete this._itemNodesMap[identity];
+/*=====
+       lang.mixin(dojo, {
+               colors: {
+                       // summary: Color utilities, extending Base dojo.Color
                }
-       },
-
-       /////////////// Miscellaneous funcs
+       });
+=====*/
 
-       _initState: function(){
+       // this is a standard conversion prescribed by the CSS3 Color Module
+       var hue2rgb = function(m1, m2, h){
+               if(h < 0){ ++h; }
+               if(h > 1){ --h; }
+               var h6 = 6 * h;
+               if(h6 < 1){ return m1 + (m2 - m1) * h6; }
+               if(2 * h < 1){ return m2; }
+               if(3 * h < 2){ return m1 + (m2 - m1) * (2 / 3 - h) * 6; }
+               return m1;
+       };
+       // Override base Color.fromRgb with the impl in this module
+       dojo.colorFromRgb = Color.fromRgb = function(/*String*/ color, /*dojo.Color?*/ obj){
                // summary:
-               //              Load in which nodes should be opened automatically
-               if(this.persist){
-                       var cookie = dojo.cookie(this.cookieName);
-                       this._openedItemIds = {};
-                       if(cookie){
-                               dojo.forEach(cookie.split(','), function(item){
-                                       this._openedItemIds[item] = true;
-                               }, this);
+               //              get rgb(a) array from css-style color declarations
+               // description:
+               //              this function can handle all 4 CSS3 Color Module formats: rgb,
+               //              rgba, hsl, hsla, including rgb(a) with percentage values.
+               var m = color.toLowerCase().match(/^(rgba?|hsla?)\(([\s\.\-,%0-9]+)\)/);
+               if(m){
+                       var c = m[2].split(/\s*,\s*/), l = c.length, t = m[1], a;
+                       if((t == "rgb" && l == 3) || (t == "rgba" && l == 4)){
+                               var r = c[0];
+                               if(r.charAt(r.length - 1) == "%"){
+                                       // 3 rgb percentage values
+                                       a = ArrayUtil.map(c, function(x){
+                                               return parseFloat(x) * 2.56;
+                                       });
+                                       if(l == 4){ a[3] = c[3]; }
+                                       return Color.fromArray(a, obj); // dojo.Color
+                               }
+                               return Color.fromArray(c, obj); // dojo.Color
+                       }
+                       if((t == "hsl" && l == 3) || (t == "hsla" && l == 4)){
+                               // normalize hsl values
+                               var H = ((parseFloat(c[0]) % 360) + 360) % 360 / 360,
+                                       S = parseFloat(c[1]) / 100,
+                                       L = parseFloat(c[2]) / 100,
+                                       // calculate rgb according to the algorithm
+                                       // recommended by the CSS3 Color Module
+                                       m2 = L <= 0.5 ? L * (S + 1) : L + S - L * S,
+                                       m1 = 2 * L - m2;
+                               a = [
+                                       hue2rgb(m1, m2, H + 1 / 3) * 256,
+                                       hue2rgb(m1, m2, H) * 256,
+                                       hue2rgb(m1, m2, H - 1 / 3) * 256,
+                                       1
+                               ];
+                               if(l == 4){ a[3] = c[3]; }
+                               return Color.fromArray(a, obj); // dojo.Color
                        }
                }
-       },
-       _state: function(item,expanded){
+               return null;    // dojo.Color
+       };
+
+       var confine = function(c, low, high){
                // summary:
-               //              Query or set expanded state for an item,
-               if(!this.persist){
-                       return false;
-               }
-               var id=this.model.getIdentity(item);
-               if(arguments.length === 1){
-                       return this._openedItemIds[id];
-               }
-               if(expanded){
-                       this._openedItemIds[id] = true;
-               }else{
-                       delete this._openedItemIds[id];
-               }
-       },
-       _saveState: function(){
-               // summary:
-               //              Create and save a cookie with the currently expanded nodes identifiers
-               if(!this.persist){
-                       return;
-               }
-               var ary = [];
-               for(var id in this._openedItemIds){
-                       ary.push(id);
-               }
-               dojo.cookie(this.cookieName, ary.join(","), {expires:365});
-       },
-
-       destroy: function(){
-               if(this._curSearch){
-                       clearTimeout(this._curSearch.timer);
-                       delete this._curSearch;
-               }
-               if(this.rootNode){
-                       this.rootNode.destroyRecursive();
-               }
-               if(this.dndController && !dojo.isString(this.dndController)){
-                       this.dndController.destroy();
-               }
-               this.rootNode = null;
-               this.inherited(arguments);
-       },
-
-       destroyRecursive: function(){
-               // A tree is treated as a leaf, not as a node with children (like a grid),
-               // but defining destroyRecursive for back-compat.
-               this.destroy();
-       },
+               //              sanitize a color component by making sure it is a number,
+               //              and clamping it to valid values
+               c = Number(c);
+               return isNaN(c) ? high : c < low ? low : c > high ? high : c;   // Number
+       };
 
-       resize: function(changeSize){
-               if(changeSize){
-                       dojo.marginBox(this.domNode, changeSize);
-                       dojo.style(this.domNode, "overflow", "auto");   // for scrollbars
-               }
+       Color.prototype.sanitize = function(){
+               // summary: makes sure that the object has correct attributes
+               var t = this;
+               t.r = Math.round(confine(t.r, 0, 255));
+               t.g = Math.round(confine(t.g, 0, 255));
+               t.b = Math.round(confine(t.b, 0, 255));
+               t.a = confine(t.a, 0, 1);
+               return this;    // dojo.Color
+       };
 
-               // The only JS sizing involved w/tree is the indentation, which is specified
-               // in CSS and read in through this dummy indentDetector node (tree must be
-               // visible and attached to the DOM to read this)
-               this._nodePixelIndent = dojo.marginBox(this.tree.indentDetector).w;
+       ColorExt.makeGrey = Color.makeGrey = function(/*Number*/ g, /*Number?*/ a){
+               // summary: creates a greyscale color with an optional alpha
+               return Color.fromArray([g, g, g, a]);   // dojo.Color
+       };
 
-               if(this.tree.rootNode){
-                       // If tree has already loaded, then reset indent for all the nodes
-                       this.tree.rootNode.set('indent', this.showRoot ? 0 : -1);
-               }
-       },
+       // mixin all CSS3 named colors not already in _base, along with SVG 1.0 variant spellings
+       lang.mixin(Color.named, {
+               "aliceblue":    [240,248,255],
+               "antiquewhite": [250,235,215],
+               "aquamarine":   [127,255,212],
+               "azure":        [240,255,255],
+               "beige":        [245,245,220],
+               "bisque":       [255,228,196],
+               "blanchedalmond":       [255,235,205],
+               "blueviolet":   [138,43,226],
+               "brown":        [165,42,42],
+               "burlywood":    [222,184,135],
+               "cadetblue":    [95,158,160],
+               "chartreuse":   [127,255,0],
+               "chocolate":    [210,105,30],
+               "coral":        [255,127,80],
+               "cornflowerblue":       [100,149,237],
+               "cornsilk": [255,248,220],
+               "crimson":      [220,20,60],
+               "cyan": [0,255,255],
+               "darkblue": [0,0,139],
+               "darkcyan": [0,139,139],
+               "darkgoldenrod":        [184,134,11],
+               "darkgray": [169,169,169],
+               "darkgreen":    [0,100,0],
+               "darkgrey": [169,169,169],
+               "darkkhaki":    [189,183,107],
+               "darkmagenta":  [139,0,139],
+               "darkolivegreen":       [85,107,47],
+               "darkorange":   [255,140,0],
+               "darkorchid":   [153,50,204],
+               "darkred":      [139,0,0],
+               "darksalmon":   [233,150,122],
+               "darkseagreen": [143,188,143],
+               "darkslateblue":        [72,61,139],
+               "darkslategray":        [47,79,79],
+               "darkslategrey":        [47,79,79],
+               "darkturquoise":        [0,206,209],
+               "darkviolet":   [148,0,211],
+               "deeppink": [255,20,147],
+               "deepskyblue":  [0,191,255],
+               "dimgray":      [105,105,105],
+               "dimgrey":      [105,105,105],
+               "dodgerblue":   [30,144,255],
+               "firebrick":    [178,34,34],
+               "floralwhite":  [255,250,240],
+               "forestgreen":  [34,139,34],
+               "gainsboro":    [220,220,220],
+               "ghostwhite":   [248,248,255],
+               "gold": [255,215,0],
+               "goldenrod":    [218,165,32],
+               "greenyellow":  [173,255,47],
+               "grey": [128,128,128],
+               "honeydew": [240,255,240],
+               "hotpink":      [255,105,180],
+               "indianred":    [205,92,92],
+               "indigo":       [75,0,130],
+               "ivory":        [255,255,240],
+               "khaki":        [240,230,140],
+               "lavender": [230,230,250],
+               "lavenderblush":        [255,240,245],
+               "lawngreen":    [124,252,0],
+               "lemonchiffon": [255,250,205],
+               "lightblue":    [173,216,230],
+               "lightcoral":   [240,128,128],
+               "lightcyan":    [224,255,255],
+               "lightgoldenrodyellow": [250,250,210],
+               "lightgray":    [211,211,211],
+               "lightgreen":   [144,238,144],
+               "lightgrey":    [211,211,211],
+               "lightpink":    [255,182,193],
+               "lightsalmon":  [255,160,122],
+               "lightseagreen":        [32,178,170],
+               "lightskyblue": [135,206,250],
+               "lightslategray":       [119,136,153],
+               "lightslategrey":       [119,136,153],
+               "lightsteelblue":       [176,196,222],
+               "lightyellow":  [255,255,224],
+               "limegreen":    [50,205,50],
+               "linen":        [250,240,230],
+               "magenta":      [255,0,255],
+               "mediumaquamarine": [102,205,170],
+               "mediumblue":   [0,0,205],
+               "mediumorchid": [186,85,211],
+               "mediumpurple": [147,112,219],
+               "mediumseagreen":       [60,179,113],
+               "mediumslateblue":      [123,104,238],
+               "mediumspringgreen":    [0,250,154],
+               "mediumturquoise":      [72,209,204],
+               "mediumvioletred":      [199,21,133],
+               "midnightblue": [25,25,112],
+               "mintcream":    [245,255,250],
+               "mistyrose":    [255,228,225],
+               "moccasin": [255,228,181],
+               "navajowhite":  [255,222,173],
+               "oldlace":      [253,245,230],
+               "olivedrab":    [107,142,35],
+               "orange":       [255,165,0],
+               "orangered":    [255,69,0],
+               "orchid":       [218,112,214],
+               "palegoldenrod":        [238,232,170],
+               "palegreen":    [152,251,152],
+               "paleturquoise":        [175,238,238],
+               "palevioletred":        [219,112,147],
+               "papayawhip":   [255,239,213],
+               "peachpuff":    [255,218,185],
+               "peru": [205,133,63],
+               "pink": [255,192,203],
+               "plum": [221,160,221],
+               "powderblue":   [176,224,230],
+               "rosybrown":    [188,143,143],
+               "royalblue":    [65,105,225],
+               "saddlebrown":  [139,69,19],
+               "salmon":       [250,128,114],
+               "sandybrown":   [244,164,96],
+               "seagreen": [46,139,87],
+               "seashell": [255,245,238],
+               "sienna":       [160,82,45],
+               "skyblue":      [135,206,235],
+               "slateblue":    [106,90,205],
+               "slategray":    [112,128,144],
+               "slategrey":    [112,128,144],
+               "snow": [255,250,250],
+               "springgreen":  [0,255,127],
+               "steelblue":    [70,130,180],
+               "tan":  [210,180,140],
+               "thistle":      [216,191,216],
+               "tomato":       [255,99,71],
+               "turquoise":    [64,224,208],
+               "violet":       [238,130,238],
+               "wheat":        [245,222,179],
+               "whitesmoke":   [245,245,245],
+               "yellowgreen":  [154,205,50]
+       });
 
-       _createTreeNode: function(/*Object*/ args){
-               // summary:
-               //              creates a TreeNode
-               // description:
-               //              Developers can override this method to define their own TreeNode class;
-               //              However it will probably be removed in a future release in favor of a way
-               //              of just specifying a widget for the label, rather than one that contains
-               //              the children too.
-               return new dijit._TreeNode(args);
-       }
+       return Color;
 });
 
-// For back-compat.  TODO: remove in 2.0
+},
+'dijit/registry':function(){
+define("dijit/registry", [
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/_base/sniff", // has("ie")
+       "dojo/_base/unload", // unload.addOnWindowUnload
+       "dojo/_base/window", // win.body
+       "."     // dijit._scopeName
+], function(array, has, unload, win, dijit){
+
+       // module:
+       //              dijit/registry
+       // summary:
+       //              Registry of existing widget on page, plus some utility methods.
+       //              Must be accessed through AMD api, ex:
+       //              require(["dijit/registry"], function(registry){ registry.byId("foo"); })
 
+       var _widgetTypeCtr = {}, hash = {};
 
+       var registry =  {
+               // summary:
+               //              A set of widgets indexed by id
 
-}
+               length: 0,
 
-if(!dojo._hasResource["dojo.dnd.Container"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Container"] = true;
-dojo.provide("dojo.dnd.Container");
+               add: function(/*dijit._Widget*/ widget){
+                       // summary:
+                       //              Add a widget to the registry. If a duplicate ID is detected, a error is thrown.
+                       //
+                       // widget: dijit._Widget
+                       //              Any dijit._Widget subclass.
+                       if(hash[widget.id]){
+                               throw new Error("Tried to register widget with id==" + widget.id + " but that id is already registered");
+                       }
+                       hash[widget.id] = widget;
+                       this.length++;
+               },
 
+               remove: function(/*String*/ id){
+                       // summary:
+                       //              Remove a widget from the registry. Does not destroy the widget; simply
+                       //              removes the reference.
+                       if(hash[id]){
+                               delete hash[id];
+                               this.length--;
+                       }
+               },
 
+               byId: function(/*String|Widget*/ id){
+                       // summary:
+                       //              Find a widget by it's id.
+                       //              If passed a widget then just returns the widget.
+                       return typeof id == "string" ? hash[id] : id;   // dijit._Widget
+               },
 
+               byNode: function(/*DOMNode*/ node){
+                       // summary:
+                       //              Returns the widget corresponding to the given DOMNode
+                       return hash[node.getAttribute("widgetId")]; // dijit._Widget
+               },
 
-/*
-       Container states:
-               ""              - normal state
-               "Over"  - mouse over a container
-       Container item states:
-               ""              - normal state
-               "Over"  - mouse over a container item
-*/
+               toArray: function(){
+                       // summary:
+                       //              Convert registry into a true Array
+                       //
+                       // example:
+                       //              Work with the widget .domNodes in a real Array
+                       //              |       array.map(dijit.registry.toArray(), function(w){ return w.domNode; });
 
-/*=====
-dojo.declare("dojo.dnd.__ContainerArgs", [], {
-       creator: function(){
-               // summary:
-               //              a creator function, which takes a data item, and returns an object like that:
-               //              {node: newNode, data: usedData, type: arrayOfStrings}
-       },
+                       var ar = [];
+                       for(var id in hash){
+                               ar.push(hash[id]);
+                       }
+                       return ar;      // dijit._Widget[]
+               },
 
-       // skipForm: Boolean
-       //              don't start the drag operation, if clicked on form elements
-       skipForm: false,
+               getUniqueId: function(/*String*/widgetType){
+                       // summary:
+                       //              Generates a unique id for a given widgetType
 
-       // dropParent: Node||String
-       //              node or node's id to use as the parent node for dropped items
-       //              (must be underneath the 'node' parameter in the DOM)
-       dropParent: null,
+                       var id;
+                       do{
+                               id = widgetType + "_" +
+                                       (widgetType in _widgetTypeCtr ?
+                                               ++_widgetTypeCtr[widgetType] : _widgetTypeCtr[widgetType] = 0);
+                       }while(hash[id]);
+                       return dijit._scopeName == "dijit" ? id : dijit._scopeName + "_" + id; // String
+               },
 
-       // _skipStartup: Boolean
-       //              skip startup(), which collects children, for deferred initialization
-       //              (this is used in the markup mode)
-       _skipStartup: false
-});
+               findWidgets: function(/*DomNode*/ root){
+                       // summary:
+                       //              Search subtree under root returning widgets found.
+                       //              Doesn't search for nested widgets (ie, widgets inside other widgets).
+
+                       var outAry = [];
+
+                       function getChildrenHelper(root){
+                               for(var node = root.firstChild; node; node = node.nextSibling){
+                                       if(node.nodeType == 1){
+                                               var widgetId = node.getAttribute("widgetId");
+                                               if(widgetId){
+                                                       var widget = hash[widgetId];
+                                                       if(widget){     // may be null on page w/multiple dojo's loaded
+                                                               outAry.push(widget);
+                                                       }
+                                               }else{
+                                                       getChildrenHelper(node);
+                                               }
+                                       }
+                               }
+                       }
 
-dojo.dnd.Item = function(){
-       // summary:
-       //              Represents (one of) the source node(s) being dragged.
-       //              Contains (at least) the "type" and "data" attributes.
-       // type: String[]
-       //              Type(s) of this item, by default this is ["text"]
-       // data: Object
-       //              Logical representation of the object being dragged.
-       //              If the drag object's type is "text" then data is a String,
-       //              if it's another type then data could be a different Object,
-       //              perhaps a name/value hash.
-       
-       this.type = type;
-       this.data = data;
-}
-=====*/
+                       getChildrenHelper(root);
+                       return outAry;
+               },
 
-dojo.declare("dojo.dnd.Container", null, {
-       // summary:
-       //              a Container object, which knows when mouse hovers over it, 
-       //              and over which element it hovers
-       
-       // object attributes (for markup)
-       skipForm: false,
-       
-       /*=====
-       // current: DomNode
-       //              The DOM node the mouse is currently hovered over
-       current: null,
-       
-       // map: Hash<String, dojo.dnd.Item>
-       //              Map from an item's id (which is also the DOMNode's id) to
-       //              the dojo.dnd.Item itself.
-       map: {},
-       =====*/
-       
-       constructor: function(node, params){
-               // summary:
-               //              a constructor of the Container
-               // node: Node
-               //              node or node's id to build the container on
-               // params: dojo.dnd.__ContainerArgs
-               //              a dictionary of parameters
-               this.node = dojo.byId(node);
-               if(!params){ params = {}; }
-               this.creator = params.creator || null;
-               this.skipForm = params.skipForm;
-               this.parent = params.dropParent && dojo.byId(params.dropParent);
-               
-               // class-specific variables
-               this.map = {};
-               this.current = null;
+               _destroyAll: function(){
+                       // summary:
+                       //              Code to destroy all widgets and do other cleanup on page unload
 
-               // states
-               this.containerState = "";
-               dojo.addClass(this.node, "dojoDndContainer");
-               
-               // mark up children
-               if(!(params && params._skipStartup)){
-                       this.startup();
-               }
+                       // Clean up focus manager lingering references to widgets and nodes
+                       dijit._curFocus = null;
+                       dijit._prevFocus = null;
+                       dijit._activeStack = [];
+
+                       // Destroy all the widgets, top down
+                       array.forEach(registry.findWidgets(win.body()), function(widget){
+                               // Avoid double destroy of widgets like Menu that are attached to <body>
+                               // even though they are logically children of other widgets.
+                               if(!widget._destroyed){
+                                       if(widget.destroyRecursive){
+                                               widget.destroyRecursive();
+                                       }else if(widget.destroy){
+                                               widget.destroy();
+                                       }
+                               }
+                       });
+               },
 
-               // set up events
-               this.events = [
-                       dojo.connect(this.node, "onmouseover", this, "onMouseOver"),
-                       dojo.connect(this.node, "onmouseout",  this, "onMouseOut"),
-                       // cancel text selection and text dragging
-                       dojo.connect(this.node, "ondragstart",   this, "onSelectStart"),
-                       dojo.connect(this.node, "onselectstart", this, "onSelectStart")
-               ];
-       },
-       
-       // object attributes (for markup)
-       creator: function(){
-               // summary:
-               //              creator function, dummy at the moment
-       },
-       
-       // abstract access to the map
-       getItem: function(/*String*/ key){
-               // summary:
-               //              returns a data item by its key (id)
-               return this.map[key];   // dojo.dnd.Item
-       },
-       setItem: function(/*String*/ key, /*dojo.dnd.Item*/ data){
-               // summary:
-               //              associates a data item with its key (id)
-               this.map[key] = data;
-       },
-       delItem: function(/*String*/ key){
-               // summary:
-               //              removes a data item from the map by its key (id)
-               delete this.map[key];
-       },
-       forInItems: function(/*Function*/ f, /*Object?*/ o){
-               // summary:
-               //              iterates over a data map skipping members that 
-               //              are present in the empty object (IE and/or 3rd-party libraries).
-               o = o || dojo.global;
-               var m = this.map, e = dojo.dnd._empty;
-               for(var i in m){
-                       if(i in e){ continue; }
-                       f.call(o, m[i], i, this);
-               }
-               return o;       // Object
-       },
-       clearItems: function(){
-               // summary:
-               //              removes all data items from the map
-               this.map = {};
-       },
-       
-       // methods
-       getAllNodes: function(){
-               // summary:
-               //              returns a list (an array) of all valid child nodes
-               return dojo.query("> .dojoDndItem", this.parent);       // NodeList
-       },
-       sync: function(){
-               // summary:
-               //              sync up the node list with the data map
-               var map = {};
-               this.getAllNodes().forEach(function(node){
-                       if(node.id){
-                               var item = this.getItem(node.id);
-                               if(item){
-                                       map[node.id] = item;
-                                       return;
+               getEnclosingWidget: function(/*DOMNode*/ node){
+                       // summary:
+                       //              Returns the widget whose DOM tree contains the specified DOMNode, or null if
+                       //              the node is not contained within the DOM tree of any widget
+                       while(node){
+                               var id = node.getAttribute && node.getAttribute("widgetId");
+                               if(id){
+                                       return hash[id];
                                }
-                       }else{
-                               node.id = dojo.dnd.getUniqueId();
-                       }
-                       var type = node.getAttribute("dndType"),
-                               data = node.getAttribute("dndData");
-                       map[node.id] = {
-                               data: data || node.innerHTML,
-                               type: type ? type.split(/\s*,\s*/) : ["text"]
-                       };
-               }, this);
-               this.map = map;
-               return this;    // self
-       },
-       insertNodes: function(data, before, anchor){
-               // summary:
-               //              inserts an array of new nodes before/after an anchor node
-               // data: Array
-               //              a list of data items, which should be processed by the creator function
-               // before: Boolean
-               //              insert before the anchor, if true, and after the anchor otherwise
-               // anchor: Node
-               //              the anchor node to be used as a point of insertion
-               if(!this.parent.firstChild){
-                       anchor = null;
-               }else if(before){
-                       if(!anchor){
-                               anchor = this.parent.firstChild;
-                       }
-               }else{
-                       if(anchor){
-                               anchor = anchor.nextSibling;
-                       }
-               }
-               if(anchor){
-                       for(var i = 0; i < data.length; ++i){
-                               var t = this._normalizedCreator(data[i]);
-                               this.setItem(t.node.id, {data: t.data, type: t.type});
-                               this.parent.insertBefore(t.node, anchor);
-                       }
-               }else{
-                       for(var i = 0; i < data.length; ++i){
-                               var t = this._normalizedCreator(data[i]);
-                               this.setItem(t.node.id, {data: t.data, type: t.type});
-                               this.parent.appendChild(t.node);
+                               node = node.parentNode;
                        }
-               }
-               return this;    // self
-       },
-       destroy: function(){
-               // summary:
-               //              prepares this object to be garbage-collected
-               dojo.forEach(this.events, dojo.disconnect);
-               this.clearItems();
-               this.node = this.parent = this.current = null;
-       },
+                       return null;
+               },
 
-       // markup methods
-       markupFactory: function(params, node){
-               params._skipStartup = true;
-               return new dojo.dnd.Container(node, params);
-       },
-       startup: function(){
-               // summary:
-               //              collects valid child items and populate the map
-               
-               // set up the real parent node
-               if(!this.parent){
-                       // use the standard algorithm, if not assigned
-                       this.parent = this.node;
-                       if(this.parent.tagName.toLowerCase() == "table"){
-                               var c = this.parent.getElementsByTagName("tbody");
-                               if(c && c.length){ this.parent = c[0]; }
-                       }
-               }
-               this.defaultCreator = dojo.dnd._defaultCreator(this.parent);
+               // In case someone needs to access hash.
+               // Actually, this is accessed from WidgetSet back-compatibility code
+               _hash: hash
+       };
 
-               // process specially marked children
-               this.sync();
-       },
+       if(has("ie")){
+               // Only run _destroyAll() for IE because we think it's only necessary in that case,
+               // and because it causes problems on FF.  See bug #3531 for details.
+               unload.addOnWindowUnload(function(){
+                       registry._destroyAll();
+               });
+       }
 
-       // mouse events
-       onMouseOver: function(e){
-               // summary:
-               //              event processor for onmouseover
-               // e: Event
-               //              mouse event
-               var n = e.relatedTarget;
-               while(n){
-                       if(n == this.node){ break; }
-                       try{
-                               n = n.parentNode;
-                       }catch(x){
-                               n = null;
-                       }
-               }
-               if(!n){
-                       this._changeState("Container", "Over");
-                       this.onOverEvent();
-               }
-               n = this._getChildByEvent(e);
-               if(this.current == n){ return; }
-               if(this.current){ this._removeItemClass(this.current, "Over"); }
-               if(n){ this._addItemClass(n, "Over"); }
-               this.current = n;
-       },
-       onMouseOut: function(e){
-               // summary:
-               //              event processor for onmouseout
-               // e: Event
-               //              mouse event
-               for(var n = e.relatedTarget; n;){
-                       if(n == this.node){ return; }
-                       try{
-                               n = n.parentNode;
-                       }catch(x){
-                               n = null;
-                       }
-               }
-               if(this.current){
-                       this._removeItemClass(this.current, "Over");
-                       this.current = null;
-               }
-               this._changeState("Container", "");
-               this.onOutEvent();
-       },
-       onSelectStart: function(e){
-               // summary:
-               //              event processor for onselectevent and ondragevent
-               // e: Event
-               //              mouse event
-               if(!this.skipForm || !dojo.dnd.isFormElement(e)){
-                       dojo.stopEvent(e);
-               }
-       },
-       
-       // utilities
-       onOverEvent: function(){
-               // summary:
-               //              this function is called once, when mouse is over our container
-       },
-       onOutEvent: function(){
-               // summary:
-               //              this function is called once, when mouse is out of our container
-       },
-       _changeState: function(type, newState){
-               // summary:
-               //              changes a named state to new state value
-               // type: String
-               //              a name of the state to change
-               // newState: String
-               //              new state
-               var prefix = "dojoDnd" + type;
-               var state  = type.toLowerCase() + "State";
-               //dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
-               dojo.removeClass(this.node, prefix + this[state]);
-               dojo.addClass(this.node, prefix + newState);
-               this[state] = newState;
-       },
-       _addItemClass: function(node, type){
-               // summary:
-               //              adds a class with prefix "dojoDndItem"
-               // node: Node
-               //              a node
-               // type: String
-               //              a variable suffix for a class name
-               dojo.addClass(node, "dojoDndItem" + type);
-       },
-       _removeItemClass: function(node, type){
-               // summary:
-               //              removes a class with prefix "dojoDndItem"
-               // node: Node
-               //              a node
-               // type: String
-               //              a variable suffix for a class name
-               dojo.removeClass(node, "dojoDndItem" + type);
-       },
-       _getChildByEvent: function(e){
-               // summary:
-               //              gets a child, which is under the mouse at the moment, or null
-               // e: Event
-               //              a mouse event
-               var node = e.target;
-               if(node){
-                       for(var parent = node.parentNode; parent; node = parent, parent = node.parentNode){
-                               if(parent == this.parent && dojo.hasClass(node, "dojoDndItem")){ return node; }
-                       }
-               }
-               return null;
-       },
-       _normalizedCreator: function(/*dojo.dnd.Item*/ item, /*String*/ hint){
+       /*=====
+       dijit.registry = {
                // summary:
-               //              adds all necessary data to the output of the user-supplied creator function
-               var t = (this.creator || this.defaultCreator).call(this, item, hint);
-               if(!dojo.isArray(t.type)){ t.type = ["text"]; }
-               if(!t.node.id){ t.node.id = dojo.dnd.getUniqueId(); }
-               dojo.addClass(t.node, "dojoDndItem");
-               return t;
-       }
+               //              A list of widgets on a page.
+       };
+       =====*/
+       dijit.registry = registry;
+
+       return registry;
 });
 
-dojo.dnd._createNode = function(tag){
+},
+'dijit/tree/_dndContainer':function(){
+define("dijit/tree/_dndContainer", [
+       "dojo/aspect",  // aspect.after
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.remove domClass.replace
+       "dojo/_base/event",     // event.stop
+       "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch
+       "dojo/mouse",   // mouse.enter, mouse.leave
+       "dojo/on"
+], function(aspect, declare, domClass, event, lang, mouse, on){
+
+       // module:
+       //              dijit/tree/_dndContainer
        // summary:
-       //              returns a function, which creates an element of given tag 
-       //              (SPAN by default) and sets its innerHTML to given text
-       // tag: String
-       //              a tag name or empty for SPAN
-       if(!tag){ return dojo.dnd._createSpan; }
-       return function(text){  // Function
-               return dojo.create(tag, {innerHTML: text});     // Node
-       };
-};
-
-dojo.dnd._createTrTd = function(text){
-       // summary:
-       //              creates a TR/TD structure with given text as an innerHTML of TD
-       // text: String
-       //              a text for TD
-       var tr = dojo.create("tr");
-       dojo.create("td", {innerHTML: text}, tr);
-       return tr;      // Node
-};
-
-dojo.dnd._createSpan = function(text){
-       // summary:
-       //              creates a SPAN element with given text as its innerHTML
-       // text: String
-       //              a text for SPAN
-       return dojo.create("span", {innerHTML: text});  // Node
-};
-
-// dojo.dnd._defaultCreatorNodes: Object
-//             a dictionary that maps container tag names to child tag names
-dojo.dnd._defaultCreatorNodes = {ul: "li", ol: "li", div: "div", p: "div"};
-
-dojo.dnd._defaultCreator = function(node){
-       // summary:
-       //              takes a parent node, and returns an appropriate creator function
-       // node: Node
-       //              a container node
-       var tag = node.tagName.toLowerCase();
-       var c = tag == "tbody" || tag == "thead" ? dojo.dnd._createTrTd :
-                       dojo.dnd._createNode(dojo.dnd._defaultCreatorNodes[tag]);
-       return function(item, hint){    // Function
-               var isObj = item && dojo.isObject(item), data, type, n;
-               if(isObj && item.tagName && item.nodeType && item.getAttribute){
-                       // process a DOM node
-                       data = item.getAttribute("dndData") || item.innerHTML;
-                       type = item.getAttribute("dndType");
-                       type = type ? type.split(/\s*,\s*/) : ["text"];
-                       n = item;       // this node is going to be moved rather than copied
-               }else{
-                       // process a DnD item object or a string
-                       data = (isObj && item.data) ? item.data : item;
-                       type = (isObj && item.type) ? item.type : ["text"];
-                       n = (hint == "avatar" ? dojo.dnd._createSpan : c)(String(data));
-               }
-               if(!n.id){
-                       n.id = dojo.dnd.getUniqueId();
-               }
-               return {node: n, data: data, type: type};
-       };
-};
-
-}
-
-if(!dojo._hasResource["dijit.tree._dndContainer"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree._dndContainer"] = true;
-dojo.provide("dijit.tree._dndContainer");
+       //              This is a base class for `dijit.tree._dndSelector`, and isn't meant to be used directly.
+       //              It's modeled after `dojo.dnd.Container`.
 
-
-
-dojo.declare("dijit.tree._dndContainer",
-       null,
-       {
+       return declare("dijit.tree._dndContainer", null, {
 
                // summary:
                //              This is a base class for `dijit.tree._dndSelector`, and isn't meant to be used directly.
@@ -23884,74 +25870,61 @@ dojo.declare("dijit.tree._dndContainer",
                        //              private
                        this.tree = tree;
                        this.node = tree.domNode;       // TODO: rename; it's not a TreeNode but the whole Tree
-                       dojo.mixin(this, params);
+                       lang.mixin(this, params);
 
                        // class-specific variables
-                       this.map = {};
                        this.current = null;    // current TreeNode's DOM node
 
                        // states
                        this.containerState = "";
-                       dojo.addClass(this.node, "dojoDndContainer");
+                       domClass.add(this.node, "dojoDndContainer");
 
                        // set up events
                        this.events = [
                                // container level events
-                               dojo.connect(this.node, "onmouseenter", this, "onOverEvent"),
-                               dojo.connect(this.node, "onmouseleave", this, "onOutEvent"),
+                               on(this.node, mouse.enter, lang.hitch(this, "onOverEvent")),
+                               on(this.node, mouse.leave,      lang.hitch(this, "onOutEvent")),
 
                                // switching between TreeNodes
-                               dojo.connect(this.tree, "_onNodeMouseEnter", this, "onMouseOver"),
-                               dojo.connect(this.tree, "_onNodeMouseLeave", this, "onMouseOut"),
+                               aspect.after(this.tree, "_onNodeMouseEnter", lang.hitch(this, "onMouseOver"), true),
+                               aspect.after(this.tree, "_onNodeMouseLeave", lang.hitch(this, "onMouseOut"), true),
 
                                // cancel text selection and text dragging
-                               dojo.connect(this.node, "ondragstart", dojo, "stopEvent"),
-                               dojo.connect(this.node, "onselectstart", dojo, "stopEvent")
+                               on(this.node, "dragstart", lang.hitch(event, "stop")),
+                               on(this.node, "selectstart", lang.hitch(event, "stop"))
                        ];
                },
 
-               getItem: function(/*String*/ key){
-                       // summary:
-                       //              Returns the dojo.dnd.Item (representing a dragged node) by it's key (id).
-                       //              Called by dojo.dnd.Source.checkAcceptance().
-                       // tags:
-                       //              protected
-
-                       var node = this.selection[key],
-                               ret = {
-                                       data: dijit.getEnclosingWidget(node),
-                                       type: ["treeNode"]
-                               };
-
-                       return ret;     // dojo.dnd.Item
-               },
-
                destroy: function(){
                        // summary:
                        //              Prepares this object to be garbage-collected
 
-                       dojo.forEach(this.events, dojo.disconnect);
+                       var h;
+                       while(h = this.events.pop()){ h.remove(); }
+
                        // this.clearItems();
                        this.node = this.parent = null;
                },
 
                // mouse events
-               onMouseOver: function(/*TreeNode*/ widget, /*Event*/ evt){
+               onMouseOver: function(widget /*===== , evt =====*/){
                        // summary:
                        //              Called when mouse is moved over a TreeNode
+                       // widget: TreeNode
+                       // evt: Event
                        // tags:
                        //              protected
-                       this.current = widget.rowNode;
-                       this.currentWidget = widget;
+                       this.current = widget;
                },
 
-               onMouseOut: function(/*TreeNode*/ widget, /*Event*/ evt){
+               onMouseOut: function(/*===== widget, evt =====*/){
                        // summary:
                        //              Called when mouse is moved away from a TreeNode
+                       // widget: TreeNode
+                       // evt: Event
                        // tags:
                        //              protected
                        this.current = null;
-                       this.currentWidget = null;
                },
 
                _changeState: function(type, newState){
@@ -23963,9 +25936,8 @@ dojo.declare("dijit.tree._dndContainer",
                        //              new state
                        var prefix = "dojoDnd" + type;
                        var state = type.toLowerCase() + "State";
-                       //dojo.replaceClass(this.node, prefix + newState, prefix + this[state]);
-                       dojo.removeClass(this.node, prefix + this[state]);
-                       dojo.addClass(this.node, prefix + newState);
+                       //domClass.replace(this.node, prefix + newState, prefix + this[state]);
+                       domClass.replace(this.node, prefix + newState, prefix + this[state]);
                        this[state] = newState;
                },
 
@@ -23976,7 +25948,7 @@ dojo.declare("dijit.tree._dndContainer",
                        //              A node
                        // type: String
                        //              A variable suffix for a class name
-                       dojo.addClass(node, "dojoDndItem" + type);
+                       domClass.add(node, "dojoDndItem" + type);
                },
 
                _removeItemClass: function(node, type){
@@ -23986,7 +25958,7 @@ dojo.declare("dijit.tree._dndContainer",
                        //              A node
                        // type: String
                        //              A variable suffix for a class name
-                       dojo.removeClass(node, "dojoDndItem" + type);
+                       domClass.remove(node, "dojoDndItem" + type);
                },
 
                onOverEvent: function(){
@@ -24004,2841 +25976,6272 @@ dojo.declare("dijit.tree._dndContainer",
                        //              protected
                        this._changeState("Container", "");
                }
+       });
 });
 
-}
-
-if(!dojo._hasResource["dijit.tree._dndSelector"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree._dndSelector"] = true;
-dojo.provide("dijit.tree._dndSelector");
-
-
-
-dojo.declare("dijit.tree._dndSelector",
-       dijit.tree._dndContainer,
-       {
-               // summary:
-               //              This is a base class for `dijit.tree.dndSource` , and isn't meant to be used directly.
-               //              It's based on `dojo.dnd.Selector`.
-               // tags:
-               //              protected
-
-               /*=====
-               // selection: Hash<String, DomNode>
-               //              (id, DomNode) map for every TreeNode that's currently selected.
-               //              The DOMNode is the TreeNode.rowNode.
-               selection: {},
-               =====*/
+},
+'url:dijit/templates/InlineEditBox.html':"<span data-dojo-attach-point=\"editNode\" role=\"presentation\" style=\"position: absolute; visibility:hidden\" class=\"dijitReset dijitInline\"\n\tdata-dojo-attach-event=\"onkeypress: _onKeyPress\"\n\t><span data-dojo-attach-point=\"editorPlaceholder\"></span\n\t><span data-dojo-attach-point=\"buttonContainer\"\n\t\t><button data-dojo-type=\"dijit.form.Button\" data-dojo-props=\"label: '${buttonSave}', 'class': 'saveButton'\"\n\t\t\tdata-dojo-attach-point=\"saveButton\" data-dojo-attach-event=\"onClick:save\"></button\n\t\t><button data-dojo-type=\"dijit.form.Button\"  data-dojo-props=\"label: '${buttonCancel}', 'class': 'cancelButton'\"\n\t\t\tdata-dojo-attach-point=\"cancelButton\" data-dojo-attach-event=\"onClick:cancel\"></button\n\t></span\n></span>\n",
+'dijit/_base/wai':function(){
+define("dijit/_base/wai", [
+       "dojo/dom-attr", // domAttr.attr
+       "dojo/_base/lang", // lang.mixin
+       "..",   // export symbols to dijit
+       "../hccss"                      // not using this module directly, but loading it sets CSS flag on <html>
+], function(domAttr, lang, dijit){
+
+       // module:
+       //              dijit/_base/wai
+       // summary:
+       //              Deprecated methods for setting/getting wai roles and states.
+       //              New code should call setAttribute()/getAttribute() directly.
+       //
+       //              Also loads hccss to apply dijit_a11y class to root node if machine is in high-contrast mode.
 
-               constructor: function(tree, params){
+       lang.mixin(dijit, {
+               hasWaiRole: function(/*Element*/ elem, /*String?*/ role){
                        // summary:
-                       //              Initialization
-                       // tags:
-                       //              private
-
-                       this.selection={};
-                       this.anchor = null;
-                       this.simpleSelection=false;
+                       //              Determines if an element has a particular role.
+                       // returns:
+                       //              True if elem has the specific role attribute and false if not.
+                       //              For backwards compatibility if role parameter not provided,
+                       //              returns true if has a role
+                       var waiRole = this.getWaiRole(elem);
+                       return role ? (waiRole.indexOf(role) > -1) : (waiRole.length > 0);
+               },
 
-                       this.events.push(
-                               dojo.connect(this.tree.domNode, "onmousedown", this,"onMouseDown"),
-                               dojo.connect(this.tree.domNode, "onmouseup", this,"onMouseUp"),
-                               dojo.connect(this.tree.domNode, "onmousemove", this,"onMouseMove")
-                       );
+               getWaiRole: function(/*Element*/ elem){
+                       // summary:
+                       //              Gets the role for an element (which should be a wai role).
+                       // returns:
+                       //              The role of elem or an empty string if elem
+                       //              does not have a role.
+                        return lang.trim((domAttr.get(elem, "role") || "").replace("wairole:",""));
                },
 
-               //      singular: Boolean
-               //              Allows selection of only one element, if true.
-               //              Tree hasn't been tested in singular=true mode, unclear if it works.
-               singular: false,
+               setWaiRole: function(/*Element*/ elem, /*String*/ role){
+                       // summary:
+                       //              Sets the role on an element.
+                       // description:
+                       //              Replace existing role attribute with new role.
 
-               // methods
+                       domAttr.set(elem, "role", role);
+               },
 
-               getSelectedNodes: function(){
+               removeWaiRole: function(/*Element*/ elem, /*String*/ role){
                        // summary:
-                       //              Returns the set of selected nodes.
-                       //              Used by dndSource on the start of a drag.
-                       // tags:
-                       //              protected
-                       return this.selection;
+                       //              Removes the specified role from an element.
+                       //              Removes role attribute if no specific role provided (for backwards compat.)
+
+                       var roleValue = domAttr.get(elem, "role");
+                       if(!roleValue){ return; }
+                       if(role){
+                               var t = lang.trim((" " + roleValue + " ").replace(" " + role + " ", " "));
+                               domAttr.set(elem, "role", t);
+                       }else{
+                               elem.removeAttribute("role");
+                       }
                },
 
-               selectNone: function(){
+               hasWaiState: function(/*Element*/ elem, /*String*/ state){
                        // summary:
-                       //              Unselects all items
-                       // tags:
-                       //              private
+                       //              Determines if an element has a given state.
+                       // description:
+                       //              Checks for an attribute called "aria-"+state.
+                       // returns:
+                       //              true if elem has a value for the given state and
+                       //              false if it does not.
 
-                       return this._removeSelection()._removeAnchor(); // self
+                       return elem.hasAttribute ? elem.hasAttribute("aria-"+state) : !!elem.getAttribute("aria-"+state);
                },
 
-               destroy: function(){
+               getWaiState: function(/*Element*/ elem, /*String*/ state){
                        // summary:
-                       //              Prepares the object to be garbage-collected
-                       this.inherited(arguments);
-                       this.selection = this.anchor = null;
+                       //              Gets the value of a state on an element.
+                       // description:
+                       //              Checks for an attribute called "aria-"+state.
+                       // returns:
+                       //              The value of the requested state on elem
+                       //              or an empty string if elem has no value for state.
+
+                       return elem.getAttribute("aria-"+state) || "";
                },
 
-               // mouse events
-               onMouseDown: function(e){
+               setWaiState: function(/*Element*/ elem, /*String*/ state, /*String*/ value){
                        // summary:
-                       //              Event processor for onmousedown
-                       // e: Event
-                       //              mouse event
-                       // tags:
-                       //              protected
+                       //              Sets a state on an element.
+                       // description:
+                       //              Sets an attribute called "aria-"+state.
 
-                       if(!this.current){ return; }
+                       elem.setAttribute("aria-"+state, value);
+               },
 
-                       if(e.button == dojo.mouseButtons.RIGHT){ return; }      // ignore right-click
+               removeWaiState: function(/*Element*/ elem, /*String*/ state){
+                       // summary:
+                       //              Removes a state from an element.
+                       // description:
+                       //              Sets an attribute called "aria-"+state.
 
-                       var treeNode = dijit.getEnclosingWidget(this.current),
-                               id = treeNode.id + "-dnd"       // so id doesn't conflict w/widget
+                       elem.removeAttribute("aria-"+state);
+               }
+       });
 
-                       if(!dojo.hasAttr(this.current, "id")){
-                               dojo.attr(this.current, "id", id);
-                       }
+       return dijit;
+});
 
-                       if(!this.singular && !dojo.isCopyKey(e) && !e.shiftKey && (this.current.id in this.selection)){
-                               this.simpleSelection = true;
-                               dojo.stopEvent(e);
-                               return;
-                       }
-                       if(this.singular){
-                               if(this.anchor == this.current){
-                                       if(dojo.isCopyKey(e)){
-                                               this.selectNone();
-                                       }
-                               }else{
-                                       this.selectNone();
-                                       this.anchor = this.current;
-                                       this._addItemClass(this.anchor, "Anchor");
+},
+'dijit/form/_FormSelectWidget':function(){
+define("dijit/form/_FormSelectWidget", [
+       "dojo/_base/array", // array.filter array.forEach array.map array.some
+       "dojo/aspect", // aspect.after
+       "dojo/data/util/sorter", // util.sorter.createSortFunction
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.setSelectable
+       "dojo/dom-class", // domClass.toggle
+       "dojo/_base/kernel",    // _scopeName
+       "dojo/_base/lang", // lang.delegate lang.isArray lang.isObject lang.hitch
+       "dojo/query", // query
+       "./_FormValueWidget"
+], function(array, aspect, sorter, declare, dom, domClass, kernel, lang, query, _FormValueWidget){
 
-                                       this.selection[this.current.id] = this.current;
-                               }
-                       }else{
-                               if(!this.singular && e.shiftKey){
-                                       if(dojo.isCopyKey(e)){
-                                               //TODO add range to selection
-                                       }else{
-                                               //TODO select new range from anchor
-                                       }
-                               }else{
-                                       if(dojo.isCopyKey(e)){
-                                               if(this.anchor == this.current){
-                                                       delete this.selection[this.anchor.id];
-                                                       this._removeAnchor();
-                                               }else{
-                                                       if(this.current.id in this.selection){
-                                                               this._removeItemClass(this.current, "Selected");
-                                                               delete this.selection[this.current.id];
-                                                       }else{
-                                                               if(this.anchor){
-                                                                       this._removeItemClass(this.anchor, "Anchor");
-                                                                       this._addItemClass(this.anchor, "Selected");
-                                                               }
-                                                               this.anchor = this.current;
-                                                               this._addItemClass(this.current, "Anchor");
-                                                               this.selection[this.current.id] = this.current;
-                                                       }
-                                               }
-                                       }else{
-                                               if(!(id in this.selection)){
-                                                       this.selectNone();
-                                                       this.anchor = this.current;
-                                                       this._addItemClass(this.current, "Anchor");
-                                                       this.selection[id] = this.current;
-                                               }
-                                       }
-                               }
-                       }
+/*=====
+       var _FormValueWidget = dijit.form._FormValueWidget;
+=====*/
 
-                       dojo.stopEvent(e);
-               },
+// module:
+//             dijit/form/_FormSelectWidget
+// summary:
+//             Extends _FormValueWidget in order to provide "select-specific"
+//             values - i.e., those values that are unique to <select> elements.
 
-               onMouseUp: function(e){
-                       // summary:
-                       //              Event processor for onmouseup
-                       // e: Event
-                       //              mouse event
-                       // tags:
-                       //              protected
 
-                       // TODO: this code is apparently for handling an edge case when the user is selecting
-                       // multiple nodes and then mousedowns on a node by accident... it lets the user keep the
-                       // current selection by moving the mouse away (or something like that).   It doesn't seem
-                       // to work though and requires a lot of plumbing (including this code, the onmousemove
-                       // handler, and the this.simpleSelection attribute.   Consider getting rid of all of it.
+/*=====
+dijit.form.__SelectOption = function(){
+       // value: String
+       //              The value of the option.  Setting to empty (or missing) will
+       //              place a separator at that location
+       // label: String
+       //              The label for our option.  It can contain html tags.
+       // selected: Boolean
+       //              Whether or not we are a selected option
+       // disabled: Boolean
+       //              Whether or not this specific option is disabled
+       this.value = value;
+       this.label = label;
+       this.selected = selected;
+       this.disabled = disabled;
+}
+=====*/
 
-                       if(!this.simpleSelection){ return; }
-                       this.simpleSelection = false;
-                       this.selectNone();
-                       if(this.current){
-                               this.anchor = this.current;
-                               this._addItemClass(this.anchor, "Anchor");
-                               this.selection[this.current.id] = this.current;
-                       }
-               },
-               onMouseMove: function(e){
-                       // summary
-                       //              event processor for onmousemove
-                       // e: Event
-                       //              mouse event
-                       this.simpleSelection = false;
-               },
+return declare("dijit.form._FormSelectWidget", _FormValueWidget, {
+       // summary:
+       //              Extends _FormValueWidget in order to provide "select-specific"
+       //              values - i.e., those values that are unique to <select> elements.
+       //              This also provides the mechanism for reading the elements from
+       //              a store, if desired.
 
-               _removeSelection: function(){
-                       // summary:
-                       //              Unselects all items
-                       // tags:
-                       //              private
-                       var e = dojo.dnd._empty;
-                       for(var i in this.selection){
-                               if(i in e){ continue; }
-                               var node = dojo.byId(i);
-                               if(node){ this._removeItemClass(node, "Selected"); }
-                       }
-                       this.selection = {};
-                       return this;    // self
-               },
+       // multiple: [const] Boolean
+       //              Whether or not we are multi-valued
+       multiple: false,
 
-               _removeAnchor: function(){
-                       // summary:
-                       //              Removes the Anchor CSS class from a node.
-                       //              According to `dojo.dnd.Selector`, anchor means that
-                       //              "an item is selected, and is an anchor for a 'shift' selection".
-                       //              It's not relevant for Tree at this point, since we don't support multiple selection.
-                       // tags:
-                       //              private
-                       if(this.anchor){
-                               this._removeItemClass(this.anchor, "Anchor");
-                               this.anchor = null;
-                       }
-                       return this;    // self
-               },
+       // options: dijit.form.__SelectOption[]
+       //              The set of options for our select item.  Roughly corresponds to
+       //              the html <option> tag.
+       options: null,
 
-               forInSelectedItems: function(/*Function*/ f, /*Object?*/ o){
-                       // summary:
-                       //              Iterates over selected items;
-                       //              see `dojo.dnd.Container.forInItems()` for details
-                       o = o || dojo.global;
-                       for(var id in this.selection){
-                               console.log("selected item id: " + id);
-                               f.call(o, this.getItem(id), id, this);
-                       }
-               }
-});
+       // store: dojo.data.api.Identity
+       //              A store which, at the very least implements dojo.data.api.Identity
+       //              to use for getting our list of options - rather than reading them
+       //              from the <option> html tags.
+       store: null,
 
-}
+       // query: object
+       //              A query to use when fetching items from our store
+       query: null,
 
-if(!dojo._hasResource["dojo.dnd.Avatar"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Avatar"] = true;
-dojo.provide("dojo.dnd.Avatar");
+       // queryOptions: object
+       //              Query options to use when fetching from the store
+       queryOptions: null,
 
+       // onFetch: Function
+       //              A callback to do with an onFetch - but before any items are actually
+       //              iterated over (i.e. to filter even further what you want to add)
+       onFetch: null,
 
+       // sortByLabel: Boolean
+       //              Flag to sort the options returned from a store by the label of
+       //              the store.
+       sortByLabel: true,
 
-dojo.declare("dojo.dnd.Avatar", null, {
-       // summary:
-       //              Object that represents transferred DnD items visually
-       // manager: Object
-       //              a DnD manager object
 
-       constructor: function(manager){
-               this.manager = manager;
-               this.construct();
-       },
+       // loadChildrenOnOpen: Boolean
+       //              By default loadChildren is called when the items are fetched from the
+       //              store.  This property allows delaying loadChildren (and the creation
+       //              of the options/menuitems) until the user clicks the button to open the
+       //              dropdown.
+       loadChildrenOnOpen: false,
 
-       // methods
-       construct: function(){
+       getOptions: function(/*anything*/ valueOrIdx){
                // summary:
-               //              constructor function;
-               //              it is separate so it can be (dynamically) overwritten in case of need
-               this.isA11y = dojo.hasClass(dojo.body(),"dijit_a11y");
-               var a = dojo.create("table", {
-                               "class": "dojoDndAvatar",
-                               style: {
-                                       position: "absolute",
-                                       zIndex:   "1999",
-                                       margin:   "0px"
-                               }
-                       }),
-                       source = this.manager.source, node,
-                       b = dojo.create("tbody", null, a),
-                       tr = dojo.create("tr", null, b),
-                       td = dojo.create("td", null, tr),
-                       icon = this.isA11y ? dojo.create("span", {
-                                               id : "a11yIcon",
-                                               innerHTML : this.manager.copy ? '+' : "<"
-                                       }, td) : null,
-                       span = dojo.create("span", {
-                               innerHTML: source.generateText ? this._generateText() : ""
-                       }, td),
-                       k = Math.min(5, this.manager.nodes.length), i = 0;
-               // we have to set the opacity on IE only after the node is live
-               dojo.attr(tr, {
-                       "class": "dojoDndAvatarHeader",
-                       style: {opacity: 0.9}
-               });
-               for(; i < k; ++i){
-                       if(source.creator){
-                               // create an avatar representation of the node
-                               node = source._normalizedCreator(source.getItem(this.manager.nodes[i].id).data, "avatar").node;
-                       }else{
-                               // or just clone the node and hope it works
-                               node = this.manager.nodes[i].cloneNode(true);
-                               if(node.tagName.toLowerCase() == "tr"){
-                                       // insert extra table nodes
-                                       var table = dojo.create("table"),
-                                               tbody = dojo.create("tbody", null, table);
-                                       tbody.appendChild(node);
-                                       node = table;
+               //              Returns a given option (or options).
+               // valueOrIdx:
+               //              If passed in as a string, that string is used to look up the option
+               //              in the array of options - based on the value property.
+               //              (See dijit.form.__SelectOption).
+               //
+               //              If passed in a number, then the option with the given index (0-based)
+               //              within this select will be returned.
+               //
+               //              If passed in a dijit.form.__SelectOption, the same option will be
+               //              returned if and only if it exists within this select.
+               //
+               //              If passed an array, then an array will be returned with each element
+               //              in the array being looked up.
+               //
+               //              If not passed a value, then all options will be returned
+               //
+               // returns:
+               //              The option corresponding with the given value or index.  null
+               //              is returned if any of the following are true:
+               //                      - A string value is passed in which doesn't exist
+               //                      - An index is passed in which is outside the bounds of the array of options
+               //                      - A dijit.form.__SelectOption is passed in which is not a part of the select
+
+               // NOTE: the compare for passing in a dijit.form.__SelectOption checks
+               //              if the value property matches - NOT if the exact option exists
+               // NOTE: if passing in an array, null elements will be placed in the returned
+               //              array when a value is not found.
+               var lookupValue = valueOrIdx, opts = this.options || [], l = opts.length;
+
+               if(lookupValue === undefined){
+                       return opts; // dijit.form.__SelectOption[]
+               }
+               if(lang.isArray(lookupValue)){
+                       return array.map(lookupValue, "return this.getOptions(item);", this); // dijit.form.__SelectOption[]
+               }
+               if(lang.isObject(valueOrIdx)){
+                       // We were passed an option - so see if it's in our array (directly),
+                       // and if it's not, try and find it by value.
+                       if(!array.some(this.options, function(o, idx){
+                               if(o === lookupValue ||
+                                       (o.value && o.value === lookupValue.value)){
+                                       lookupValue = idx;
+                                       return true;
                                }
+                               return false;
+                       })){
+                               lookupValue = -1;
                        }
-                       node.id = "";
-                       tr = dojo.create("tr", null, b);
-                       td = dojo.create("td", null, tr);
-                       td.appendChild(node);
-                       dojo.attr(tr, {
-                               "class": "dojoDndAvatarItem",
-                               style: {opacity: (9 - i) / 10}
-                       });
                }
-               this.node = a;
+               if(typeof lookupValue == "string"){
+                       for(var i=0; i<l; i++){
+                               if(opts[i].value === lookupValue){
+                                       lookupValue = i;
+                                       break;
+                               }
+                       }
+               }
+               if(typeof lookupValue == "number" && lookupValue >= 0 && lookupValue < l){
+                       return this.options[lookupValue]; // dijit.form.__SelectOption
+               }
+               return null; // null
        },
-       destroy: function(){
+
+       addOption: function(/*dijit.form.__SelectOption|dijit.form.__SelectOption[]*/ option){
                // summary:
-               //              destructor for the avatar; called to remove all references so it can be garbage-collected
-               dojo.destroy(this.node);
-               this.node = false;
+               //              Adds an option or options to the end of the select.  If value
+               //              of the option is empty or missing, a separator is created instead.
+               //              Passing in an array of options will yield slightly better performance
+               //              since the children are only loaded once.
+               if(!lang.isArray(option)){ option = [option]; }
+               array.forEach(option, function(i){
+                       if(i && lang.isObject(i)){
+                               this.options.push(i);
+                       }
+               }, this);
+               this._loadChildren();
        },
-       update: function(){
+
+       removeOption: function(/*String|dijit.form.__SelectOption|Number|Array*/ valueOrIdx){
                // summary:
-               //              updates the avatar to reflect the current DnD state
-               dojo[(this.manager.canDropFlag ? "add" : "remove") + "Class"](this.node, "dojoDndAvatarCanDrop");
-               if (this.isA11y){
-                       var icon = dojo.byId("a11yIcon");
-                       var text = '+';   // assume canDrop && copy
-                       if (this.manager.canDropFlag && !this.manager.copy) {
-                               text = '< '; // canDrop && move 
-                       }else if (!this.manager.canDropFlag && !this.manager.copy) {
-                               text = "o"; //!canDrop && move
-                       }else if(!this.manager.canDropFlag){
-                               text = 'x';  // !canDrop && copy
+               //              Removes the given option or options.  You can remove by string
+               //              (in which case the value is removed), number (in which case the
+               //              index in the options array is removed), or select option (in
+               //              which case, the select option with a matching value is removed).
+               //              You can also pass in an array of those values for a slightly
+               //              better performance since the children are only loaded once.
+               if(!lang.isArray(valueOrIdx)){ valueOrIdx = [valueOrIdx]; }
+               var oldOpts = this.getOptions(valueOrIdx);
+               array.forEach(oldOpts, function(i){
+                       // We can get null back in our array - if our option was not found.  In
+                       // that case, we don't want to blow up...
+                       if(i){
+                               this.options = array.filter(this.options, function(node){
+                                       return (node.value !== i.value || node.label !== i.label);
+                               });
+                               this._removeOptionItem(i);
                        }
-                       icon.innerHTML=text;
-               }
-               // replace text
-               dojo.query(("tr.dojoDndAvatarHeader td span" +(this.isA11y ? " span" : "")), this.node).forEach(
-                       function(node){
-                               node.innerHTML = this._generateText();
-                       }, this);
+               }, this);
+               this._loadChildren();
        },
-       _generateText: function(){
-               // summary: generates a proper text to reflect copying or moving of items
-               return this.manager.nodes.length.toString();
-       }
-});
 
-}
+       updateOption: function(/*dijit.form.__SelectOption|dijit.form.__SelectOption[]*/ newOption){
+               // summary:
+               //              Updates the values of the given option.  The option to update
+               //              is matched based on the value of the entered option.  Passing
+               //              in an array of new options will yield better performance since
+               //              the children will only be loaded once.
+               if(!lang.isArray(newOption)){ newOption = [newOption]; }
+               array.forEach(newOption, function(i){
+                       var oldOpt = this.getOptions(i), k;
+                       if(oldOpt){
+                               for(k in i){ oldOpt[k] = i[k]; }
+                       }
+               }, this);
+               this._loadChildren();
+       },
+
+       setStore: function(/*dojo.data.api.Identity*/ store,
+                                               /*anything?*/ selectedValue,
+                                               /*Object?*/ fetchArgs){
+               // summary:
+               //              Sets the store you would like to use with this select widget.
+               //              The selected value is the value of the new store to set.  This
+               //              function returns the original store, in case you want to reuse
+               //              it or something.
+               // store: dojo.data.api.Identity
+               //              The store you would like to use - it MUST implement dojo.data.api.Identity,
+               //              and MAY implement dojo.data.api.Notification.
+               // selectedValue: anything?
+               //              The value that this widget should set itself to *after* the store
+               //              has been loaded
+               // fetchArgs: Object?
+               //              The arguments that will be passed to the store's fetch() function
+               var oStore = this.store;
+               fetchArgs = fetchArgs || {};
+               if(oStore !== store){
+                       // Our store has changed, so update our notifications
+                       var h;
+                       while(h = this._notifyConnections.pop()){ h.remove(); }
+
+                       if(store && store.getFeatures()["dojo.data.api.Notification"]){
+                               this._notifyConnections = [
+                                       aspect.after(store, "onNew", lang.hitch(this, "_onNewItem"), true),
+                                       aspect.after(store, "onDelete", lang.hitch(this, "_onDeleteItem"), true),
+                                       aspect.after(store, "onSet", lang.hitch(this, "_onSetItem"), true)
+                               ];
+                       }
+                       this._set("store", store);
+               }
 
-if(!dojo._hasResource["dojo.dnd.Manager"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.dnd.Manager"] = true;
-dojo.provide("dojo.dnd.Manager");
+               // Turn off change notifications while we make all these changes
+               this._onChangeActive = false;
 
+               // Remove existing options (if there are any)
+               if(this.options && this.options.length){
+                       this.removeOption(this.options);
+               }
 
+               // Add our new options
+               if(store){
+                       this._loadingStore = true;
+                       store.fetch(lang.delegate(fetchArgs, {
+                               onComplete: function(items, opts){
+                                       if(this.sortByLabel && !fetchArgs.sort && items.length){
+                                               items.sort(sorter.createSortFunction([{
+                                                       attribute: store.getLabelAttributes(items[0])[0]
+                                               }], store));
+                                       }
 
+                                       if(fetchArgs.onFetch){
+                                                       items = fetchArgs.onFetch.call(this, items, opts);
+                                       }
+                                       // TODO: Add these guys as a batch, instead of separately
+                                       array.forEach(items, function(i){
+                                               this._addOptionForItem(i);
+                                       }, this);
 
+                                       // Set our value (which might be undefined), and then tweak
+                                       // it to send a change event with the real value
+                                       this._loadingStore = false;
+                                               this.set("value", "_pendingValue" in this ? this._pendingValue : selectedValue);
+                                       delete this._pendingValue;
 
-dojo.declare("dojo.dnd.Manager", null, {
-       // summary:
-       //              the manager of DnD operations (usually a singleton)
-       constructor: function(){
-               this.avatar  = null;
-               this.source = null;
-               this.nodes = [];
-               this.copy  = true;
-               this.target = null;
-               this.canDropFlag = false;
-               this.events = [];
+                                       if(!this.loadChildrenOnOpen){
+                                               this._loadChildren();
+                                       }else{
+                                               this._pseudoLoadChildren(items);
+                                       }
+                                       this._fetchedWith = opts;
+                                       this._lastValueReported = this.multiple ? [] : null;
+                                       this._onChangeActive = true;
+                                       this.onSetStore();
+                                       this._handleOnChange(this.value);
+                               },
+                               scope: this
+                       }));
+               }else{
+                       delete this._fetchedWith;
+               }
+               return oStore;  // dojo.data.api.Identity
        },
 
-       // avatar's offset from the mouse
-       OFFSET_X: 16,
-       OFFSET_Y: 16,
-       
-       // methods
-       overSource: function(source){
+       // TODO: implement set() and watch() for store and query, although not sure how to handle
+       // setting them individually rather than together (as in setStore() above)
+
+       _setValueAttr: function(/*anything*/ newValue, /*Boolean?*/ priorityChange){
                // summary:
-               //              called when a source detected a mouse-over condition
-               // source: Object
-               //              the reporter
-               if(this.avatar){
-                       this.target = (source && source.targetState != "Disabled") ? source : null;
-                       this.canDropFlag = Boolean(this.target);
-                       this.avatar.update();
+               //              set the value of the widget.
+               //              If a string is passed, then we set our value from looking it up.
+               if(this._loadingStore){
+                       // Our store is loading - so save our value, and we'll set it when
+                       // we're done
+                       this._pendingValue = newValue;
+                       return;
                }
-               dojo.publish("/dnd/source/over", [source]);
+               var opts = this.getOptions() || [];
+               if(!lang.isArray(newValue)){
+                       newValue = [newValue];
+               }
+               array.forEach(newValue, function(i, idx){
+                       if(!lang.isObject(i)){
+                               i = i + "";
+                       }
+                       if(typeof i === "string"){
+                               newValue[idx] = array.filter(opts, function(node){
+                                       return node.value === i;
+                               })[0] || {value: "", label: ""};
+                       }
+               }, this);
+
+               // Make sure some sane default is set
+               newValue = array.filter(newValue, function(i){ return i && i.value; });
+               if(!this.multiple && (!newValue[0] || !newValue[0].value) && opts.length){
+                       newValue[0] = opts[0];
+               }
+               array.forEach(opts, function(i){
+                       i.selected = array.some(newValue, function(v){ return v.value === i.value; });
+               });
+               var val = array.map(newValue, function(i){ return i.value; }),
+                       disp = array.map(newValue, function(i){ return i.label; });
+
+               this._set("value", this.multiple ? val : val[0]);
+               this._setDisplay(this.multiple ? disp : disp[0]);
+               this._updateSelection();
+               this._handleOnChange(this.value, priorityChange);
        },
-       outSource: function(source){
+
+       _getDisplayedValueAttr: function(){
                // summary:
-               //              called when a source detected a mouse-out condition
-               // source: Object
-               //              the reporter
-               if(this.avatar){
-                       if(this.target == source){
-                               this.target = null;
-                               this.canDropFlag = false;
-                               this.avatar.update();
-                               dojo.publish("/dnd/source/over", [null]);
-                       }
-               }else{
-                       dojo.publish("/dnd/source/over", [null]);
+               //              returns the displayed value of the widget
+               var val = this.get("value");
+               if(!lang.isArray(val)){
+                       val = [val];
                }
+               var ret = array.map(this.getOptions(val), function(v){
+                       if(v && "label" in v){
+                               return v.label;
+                       }else if(v){
+                               return v.value;
+                       }
+                       return null;
+               }, this);
+               return this.multiple ? ret : ret[0];
        },
-       startDrag: function(source, nodes, copy){
+
+       _loadChildren: function(){
                // summary:
-               //              called to initiate the DnD operation
-               // source: Object
-               //              the source which provides items
-               // nodes: Array
-               //              the list of transferred items
-               // copy: Boolean
-               //              copy items, if true, move items otherwise
-               this.source = source;
-               this.nodes  = nodes;
-               this.copy   = Boolean(copy); // normalizing to true boolean
-               this.avatar = this.makeAvatar();
-               dojo.body().appendChild(this.avatar.node);
-               dojo.publish("/dnd/start", [source, nodes, this.copy]);
-               this.events = [
-                       dojo.connect(dojo.doc, "onmousemove", this, "onMouseMove"),
-                       dojo.connect(dojo.doc, "onmouseup",   this, "onMouseUp"),
-                       dojo.connect(dojo.doc, "onkeydown",   this, "onKeyDown"),
-                       dojo.connect(dojo.doc, "onkeyup",     this, "onKeyUp"),
-                       // cancel text selection and text dragging
-                       dojo.connect(dojo.doc, "ondragstart",   dojo.stopEvent),
-                       dojo.connect(dojo.body(), "onselectstart", dojo.stopEvent)
-               ];
-               var c = "dojoDnd" + (copy ? "Copy" : "Move");
-               dojo.addClass(dojo.body(), c); 
+               //              Loads the children represented by this widget's options.
+               //              reset the menu to make it populatable on the next click
+               if(this._loadingStore){ return; }
+               array.forEach(this._getChildren(), function(child){
+                       child.destroyRecursive();
+               });
+               // Add each menu item
+               array.forEach(this.options, this._addOptionItem, this);
+
+               // Update states
+               this._updateSelection();
        },
-       canDrop: function(flag){
+
+       _updateSelection: function(){
                // summary:
-               //              called to notify if the current target can accept items
-               var canDropFlag = Boolean(this.target && flag);
-               if(this.canDropFlag != canDropFlag){
-                       this.canDropFlag = canDropFlag;
-                       this.avatar.update();
+               //              Sets the "selected" class on the item for styling purposes
+               this._set("value", this._getValueFromOpts());
+               var val = this.value;
+               if(!lang.isArray(val)){
+                       val = [val];
+               }
+               if(val && val[0]){
+                       array.forEach(this._getChildren(), function(child){
+                               var isSelected = array.some(val, function(v){
+                                       return child.option && (v === child.option.value);
+                               });
+                               domClass.toggle(child.domNode, this.baseClass + "SelectedOption", isSelected);
+                               child.domNode.setAttribute("aria-selected", isSelected);
+                       }, this);
                }
        },
-       stopDrag: function(){
+
+       _getValueFromOpts: function(){
                // summary:
-               //              stop the DnD in progress
-               dojo.removeClass(dojo.body(), "dojoDndCopy");
-               dojo.removeClass(dojo.body(), "dojoDndMove");
-               dojo.forEach(this.events, dojo.disconnect);
-               this.events = [];
-               this.avatar.destroy();
-               this.avatar = null;
-               this.source = this.target = null;
-               this.nodes = [];
+               //              Returns the value of the widget by reading the options for
+               //              the selected flag
+               var opts = this.getOptions() || [];
+               if(!this.multiple && opts.length){
+                       // Mirror what a select does - choose the first one
+                       var opt = array.filter(opts, function(i){
+                               return i.selected;
+                       })[0];
+                       if(opt && opt.value){
+                               return opt.value
+                       }else{
+                               opts[0].selected = true;
+                               return opts[0].value;
+                       }
+               }else if(this.multiple){
+                       // Set value to be the sum of all selected
+                       return array.map(array.filter(opts, function(i){
+                               return i.selected;
+                       }), function(i){
+                               return i.value;
+                       }) || [];
+               }
+               return "";
        },
-       makeAvatar: function(){
+
+       // Internal functions to call when we have store notifications come in
+       _onNewItem: function(/*item*/ item, /*Object?*/ parentInfo){
+               if(!parentInfo || !parentInfo.parent){
+                       // Only add it if we are top-level
+                       this._addOptionForItem(item);
+               }
+       },
+       _onDeleteItem: function(/*item*/ item){
+               var store = this.store;
+               this.removeOption(store.getIdentity(item));
+       },
+       _onSetItem: function(/*item*/ item){
+               this.updateOption(this._getOptionObjForItem(item));
+       },
+
+       _getOptionObjForItem: function(item){
                // summary:
-               //              makes the avatar; it is separate to be overwritten dynamically, if needed
-               return new dojo.dnd.Avatar(this);
+               //              Returns an option object based off the given item.  The "value"
+               //              of the option item will be the identity of the item, the "label"
+               //              of the option will be the label of the item.  If the item contains
+               //              children, the children value of the item will be set
+               var store = this.store, label = store.getLabel(item),
+                       value = (label ? store.getIdentity(item) : null);
+               return {value: value, label: label, item:item}; // dijit.form.__SelectOption
        },
-       updateAvatar: function(){
+
+       _addOptionForItem: function(/*item*/ item){
                // summary:
-               //              updates the avatar; it is separate to be overwritten dynamically, if needed
-               this.avatar.update();
+               //              Creates (and adds) the option for the given item
+               var store = this.store;
+               if(!store.isItemLoaded(item)){
+                       // We are not loaded - so let's load it and add later
+                       store.loadItem({item: item, onItem: function(i){
+                               this._addOptionForItem(i);
+                       },
+                       scope: this});
+                       return;
+               }
+               var newOpt = this._getOptionObjForItem(item);
+               this.addOption(newOpt);
        },
-       
-       // mouse event processors
-       onMouseMove: function(e){
+
+       constructor: function(/*Object*/ keywordArgs){
                // summary:
-               //              event processor for onmousemove
-               // e: Event
-               //              mouse event
-               var a = this.avatar;
-               if(a){
-                       dojo.dnd.autoScrollNodes(e);
-                       //dojo.dnd.autoScroll(e);
-                       var s = a.node.style;
-                       s.left = (e.pageX + this.OFFSET_X) + "px";
-                       s.top  = (e.pageY + this.OFFSET_Y) + "px";
-                       var copy = Boolean(this.source.copyState(dojo.isCopyKey(e)));
-                       if(this.copy != copy){ 
-                               this._setCopyStatus(copy);
-                       }
+               //              Saves off our value, if we have an initial one set so we
+               //              can use it if we have a store as well (see startup())
+               this._oValue = (keywordArgs || {}).value || null;
+               this._notifyConnections = [];
+       },
+
+       buildRendering: function(){
+               this.inherited(arguments);
+               dom.setSelectable(this.focusNode, false);
+       },
+
+       _fillContent: function(){
+               // summary:
+               //              Loads our options and sets up our dropdown correctly.  We
+               //              don't want any content, so we don't call any inherit chain
+               //              function.
+               var opts = this.options;
+               if(!opts){
+                       opts = this.options = this.srcNodeRef ? query("> *",
+                                               this.srcNodeRef).map(function(node){
+                                                       if(node.getAttribute("type") === "separator"){
+                                                               return { value: "", label: "", selected: false, disabled: false };
+                                                       }
+                                                       return {
+                                                               value: (node.getAttribute("data-" + kernel._scopeName + "-value") || node.getAttribute("value")),
+                                                                               label: String(node.innerHTML),
+                                                               // FIXME: disabled and selected are not valid on complex markup children (which is why we're
+                                                               // looking for data-dojo-value above.  perhaps we should data-dojo-props="" this whole thing?)
+                                                               // decide before 1.6
+                                                                               selected: node.getAttribute("selected") || false,
+                                                               disabled: node.getAttribute("disabled") || false
+                                                       };
+                                               }, this) : [];
+               }
+               if(!this.value){
+                       this._set("value", this._getValueFromOpts());
+               }else if(this.multiple && typeof this.value == "string"){
+                       this._set("value", this.value.split(","));
                }
        },
-       onMouseUp: function(e){
+
+       postCreate: function(){
                // summary:
-               //              event processor for onmouseup
-               // e: Event
-               //              mouse event
-               if(this.avatar){
-                       if(this.target && this.canDropFlag){
-                               var copy = Boolean(this.source.copyState(dojo.isCopyKey(e))),
-                               params = [this.source, this.nodes, copy, this.target, e];
-                               dojo.publish("/dnd/drop/before", params);
-                               dojo.publish("/dnd/drop", params);
-                       }else{
-                               dojo.publish("/dnd/cancel");
+               //              sets up our event handling that we need for functioning
+               //              as a select
+               this.inherited(arguments);
+
+               // Make our event connections for updating state
+               this.connect(this, "onChange", "_updateSelection");
+               this.connect(this, "startup", "_loadChildren");
+
+               this._setValueAttr(this.value, null);
+       },
+
+       startup: function(){
+               // summary:
+               //              Connects in our store, if we have one defined
+               this.inherited(arguments);
+               var store = this.store, fetchArgs = {};
+               array.forEach(["query", "queryOptions", "onFetch"], function(i){
+                       if(this[i]){
+                               fetchArgs[i] = this[i];
                        }
-                       this.stopDrag();
+                       delete this[i];
+               }, this);
+               if(store && store.getFeatures()["dojo.data.api.Identity"]){
+                       // Temporarily set our store to null so that it will get set
+                       // and connected appropriately
+                       this.store = null;
+                       this.setStore(store, this._oValue, fetchArgs);
                }
        },
-       
-       // keyboard event processors
-       onKeyDown: function(e){
+
+       destroy: function(){
                // summary:
-               //              event processor for onkeydown:
-               //              watching for CTRL for copy/move status, watching for ESCAPE to cancel the drag
-               // e: Event
-               //              keyboard event
-               if(this.avatar){
-                       switch(e.keyCode){
-                               case dojo.keys.CTRL:
-                                       var copy = Boolean(this.source.copyState(true));
-                                       if(this.copy != copy){ 
-                                               this._setCopyStatus(copy);
+               //              Clean up our connections
+               var h;
+               while(h = this._notifyConnections.pop()){ h.remove(); }
+               this.inherited(arguments);
+       },
+
+       _addOptionItem: function(/*dijit.form.__SelectOption*/ /*===== option =====*/){
+               // summary:
+               //              User-overridable function which, for the given option, adds an
+               //              item to the select.  If the option doesn't have a value, then a
+               //              separator is added in that place.  Make sure to store the option
+               //              in the created option widget.
+       },
+
+       _removeOptionItem: function(/*dijit.form.__SelectOption*/ /*===== option =====*/){
+               // summary:
+               //              User-overridable function which, for the given option, removes
+               //              its item from the select.
+       },
+
+       _setDisplay: function(/*String or String[]*/ /*===== newDisplay =====*/){
+               // summary:
+               //              Overridable function which will set the display for the
+               //              widget.  newDisplay is either a string (in the case of
+               //              single selects) or array of strings (in the case of multi-selects)
+       },
+
+       _getChildren: function(){
+               // summary:
+               //              Overridable function to return the children that this widget contains.
+               return [];
+       },
+
+       _getSelectedOptionsAttr: function(){
+               // summary:
+               //              hooks into this.attr to provide a mechanism for getting the
+               //              option items for the current value of the widget.
+               return this.getOptions(this.get("value"));
+       },
+
+       _pseudoLoadChildren: function(/*item[]*/ /*===== items =====*/){
+               // summary:
+               //              a function that will "fake" loading children, if needed, and
+               //              if we have set to not load children until the widget opens.
+               // items:
+               //              An array of items that will be loaded, when needed
+       },
+
+       onSetStore: function(){
+               // summary:
+               //              a function that can be connected to in order to receive a
+               //              notification that the store has finished loading and all options
+               //              from that store are available
+       }
+});
+
+});
+
+},
+'dijit/form/Select':function(){
+require({cache:{
+'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"combobox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\" role=\"presentation\"\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"  data-dojo-attach-point=\"containerNode,_popupStateNode\"></span\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">&#9660;</div\n\t\t></td\n\t></tr></tbody\n></table>\n"}});
+define("dijit/form/Select", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr", // domAttr.set
+       "dojo/dom-class", // domClass.add domClass.remove domClass.toggle
+       "dojo/dom-construct", // domConstruct.create
+       "dojo/dom-geometry", // domGeometry.setMarginBox
+       "dojo/_base/event", // event.stop
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/lang", // lang.hitch
+       "./_FormSelectWidget",
+       "../_HasDropDown",
+       "../Menu",
+       "../MenuItem",
+       "../MenuSeparator",
+       "../Tooltip",
+       "dojo/text!./templates/Select.html",
+       "dojo/i18n!./nls/validate"
+], function(array, declare, domAttr, domClass, domConstruct, domGeometry, event, i18n, lang,
+                       _FormSelectWidget, _HasDropDown, Menu, MenuItem, MenuSeparator, Tooltip, template){
+
+/*=====
+       var _FormSelectWidget = dijit.form._FormSelectWidget;
+       var _HasDropDown = dijit._HasDropDown;
+       var _FormSelectWidget = dijit._FormSelectWidget;
+       var Menu = dijit.Menu;
+       var MenuItem = dijit.MenuItem;
+       var MenuSeparator = dijit.MenuSeparator;
+       var Tooltip = dijit.Tooltip;
+=====*/
+
+// module:
+//             dijit/form/Select
+// summary:
+//             This is a "styleable" select box - it is basically a DropDownButton which
+//             can take a <select> as its input.
+
+
+var _SelectMenu = declare("dijit.form._SelectMenu", Menu, {
+       // summary:
+       //              An internally-used menu for dropdown that allows us a vertical scrollbar
+       buildRendering: function(){
+               // summary:
+               //              Stub in our own changes, so that our domNode is not a table
+               //              otherwise, we won't respond correctly to heights/overflows
+               this.inherited(arguments);
+               var o = (this.menuTableNode = this.domNode);
+               var n = (this.domNode = domConstruct.create("div", {style: {overflowX: "hidden", overflowY: "scroll"}}));
+               if(o.parentNode){
+                       o.parentNode.replaceChild(n, o);
+               }
+               domClass.remove(o, "dijitMenuTable");
+               n.className = o.className + " dijitSelectMenu";
+               o.className = "dijitReset dijitMenuTable";
+               o.setAttribute("role", "listbox");
+               n.setAttribute("role", "presentation");
+               n.appendChild(o);
+       },
+
+       postCreate: function(){
+               // summary:
+               //              stop mousemove from selecting text on IE to be consistent with other browsers
+
+               this.inherited(arguments);
+
+               this.connect(this.domNode, "onmousemove", event.stop);
+       },
+
+       resize: function(/*Object*/ mb){
+               // summary:
+               //              Overridden so that we are able to handle resizing our
+               //              internal widget.  Note that this is not a "full" resize
+               //              implementation - it only works correctly if you pass it a
+               //              marginBox.
+               //
+               // mb: Object
+               //              The margin box to set this dropdown to.
+               if(mb){
+                       domGeometry.setMarginBox(this.domNode, mb);
+                       if("w" in mb){
+                               // We've explicitly set the wrapper <div>'s width, so set <table> width to match.
+                               // 100% is safer than a pixel value because there may be a scroll bar with
+                               // browser/OS specific width.
+                               this.menuTableNode.style.width = "100%";
+                       }
+               }
+       }
+});
+
+var Select = declare("dijit.form.Select", [_FormSelectWidget, _HasDropDown], {
+       // summary:
+       //              This is a "styleable" select box - it is basically a DropDownButton which
+       //              can take a <select> as its input.
+
+       baseClass: "dijitSelect",
+
+       templateString: template,
+
+       // required: Boolean
+       //              Can be true or false, default is false.
+       required: false,
+
+       // state: [readonly] String
+       //              "Incomplete" if this select is required but unset (i.e. blank value), "" otherwise
+       state: "",
+
+       // message: String
+       //              Currently displayed error/prompt message
+       message: "",
+
+       //      tooltipPosition: String[]
+       //              See description of dijit.Tooltip.defaultPosition for details on this parameter.
+       tooltipPosition: [],
+
+       // emptyLabel: string
+       //              What to display in an "empty" dropdown
+       emptyLabel: "&#160;",   // &nbsp;
+
+       // _isLoaded: Boolean
+       //              Whether or not we have been loaded
+       _isLoaded: false,
+
+       // _childrenLoaded: Boolean
+       //              Whether or not our children have been loaded
+       _childrenLoaded: false,
+
+       _fillContent: function(){
+               // summary:
+               //              Set the value to be the first, or the selected index
+               this.inherited(arguments);
+               // set value from selected option
+               if(this.options.length && !this.value && this.srcNodeRef){
+                       var si = this.srcNodeRef.selectedIndex || 0; // || 0 needed for when srcNodeRef is not a SELECT
+                       this.value = this.options[si >= 0 ? si : 0].value;
+               }
+               // Create the dropDown widget
+               this.dropDown = new _SelectMenu({id: this.id + "_menu"});
+               domClass.add(this.dropDown.domNode, this.baseClass + "Menu");
+       },
+
+       _getMenuItemForOption: function(/*dijit.form.__SelectOption*/ option){
+               // summary:
+               //              For the given option, return the menu item that should be
+               //              used to display it.  This can be overridden as needed
+               if(!option.value && !option.label){
+                       // We are a separator (no label set for it)
+                       return new MenuSeparator();
+               }else{
+                       // Just a regular menu option
+                       var click = lang.hitch(this, "_setValueAttr", option);
+                       var item = new MenuItem({
+                               option: option,
+                               label: option.label || this.emptyLabel,
+                               onClick: click,
+                               disabled: option.disabled || false
+                       });
+                       item.focusNode.setAttribute("role", "listitem");
+                       return item;
+               }
+       },
+
+       _addOptionItem: function(/*dijit.form.__SelectOption*/ option){
+               // summary:
+               //              For the given option, add an option to our dropdown.
+               //              If the option doesn't have a value, then a separator is added
+               //              in that place.
+               if(this.dropDown){
+                       this.dropDown.addChild(this._getMenuItemForOption(option));
+               }
+       },
+
+       _getChildren: function(){
+               if(!this.dropDown){
+                       return [];
+               }
+               return this.dropDown.getChildren();
+       },
+
+       _loadChildren: function(/*Boolean*/ loadMenuItems){
+               // summary:
+               //              Resets the menu and the length attribute of the button - and
+               //              ensures that the label is appropriately set.
+               //      loadMenuItems: Boolean
+               //              actually loads the child menu items - we only do this when we are
+               //              populating for showing the dropdown.
+
+               if(loadMenuItems === true){
+                       // this.inherited destroys this.dropDown's child widgets (MenuItems).
+                       // Avoid this.dropDown (Menu widget) having a pointer to a destroyed widget (which will cause
+                       // issues later in _setSelected). (see #10296)
+                       if(this.dropDown){
+                               delete this.dropDown.focusedChild;
+                       }
+                       if(this.options.length){
+                               this.inherited(arguments);
+                       }else{
+                               // Drop down menu is blank but add one blank entry just so something appears on the screen
+                               // to let users know that they are no choices (mimicing native select behavior)
+                               array.forEach(this._getChildren(), function(child){ child.destroyRecursive(); });
+                               var item = new MenuItem({label: "&#160;"});
+                               this.dropDown.addChild(item);
+                       }
+               }else{
+                       this._updateSelection();
+               }
+
+               this._isLoaded = false;
+               this._childrenLoaded = true;
+
+               if(!this._loadingStore){
+                       // Don't call this if we are loading - since we will handle it later
+                       this._setValueAttr(this.value);
+               }
+       },
+
+       _setValueAttr: function(value){
+               this.inherited(arguments);
+               domAttr.set(this.valueNode, "value", this.get("value"));
+               this.validate(this.focused);    // to update this.state
+       },
+
+       _setDisabledAttr: function(/*Boolean*/ value){
+               this.inherited(arguments);
+               this.validate(this.focused);    // to update this.state
+       },
+
+       _setRequiredAttr: function(/*Boolean*/ value){
+               this._set("required", value);
+               this.focusNode.setAttribute("aria-required", value);
+               this.validate(this.focused);    // to update this.state
+       },
+
+       _setDisplay: function(/*String*/ newDisplay){
+               // summary:
+               //              sets the display for the given value (or values)
+               var lbl = newDisplay || this.emptyLabel;
+               this.containerNode.innerHTML = '<span class="dijitReset dijitInline ' + this.baseClass + 'Label">' + lbl + '</span>';
+               this.focusNode.setAttribute("aria-valuetext", lbl);
+       },
+
+       validate: function(/*Boolean*/ isFocused){
+               // summary:
+               //              Called by oninit, onblur, and onkeypress, and whenever required/disabled state changes
+               // description:
+               //              Show missing or invalid messages if appropriate, and highlight textbox field.
+               //              Used when a select is initially set to no value and the user is required to
+               //              set the value.
+
+               var isValid = this.disabled || this.isValid(isFocused);
+               this._set("state", isValid ? "" : "Incomplete");
+               this.focusNode.setAttribute("aria-invalid", isValid ? "false" : "true");
+               var message = isValid ? "" : this._missingMsg;
+               if(message && this.focused && this._hasBeenBlurred){
+                       Tooltip.show(message, this.domNode, this.tooltipPosition, !this.isLeftToRight());
+               }else{
+                       Tooltip.hide(this.domNode);
+               }
+               this._set("message", message);
+               return isValid;
+       },
+
+       isValid: function(/*Boolean*/ /*===== isFocused =====*/){
+               // summary:
+               //              Whether or not this is a valid value.  The only way a Select
+               //              can be invalid is when it's required but nothing is selected.
+               return (!this.required || this.value === 0 || !(/^\s*$/.test(this.value || ""))); // handle value is null or undefined
+       },
+
+       reset: function(){
+               // summary:
+               //              Overridden so that the state will be cleared.
+               this.inherited(arguments);
+               Tooltip.hide(this.domNode);
+               this.validate(this.focused);    // to update this.state
+       },
+
+       postMixInProperties: function(){
+               // summary:
+               //              set the missing message
+               this.inherited(arguments);
+               this._missingMsg = i18n.getLocalization("dijit.form", "validate",
+                                                                       this.lang).missingMessage;
+       },
+
+       postCreate: function(){
+               // summary:
+               //              stop mousemove from selecting text on IE to be consistent with other browsers
+
+               this.inherited(arguments);
+
+               this.connect(this.domNode, "onmousemove", event.stop);
+       },
+
+       _setStyleAttr: function(/*String||Object*/ value){
+               this.inherited(arguments);
+               domClass.toggle(this.domNode, this.baseClass + "FixedWidth", !!this.domNode.style.width);
+       },
+
+       isLoaded: function(){
+               return this._isLoaded;
+       },
+
+       loadDropDown: function(/*Function*/ loadCallback){
+               // summary:
+               //              populates the menu
+               this._loadChildren(true);
+               this._isLoaded = true;
+               loadCallback();
+       },
+
+       closeDropDown: function(){
+               // overriding _HasDropDown.closeDropDown()
+               this.inherited(arguments);
+
+               if(this.dropDown && this.dropDown.menuTableNode){
+                       // Erase possible width: 100% setting from _SelectMenu.resize().
+                       // Leaving it would interfere with the next openDropDown() call, which
+                       // queries the natural size of the drop down.
+                       this.dropDown.menuTableNode.style.width = "";
+               }
+       },
+
+       uninitialize: function(preserveDom){
+               if(this.dropDown && !this.dropDown._destroyed){
+                       this.dropDown.destroyRecursive(preserveDom);
+                       delete this.dropDown;
+               }
+               this.inherited(arguments);
+       },
+
+       _onFocus: function(){
+               this.validate(true);    // show tooltip if second focus of required tooltip, but no selection
+               this.inherited(arguments);
+       },
+
+       _onBlur: function(){
+               Tooltip.hide(this.domNode);
+               this.inherited(arguments);
+       }
+});
+
+Select._Menu = _SelectMenu;    // for monkey patching
+
+return Select;
+});
+
+},
+'dojo/store/util/QueryResults':function(){
+define("dojo/store/util/QueryResults", ["../../_base/array", "../../_base/lang", "../../_base/Deferred"
+], function(array, lang, Deferred) {
+  //  module:
+  //    dojo/store/util/QueryResults
+  //  summary:
+  //    The module defines a query results wrapper
+
+var util = lang.getObject("dojo.store.util", true);
+
+util.QueryResults = function(results){
+       // summary:
+       //              A function that wraps the results of a store query with additional
+       //              methods.
+       //
+       // description:
+       //              QueryResults is a basic wrapper that allows for array-like iteration
+       //              over any kind of returned data from a query.  While the simplest store
+       //              will return a plain array of data, other stores may return deferreds or
+       //              promises; this wrapper makes sure that *all* results can be treated
+       //              the same.
+       //
+       //              Additional methods include `forEach`, `filter` and `map`.
+       //
+       // returns: Object
+       //              An array-like object that can be used for iterating over.
+       //
+       // example:
+       //              Query a store and iterate over the results.
+       //
+       //      |       store.query({ prime: true }).forEach(function(item){
+       //      |               //      do something
+       //      |       });
+
+       if(!results){
+               return results;
+       }
+       // if it is a promise it may be frozen
+       if(results.then){
+               results = lang.delegate(results);
+       }
+       function addIterativeMethod(method){
+               if(!results[method]){
+                       results[method] = function(){
+                               var args = arguments;
+                               return Deferred.when(results, function(results){
+                                       Array.prototype.unshift.call(args, results);
+                                       return util.QueryResults(array[method].apply(array, args));
+                               });
+                       };
+               }
+       }
+       addIterativeMethod("forEach");
+       addIterativeMethod("filter");
+       addIterativeMethod("map");
+       if(!results.total){
+               results.total = Deferred.when(results, function(results){
+                       return results.length;
+               });
+       }
+       return results;
+};
+
+return util.QueryResults;
+});
+
+},
+'dijit/form/_ListBase':function(){
+define("dijit/form/_ListBase", [
+       "dojo/_base/declare",   // declare
+       "dojo/window" // winUtils.scrollIntoView
+], function(declare, winUtils){
+
+// module:
+//             dijit/form/_ListBase
+// summary:
+//             Focus-less menu to handle UI events consistently
+
+return declare( "dijit.form._ListBase", null, {
+       // summary:
+       //              Focus-less menu to handle UI events consistently
+       //              Abstract methods that must be defined externally:
+       //                      onSelect: item is active (mousedown but not yet mouseup, or keyboard arrow selected but no Enter)
+       //                      onDeselect:  cancels onSelect
+       // tags:
+       //              private
+
+       // selected: DOMnode
+       //              currently selected node
+       selected: null,
+
+       _getTarget: function(/*Event*/ evt){
+               var tgt = evt.target;
+               var container = this.containerNode;
+               if(tgt == container || tgt == this.domNode){ return null; }
+               while(tgt && tgt.parentNode != container){
+                       // recurse to the top
+                       tgt = tgt.parentNode;
+               }
+               return tgt;
+       },
+
+       selectFirstNode: function(){
+               // summary:
+               //              Select the first displayed item in the list.
+               var first = this.containerNode.firstChild;
+               while(first && first.style.display == "none"){
+                       first = first.nextSibling;
+               }
+               this._setSelectedAttr(first);
+       },
+
+       selectLastNode: function(){
+               // summary:
+               //              Select the last displayed item in the list
+               var last = this.containerNode.lastChild;
+               while(last && last.style.display == "none"){
+                       last = last.previousSibling;
+               }
+               this._setSelectedAttr(last);
+       },
+
+       selectNextNode: function(){
+               // summary:
+               //              Select the item just below the current selection.
+               //              If nothing selected, select first node.
+               var selectedNode = this._getSelectedAttr();
+               if(!selectedNode){
+                       this.selectFirstNode();
+               }else{
+                       var next = selectedNode.nextSibling;
+                       while(next && next.style.display == "none"){
+                               next = next.nextSibling;
+                       }
+                       if(!next){
+                               this.selectFirstNode();
+                       }else{
+                               this._setSelectedAttr(next);
+                       }
+               }
+       },
+
+       selectPreviousNode: function(){
+               // summary:
+               //              Select the item just above the current selection.
+               //              If nothing selected, select last node (if
+               //              you select Previous and try to keep scrolling up the list).
+               var selectedNode = this._getSelectedAttr();
+               if(!selectedNode){
+                       this.selectLastNode();
+               }else{
+                       var prev = selectedNode.previousSibling;
+                       while(prev && prev.style.display == "none"){
+                               prev = prev.previousSibling;
+                       }
+                       if(!prev){
+                               this.selectLastNode();
+                       }else{
+                               this._setSelectedAttr(prev);
+                       }
+               }
+       },
+
+       _setSelectedAttr: function(/*DomNode*/ node){
+               // summary:
+               //              Does the actual select.
+               if(this.selected != node){
+                       var selectedNode = this._getSelectedAttr();
+                       if(selectedNode){
+                               this.onDeselect(selectedNode);
+                               this.selected = null;
+                       }
+                       if(node && node.parentNode == this.containerNode){
+                               this.selected = node;
+                               winUtils.scrollIntoView(node);
+                               this.onSelect(node);
+                       }
+               }else if(node){
+                       this.onSelect(node);
+               }
+       },
+
+       _getSelectedAttr: function(){
+               // summary:
+               //              Returns the selected node.
+               var v = this.selected;
+               return (v && v.parentNode == this.containerNode) ? v : (this.selected = null);
+       }
+});
+
+});
+
+},
+'dijit/form/_FormWidget':function(){
+define("dijit/form/_FormWidget", [
+       "dojo/_base/declare",   // declare
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/ready",
+       "../_Widget",
+       "../_CssStateMixin",
+       "../_TemplatedMixin",
+       "./_FormWidgetMixin"
+], function(declare, kernel, ready, _Widget, _CssStateMixin, _TemplatedMixin, _FormWidgetMixin){
+
+/*=====
+var _Widget = dijit._Widget;
+var _TemplatedMixin = dijit._TemplatedMixin;
+var _CssStateMixin = dijit._CssStateMixin;
+var _FormWidgetMixin = dijit.form._FormWidgetMixin;
+=====*/
+
+// module:
+//             dijit/form/_FormWidget
+// summary:
+//             FormWidget
+
+
+// Back compat w/1.6, remove for 2.0
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/form/_FormValueWidget"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
+
+return declare("dijit.form._FormWidget", [_Widget, _TemplatedMixin, _CssStateMixin, _FormWidgetMixin], {
+       // summary:
+       //              Base class for widgets corresponding to native HTML elements such as <checkbox> or <button>,
+       //              which can be children of a <form> node or a `dijit.form.Form` widget.
+       //
+       // description:
+       //              Represents a single HTML element.
+       //              All these widgets should have these attributes just like native HTML input elements.
+       //              You can set them during widget construction or afterwards, via `dijit._Widget.attr`.
+       //
+       //              They also share some common methods.
+
+       setDisabled: function(/*Boolean*/ disabled){
+               // summary:
+               //              Deprecated.  Use set('disabled', ...) instead.
+               kernel.deprecated("setDisabled("+disabled+") is deprecated. Use set('disabled',"+disabled+") instead.", "", "2.0");
+               this.set('disabled', disabled);
+       },
+
+       setValue: function(/*String*/ value){
+               // summary:
+               //              Deprecated.  Use set('value', ...) instead.
+               kernel.deprecated("dijit.form._FormWidget:setValue("+value+") is deprecated.  Use set('value',"+value+") instead.", "", "2.0");
+               this.set('value', value);
+       },
+
+       getValue: function(){
+               // summary:
+               //              Deprecated.  Use get('value') instead.
+               kernel.deprecated(this.declaredClass+"::getValue() is deprecated. Use get('value') instead.", "", "2.0");
+               return this.get('value');
+       },
+
+       postMixInProperties: function(){
+               // Setup name=foo string to be referenced from the template (but only if a name has been specified)
+               // Unfortunately we can't use _setNameAttr to set the name due to IE limitations, see #8484, #8660.
+               // Regarding escaping, see heading "Attribute values" in
+               // http://www.w3.org/TR/REC-html40/appendix/notes.html#h-B.3.2
+               this.nameAttrSetting = this.name ? ('name="' + this.name.replace(/'/g, "&quot;") + '"') : '';
+               this.inherited(arguments);
+       },
+
+       // Override automatic assigning type --> focusNode, it causes exception on IE.
+       // Instead, type must be specified as ${type} in the template, as part of the original DOM
+       _setTypeAttr: null
+});
+
+});
+
+},
+'dojo/DeferredList':function(){
+define("dojo/DeferredList", ["./_base/kernel", "./_base/Deferred", "./_base/array"], function(dojo, Deferred, darray) {
+       // module:
+       //              dojo/DeferredList
+       // summary:
+       //              TODOC
+
+
+dojo.DeferredList = function(/*Array*/ list, /*Boolean?*/ fireOnOneCallback, /*Boolean?*/ fireOnOneErrback, /*Boolean?*/ consumeErrors, /*Function?*/ canceller){
+       // summary:
+       //              Provides event handling for a group of Deferred objects.
+       // description:
+       //              DeferredList takes an array of existing deferreds and returns a new deferred of its own
+       //              this new deferred will typically have its callback fired when all of the deferreds in
+       //              the given list have fired their own deferreds.  The parameters `fireOnOneCallback` and
+       //              fireOnOneErrback, will fire before all the deferreds as appropriate
+       //
+       // list:
+       //              The list of deferreds to be synchronizied with this DeferredList
+       // fireOnOneCallback:
+       //              Will cause the DeferredLists callback to be fired as soon as any
+       //              of the deferreds in its list have been fired instead of waiting until
+       //              the entire list has finished
+       // fireonOneErrback:
+       //              Will cause the errback to fire upon any of the deferreds errback
+       // canceller:
+       //              A deferred canceller function, see dojo.Deferred
+       var resultList = [];
+       Deferred.call(this);
+       var self = this;
+       if(list.length === 0 && !fireOnOneCallback){
+               this.resolve([0, []]);
+       }
+       var finished = 0;
+       darray.forEach(list, function(item, i){
+               item.then(function(result){
+                       if(fireOnOneCallback){
+                               self.resolve([i, result]);
+                       }else{
+                               addResult(true, result);
+                       }
+               },function(error){
+                       if(fireOnOneErrback){
+                               self.reject(error);
+                       }else{
+                               addResult(false, error);
+                       }
+                       if(consumeErrors){
+                               return null;
+                       }
+                       throw error;
+               });
+               function addResult(succeeded, result){
+                       resultList[i] = [succeeded, result];
+                       finished++;
+                       if(finished === list.length){
+                               self.resolve(resultList);
+                       }
+
+               }
+       });
+};
+dojo.DeferredList.prototype = new Deferred();
+
+dojo.DeferredList.prototype.gatherResults = function(deferredList){
+       // summary:
+       //              Gathers the results of the deferreds for packaging
+       //              as the parameters to the Deferred Lists' callback
+       // deferredList: dojo.DeferredList
+       //              The deferred list from which this function gathers results.
+       // returns: dojo.DeferredList
+       //              The newly created deferred list which packs results as
+       //              parameters to its callback.
+
+       var d = new dojo.DeferredList(deferredList, false, true, false);
+       d.addCallback(function(results){
+               var ret = [];
+               darray.forEach(results, function(result){
+                       ret.push(result[1]);
+               });
+               return ret;
+       });
+       return d;
+};
+
+return dojo.DeferredList;
+});
+
+},
+'dojo/dnd/common':function(){
+define("dojo/dnd/common", ["../main"], function(dojo) {
+       // module:
+       //              dojo/dnd/common
+       // summary:
+       //              TODOC
+
+dojo.getObject("dnd", true, dojo);
+
+dojo.dnd.getCopyKeyState = dojo.isCopyKey;
+
+dojo.dnd._uniqueId = 0;
+dojo.dnd.getUniqueId = function(){
+       // summary:
+       //              returns a unique string for use with any DOM element
+       var id;
+       do{
+               id = dojo._scopeName + "Unique" + (++dojo.dnd._uniqueId);
+       }while(dojo.byId(id));
+       return id;
+};
+
+dojo.dnd._empty = {};
+
+dojo.dnd.isFormElement = function(/*Event*/ e){
+       // summary:
+       //              returns true if user clicked on a form element
+       var t = e.target;
+       if(t.nodeType == 3 /*TEXT_NODE*/){
+               t = t.parentNode;
+       }
+       return " button textarea input select option ".indexOf(" " + t.tagName.toLowerCase() + " ") >= 0;       // Boolean
+};
+
+return dojo.dnd;
+});
+
+},
+'dijit/_base/place':function(){
+define("dijit/_base/place", [
+       "dojo/_base/array", // array.forEach
+       "dojo/_base/lang", // lang.isArray
+       "dojo/window", // windowUtils.getBox
+       "../place",
+       ".."    // export to dijit namespace
+], function(array, lang, windowUtils, place, dijit){
+
+       // module:
+       //              dijit/_base/place
+       // summary:
+       //              Back compatibility module, new code should use dijit/place directly instead of using this module.
+
+       dijit.getViewport = function(){
+               // summary:
+               //              Deprecated method to return the dimensions and scroll position of the viewable area of a browser window.
+               //              New code should use windowUtils.getBox()
+
+               return windowUtils.getBox();
+       };
+
+       /*=====
+       dijit.placeOnScreen = function(node, pos, corners, padding){
+               // summary:
+               //              Positions one of the node's corners at specified position
+               //              such that node is fully visible in viewport.
+               //              Deprecated, new code should use dijit.place.at() instead.
+       };
+       =====*/
+       dijit.placeOnScreen = place.at;
+
+       /*=====
+       dijit.placeOnScreenAroundElement = function(node, aroundElement, aroundCorners, layoutNode){
+               // summary:
+               //              Like dijit.placeOnScreenAroundNode(), except it accepts an arbitrary object
+               //              for the "around" argument and finds a proper processor to place a node.
+               //              Deprecated, new code should use dijit.place.around() instead.
+       };
+       ====*/
+       dijit.placeOnScreenAroundElement = function(node, aroundNode, aroundCorners, layoutNode){
+               // Convert old style {"BL": "TL", "BR": "TR"} type argument
+               // to style needed by dijit.place code:
+               //              [
+               //                      {aroundCorner: "BL", corner: "TL" },
+               //                      {aroundCorner: "BR", corner: "TR" }
+               //              ]
+               var positions;
+               if(lang.isArray(aroundCorners)){
+                       positions = aroundCorners;
+               }else{
+                       positions = [];
+                       for(var key in aroundCorners){
+                               positions.push({aroundCorner: key, corner: aroundCorners[key]});
+                       }
+               }
+
+               return place.around(node, aroundNode, positions, true, layoutNode);
+       };
+
+       /*=====
+       dijit.placeOnScreenAroundNode = function(node, aroundNode, aroundCorners, layoutNode){
+               // summary:
+               //              Position node adjacent or kitty-corner to aroundNode
+               //              such that it's fully visible in viewport.
+               //              Deprecated, new code should use dijit.place.around() instead.
+       };
+       =====*/
+       dijit.placeOnScreenAroundNode = dijit.placeOnScreenAroundElement;
+
+       /*=====
+       dijit.placeOnScreenAroundRectangle = function(node, aroundRect, aroundCorners, layoutNode){
+               // summary:
+               //              Like dijit.placeOnScreenAroundNode(), except that the "around"
+               //              parameter is an arbitrary rectangle on the screen (x, y, width, height)
+               //              instead of a dom node.
+               //              Deprecated, new code should use dijit.place.around() instead.
+       };
+       =====*/
+       dijit.placeOnScreenAroundRectangle = dijit.placeOnScreenAroundElement;
+
+       dijit.getPopupAroundAlignment = function(/*Array*/ position, /*Boolean*/ leftToRight){
+               // summary:
+               //              Deprecated method, unneeded when using dijit/place directly.
+               //              Transforms the passed array of preferred positions into a format suitable for
+               //              passing as the aroundCorners argument to dijit.placeOnScreenAroundElement.
+               //
+               // position: String[]
+               //              This variable controls the position of the drop down.
+               //              It's an array of strings with the following values:
+               //
+               //                      * before: places drop down to the left of the target node/widget, or to the right in
+               //                        the case of RTL scripts like Hebrew and Arabic
+               //                      * after: places drop down to the right of the target node/widget, or to the left in
+               //                        the case of RTL scripts like Hebrew and Arabic
+               //                      * above: drop down goes above target node
+               //                      * below: drop down goes below target node
+               //
+               //              The list is positions is tried, in order, until a position is found where the drop down fits
+               //              within the viewport.
+               //
+               // leftToRight: Boolean
+               //              Whether the popup will be displaying in leftToRight mode.
+               //
+               var align = {};
+               array.forEach(position, function(pos){
+                       var ltr = leftToRight;
+                       switch(pos){
+                               case "after":
+                                       align[leftToRight ? "BR" : "BL"] = leftToRight ? "BL" : "BR";
+                                       break;
+                               case "before":
+                                       align[leftToRight ? "BL" : "BR"] = leftToRight ? "BR" : "BL";
+                                       break;
+                               case "below-alt":
+                                       ltr = !ltr;
+                                       // fall through
+                               case "below":
+                                       // first try to align left borders, next try to align right borders (or reverse for RTL mode)
+                                       align[ltr ? "BL" : "BR"] = ltr ? "TL" : "TR";
+                                       align[ltr ? "BR" : "BL"] = ltr ? "TR" : "TL";
+                                       break;
+                               case "above-alt":
+                                       ltr = !ltr;
+                                       // fall through
+                               case "above":
+                               default:
+                                       // first try to align left borders, next try to align right borders (or reverse for RTL mode)
+                                       align[ltr ? "TL" : "TR"] = ltr ? "BL" : "BR";
+                                       align[ltr ? "TR" : "TL"] = ltr ? "BR" : "BL";
+                                       break;
+                       }
+               });
+               return align;
+       };
+
+       return dijit;
+});
+
+},
+'dijit/MenuSeparator':function(){
+require({cache:{
+'url:dijit/templates/MenuSeparator.html':"<tr class=\"dijitMenuSeparator\">\n\t<td class=\"dijitMenuSeparatorIconCell\">\n\t\t<div class=\"dijitMenuSeparatorTop\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n\t<td colspan=\"3\" class=\"dijitMenuSeparatorLabelCell\">\n\t\t<div class=\"dijitMenuSeparatorTop dijitMenuSeparatorLabel\"></div>\n\t\t<div class=\"dijitMenuSeparatorBottom\"></div>\n\t</td>\n</tr>"}});
+define("dijit/MenuSeparator", [
+       "dojo/_base/declare", // declare
+       "dojo/dom", // dom.setSelectable
+       "./_WidgetBase",
+       "./_TemplatedMixin",
+       "./_Contained",
+       "dojo/text!./templates/MenuSeparator.html"
+], function(declare, dom, _WidgetBase, _TemplatedMixin, _Contained, template){
+
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _Contained = dijit._Contained;
+=====*/
+
+       // module:
+       //              dijit/MenuSeparator
+       // summary:
+       //              A line between two menu items
+
+       return declare("dijit.MenuSeparator", [_WidgetBase, _TemplatedMixin, _Contained], {
+               // summary:
+               //              A line between two menu items
+
+               templateString: template,
+
+               buildRendering: function(){
+                       this.inherited(arguments);
+                       dom.setSelectable(this.domNode, false);
+               },
+
+               isFocusable: function(){
+                       // summary:
+                       //              Override to always return false
+                       // tags:
+                       //              protected
+
+                       return false; // Boolean
+               }
+       });
+});
+
+},
+'dijit/form/_ComboBoxMenu':function(){
+define("dijit/form/_ComboBoxMenu", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add domClass.remove
+       "dojo/dom-construct", // domConstruct.create
+       "dojo/dom-style", // domStyle.get
+       "dojo/keys", // keys.DOWN_ARROW keys.PAGE_DOWN keys.PAGE_UP keys.UP_ARROW
+       "../_WidgetBase",
+       "../_TemplatedMixin",
+       "./_ComboBoxMenuMixin",
+       "./_ListMouseMixin"
+], function(declare, domClass, domConstruct, domStyle, keys,
+                       _WidgetBase, _TemplatedMixin, _ComboBoxMenuMixin, _ListMouseMixin){
+
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _ComboBoxMenuMixin = dijit.form._ComboBoxMenuMixin;
+       var _ListMouseMixin = dijit.form._ListMouseMixin;
+=====*/
+
+       // module:
+       //              dijit/form/_ComboBoxMenu
+       // summary:
+       //              Focus-less menu for internal use in `dijit.form.ComboBox`
+
+       return declare("dijit.form._ComboBoxMenu",[_WidgetBase, _TemplatedMixin, _ListMouseMixin, _ComboBoxMenuMixin], {
+               // summary:
+               //              Focus-less menu for internal use in `dijit.form.ComboBox`
+               //              Abstract methods that must be defined externally:
+               //                      onChange: item was explicitly chosen (mousedown somewhere on the menu and mouseup somewhere on the menu)
+               //                      onPage: next(1) or previous(-1) button pressed
+               // tags:
+               //              private
+
+               templateString: "<div class='dijitReset dijitMenu' data-dojo-attach-point='containerNode' style='overflow: auto; overflow-x: hidden;'>"
+                               +"<div class='dijitMenuItem dijitMenuPreviousButton' data-dojo-attach-point='previousButton' role='option'></div>"
+                               +"<div class='dijitMenuItem dijitMenuNextButton' data-dojo-attach-point='nextButton' role='option'></div>"
+                               +"</div>",
+
+               baseClass: "dijitComboBoxMenu",
+
+               postCreate: function(){
+                       this.inherited(arguments);
+                       if(!this.isLeftToRight()){
+                               domClass.add(this.previousButton, "dijitMenuItemRtl");
+                               domClass.add(this.nextButton, "dijitMenuItemRtl");
+                       }
+               },
+
+               _createMenuItem: function(){
+                       return domConstruct.create("div", {
+                               "class": "dijitReset dijitMenuItem" +(this.isLeftToRight() ? "" : " dijitMenuItemRtl"),
+                               role: "option"
+                       });
+               },
+
+               onHover: function(/*DomNode*/ node){
+                       // summary:
+                       //              Add hover CSS
+                       domClass.add(node, "dijitMenuItemHover");
+               },
+
+               onUnhover: function(/*DomNode*/ node){
+                       // summary:
+                       //              Remove hover CSS
+                       domClass.remove(node, "dijitMenuItemHover");
+               },
+
+               onSelect: function(/*DomNode*/ node){
+                       // summary:
+                       //              Add selected CSS
+                       domClass.add(node, "dijitMenuItemSelected");
+               },
+
+               onDeselect: function(/*DomNode*/ node){
+                       // summary:
+                       //              Remove selected CSS
+                       domClass.remove(node, "dijitMenuItemSelected");
+               },
+
+               _page: function(/*Boolean*/ up){
+                       // summary:
+                       //              Handles page-up and page-down keypresses
+
+                       var scrollamount = 0;
+                       var oldscroll = this.domNode.scrollTop;
+                       var height = domStyle.get(this.domNode, "height");
+                       // if no item is highlighted, highlight the first option
+                       if(!this.getHighlightedOption()){
+                               this.selectNextNode();
+                       }
+                       while(scrollamount<height){
+                               var highlighted_option = this.getHighlightedOption();
+                               if(up){
+                                       // stop at option 1
+                                       if(!highlighted_option.previousSibling ||
+                                               highlighted_option.previousSibling.style.display == "none"){
+                                               break;
+                                       }
+                                       this.selectPreviousNode();
+                               }else{
+                                       // stop at last option
+                                       if(!highlighted_option.nextSibling ||
+                                               highlighted_option.nextSibling.style.display == "none"){
+                                               break;
+                                       }
+                                       this.selectNextNode();
+                               }
+                               // going backwards
+                               var newscroll = this.domNode.scrollTop;
+                               scrollamount += (newscroll-oldscroll)*(up ? -1:1);
+                               oldscroll = newscroll;
+                       }
+               },
+
+               handleKey: function(evt){
+                       // summary:
+                       //              Handle keystroke event forwarded from ComboBox, returning false if it's
+                       //              a keystroke I recognize and process, true otherwise.
+                       switch(evt.charOrCode){
+                               case keys.DOWN_ARROW:
+                                       this.selectNextNode();
+                                       return false;
+                               case keys.PAGE_DOWN:
+                                       this._page(false);
+                                       return false;
+                               case keys.UP_ARROW:
+                                       this.selectPreviousNode();
+                                       return false;
+                               case keys.PAGE_UP:
+                                       this._page(true);
+                                       return false;
+                               default:
+                                       return true;
+                       }
+               }
+       });
+});
+
+},
+'url:dijit/layout/templates/ScrollingTabController.html':"<div class=\"dijitTabListContainer-${tabPosition}\" style=\"visibility:hidden\">\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerMenuButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_menuBtn\"\n\t\t\tdata-dojo-props=\"containerId: '${containerId}', iconClass: 'dijitTabStripMenuIcon',\n\t\t\t\t\tdropDownPosition: ['below-alt', 'above-alt']\"\n\t\t\tdata-dojo-attach-point=\"_menuBtn\" showLabel=\"false\" title=\"\">&#9660;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_leftBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideLeftIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_leftBtn\" data-dojo-attach-event=\"onClick: doSlideLeft\">&#9664;</div>\n\t<div data-dojo-type=\"dijit.layout._ScrollingTabControllerButton\"\n\t\t\tclass=\"tabStripButton-${tabPosition}\"\n\t\t\tid=\"${id}_rightBtn\"\n\t\t\tdata-dojo-props=\"iconClass:'dijitTabStripSlideRightIcon', showLabel:false, title:''\"\n\t\t\tdata-dojo-attach-point=\"_rightBtn\" data-dojo-attach-event=\"onClick: doSlideRight\">&#9654;</div>\n\t<div class='dijitTabListWrapper' data-dojo-attach-point='tablistWrapper'>\n\t\t<div role='tablist' data-dojo-attach-event='onkeypress:onkeypress'\n\t\t\t\tdata-dojo-attach-point='containerNode' class='nowrapTabStrip'></div>\n\t</div>\n</div>",
+'dijit/Dialog':function(){
+require({cache:{
+'url:dijit/templates/Dialog.html':"<div class=\"dijitDialog\" role=\"dialog\" aria-labelledby=\"${id}_title\">\n\t<div data-dojo-attach-point=\"titleBar\" class=\"dijitDialogTitleBar\">\n\t<span data-dojo-attach-point=\"titleNode\" class=\"dijitDialogTitle\" id=\"${id}_title\"></span>\n\t<span data-dojo-attach-point=\"closeButtonNode\" class=\"dijitDialogCloseIcon\" data-dojo-attach-event=\"ondijitclick: onCancel\" title=\"${buttonCancel}\" role=\"button\" tabIndex=\"-1\">\n\t\t<span data-dojo-attach-point=\"closeText\" class=\"closeText\" title=\"${buttonCancel}\">x</span>\n\t</span>\n\t</div>\n\t\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitDialogPaneContent\"></div>\n</div>\n"}});
+define("dijit/Dialog", [
+       "require",
+       "dojo/_base/array", // array.forEach array.indexOf array.map
+       "dojo/_base/connect", // connect._keypress
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred", // Deferred
+       "dojo/dom", // dom.isDescendant
+       "dojo/dom-class", // domClass.add domClass.contains
+       "dojo/dom-geometry", // domGeometry.position
+       "dojo/dom-style", // domStyle.set
+       "dojo/_base/event", // event.stop
+       "dojo/_base/fx", // fx.fadeIn fx.fadeOut
+       "dojo/i18n", // i18n.getLocalization
+       "dojo/_base/kernel", // kernel.isAsync
+       "dojo/keys",
+       "dojo/_base/lang", // lang.mixin lang.hitch
+       "dojo/on",
+       "dojo/ready",
+       "dojo/_base/sniff", // has("ie") has("opera")
+       "dojo/_base/window", // win.body
+       "dojo/window", // winUtils.getBox
+       "dojo/dnd/Moveable", // Moveable
+       "dojo/dnd/TimedMoveable", // TimedMoveable
+       "./focus",
+       "./_base/manager",      // manager.defaultDuration
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_CssStateMixin",
+       "./form/_FormMixin",
+       "./_DialogMixin",
+       "./DialogUnderlay",
+       "./layout/ContentPane",
+       "dojo/text!./templates/Dialog.html",
+       ".",                    // for back-compat, exporting dijit._underlay (remove in 2.0)
+       "dojo/i18n!./nls/common"
+], function(require, array, connect, declare, Deferred,
+                       dom, domClass, domGeometry, domStyle, event, fx, i18n, kernel, keys, lang, on, ready, has, win, winUtils,
+                       Moveable, TimedMoveable, focus, manager, _Widget, _TemplatedMixin, _CssStateMixin, _FormMixin, _DialogMixin,
+                       DialogUnderlay, ContentPane, template, dijit){
+       
+/*=====
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _CssStateMixin = dijit._CssStateMixin;
+       var _FormMixin = dijit.form._FormMixin;
+       var _DialogMixin = dijit._DialogMixin;
+=====*/        
+
+
+       // module:
+       //              dijit/Dialog
+       // summary:
+       //              A modal dialog Widget
+
+
+       /*=====
+       dijit._underlay = function(kwArgs){
+               // summary:
+               //              A shared instance of a `dijit.DialogUnderlay`
+               //
+               // description:
+               //              A shared instance of a `dijit.DialogUnderlay` created and
+               //              used by `dijit.Dialog`, though never created until some Dialog
+               //              or subclass thereof is shown.
+       };
+       =====*/
+
+       var _DialogBase = declare("dijit._DialogBase", [_TemplatedMixin, _FormMixin, _DialogMixin, _CssStateMixin], {
+               // summary:
+               //              A modal dialog Widget
+               //
+               // description:
+               //              Pops up a modal dialog window, blocking access to the screen
+               //              and also graying out the screen Dialog is extended from
+               //              ContentPane so it supports all the same parameters (href, etc.)
+               //
+               // example:
+               // |    <div data-dojo-type="dijit.Dialog" data-dojo-props="href: 'test.html'"></div>
+               //
+               // example:
+               // |    var foo = new dijit.Dialog({ title: "test dialog", content: "test content" };
+               // |    dojo.body().appendChild(foo.domNode);
+               // |    foo.startup();
+
+               templateString: template,
+
+               baseClass: "dijitDialog",
+
+               cssStateNodes: {
+                       closeButtonNode: "dijitDialogCloseIcon"
+               },
+
+               // Map widget attributes to DOMNode attributes.
+               _setTitleAttr: [
+                       { node: "titleNode", type: "innerHTML" },
+                       { node: "titleBar", type: "attribute" }
+               ],
+
+               // open: [readonly] Boolean
+               //              True if Dialog is currently displayed on screen.
+               open: false,
+
+               // duration: Integer
+               //              The time in milliseconds it takes the dialog to fade in and out
+               duration: manager.defaultDuration,
+
+               // refocus: Boolean
+               //              A Toggle to modify the default focus behavior of a Dialog, which
+               //              is to re-focus the element which had focus before being opened.
+               //              False will disable refocusing. Default: true
+               refocus: true,
+
+               // autofocus: Boolean
+               //              A Toggle to modify the default focus behavior of a Dialog, which
+               //              is to focus on the first dialog element after opening the dialog.
+               //              False will disable autofocusing. Default: true
+               autofocus: true,
+
+               // _firstFocusItem: [private readonly] DomNode
+               //              The pointer to the first focusable node in the dialog.
+               //              Set by `dijit._DialogMixin._getFocusItems`.
+               _firstFocusItem: null,
+
+               // _lastFocusItem: [private readonly] DomNode
+               //              The pointer to which node has focus prior to our dialog.
+               //              Set by `dijit._DialogMixin._getFocusItems`.
+               _lastFocusItem: null,
+
+               // doLayout: [protected] Boolean
+               //              Don't change this parameter from the default value.
+               //              This ContentPane parameter doesn't make sense for Dialog, since Dialog
+               //              is never a child of a layout container, nor can you specify the size of
+               //              Dialog in order to control the size of an inner widget.
+               doLayout: false,
+
+               // draggable: Boolean
+               //              Toggles the moveable aspect of the Dialog. If true, Dialog
+               //              can be dragged by it's title. If false it will remain centered
+               //              in the viewport.
+               draggable: true,
+
+               //aria-describedby: String
+               //              Allows the user to add an aria-describedby attribute onto the dialog.   The value should
+               //              be the id of the container element of text that describes the dialog purpose (usually
+               //              the first text in the dialog).
+               //              <div data-dojo-type="dijit.Dialog" aria-describedby="intro" .....>
+               //                      <div id="intro">Introductory text</div>
+               //                      <div>rest of dialog contents</div>
+               //              </div>
+               "aria-describedby":"",
+
+               postMixInProperties: function(){
+                       var _nlsResources = i18n.getLocalization("dijit", "common");
+                       lang.mixin(this, _nlsResources);
+                       this.inherited(arguments);
+               },
+
+               postCreate: function(){
+                       domStyle.set(this.domNode, {
+                               display: "none",
+                               position:"absolute"
+                       });
+                       win.body().appendChild(this.domNode);
+
+                       this.inherited(arguments);
+
+                       this.connect(this, "onExecute", "hide");
+                       this.connect(this, "onCancel", "hide");
+                       this._modalconnects = [];
+               },
+
+               onLoad: function(){
+                       // summary:
+                       //              Called when data has been loaded from an href.
+                       //              Unlike most other callbacks, this function can be connected to (via `dojo.connect`)
+                       //              but should *not* be overridden.
+                       // tags:
+                       //              callback
+
+                       // when href is specified we need to reposition the dialog after the data is loaded
+                       // and find the focusable elements
+                       this._position();
+                       if(this.autofocus && DialogLevelManager.isTop(this)){
+                               this._getFocusItems(this.domNode);
+                               focus.focus(this._firstFocusItem);
+                       }
+                       this.inherited(arguments);
+               },
+
+               _endDrag: function(){
+                       // summary:
+                       //              Called after dragging the Dialog. Saves the position of the dialog in the viewport,
+                       //              and also adjust position to be fully within the viewport, so user doesn't lose access to handle
+                       var nodePosition = domGeometry.position(this.domNode),
+                               viewport = winUtils.getBox();
+                       nodePosition.y = Math.min(Math.max(nodePosition.y, 0), (viewport.h - nodePosition.h));
+                       nodePosition.x = Math.min(Math.max(nodePosition.x, 0), (viewport.w - nodePosition.w));
+                       this._relativePosition = nodePosition;
+                       this._position();
+               },
+
+               _setup: function(){
+                       // summary:
+                       //              Stuff we need to do before showing the Dialog for the first
+                       //              time (but we defer it until right beforehand, for
+                       //              performance reasons).
+                       // tags:
+                       //              private
+
+                       var node = this.domNode;
+
+                       if(this.titleBar && this.draggable){
+                               this._moveable = new ((has("ie") == 6) ? TimedMoveable // prevent overload, see #5285
+                                       : Moveable)(node, { handle: this.titleBar });
+                               this.connect(this._moveable, "onMoveStop", "_endDrag");
+                       }else{
+                               domClass.add(node,"dijitDialogFixed");
+                       }
+
+                       this.underlayAttrs = {
+                               dialogId: this.id,
+                               "class": array.map(this["class"].split(/\s/), function(s){ return s+"_underlay"; }).join(" ")
+                       };
+               },
+
+               _size: function(){
+                       // summary:
+                       //              If necessary, shrink dialog contents so dialog fits in viewport
+                       // tags:
+                       //              private
+
+                       this._checkIfSingleChild();
+
+                       // If we resized the dialog contents earlier, reset them back to original size, so
+                       // that if the user later increases the viewport size, the dialog can display w/out a scrollbar.
+                       // Need to do this before the domGeometry.position(this.domNode) call below.
+                       if(this._singleChild){
+                               if(this._singleChildOriginalStyle){
+                                       this._singleChild.domNode.style.cssText = this._singleChildOriginalStyle;
+                               }
+                               delete this._singleChildOriginalStyle;
+                       }else{
+                               domStyle.set(this.containerNode, {
+                                       width:"auto",
+                                       height:"auto"
+                               });
+                       }
+
+                       var bb = domGeometry.position(this.domNode);
+                       var viewport = winUtils.getBox();
+                       if(bb.w >= viewport.w || bb.h >= viewport.h){
+                               // Reduce size of dialog contents so that dialog fits in viewport
+
+                               var w = Math.min(bb.w, Math.floor(viewport.w * 0.75)),
+                                       h = Math.min(bb.h, Math.floor(viewport.h * 0.75));
+
+                               if(this._singleChild && this._singleChild.resize){
+                                       this._singleChildOriginalStyle = this._singleChild.domNode.style.cssText;
+                                       this._singleChild.resize({w: w, h: h});
+                               }else{
+                                       domStyle.set(this.containerNode, {
+                                               width: w + "px",
+                                               height: h + "px",
+                                               overflow: "auto",
+                                               position: "relative"    // workaround IE bug moving scrollbar or dragging dialog
+                                       });
+                               }
+                       }else{
+                               if(this._singleChild && this._singleChild.resize){
+                                       this._singleChild.resize();
+                               }
+                       }
+               },
+
+               _position: function(){
+                       // summary:
+                       //              Position modal dialog in the viewport. If no relative offset
+                       //              in the viewport has been determined (by dragging, for instance),
+                       //              center the node. Otherwise, use the Dialog's stored relative offset,
+                       //              and position the node to top: left: values based on the viewport.
+                       if(!domClass.contains(win.body(), "dojoMove")){ // don't do anything if called during auto-scroll
+                               var node = this.domNode,
+                                       viewport = winUtils.getBox(),
+                                       p = this._relativePosition,
+                                       bb = p ? null : domGeometry.position(node),
+                                       l = Math.floor(viewport.l + (p ? p.x : (viewport.w - bb.w) / 2)),
+                                       t = Math.floor(viewport.t + (p ? p.y : (viewport.h - bb.h) / 2))
+                               ;
+                               domStyle.set(node,{
+                                       left: l + "px",
+                                       top: t + "px"
+                               });
+                       }
+               },
+
+               _onKey: function(/*Event*/ evt){
+                       // summary:
+                       //              Handles the keyboard events for accessibility reasons
+                       // tags:
+                       //              private
+
+                       if(evt.charOrCode){
+                               var node = evt.target;
+                               if(evt.charOrCode === keys.TAB){
+                                       this._getFocusItems(this.domNode);
+                               }
+                               var singleFocusItem = (this._firstFocusItem == this._lastFocusItem);
+                               // see if we are shift-tabbing from first focusable item on dialog
+                               if(node == this._firstFocusItem && evt.shiftKey && evt.charOrCode === keys.TAB){
+                                       if(!singleFocusItem){
+                                               focus.focus(this._lastFocusItem); // send focus to last item in dialog
+                                       }
+                                       event.stop(evt);
+                               }else if(node == this._lastFocusItem && evt.charOrCode === keys.TAB && !evt.shiftKey){
+                                       if(!singleFocusItem){
+                                               focus.focus(this._firstFocusItem); // send focus to first item in dialog
+                                       }
+                                       event.stop(evt);
+                               }else{
+                                       // see if the key is for the dialog
+                                       while(node){
+                                               if(node == this.domNode || domClass.contains(node, "dijitPopup")){
+                                                       if(evt.charOrCode == keys.ESCAPE){
+                                                               this.onCancel();
+                                                       }else{
+                                                               return; // just let it go
+                                                       }
+                                               }
+                                               node = node.parentNode;
+                                       }
+                                       // this key is for the disabled document window
+                                       if(evt.charOrCode !== keys.TAB){ // allow tabbing into the dialog for a11y
+                                               event.stop(evt);
+                                       // opera won't tab to a div
+                                       }else if(!has("opera")){
+                                               try{
+                                                       this._firstFocusItem.focus();
+                                               }catch(e){ /*squelch*/ }
+                                       }
+                               }
+                       }
+               },
+
+               show: function(){
+                       // summary:
+                       //              Display the dialog
+                       // returns: dojo.Deferred
+                       //              Deferred object that resolves when the display animation is complete
+
+                       if(this.open){ return; }
+
+                       if(!this._started){
+                               this.startup();
+                       }
+
+                       // first time we show the dialog, there's some initialization stuff to do
+                       if(!this._alreadyInitialized){
+                               this._setup();
+                               this._alreadyInitialized=true;
+                       }
+
+                       if(this._fadeOutDeferred){
+                               this._fadeOutDeferred.cancel();
+                       }
+
+                       this._modalconnects.push(on(window, "scroll", lang.hitch(this, "layout")));
+                       this._modalconnects.push(on(window, "resize", lang.hitch(this, function(){
+                               // IE gives spurious resize events and can actually get stuck
+                               // in an infinite loop if we don't ignore them
+                               var viewport = winUtils.getBox();
+                               if(!this._oldViewport ||
+                                               viewport.h != this._oldViewport.h ||
+                                               viewport.w != this._oldViewport.w){
+                                       this.layout();
+                                       this._oldViewport = viewport;
+                               }
+                       })));
+                       this._modalconnects.push(on(this.domNode, connect._keypress, lang.hitch(this, "_onKey")));
+
+                       domStyle.set(this.domNode, {
+                               opacity:0,
+                               display:""
+                       });
+
+                       this._set("open", true);
+                       this._onShow(); // lazy load trigger
+
+                       this._size();
+                       this._position();
+
+                       // fade-in Animation object, setup below
+                       var fadeIn;
+
+                       this._fadeInDeferred = new Deferred(lang.hitch(this, function(){
+                               fadeIn.stop();
+                               delete this._fadeInDeferred;
+                       }));
+
+                       fadeIn = fx.fadeIn({
+                               node: this.domNode,
+                               duration: this.duration,
+                               beforeBegin: lang.hitch(this, function(){
+                                       DialogLevelManager.show(this, this.underlayAttrs);
+                               }),
+                               onEnd: lang.hitch(this, function(){
+                                       if(this.autofocus && DialogLevelManager.isTop(this)){
+                                               // find focusable items each time dialog is shown since if dialog contains a widget the
+                                               // first focusable items can change
+                                               this._getFocusItems(this.domNode);
+                                               focus.focus(this._firstFocusItem);
+                                       }
+                                       this._fadeInDeferred.callback(true);
+                                       delete this._fadeInDeferred;
+                               })
+                       }).play();
+
+                       return this._fadeInDeferred;
+               },
+
+               hide: function(){
+                       // summary:
+                       //              Hide the dialog
+                       // returns: dojo.Deferred
+                       //              Deferred object that resolves when the hide animation is complete
+
+                       // if we haven't been initialized yet then we aren't showing and we can just return
+                       if(!this._alreadyInitialized){
+                               return;
+                       }
+                       if(this._fadeInDeferred){
+                               this._fadeInDeferred.cancel();
+                       }
+
+                       // fade-in Animation object, setup below
+                       var fadeOut;
+
+                       this._fadeOutDeferred = new Deferred(lang.hitch(this, function(){
+                               fadeOut.stop();
+                               delete this._fadeOutDeferred;
+                       }));
+                       // fire onHide when the promise resolves.
+                       this._fadeOutDeferred.then(lang.hitch(this, 'onHide'));
+
+                       fadeOut = fx.fadeOut({
+                               node: this.domNode,
+                               duration: this.duration,
+                               onEnd: lang.hitch(this, function(){
+                                       this.domNode.style.display = "none";
+                                       DialogLevelManager.hide(this);
+                                       this._fadeOutDeferred.callback(true);
+                                       delete this._fadeOutDeferred;
+                               })
+                        }).play();
+
+                       if(this._scrollConnected){
+                               this._scrollConnected = false;
+                       }
+                       var h;
+                       while(h = this._modalconnects.pop()){
+                               h.remove();
+                       }
+
+                       if(this._relativePosition){
+                               delete this._relativePosition;
+                       }
+                       this._set("open", false);
+
+                       return this._fadeOutDeferred;
+               },
+
+               layout: function(){
+                       // summary:
+                       //              Position the Dialog and the underlay
+                       // tags:
+                       //              private
+                       if(this.domNode.style.display != "none"){
+                               if(dijit._underlay){    // avoid race condition during show()
+                                       dijit._underlay.layout();
+                               }
+                               this._position();
+                       }
+               },
+
+               destroy: function(){
+                       if(this._fadeInDeferred){
+                               this._fadeInDeferred.cancel();
+                       }
+                       if(this._fadeOutDeferred){
+                               this._fadeOutDeferred.cancel();
+                       }
+                       if(this._moveable){
+                               this._moveable.destroy();
+                       }
+                       var h;
+                       while(h = this._modalconnects.pop()){
+                               h.remove();
+                       }
+
+                       DialogLevelManager.hide(this);
+
+                       this.inherited(arguments);
+               }
+       });
+
+       var Dialog = declare("dijit.Dialog", [ContentPane, _DialogBase], {});
+       Dialog._DialogBase = _DialogBase;       // for monkey patching
+
+       var DialogLevelManager = Dialog._DialogLevelManager = {
+               // summary:
+               //              Controls the various active "levels" on the page, starting with the
+               //              stuff initially visible on the page (at z-index 0), and then having an entry for
+               //              each Dialog shown.
+
+               _beginZIndex: 950,
+
+               show: function(/*dijit._Widget*/ dialog, /*Object*/ underlayAttrs){
+                       // summary:
+                       //              Call right before fade-in animation for new dialog.
+                       //              Saves current focus, displays/adjusts underlay for new dialog,
+                       //              and sets the z-index of the dialog itself.
+                       //
+                       //              New dialog will be displayed on top of all currently displayed dialogs.
+                       //
+                       //              Caller is responsible for setting focus in new dialog after the fade-in
+                       //              animation completes.
+
+                       // Save current focus
+                       ds[ds.length-1].focus = focus.curNode;
+
+                       // Display the underlay, or if already displayed then adjust for this new dialog
+                       var underlay = dijit._underlay;
+                       if(!underlay || underlay._destroyed){
+                               underlay = dijit._underlay = new DialogUnderlay(underlayAttrs);
+                       }else{
+                               underlay.set(dialog.underlayAttrs);
+                       }
+
+                       // Set z-index a bit above previous dialog
+                       var zIndex = ds[ds.length-1].dialog ? ds[ds.length-1].zIndex + 2 : Dialog._DialogLevelManager._beginZIndex;
+                       if(ds.length == 1){     // first dialog
+                               underlay.show();
+                       }
+                       domStyle.set(dijit._underlay.domNode, 'zIndex', zIndex - 1);
+
+                       // Dialog
+                       domStyle.set(dialog.domNode, 'zIndex', zIndex);
+
+                       ds.push({dialog: dialog, underlayAttrs: underlayAttrs, zIndex: zIndex});
+               },
+
+               hide: function(/*dijit._Widget*/ dialog){
+                       // summary:
+                       //              Called when the specified dialog is hidden/destroyed, after the fade-out
+                       //              animation ends, in order to reset page focus, fix the underlay, etc.
+                       //              If the specified dialog isn't open then does nothing.
+                       //
+                       //              Caller is responsible for either setting display:none on the dialog domNode,
+                       //              or calling dijit.popup.hide(), or removing it from the page DOM.
+
+                       if(ds[ds.length-1].dialog == dialog){
+                               // Removing the top (or only) dialog in the stack, return focus
+                               // to previous dialog
+
+                               ds.pop();
+
+                               var pd = ds[ds.length-1];       // the new active dialog (or the base page itself)
+
+                               // Adjust underlay
+                               if(ds.length == 1){
+                                       // Returning to original page.
+                                       // Hide the underlay, unless the underlay widget has already been destroyed
+                                       // because we are being called during page unload (when all widgets are destroyed)
+                                       if(!dijit._underlay._destroyed){
+                                               dijit._underlay.hide();
+                                       }
+                               }else{
+                                       // Popping back to previous dialog, adjust underlay
+                                       domStyle.set(dijit._underlay.domNode, 'zIndex', pd.zIndex - 1);
+                                       dijit._underlay.set(pd.underlayAttrs);
+                               }
+
+                               // Adjust focus
+                               if(dialog.refocus){
+                                       // If we are returning control to a previous dialog but for some reason
+                                       // that dialog didn't have a focused field, set focus to first focusable item.
+                                       // This situation could happen if two dialogs appeared at nearly the same time,
+                                       // since a dialog doesn't set it's focus until the fade-in is finished.
+                                       var focus = pd.focus;
+                                       if(pd.dialog && (!focus || !dom.isDescendant(focus, pd.dialog.domNode))){
+                                               pd.dialog._getFocusItems(pd.dialog.domNode);
+                                               focus = pd.dialog._firstFocusItem;
+                                       }
+
+                                       if(focus){
+                                               // Refocus the button that spawned the Dialog.   This will fail in corner cases including
+                                               // page unload on IE, because the dijit/form/Button that launched the Dialog may get destroyed
+                                               // before this code runs.  (#15058)
+                                               try{
+                                                       focus.focus();
+                                               }catch(e){}
+                                       }
+                               }
+                       }else{
+                               // Removing a dialog out of order (#9944, #10705).
+                               // Don't need to mess with underlay or z-index or anything.
+                               var idx = array.indexOf(array.map(ds, function(elem){return elem.dialog}), dialog);
+                               if(idx != -1){
+                                       ds.splice(idx, 1);
+                               }
+                       }
+               },
+
+               isTop: function(/*dijit._Widget*/ dialog){
+                       // summary:
+                       //              Returns true if specified Dialog is the top in the task
+                       return ds[ds.length-1].dialog == dialog;
+               }
+       };
+
+       // Stack representing the various active "levels" on the page, starting with the
+       // stuff initially visible on the page (at z-index 0), and then having an entry for
+       // each Dialog shown.
+       // Each element in stack has form {
+       //              dialog: dialogWidget,
+       //              focus: returnFromGetFocus(),
+       //              underlayAttrs: attributes to set on underlay (when this widget is active)
+       // }
+       var ds = Dialog._dialogStack = [
+               {dialog: null, focus: null, underlayAttrs: null}        // entry for stuff at z-index: 0
+       ];
+
+       // Back compat w/1.6, remove for 2.0
+       if(!kernel.isAsync){
+               ready(0, function(){
+                       var requires = ["dijit/TooltipDialog"];
+                       require(requires);      // use indirection so modules not rolled into a build
+               });
+       }
+
+       return Dialog;
+});
+
+},
+'dijit/_base/focus':function(){
+define("dijit/_base/focus", [
+       "dojo/_base/array", // array.forEach
+       "dojo/dom", // dom.isDescendant
+       "dojo/_base/lang", // lang.isArray
+       "dojo/topic", // publish
+       "dojo/_base/window", // win.doc win.doc.selection win.global win.global.getSelection win.withGlobal
+       "../focus",
+       ".."    // for exporting symbols to dijit
+], function(array, dom, lang, topic, win, focus, dijit){
+
+       // module:
+       //              dijit/_base/focus
+       // summary:
+       //              Deprecated module to monitor currently focused node and stack of currently focused widgets.
+       //              New code should access dijit/focus directly.
+
+       lang.mixin(dijit, {
+               // _curFocus: DomNode
+               //              Currently focused item on screen
+               _curFocus: null,
+
+               // _prevFocus: DomNode
+               //              Previously focused item on screen
+               _prevFocus: null,
+
+               isCollapsed: function(){
+                       // summary:
+                       //              Returns true if there is no text selected
+                       return dijit.getBookmark().isCollapsed;
+               },
+
+               getBookmark: function(){
+                       // summary:
+                       //              Retrieves a bookmark that can be used with moveToBookmark to return to the same range
+                       var bm, rg, tg, sel = win.doc.selection, cf = focus.curNode;
+
+                       if(win.global.getSelection){
+                               //W3C Range API for selections.
+                               sel = win.global.getSelection();
+                               if(sel){
+                                       if(sel.isCollapsed){
+                                               tg = cf? cf.tagName : "";
+                                               if(tg){
+                                                       //Create a fake rangelike item to restore selections.
+                                                       tg = tg.toLowerCase();
+                                                       if(tg == "textarea" ||
+                                                                       (tg == "input" && (!cf.type || cf.type.toLowerCase() == "text"))){
+                                                               sel = {
+                                                                       start: cf.selectionStart,
+                                                                       end: cf.selectionEnd,
+                                                                       node: cf,
+                                                                       pRange: true
+                                                               };
+                                                               return {isCollapsed: (sel.end <= sel.start), mark: sel}; //Object.
+                                                       }
+                                               }
+                                               bm = {isCollapsed:true};
+                                               if(sel.rangeCount){
+                                                       bm.mark = sel.getRangeAt(0).cloneRange();
+                                               }
+                                       }else{
+                                               rg = sel.getRangeAt(0);
+                                               bm = {isCollapsed: false, mark: rg.cloneRange()};
+                                       }
+                               }
+                       }else if(sel){
+                               // If the current focus was a input of some sort and no selection, don't bother saving
+                               // a native bookmark.  This is because it causes issues with dialog/page selection restore.
+                               // So, we need to create psuedo bookmarks to work with.
+                               tg = cf ? cf.tagName : "";
+                               tg = tg.toLowerCase();
+                               if(cf && tg && (tg == "button" || tg == "textarea" || tg == "input")){
+                                       if(sel.type && sel.type.toLowerCase() == "none"){
+                                               return {
+                                                       isCollapsed: true,
+                                                       mark: null
+                                               }
+                                       }else{
+                                               rg = sel.createRange();
+                                               return {
+                                                       isCollapsed: rg.text && rg.text.length?false:true,
+                                                       mark: {
+                                                               range: rg,
+                                                               pRange: true
+                                                       }
+                                               };
+                                       }
+                               }
+                               bm = {};
+
+                               //'IE' way for selections.
+                               try{
+                                       // createRange() throws exception when dojo in iframe
+                                       //and nothing selected, see #9632
+                                       rg = sel.createRange();
+                                       bm.isCollapsed = !(sel.type == 'Text' ? rg.htmlText.length : rg.length);
+                               }catch(e){
+                                       bm.isCollapsed = true;
+                                       return bm;
+                               }
+                               if(sel.type.toUpperCase() == 'CONTROL'){
+                                       if(rg.length){
+                                               bm.mark=[];
+                                               var i=0,len=rg.length;
+                                               while(i<len){
+                                                       bm.mark.push(rg.item(i++));
+                                               }
+                                       }else{
+                                               bm.isCollapsed = true;
+                                               bm.mark = null;
+                                       }
+                               }else{
+                                       bm.mark = rg.getBookmark();
+                               }
+                       }else{
+                               console.warn("No idea how to store the current selection for this browser!");
+                       }
+                       return bm; // Object
+               },
+
+               moveToBookmark: function(/*Object*/ bookmark){
+                       // summary:
+                       //              Moves current selection to a bookmark
+                       // bookmark:
+                       //              This should be a returned object from dijit.getBookmark()
+
+                       var _doc = win.doc,
+                               mark = bookmark.mark;
+                       if(mark){
+                               if(win.global.getSelection){
+                                       //W3C Rangi API (FF, WebKit, Opera, etc)
+                                       var sel = win.global.getSelection();
+                                       if(sel && sel.removeAllRanges){
+                                               if(mark.pRange){
+                                                       var n = mark.node;
+                                                       n.selectionStart = mark.start;
+                                                       n.selectionEnd = mark.end;
+                                               }else{
+                                                       sel.removeAllRanges();
+                                                       sel.addRange(mark);
+                                               }
+                                       }else{
+                                               console.warn("No idea how to restore selection for this browser!");
+                                       }
+                               }else if(_doc.selection && mark){
+                                       //'IE' way.
+                                       var rg;
+                                       if(mark.pRange){
+                                               rg = mark.range;
+                                       }else if(lang.isArray(mark)){
+                                               rg = _doc.body.createControlRange();
+                                               //rg.addElement does not have call/apply method, so can not call it directly
+                                               //rg is not available in "range.addElement(item)", so can't use that either
+                                               array.forEach(mark, function(n){
+                                                       rg.addElement(n);
+                                               });
+                                       }else{
+                                               rg = _doc.body.createTextRange();
+                                               rg.moveToBookmark(mark);
+                                       }
+                                       rg.select();
+                               }
+                       }
+               },
+
+               getFocus: function(/*Widget?*/ menu, /*Window?*/ openedForWindow){
+                       // summary:
+                       //              Called as getFocus(), this returns an Object showing the current focus
+                       //              and selected text.
+                       //
+                       //              Called as getFocus(widget), where widget is a (widget representing) a button
+                       //              that was just pressed, it returns where focus was before that button
+                       //              was pressed.   (Pressing the button may have either shifted focus to the button,
+                       //              or removed focus altogether.)   In this case the selected text is not returned,
+                       //              since it can't be accurately determined.
+                       //
+                       // menu: dijit._Widget or {domNode: DomNode} structure
+                       //              The button that was just pressed.  If focus has disappeared or moved
+                       //              to this button, returns the previous focus.  In this case the bookmark
+                       //              information is already lost, and null is returned.
+                       //
+                       // openedForWindow:
+                       //              iframe in which menu was opened
+                       //
+                       // returns:
+                       //              A handle to restore focus/selection, to be passed to `dijit.focus`
+                       var node = !focus.curNode || (menu && dom.isDescendant(focus.curNode, menu.domNode)) ? dijit._prevFocus : focus.curNode;
+                       return {
+                               node: node,
+                               bookmark: node && (node == focus.curNode) && win.withGlobal(openedForWindow || win.global, dijit.getBookmark),
+                               openedForWindow: openedForWindow
+                       }; // Object
+               },
+
+               // _activeStack: dijit._Widget[]
+               //              List of currently active widgets (focused widget and it's ancestors)
+               _activeStack: [],
+
+               registerIframe: function(/*DomNode*/ iframe){
+                       // summary:
+                       //              Registers listeners on the specified iframe so that any click
+                       //              or focus event on that iframe (or anything in it) is reported
+                       //              as a focus/click event on the <iframe> itself.
+                       // description:
+                       //              Currently only used by editor.
+                       // returns:
+                       //              Handle to pass to unregisterIframe()
+                       return focus.registerIframe(iframe);
+               },
+
+               unregisterIframe: function(/*Object*/ handle){
+                       // summary:
+                       //              Unregisters listeners on the specified iframe created by registerIframe.
+                       //              After calling be sure to delete or null out the handle itself.
+                       // handle:
+                       //              Handle returned by registerIframe()
+
+                       handle && handle.remove();
+               },
+
+               registerWin: function(/*Window?*/targetWindow, /*DomNode?*/ effectiveNode){
+                       // summary:
+                       //              Registers listeners on the specified window (either the main
+                       //              window or an iframe's window) to detect when the user has clicked somewhere
+                       //              or focused somewhere.
+                       // description:
+                       //              Users should call registerIframe() instead of this method.
+                       // targetWindow:
+                       //              If specified this is the window associated with the iframe,
+                       //              i.e. iframe.contentWindow.
+                       // effectiveNode:
+                       //              If specified, report any focus events inside targetWindow as
+                       //              an event on effectiveNode, rather than on evt.target.
+                       // returns:
+                       //              Handle to pass to unregisterWin()
+
+                       return focus.registerWin(targetWindow, effectiveNode);
+               },
+
+               unregisterWin: function(/*Handle*/ handle){
+                       // summary:
+                       //              Unregisters listeners on the specified window (either the main
+                       //              window or an iframe's window) according to handle returned from registerWin().
+                       //              After calling be sure to delete or null out the handle itself.
+
+                       handle && handle.remove();
+               }
+       });
+
+       // Override focus singleton's focus function so that dijit.focus()
+       // has backwards compatible behavior of restoring selection (although
+       // probably no one is using that).
+       focus.focus = function(/*Object || DomNode */ handle){
+               // summary:
+               //              Sets the focused node and the selection according to argument.
+               //              To set focus to an iframe's content, pass in the iframe itself.
+               // handle:
+               //              object returned by get(), or a DomNode
+
+               if(!handle){ return; }
+
+               var node = "node" in handle ? handle.node : handle,             // because handle is either DomNode or a composite object
+                       bookmark = handle.bookmark,
+                       openedForWindow = handle.openedForWindow,
+                       collapsed = bookmark ? bookmark.isCollapsed : false;
+
+               // Set the focus
+               // Note that for iframe's we need to use the <iframe> to follow the parentNode chain,
+               // but we need to set focus to iframe.contentWindow
+               if(node){
+                       var focusNode = (node.tagName.toLowerCase() == "iframe") ? node.contentWindow : node;
+                       if(focusNode && focusNode.focus){
+                               try{
+                                       // Gecko throws sometimes if setting focus is impossible,
+                                       // node not displayed or something like that
+                                       focusNode.focus();
+                               }catch(e){/*quiet*/}
+                       }
+                       focus._onFocusNode(node);
+               }
+
+               // set the selection
+               // do not need to restore if current selection is not empty
+               // (use keyboard to select a menu item) or if previous selection was collapsed
+               // as it may cause focus shift (Esp in IE).
+               if(bookmark && win.withGlobal(openedForWindow || win.global, dijit.isCollapsed) && !collapsed){
+                       if(openedForWindow){
+                               openedForWindow.focus();
+                       }
+                       try{
+                               win.withGlobal(openedForWindow || win.global, dijit.moveToBookmark, null, [bookmark]);
+                       }catch(e2){
+                               /*squelch IE internal error, see http://trac.dojotoolkit.org/ticket/1984 */
+                       }
+               }
+       };
+
+       // For back compatibility, monitor changes to focused node and active widget stack,
+       // publishing events and copying changes from focus manager variables into dijit (top level) variables
+       focus.watch("curNode", function(name, oldVal, newVal){
+               dijit._curFocus = newVal;
+               dijit._prevFocus = oldVal;
+               if(newVal){
+                       topic.publish("focusNode", newVal);     // publish
+               }
+       });
+       focus.watch("activeStack", function(name, oldVal, newVal){
+               dijit._activeStack = newVal;
+       });
+
+       focus.on("widget-blur", function(widget, by){
+               topic.publish("widgetBlur", widget, by);        // publish
+       });
+       focus.on("widget-focus", function(widget, by){
+               topic.publish("widgetFocus", widget, by);       // publish
+       });
+
+       return dijit;
+});
+
+},
+'dijit/tree/dndSource':function(){
+define("dijit/tree/dndSource", [
+       "dojo/_base/array", // array.forEach array.indexOf array.map
+       "dojo/_base/connect", // isCopyKey
+       "dojo/_base/declare", // declare
+       "dojo/dom-class", // domClass.add
+       "dojo/dom-geometry", // domGeometry.position
+       "dojo/_base/lang", // lang.mixin lang.hitch
+       "dojo/on", // subscribe
+       "dojo/touch",
+       "dojo/topic",
+       "dojo/dnd/Manager", // DNDManager.manager
+       "./_dndSelector"
+], function(array, connect, declare, domClass, domGeometry, lang, on, touch, topic, DNDManager, _dndSelector){
+
+// module:
+//             dijit/tree/dndSource
+// summary:
+//             Handles drag and drop operations (as a source or a target) for `dijit.Tree`
+
+/*=====
+dijit.tree.__SourceArgs = function(){
+       // summary:
+       //              A dict of parameters for Tree source configuration.
+       // isSource: Boolean?
+       //              Can be used as a DnD source. Defaults to true.
+       // accept: String[]
+       //              List of accepted types (text strings) for a target; defaults to
+       //              ["text", "treeNode"]
+       // copyOnly: Boolean?
+       //              Copy items, if true, use a state of Ctrl key otherwise,
+       // dragThreshold: Number
+       //              The move delay in pixels before detecting a drag; 0 by default
+       // betweenThreshold: Integer
+       //              Distance from upper/lower edge of node to allow drop to reorder nodes
+       this.isSource = isSource;
+       this.accept = accept;
+       this.autoSync = autoSync;
+       this.copyOnly = copyOnly;
+       this.dragThreshold = dragThreshold;
+       this.betweenThreshold = betweenThreshold;
+}
+=====*/
+
+return declare("dijit.tree.dndSource", _dndSelector, {
+       // summary:
+       //              Handles drag and drop operations (as a source or a target) for `dijit.Tree`
+
+       // isSource: [private] Boolean
+       //              Can be used as a DnD source.
+       isSource: true,
+
+       // accept: String[]
+       //              List of accepted types (text strings) for the Tree; defaults to
+       //              ["text"]
+       accept: ["text", "treeNode"],
+
+       // copyOnly: [private] Boolean
+       //              Copy items, if true, use a state of Ctrl key otherwise
+       copyOnly: false,
+
+       // dragThreshold: Number
+       //              The move delay in pixels before detecting a drag; 5 by default
+       dragThreshold: 5,
+
+       // betweenThreshold: Integer
+       //              Distance from upper/lower edge of node to allow drop to reorder nodes
+       betweenThreshold: 0,
+
+       constructor: function(/*dijit.Tree*/ tree, /*dijit.tree.__SourceArgs*/ params){
+               // summary:
+               //              a constructor of the Tree DnD Source
+               // tags:
+               //              private
+               if(!params){ params = {}; }
+               lang.mixin(this, params);
+               this.isSource = typeof params.isSource == "undefined" ? true : params.isSource;
+               var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"];
+               this.accept = null;
+               if(type.length){
+                       this.accept = {};
+                       for(var i = 0; i < type.length; ++i){
+                               this.accept[type[i]] = 1;
+                       }
+               }
+
+               // class-specific variables
+               this.isDragging = false;
+               this.mouseDown = false;
+               this.targetAnchor = null;       // DOMNode corresponding to the currently moused over TreeNode
+               this.targetBox = null;  // coordinates of this.targetAnchor
+               this.dropPosition = ""; // whether mouse is over/after/before this.targetAnchor
+               this._lastX = 0;
+               this._lastY = 0;
+
+               // states
+               this.sourceState = "";
+               if(this.isSource){
+                       domClass.add(this.node, "dojoDndSource");
+               }
+               this.targetState = "";
+               if(this.accept){
+                       domClass.add(this.node, "dojoDndTarget");
+               }
+
+               // set up events
+               this.topics = [
+                       topic.subscribe("/dnd/source/over", lang.hitch(this, "onDndSourceOver")),
+                       topic.subscribe("/dnd/start", lang.hitch(this, "onDndStart")),
+                       topic.subscribe("/dnd/drop", lang.hitch(this, "onDndDrop")),
+                       topic.subscribe("/dnd/cancel", lang.hitch(this, "onDndCancel"))
+               ];
+       },
+
+       // methods
+       checkAcceptance: function(/*===== source, nodes =====*/){
+               // summary:
+               //              Checks if the target can accept nodes from this source
+               // source: dijit.tree.dndSource
+               //              The source which provides items
+               // nodes: DOMNode[]
+               //              Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
+               //              source is a dijit.Tree.
+               // tags:
+               //              extension
+               return true;    // Boolean
+       },
+
+       copyState: function(keyPressed){
+               // summary:
+               //              Returns true, if we need to copy items, false to move.
+               //              It is separated to be overwritten dynamically, if needed.
+               // keyPressed: Boolean
+               //              The "copy" control key was pressed
+               // tags:
+               //              protected
+               return this.copyOnly || keyPressed;     // Boolean
+       },
+       destroy: function(){
+               // summary:
+               //              Prepares the object to be garbage-collected.
+               this.inherited(arguments);
+               var h;
+               while(h = this.topics.pop()){ h.remove(); }
+               this.targetAnchor = null;
+       },
+
+       _onDragMouse: function(e){
+               // summary:
+               //              Helper method for processing onmousemove/onmouseover events while drag is in progress.
+               //              Keeps track of current drop target.
+
+               var m = DNDManager.manager(),
+                       oldTarget = this.targetAnchor,                  // the TreeNode corresponding to TreeNode mouse was previously over
+                       newTarget = this.current,                               // TreeNode corresponding to TreeNode mouse is currently over
+                       oldDropPosition = this.dropPosition;    // the previous drop position (over/before/after)
+
+               // calculate if user is indicating to drop the dragged node before, after, or over
+               // (i.e., to become a child of) the target node
+               var newDropPosition = "Over";
+               if(newTarget && this.betweenThreshold > 0){
+                       // If mouse is over a new TreeNode, then get new TreeNode's position and size
+                       if(!this.targetBox || oldTarget != newTarget){
+                               this.targetBox = domGeometry.position(newTarget.rowNode, true);
+                       }
+                       if((e.pageY - this.targetBox.y) <= this.betweenThreshold){
+                               newDropPosition = "Before";
+                       }else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){
+                               newDropPosition = "After";
+                       }
+               }
+
+               if(newTarget != oldTarget || newDropPosition != oldDropPosition){
+                       if(oldTarget){
+                               this._removeItemClass(oldTarget.rowNode, oldDropPosition);
+                       }
+                       if(newTarget){
+                               this._addItemClass(newTarget.rowNode, newDropPosition);
+                       }
+
+                       // Check if it's ok to drop the dragged node on/before/after the target node.
+                       if(!newTarget){
+                               m.canDrop(false);
+                       }else if(newTarget == this.tree.rootNode && newDropPosition != "Over"){
+                               // Can't drop before or after tree's root node; the dropped node would just disappear (at least visually)
+                               m.canDrop(false);
+                       }else{
+                               // Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140)
+                               var model = this.tree.model,
+                                       sameId = false;
+                               if(m.source == this){
+                                       for(var dragId in this.selection){
+                                               var dragNode = this.selection[dragId];
+                                               if(dragNode.item === newTarget.item){
+                                                       sameId = true;
+                                                       break;
+                                               }
+                                       }
+                               }
+                               if(sameId){
+                                       m.canDrop(false);
+                               }else if(this.checkItemAcceptance(newTarget.rowNode, m.source, newDropPosition.toLowerCase())
+                                               && !this._isParentChildDrop(m.source, newTarget.rowNode)){
+                                       m.canDrop(true);
+                               }else{
+                                       m.canDrop(false);
+                               }
+                       }
+
+                       this.targetAnchor = newTarget;
+                       this.dropPosition = newDropPosition;
+               }
+       },
+
+       onMouseMove: function(e){
+               // summary:
+               //              Called for any onmousemove/ontouchmove events over the Tree
+               // e: Event
+               //              onmousemouse/ontouchmove event
+               // tags:
+               //              private
+               if(this.isDragging && this.targetState == "Disabled"){ return; }
+               this.inherited(arguments);
+               var m = DNDManager.manager();
+               if(this.isDragging){
+                       this._onDragMouse(e);
+               }else{
+                       if(this.mouseDown && this.isSource &&
+                                (Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
+                               var nodes = this.getSelectedTreeNodes();
+                               if(nodes.length){
+                                       if(nodes.length > 1){
+                                               //filter out all selected items which has one of their ancestor selected as well
+                                               var seen = this.selection, i = 0, r = [], n, p;
+                                               nextitem: while((n = nodes[i++])){
+                                                       for(p = n.getParent(); p && p !== this.tree; p = p.getParent()){
+                                                               if(seen[p.id]){ //parent is already selected, skip this node
+                                                                       continue nextitem;
+                                                               }
+                                                       }
+                                                       //this node does not have any ancestors selected, add it
+                                                       r.push(n);
+                                               }
+                                               nodes = r;
+                                       }
+                                       nodes = array.map(nodes, function(n){return n.domNode});
+                                       m.startDrag(this, nodes, this.copyState(connect.isCopyKey(e)));
+                               }
+                       }
+               }
+       },
+
+       onMouseDown: function(e){
+               // summary:
+               //              Event processor for onmousedown/ontouchstart
+               // e: Event
+               //              onmousedown/ontouchend event
+               // tags:
+               //              private
+               this.mouseDown = true;
+               this.mouseButton = e.button;
+               this._lastX = e.pageX;
+               this._lastY = e.pageY;
+               this.inherited(arguments);
+       },
+
+       onMouseUp: function(e){
+               // summary:
+               //              Event processor for onmouseup/ontouchend
+               // e: Event
+               //              onmouseup/ontouchend event
+               // tags:
+               //              private
+               if(this.mouseDown){
+                       this.mouseDown = false;
+                       this.inherited(arguments);
+               }
+       },
+
+       onMouseOut: function(){
+               // summary:
+               //              Event processor for when mouse is moved away from a TreeNode
+               // tags:
+               //              private
+               this.inherited(arguments);
+               this._unmarkTargetAnchor();
+       },
+
+       checkItemAcceptance: function(/*===== target, source, position =====*/){
+               // summary:
+               //              Stub function to be overridden if one wants to check for the ability to drop at the node/item level
+               // description:
+               //              In the base case, this is called to check if target can become a child of source.
+               //              When betweenThreshold is set, position="before" or "after" means that we
+               //              are asking if the source node can be dropped before/after the target node.
+               // target: DOMNode
+               //              The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
+               //              Use dijit.getEnclosingWidget(target) to get the TreeNode.
+               // source: dijit.tree.dndSource
+               //              The (set of) nodes we are dropping
+               // position: String
+               //              "over", "before", or "after"
+               // tags:
+               //              extension
+               return true;
+       },
+
+       // topic event processors
+       onDndSourceOver: function(source){
+               // summary:
+               //              Topic event processor for /dnd/source/over, called when detected a current source.
+               // source: Object
+               //              The dijit.tree.dndSource / dojo.dnd.Source which has the mouse over it
+               // tags:
+               //              private
+               if(this != source){
+                       this.mouseDown = false;
+                       this._unmarkTargetAnchor();
+               }else if(this.isDragging){
+                       var m = DNDManager.manager();
+                       m.canDrop(false);
+               }
+       },
+       onDndStart: function(source, nodes, copy){
+               // summary:
+               //              Topic event processor for /dnd/start, called to initiate the DnD operation
+               // source: Object
+               //              The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
+               // nodes: DomNode[]
+               //              The list of transferred items, dndTreeNode nodes if dragging from a Tree
+               // copy: Boolean
+               //              Copy items, if true, move items otherwise
+               // tags:
+               //              private
+
+               if(this.isSource){
+                       this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
+               }
+               var accepted = this.checkAcceptance(source, nodes);
+
+               this._changeState("Target", accepted ? "" : "Disabled");
+
+               if(this == source){
+                       DNDManager.manager().overSource(this);
+               }
+
+               this.isDragging = true;
+       },
+
+       itemCreator: function(nodes /*===== , target, source =====*/){
+               // summary:
+               //              Returns objects passed to `Tree.model.newItem()` based on DnD nodes
+               //              dropped onto the tree.   Developer must override this method to enable
+               //              dropping from external sources onto this Tree, unless the Tree.model's items
+               //              happen to look like {id: 123, name: "Apple" } with no other attributes.
+               // description:
+               //              For each node in nodes[], which came from source, create a hash of name/value
+               //              pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
+               // nodes: DomNode[]
+               // target: DomNode
+               // source: dojo.dnd.Source
+               // returns: Object[]
+               //              Array of name/value hashes for each new item to be added to the Tree, like:
+               // |    [
+               // |            { id: 123, label: "apple", foo: "bar" },
+               // |            { id: 456, label: "pear", zaz: "bam" }
+               // |    ]
+               // tags:
+               //              extension
+
+               // TODO: for 2.0 refactor so itemCreator() is called once per drag node, and
+               // make signature itemCreator(sourceItem, node, target) (or similar).
+
+               return array.map(nodes, function(node){
+                       return {
+                               "id": node.id,
+                               "name": node.textContent || node.innerText || ""
+                       };
+               }); // Object[]
+       },
+
+       onDndDrop: function(source, nodes, copy){
+               // summary:
+               //              Topic event processor for /dnd/drop, called to finish the DnD operation.
+               // description:
+               //              Updates data store items according to where node was dragged from and dropped
+               //              to.   The tree will then respond to those data store updates and redraw itself.
+               // source: Object
+               //              The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
+               // nodes: DomNode[]
+               //              The list of transferred items, dndTreeNode nodes if dragging from a Tree
+               // copy: Boolean
+               //              Copy items, if true, move items otherwise
+               // tags:
+               //              protected
+               if(this.containerState == "Over"){
+                       var tree = this.tree,
+                               model = tree.model,
+                               target = this.targetAnchor;
+
+                       this.isDragging = false;
+
+                       // Compute the new parent item
+                       var newParentItem;
+                       var insertIndex;
+                       newParentItem = (target && target.item) || tree.item;
+                       if(this.dropPosition == "Before" || this.dropPosition == "After"){
+                               // TODO: if there is no parent item then disallow the drop.
+                               // Actually this should be checked during onMouseMove too, to make the drag icon red.
+                               newParentItem = (target.getParent() && target.getParent().item) || tree.item;
+                               // Compute the insert index for reordering
+                               insertIndex = target.getIndexInParent();
+                               if(this.dropPosition == "After"){
+                                       insertIndex = target.getIndexInParent() + 1;
+                               }
+                       }else{
+                               newParentItem = (target && target.item) || tree.item;
+                       }
+
+                       // If necessary, use this variable to hold array of hashes to pass to model.newItem()
+                       // (one entry in the array for each dragged node).
+                       var newItemsParams;
+
+                       array.forEach(nodes, function(node, idx){
+                               // dojo.dnd.Item representing the thing being dropped.
+                               // Don't confuse the use of item here (meaning a DnD item) with the
+                               // uses below where item means dojo.data item.
+                               var sourceItem = source.getItem(node.id);
+
+                               // Information that's available if the source is another Tree
+                               // (possibly but not necessarily this tree, possibly but not
+                               // necessarily the same model as this Tree)
+                               if(array.indexOf(sourceItem.type, "treeNode") != -1){
+                                       var childTreeNode = sourceItem.data,
+                                               childItem = childTreeNode.item,
+                                               oldParentItem = childTreeNode.getParent().item;
+                               }
+
+                               if(source == this){
+                                       // This is a node from my own tree, and we are moving it, not copying.
+                                       // Remove item from old parent's children attribute.
+                                       // TODO: dijit.tree.dndSelector should implement deleteSelectedNodes()
+                                       // and this code should go there.
+
+                                       if(typeof insertIndex == "number"){
+                                               if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){
+                                                       insertIndex -= 1;
+                                               }
+                                       }
+                                       model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
+                               }else if(model.isItem(childItem)){
+                                       // Item from same model
+                                       // (maybe we should only do this branch if the source is a tree?)
+                                       model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
+                               }else{
+                                       // Get the hash to pass to model.newItem().  A single call to
+                                       // itemCreator() returns an array of hashes, one for each drag source node.
+                                       if(!newItemsParams){
+                                               newItemsParams = this.itemCreator(nodes, target.rowNode, source);
+                                       }
+
+                                       // Create new item in the tree, based on the drag source.
+                                       model.newItem(newItemsParams[idx], newParentItem, insertIndex);
+                               }
+                       }, this);
+
+                       // Expand the target node (if it's currently collapsed) so the user can see
+                       // where their node was dropped.   In particular since that node is still selected.
+                       this.tree._expandNode(target);
+               }
+               this.onDndCancel();
+       },
+
+       onDndCancel: function(){
+               // summary:
+               //              Topic event processor for /dnd/cancel, called to cancel the DnD operation
+               // tags:
+               //              private
+               this._unmarkTargetAnchor();
+               this.isDragging = false;
+               this.mouseDown = false;
+               delete this.mouseButton;
+               this._changeState("Source", "");
+               this._changeState("Target", "");
+       },
+
+       // When focus moves in/out of the entire Tree
+       onOverEvent: function(){
+               // summary:
+               //              This method is called when mouse is moved over our container (like onmouseenter)
+               // tags:
+               //              private
+               this.inherited(arguments);
+               DNDManager.manager().overSource(this);
+       },
+       onOutEvent: function(){
+               // summary:
+               //              This method is called when mouse is moved out of our container (like onmouseleave)
+               // tags:
+               //              private
+               this._unmarkTargetAnchor();
+               var m = DNDManager.manager();
+               if(this.isDragging){
+                       m.canDrop(false);
+               }
+               m.outSource(this);
+
+               this.inherited(arguments);
+       },
+
+       _isParentChildDrop: function(source, targetRow){
+               // summary:
+               //              Checks whether the dragged items are parent rows in the tree which are being
+               //              dragged into their own children.
+               //
+               // source:
+               //              The DragSource object.
+               //
+               // targetRow:
+               //              The tree row onto which the dragged nodes are being dropped.
+               //
+               // tags:
+               //              private
+
+               // If the dragged object is not coming from the tree this widget belongs to,
+               // it cannot be invalid.
+               if(!source.tree || source.tree != this.tree){
+                       return false;
+               }
+
+
+               var root = source.tree.domNode;
+               var ids = source.selection;
+
+               var node = targetRow.parentNode;
+
+               // Iterate up the DOM hierarchy from the target drop row,
+               // checking of any of the dragged nodes have the same ID.
+               while(node != root && !ids[node.id]){
+                       node = node.parentNode;
+               }
+
+               return node.id && ids[node.id];
+       },
+
+       _unmarkTargetAnchor: function(){
+               // summary:
+               //              Removes hover class of the current target anchor
+               // tags:
+               //              private
+               if(!this.targetAnchor){ return; }
+               this._removeItemClass(this.targetAnchor.rowNode, this.dropPosition);
+               this.targetAnchor = null;
+               this.targetBox = null;
+               this.dropPosition = null;
+       },
+
+       _markDndStatus: function(copy){
+               // summary:
+               //              Changes source's state based on "copy" status
+               this._changeState("Source", copy ? "Copied" : "Moved");
+       }
+});
+
+});
+
+},
+'dijit/a11y':function(){
+define("dijit/a11y", [
+       "dojo/_base/array", // array.forEach array.map
+       "dojo/_base/config", // defaultDuration
+       "dojo/_base/declare", // declare
+       "dojo/dom",                     // dom.byId
+       "dojo/dom-attr", // domAttr.attr domAttr.has
+       "dojo/dom-style", // style.style
+       "dojo/_base/sniff", // has("ie")
+       "./_base/manager",      // manager._isElementShown
+       "."     // for exporting methods to dijit namespace
+], function(array, config, declare, dom, domAttr, domStyle, has, manager, dijit){
+
+       // module:
+       //              dijit/a11y
+       // summary:
+       //              Accessibility utility functions (keyboard, tab stops, etc.)
+
+       var shown = (dijit._isElementShown = function(/*Element*/ elem){
+               var s = domStyle.get(elem);
+               return (s.visibility != "hidden")
+                       && (s.visibility != "collapsed")
+                       && (s.display != "none")
+                       && (domAttr.get(elem, "type") != "hidden");
+       });
+
+       dijit.hasDefaultTabStop = function(/*Element*/ elem){
+               // summary:
+               //              Tests if element is tab-navigable even without an explicit tabIndex setting
+
+               // No explicit tabIndex setting, need to investigate node type
+               switch(elem.nodeName.toLowerCase()){
+                       case "a":
+                               // An <a> w/out a tabindex is only navigable if it has an href
+                               return domAttr.has(elem, "href");
+                       case "area":
+                       case "button":
+                       case "input":
+                       case "object":
+                       case "select":
+                       case "textarea":
+                               // These are navigable by default
+                               return true;
+                       case "iframe":
+                               // If it's an editor <iframe> then it's tab navigable.
+                               var body;
+                               try{
+                                       // non-IE
+                                       var contentDocument = elem.contentDocument;
+                                       if("designMode" in contentDocument && contentDocument.designMode == "on"){
+                                               return true;
+                                       }
+                                       body = contentDocument.body;
+                               }catch(e1){
+                                       // contentWindow.document isn't accessible within IE7/8
+                                       // if the iframe.src points to a foreign url and this
+                                       // page contains an element, that could get focus
+                                       try{
+                                               body = elem.contentWindow.document.body;
+                                       }catch(e2){
+                                               return false;
+                                       }
+                               }
+                               return body && (body.contentEditable == 'true' ||
+                                       (body.firstChild && body.firstChild.contentEditable == 'true'));
+                       default:
+                               return elem.contentEditable == 'true';
+               }
+       };
+
+       var isTabNavigable = (dijit.isTabNavigable = function(/*Element*/ elem){
+               // summary:
+               //              Tests if an element is tab-navigable
+
+               // TODO: convert (and rename method) to return effective tabIndex; will save time in _getTabNavigable()
+               if(domAttr.get(elem, "disabled")){
+                       return false;
+               }else if(domAttr.has(elem, "tabIndex")){
+                       // Explicit tab index setting
+                       return domAttr.get(elem, "tabIndex") >= 0; // boolean
+               }else{
+                       // No explicit tabIndex setting, so depends on node type
+                       return dijit.hasDefaultTabStop(elem);
+               }
+       });
+
+       dijit._getTabNavigable = function(/*DOMNode*/ root){
+               // summary:
+               //              Finds descendants of the specified root node.
+               //
+               // description:
+               //              Finds the following descendants of the specified root node:
+               //              * the first tab-navigable element in document order
+               //                without a tabIndex or with tabIndex="0"
+               //              * the last tab-navigable element in document order
+               //                without a tabIndex or with tabIndex="0"
+               //              * the first element in document order with the lowest
+               //                positive tabIndex value
+               //              * the last element in document order with the highest
+               //                positive tabIndex value
+               var first, last, lowest, lowestTabindex, highest, highestTabindex, radioSelected = {};
+
+               function radioName(node){
+                       // If this element is part of a radio button group, return the name for that group.
+                       return node && node.tagName.toLowerCase() == "input" &&
+                               node.type && node.type.toLowerCase() == "radio" &&
+                               node.name && node.name.toLowerCase();
+               }
+
+               var walkTree = function(/*DOMNode*/parent){
+                       for(var child = parent.firstChild; child; child = child.nextSibling){
+                               // Skip text elements, hidden elements, and also non-HTML elements (those in custom namespaces) in IE,
+                               // since show() invokes getAttribute("type"), which crash on VML nodes in IE.
+                               if(child.nodeType != 1 || (has("ie") && child.scopeName !== "HTML") || !shown(child)){
+                                       continue;
+                               }
+
+                               if(isTabNavigable(child)){
+                                       var tabindex = domAttr.get(child, "tabIndex");
+                                       if(!domAttr.has(child, "tabIndex") || tabindex == 0){
+                                               if(!first){
+                                                       first = child;
+                                               }
+                                               last = child;
+                                       }else if(tabindex > 0){
+                                               if(!lowest || tabindex < lowestTabindex){
+                                                       lowestTabindex = tabindex;
+                                                       lowest = child;
+                                               }
+                                               if(!highest || tabindex >= highestTabindex){
+                                                       highestTabindex = tabindex;
+                                                       highest = child;
+                                               }
+                                       }
+                                       var rn = radioName(child);
+                                       if(domAttr.get(child, "checked") && rn){
+                                               radioSelected[rn] = child;
+                                       }
+                               }
+                               if(child.nodeName.toUpperCase() != 'SELECT'){
+                                       walkTree(child);
+                               }
+                       }
+               };
+               if(shown(root)){
+                       walkTree(root);
+               }
+               function rs(node){
+                       // substitute checked radio button for unchecked one, if there is a checked one with the same name.
+                       return radioSelected[radioName(node)] || node;
+               }
+
+               return { first: rs(first), last: rs(last), lowest: rs(lowest), highest: rs(highest) };
+       };
+       dijit.getFirstInTabbingOrder = function(/*String|DOMNode*/ root){
+               // summary:
+               //              Finds the descendant of the specified root node
+               //              that is first in the tabbing order
+               var elems = dijit._getTabNavigable(dom.byId(root));
+               return elems.lowest ? elems.lowest : elems.first; // DomNode
+       };
+
+       dijit.getLastInTabbingOrder = function(/*String|DOMNode*/ root){
+               // summary:
+               //              Finds the descendant of the specified root node
+               //              that is last in the tabbing order
+               var elems = dijit._getTabNavigable(dom.byId(root));
+               return elems.last ? elems.last : elems.highest; // DomNode
+       };
+
+       return {
+               hasDefaultTabStop: dijit.hasDefaultTabStop,
+               isTabNavigable: dijit.isTabNavigable,
+               _getTabNavigable: dijit._getTabNavigable,
+               getFirstInTabbingOrder: dijit.getFirstInTabbingOrder,
+               getLastInTabbingOrder: dijit.getLastInTabbingOrder
+       };
+});
+
+},
+'dijit/form/_ToggleButtonMixin':function(){
+define("dijit/form/_ToggleButtonMixin", [
+       "dojo/_base/declare", // declare
+       "dojo/dom-attr" // domAttr.set
+], function(declare, domAttr){
+
+// module:
+//             dijit/form/_ToggleButtonMixin
+// summary:
+//             A mixin to provide functionality to allow a button that can be in two states (checked or not).
+
+return declare("dijit.form._ToggleButtonMixin", null, {
+       // summary:
+       //              A mixin to provide functionality to allow a button that can be in two states (checked or not).
+
+       // checked: Boolean
+       //              Corresponds to the native HTML <input> element's attribute.
+       //              In markup, specified as "checked='checked'" or just "checked".
+       //              True if the button is depressed, or the checkbox is checked,
+       //              or the radio button is selected, etc.
+       checked: false,
+
+       // aria-pressed for toggle buttons, and aria-checked for checkboxes
+       _aria_attr: "aria-pressed",
+
+       _onClick: function(/*Event*/ evt){
+               var original = this.checked;
+               this._set('checked', !original); // partially set the toggled value, assuming the toggle will work, so it can be overridden in the onclick handler
+               var ret = this.inherited(arguments); // the user could reset the value here
+               this.set('checked', ret ? this.checked : original); // officially set the toggled or user value, or reset it back
+               return ret;
+       },
+
+       _setCheckedAttr: function(/*Boolean*/ value, /*Boolean?*/ priorityChange){
+               this._set("checked", value);
+               domAttr.set(this.focusNode || this.domNode, "checked", value);
+               (this.focusNode || this.domNode).setAttribute(this._aria_attr, value ? "true" : "false"); // aria values should be strings
+               this._handleOnChange(value, priorityChange);
+       },
+
+       reset: function(){
+               // summary:
+               //              Reset the widget's value to what it was at initialization time
+
+               this._hasBeenBlurred = false;
+
+               // set checked state to original setting
+               this.set('checked', this.params.checked || false);
+       }
+});
+
+});
+
+},
+'dijit/_Widget':function(){
+define("dijit/_Widget", [
+       "dojo/aspect",  // aspect.around
+       "dojo/_base/config",    // config.isDebug
+       "dojo/_base/connect",   // connect.connect
+       "dojo/_base/declare", // declare
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/_base/lang", // lang.hitch
+       "dojo/query",
+       "dojo/ready",
+       "./registry",   // registry.byNode
+       "./_WidgetBase",
+       "./_OnDijitClickMixin",
+       "./_FocusMixin",
+       "dojo/uacss",           // browser sniffing (included for back-compat; subclasses may be using)
+       "./hccss"               // high contrast mode sniffing (included to set CSS classes on <body>, module ret value unused)
+], function(aspect, config, connect, declare, kernel, lang, query, ready,
+                       registry, _WidgetBase, _OnDijitClickMixin, _FocusMixin){
+
+/*=====
+       var _WidgetBase = dijit._WidgetBase;
+       var _OnDijitClickMixin = dijit._OnDijitClickMixin;
+       var _FocusMixin = dijit._FocusMixin;
+=====*/
+
+
+// module:
+//             dijit/_Widget
+// summary:
+//             Old base for widgets.   New widgets should extend _WidgetBase instead
+
+
+function connectToDomNode(){
+       // summary:
+       //              If user connects to a widget method === this function, then they will
+       //              instead actually be connecting the equivalent event on this.domNode
+}
+
+// Trap dojo.connect() calls to connectToDomNode methods, and redirect to _Widget.on()
+function aroundAdvice(originalConnect){
+       return function(obj, event, scope, method){
+               if(obj && typeof event == "string" && obj[event] == connectToDomNode){
+                       return obj.on(event.substring(2).toLowerCase(), lang.hitch(scope, method));
+               }
+               return originalConnect.apply(connect, arguments);
+       };
+}
+aspect.around(connect, "connect", aroundAdvice);
+if(kernel.connect){
+       aspect.around(kernel, "connect", aroundAdvice);
+}
+
+var _Widget = declare("dijit._Widget", [_WidgetBase, _OnDijitClickMixin, _FocusMixin], {
+       // summary:
+       //              Base class for all Dijit widgets.
+       //
+       //              Extends _WidgetBase, adding support for:
+       //                      - declaratively/programatically specifying widget initialization parameters like
+       //                              onMouseMove="foo" that call foo when this.domNode gets a mousemove event
+       //                      - ondijitclick
+       //                              Support new data-dojo-attach-event="ondijitclick: ..." that is triggered by a mouse click or a SPACE/ENTER keypress
+       //                      - focus related functions
+       //                              In particular, the onFocus()/onBlur() callbacks.   Driven internally by
+       //                              dijit/_base/focus.js.
+       //                      - deprecated methods
+       //                      - onShow(), onHide(), onClose()
+       //
+       //              Also, by loading code in dijit/_base, turns on:
+       //                      - browser sniffing (putting browser id like .dj_ie on <html> node)
+       //                      - high contrast mode sniffing (add .dijit_a11y class to <body> if machine is in high contrast mode)
+
+
+       ////////////////// DEFERRED CONNECTS ///////////////////
+
+       onClick: connectToDomNode,
+       /*=====
+       onClick: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of mouse click events.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onDblClick: connectToDomNode,
+       /*=====
+       onDblClick: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of mouse double click events.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onKeyDown: connectToDomNode,
+       /*=====
+       onKeyDown: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of keys being pressed down.
+               // event:
+               //              key Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onKeyPress: connectToDomNode,
+       /*=====
+       onKeyPress: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of printable keys being typed.
+               // event:
+               //              key Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onKeyUp: connectToDomNode,
+       /*=====
+       onKeyUp: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of keys being released.
+               // event:
+               //              key Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseDown: connectToDomNode,
+       /*=====
+       onMouseDown: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse button is pressed down.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseMove: connectToDomNode,
+       /*=====
+       onMouseMove: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse moves over nodes contained within this widget.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseOut: connectToDomNode,
+       /*=====
+       onMouseOut: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse moves off of nodes contained within this widget.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseOver: connectToDomNode,
+       /*=====
+       onMouseOver: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse moves onto nodes contained within this widget.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseLeave: connectToDomNode,
+       /*=====
+       onMouseLeave: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse moves off of this widget.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseEnter: connectToDomNode,
+       /*=====
+       onMouseEnter: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse moves onto this widget.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+       onMouseUp: connectToDomNode,
+       /*=====
+       onMouseUp: function(event){
+               // summary:
+               //              Connect to this function to receive notifications of when the mouse button is released.
+               // event:
+               //              mouse Event
+               // tags:
+               //              callback
+       },
+       =====*/
+
+       constructor: function(params){
+               // extract parameters like onMouseMove that should connect directly to this.domNode
+               this._toConnect = {};
+               for(var name in params){
+                       if(this[name] === connectToDomNode){
+                               this._toConnect[name.replace(/^on/, "").toLowerCase()] = params[name];
+                               delete params[name];
+                       }
+               }
+       },
+
+       postCreate: function(){
+               this.inherited(arguments);
+
+               // perform connection from this.domNode to user specified handlers (ex: onMouseMove)
+               for(var name in this._toConnect){
+                       this.on(name, this._toConnect[name]);
+               }
+               delete this._toConnect;
+       },
+
+       on: function(/*String*/ type, /*Function*/ func){
+               if(this[this._onMap(type)] === connectToDomNode){
+                       // Use connect.connect() rather than on() to get handling for "onmouseenter" on non-IE, etc.
+                       // Also, need to specify context as "this" rather than the default context of the DOMNode
+                       return connect.connect(this.domNode, type.toLowerCase(), this, func);
+               }
+               return this.inherited(arguments);
+       },
+
+       _setFocusedAttr: function(val){
+               // Remove this method in 2.0 (or sooner), just here to set _focused == focused, for back compat
+               // (but since it's a private variable we aren't required to keep supporting it).
+               this._focused = val;
+               this._set("focused", val);
+       },
+
+       ////////////////// DEPRECATED METHODS ///////////////////
+
+       setAttribute: function(/*String*/ attr, /*anything*/ value){
+               // summary:
+               //              Deprecated.  Use set() instead.
+               // tags:
+               //              deprecated
+               kernel.deprecated(this.declaredClass+"::setAttribute(attr, value) is deprecated. Use set() instead.", "", "2.0");
+               this.set(attr, value);
+       },
+
+       attr: function(/*String|Object*/name, /*Object?*/value){
+               // summary:
+               //              Set or get properties on a widget instance.
+               //      name:
+               //              The property to get or set. If an object is passed here and not
+               //              a string, its keys are used as names of attributes to be set
+               //              and the value of the object as values to set in the widget.
+               //      value:
+               //              Optional. If provided, attr() operates as a setter. If omitted,
+               //              the current value of the named property is returned.
+               // description:
+               //              This method is deprecated, use get() or set() directly.
+
+               // Print deprecation warning but only once per calling function
+               if(config.isDebug){
+                       var alreadyCalledHash = arguments.callee._ach || (arguments.callee._ach = {}),
+                               caller = (arguments.callee.caller || "unknown caller").toString();
+                       if(!alreadyCalledHash[caller]){
+                               kernel.deprecated(this.declaredClass + "::attr() is deprecated. Use get() or set() instead, called from " +
+                               caller, "", "2.0");
+                               alreadyCalledHash[caller] = true;
+                       }
+               }
+
+               var args = arguments.length;
+               if(args >= 2 || typeof name === "object"){ // setter
+                       return this.set.apply(this, arguments);
+               }else{ // getter
+                       return this.get(name);
+               }
+       },
+
+       getDescendants: function(){
+               // summary:
+               //              Returns all the widgets contained by this, i.e., all widgets underneath this.containerNode.
+               //              This method should generally be avoided as it returns widgets declared in templates, which are
+               //              supposed to be internal/hidden, but it's left here for back-compat reasons.
+
+               kernel.deprecated(this.declaredClass+"::getDescendants() is deprecated. Use getChildren() instead.", "", "2.0");
+               return this.containerNode ? query('[widgetId]', this.containerNode).map(registry.byNode) : []; // dijit._Widget[]
+       },
+
+       ////////////////// MISCELLANEOUS METHODS ///////////////////
+
+       _onShow: function(){
+               // summary:
+               //              Internal method called when this widget is made visible.
+               //              See `onShow` for details.
+               this.onShow();
+       },
+
+       onShow: function(){
+               // summary:
+               //              Called when this widget becomes the selected pane in a
+               //              `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
+               //              `dijit.layout.AccordionContainer`, etc.
+               //
+               //              Also called to indicate display of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
+               // tags:
+               //              callback
+       },
+
+       onHide: function(){
+               // summary:
+                       //              Called when another widget becomes the selected pane in a
+                       //              `dijit.layout.TabContainer`, `dijit.layout.StackContainer`,
+                       //              `dijit.layout.AccordionContainer`, etc.
+                       //
+                       //              Also called to indicate hide of a `dijit.Dialog`, `dijit.TooltipDialog`, or `dijit.TitlePane`.
+                       // tags:
+                       //              callback
+       },
+
+       onClose: function(){
+               // summary:
+               //              Called when this widget is being displayed as a popup (ex: a Calendar popped
+               //              up from a DateTextBox), and it is hidden.
+               //              This is called from the dijit.popup code, and should not be called directly.
+               //
+               //              Also used as a parameter for children of `dijit.layout.StackContainer` or subclasses.
+               //              Callback if a user tries to close the child.   Child will be closed if this function returns true.
+               // tags:
+               //              extension
+
+               return true;            // Boolean
+       }
+});
+
+// For back-compat, remove in 2.0.
+if(!kernel.isAsync){
+       ready(0, function(){
+               var requires = ["dijit/_base"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
+return _Widget;
+});
+
+},
+'dojo/touch':function(){
+define("dojo/touch", ["./_base/kernel", "./on", "./has", "./mouse"], function(dojo, on, has, mouse){
+// module:
+//             dojo/touch
+
+/*=====
+       dojo.touch = {
+               // summary:
+               //              This module provides unified touch event handlers by exporting
+               //              press, move, release and cancel which can also run well on desktop.
+               //              Based on http://dvcs.w3.org/hg/webevents/raw-file/tip/touchevents.html
+               //
+               // example:
+               //              1. Used with dojo.connect()
+               //              |       dojo.connect(node, dojo.touch.press, function(e){});
+               //              |       dojo.connect(node, dojo.touch.move, function(e){});
+               //              |       dojo.connect(node, dojo.touch.release, function(e){});
+               //              |       dojo.connect(node, dojo.touch.cancel, function(e){});
+               //
+               //              2. Used with dojo.on
+               //              |       define(["dojo/on", "dojo/touch"], function(on, touch){
+               //              |               on(node, touch.press, function(e){});
+               //              |               on(node, touch.move, function(e){});
+               //              |               on(node, touch.release, function(e){});
+               //              |               on(node, touch.cancel, function(e){});
+               //
+               //              3. Used with dojo.touch.* directly
+               //              |       dojo.touch.press(node, function(e){});
+               //              |       dojo.touch.move(node, function(e){});
+               //              |       dojo.touch.release(node, function(e){});
+               //              |       dojo.touch.cancel(node, function(e){});
+               
+               press: function(node, listener){
+                       // summary:
+                       //              Register a listener to 'touchstart'|'mousedown' for the given node
+                       // node: Dom
+                       //              Target node to listen to
+                       // listener: Function
+                       //              Callback function
+                       // returns:
+                       //              A handle which will be used to remove the listener by handle.remove()
+               },
+               move: function(node, listener){
+                       // summary:
+                       //              Register a listener to 'touchmove'|'mousemove' for the given node
+                       // node: Dom
+                       //              Target node to listen to
+                       // listener: Function
+                       //              Callback function
+                       // returns:
+                       //              A handle which will be used to remove the listener by handle.remove()
+               },
+               release: function(node, listener){
+                       // summary:
+                       //              Register a listener to 'touchend'|'mouseup' for the given node
+                       // node: Dom
+                       //              Target node to listen to
+                       // listener: Function
+                       //              Callback function
+                       // returns:
+                       //              A handle which will be used to remove the listener by handle.remove()
+               },
+               cancel: function(node, listener){
+                       // summary:
+                       //              Register a listener to 'touchcancel'|'mouseleave' for the given node
+                       // node: Dom
+                       //              Target node to listen to
+                       // listener: Function
+                       //              Callback function
+                       // returns:
+                       //              A handle which will be used to remove the listener by handle.remove()
+               }
+       };
+=====*/
+
+       function _handle(/*String - press | move | release | cancel*/type){
+               return function(node, listener){//called by on(), see dojo.on
+                       return on(node, type, listener);
+               };
+       }
+       var touch = has("touch");
+       //device neutral events - dojo.touch.press|move|release|cancel
+       dojo.touch = {
+               press: _handle(touch ? "touchstart": "mousedown"),
+               move: _handle(touch ? "touchmove": "mousemove"),
+               release: _handle(touch ? "touchend": "mouseup"),
+               cancel: touch ? _handle("touchcancel") : mouse.leave
+       };
+       return dojo.touch;
+});
+},
+'url:dijit/form/templates/Select.html':"<table class=\"dijit dijitReset dijitInline dijitLeft\"\n\tdata-dojo-attach-point=\"_buttonNode,tableNode,focusNode\" cellspacing='0' cellpadding='0'\n\trole=\"combobox\" aria-haspopup=\"true\"\n\t><tbody role=\"presentation\"><tr role=\"presentation\"\n\t\t><td class=\"dijitReset dijitStretch dijitButtonContents dijitButtonNode\" role=\"presentation\"\n\t\t\t><span class=\"dijitReset dijitInline dijitButtonText\"  data-dojo-attach-point=\"containerNode,_popupStateNode\"></span\n\t\t\t><input type=\"hidden\" ${!nameAttrSetting} data-dojo-attach-point=\"valueNode\" value=\"${value}\" aria-hidden=\"true\"\n\t\t/></td><td class=\"dijitReset dijitRight dijitButtonNode dijitArrowButton dijitDownArrowButton\"\n\t\t\t\tdata-dojo-attach-point=\"titleNode\" role=\"presentation\"\n\t\t\t><div class=\"dijitReset dijitArrowButtonInner\" role=\"presentation\"></div\n\t\t\t><div class=\"dijitReset dijitArrowButtonChar\" role=\"presentation\">&#9660;</div\n\t\t></td\n\t></tr></tbody\n></table>\n",
+'dojo/fx':function(){
+define("dojo/fx", [
+       "./_base/lang",
+       "./Evented",
+       "./_base/kernel",
+       "./_base/array",
+       "./_base/connect",
+       "./_base/fx",
+       "./dom",
+       "./dom-style",
+       "./dom-geometry",
+       "./ready",
+       "require" // for context sensitive loading of Toggler
+], function(lang, Evented, dojo, arrayUtil, connect, baseFx, dom, domStyle, geom, ready, require) {
+
+       // module:
+       //              dojo/fx
+       // summary:
+       //              TODOC
+
+
+       /*=====
+       dojo.fx = {
+               // summary: Effects library on top of Base animations
+       };
+       var coreFx = dojo.fx;
+       =====*/
+       
+// For back-compat, remove in 2.0.
+if(!dojo.isAsync){
+       ready(0, function(){
+               var requires = ["./fx/Toggler"];
+               require(requires);      // use indirection so modules not rolled into a build
+       });
+}
+
+       var coreFx = dojo.fx = {};
+
+       var _baseObj = {
+                       _fire: function(evt, args){
+                               if(this[evt]){
+                                       this[evt].apply(this, args||[]);
+                               }
+                               return this;
+                       }
+               };
+
+       var _chain = function(animations){
+               this._index = -1;
+               this._animations = animations||[];
+               this._current = this._onAnimateCtx = this._onEndCtx = null;
+
+               this.duration = 0;
+               arrayUtil.forEach(this._animations, function(a){
+                       this.duration += a.duration;
+                       if(a.delay){ this.duration += a.delay; }
+               }, this);
+       };
+       _chain.prototype = new Evented();
+       lang.extend(_chain, {
+               _onAnimate: function(){
+                       this._fire("onAnimate", arguments);
+               },
+               _onEnd: function(){
+                       connect.disconnect(this._onAnimateCtx);
+                       connect.disconnect(this._onEndCtx);
+                       this._onAnimateCtx = this._onEndCtx = null;
+                       if(this._index + 1 == this._animations.length){
+                               this._fire("onEnd");
+                       }else{
+                               // switch animations
+                               this._current = this._animations[++this._index];
+                               this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
+                               this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
+                               this._current.play(0, true);
+                       }
+               },
+               play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
+                       if(!this._current){ this._current = this._animations[this._index = 0]; }
+                       if(!gotoStart && this._current.status() == "playing"){ return this; }
+                       var beforeBegin = connect.connect(this._current, "beforeBegin", this, function(){
+                                       this._fire("beforeBegin");
+                               }),
+                               onBegin = connect.connect(this._current, "onBegin", this, function(arg){
+                                       this._fire("onBegin", arguments);
+                               }),
+                               onPlay = connect.connect(this._current, "onPlay", this, function(arg){
+                                       this._fire("onPlay", arguments);
+                                       connect.disconnect(beforeBegin);
+                                       connect.disconnect(onBegin);
+                                       connect.disconnect(onPlay);
+                               });
+                       if(this._onAnimateCtx){
+                               connect.disconnect(this._onAnimateCtx);
+                       }
+                       this._onAnimateCtx = connect.connect(this._current, "onAnimate", this, "_onAnimate");
+                       if(this._onEndCtx){
+                               connect.disconnect(this._onEndCtx);
+                       }
+                       this._onEndCtx = connect.connect(this._current, "onEnd", this, "_onEnd");
+                       this._current.play.apply(this._current, arguments);
+                       return this;
+               },
+               pause: function(){
+                       if(this._current){
+                               var e = connect.connect(this._current, "onPause", this, function(arg){
+                                               this._fire("onPause", arguments);
+                                               connect.disconnect(e);
+                                       });
+                               this._current.pause();
+                       }
+                       return this;
+               },
+               gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
+                       this.pause();
+                       var offset = this.duration * percent;
+                       this._current = null;
+                       arrayUtil.some(this._animations, function(a){
+                               if(a.duration <= offset){
+                                       this._current = a;
+                                       return true;
+                               }
+                               offset -= a.duration;
+                               return false;
+                       });
+                       if(this._current){
+                               this._current.gotoPercent(offset / this._current.duration, andPlay);
+                       }
+                       return this;
+               },
+               stop: function(/*boolean?*/ gotoEnd){
+                       if(this._current){
+                               if(gotoEnd){
+                                       for(; this._index + 1 < this._animations.length; ++this._index){
+                                               this._animations[this._index].stop(true);
+                                       }
+                                       this._current = this._animations[this._index];
+                               }
+                               var e = connect.connect(this._current, "onStop", this, function(arg){
+                                               this._fire("onStop", arguments);
+                                               connect.disconnect(e);
+                                       });
+                               this._current.stop();
+                       }
+                       return this;
+               },
+               status: function(){
+                       return this._current ? this._current.status() : "stopped";
+               },
+               destroy: function(){
+                       if(this._onAnimateCtx){ connect.disconnect(this._onAnimateCtx); }
+                       if(this._onEndCtx){ connect.disconnect(this._onEndCtx); }
+               }
+       });
+       lang.extend(_chain, _baseObj);
+
+       coreFx.chain = /*===== dojo.fx.chain = =====*/ function(/*dojo.Animation[]*/ animations){
+               // summary:
+               //              Chain a list of `dojo.Animation`s to run in sequence
+               //
+               // description:
+               //              Return a `dojo.Animation` which will play all passed
+               //              `dojo.Animation` instances in sequence, firing its own
+               //              synthesized events simulating a single animation. (eg:
+               //              onEnd of this animation means the end of the chain,
+               //              not the individual animations within)
+               //
+               // example:
+               //      Once `node` is faded out, fade in `otherNode`
+               //      |       dojo.fx.chain([
+               //      |               dojo.fadeIn({ node:node }),
+               //      |               dojo.fadeOut({ node:otherNode })
+               //      |       ]).play();
+               //
+               return new _chain(animations); // dojo.Animation
+       };
+
+       var _combine = function(animations){
+               this._animations = animations||[];
+               this._connects = [];
+               this._finished = 0;
+
+               this.duration = 0;
+               arrayUtil.forEach(animations, function(a){
+                       var duration = a.duration;
+                       if(a.delay){ duration += a.delay; }
+                       if(this.duration < duration){ this.duration = duration; }
+                       this._connects.push(connect.connect(a, "onEnd", this, "_onEnd"));
+               }, this);
+
+               this._pseudoAnimation = new baseFx.Animation({curve: [0, 1], duration: this.duration});
+               var self = this;
+               arrayUtil.forEach(["beforeBegin", "onBegin", "onPlay", "onAnimate", "onPause", "onStop", "onEnd"],
+                       function(evt){
+                               self._connects.push(connect.connect(self._pseudoAnimation, evt,
+                                       function(){ self._fire(evt, arguments); }
+                               ));
+                       }
+               );
+       };
+       lang.extend(_combine, {
+               _doAction: function(action, args){
+                       arrayUtil.forEach(this._animations, function(a){
+                               a[action].apply(a, args);
+                       });
+                       return this;
+               },
+               _onEnd: function(){
+                       if(++this._finished > this._animations.length){
+                               this._fire("onEnd");
+                       }
+               },
+               _call: function(action, args){
+                       var t = this._pseudoAnimation;
+                       t[action].apply(t, args);
+               },
+               play: function(/*int?*/ delay, /*Boolean?*/ gotoStart){
+                       this._finished = 0;
+                       this._doAction("play", arguments);
+                       this._call("play", arguments);
+                       return this;
+               },
+               pause: function(){
+                       this._doAction("pause", arguments);
+                       this._call("pause", arguments);
+                       return this;
+               },
+               gotoPercent: function(/*Decimal*/percent, /*Boolean?*/ andPlay){
+                       var ms = this.duration * percent;
+                       arrayUtil.forEach(this._animations, function(a){
+                               a.gotoPercent(a.duration < ms ? 1 : (ms / a.duration), andPlay);
+                       });
+                       this._call("gotoPercent", arguments);
+                       return this;
+               },
+               stop: function(/*boolean?*/ gotoEnd){
+                       this._doAction("stop", arguments);
+                       this._call("stop", arguments);
+                       return this;
+               },
+               status: function(){
+                       return this._pseudoAnimation.status();
+               },
+               destroy: function(){
+                       arrayUtil.forEach(this._connects, connect.disconnect);
+               }
+       });
+       lang.extend(_combine, _baseObj);
+
+       coreFx.combine = /*===== dojo.fx.combine = =====*/ function(/*dojo.Animation[]*/ animations){
+               // summary:
+               //              Combine a list of `dojo.Animation`s to run in parallel
+               //
+               // description:
+               //              Combine an array of `dojo.Animation`s to run in parallel,
+               //              providing a new `dojo.Animation` instance encompasing each
+               //              animation, firing standard animation events.
+               //
+               // example:
+               //      Fade out `node` while fading in `otherNode` simultaneously
+               //      |       dojo.fx.combine([
+               //      |               dojo.fadeIn({ node:node }),
+               //      |               dojo.fadeOut({ node:otherNode })
+               //      |       ]).play();
+               //
+               // example:
+               //      When the longest animation ends, execute a function:
+               //      |       var anim = dojo.fx.combine([
+               //      |               dojo.fadeIn({ node: n, duration:700 }),
+               //      |               dojo.fadeOut({ node: otherNode, duration: 300 })
+               //      |       ]);
+               //      |       dojo.connect(anim, "onEnd", function(){
+               //      |               // overall animation is done.
+               //      |       });
+               //      |       anim.play(); // play the animation
+               //
+               return new _combine(animations); // dojo.Animation
+       };
+
+       coreFx.wipeIn = /*===== dojo.fx.wipeIn = =====*/ function(/*Object*/ args){
+               // summary:
+               //              Expand a node to it's natural height.
+               //
+               // description:
+               //              Returns an animation that will expand the
+               //              node defined in 'args' object from it's current height to
+               //              it's natural height (with no scrollbar).
+               //              Node must have no margin/border/padding.
+               //
+               // args: Object
+               //              A hash-map of standard `dojo.Animation` constructor properties
+               //              (such as easing: node: duration: and so on)
+               //
+               // example:
+               //      |       dojo.fx.wipeIn({
+               //      |               node:"someId"
+               //      |       }).play()
+               var node = args.node = dom.byId(args.node), s = node.style, o;
+
+               var anim = baseFx.animateProperty(lang.mixin({
+                       properties: {
+                               height: {
+                                       // wrapped in functions so we wait till the last second to query (in case value has changed)
+                                       start: function(){
+                                               // start at current [computed] height, but use 1px rather than 0
+                                               // because 0 causes IE to display the whole panel
+                                               o = s.overflow;
+                                               s.overflow = "hidden";
+                                               if(s.visibility == "hidden" || s.display == "none"){
+                                                       s.height = "1px";
+                                                       s.display = "";
+                                                       s.visibility = "";
+                                                       return 1;
+                                               }else{
+                                                       var height = domStyle.get(node, "height");
+                                                       return Math.max(height, 1);
+                                               }
+                                       },
+                                       end: function(){
+                                               return node.scrollHeight;
                                        }
-                                       break;
-                               case dojo.keys.ESCAPE:
-                                       dojo.publish("/dnd/cancel");
-                                       this.stopDrag();
-                                       break;
+                               }
                        }
-               }
-       },
-       onKeyUp: function(e){
+               }, args));
+
+               var fini = function(){
+                       s.height = "auto";
+                       s.overflow = o;
+               };
+               connect.connect(anim, "onStop", fini);
+               connect.connect(anim, "onEnd", fini);
+
+               return anim; // dojo.Animation
+       };
+
+       coreFx.wipeOut = /*===== dojo.fx.wipeOut = =====*/ function(/*Object*/ args){
                // summary:
-               //              event processor for onkeyup, watching for CTRL for copy/move status
-               // e: Event
-               //              keyboard event
-               if(this.avatar && e.keyCode == dojo.keys.CTRL){
-                       var copy = Boolean(this.source.copyState(false));
-                       if(this.copy != copy){ 
-                               this._setCopyStatus(copy);
+               //              Shrink a node to nothing and hide it.
+               //
+               // description:
+               //              Returns an animation that will shrink node defined in "args"
+               //              from it's current height to 1px, and then hide it.
+               //
+               // args: Object
+               //              A hash-map of standard `dojo.Animation` constructor properties
+               //              (such as easing: node: duration: and so on)
+               //
+               // example:
+               //      |       dojo.fx.wipeOut({ node:"someId" }).play()
+
+               var node = args.node = dom.byId(args.node), s = node.style, o;
+
+               var anim = baseFx.animateProperty(lang.mixin({
+                       properties: {
+                               height: {
+                                       end: 1 // 0 causes IE to display the whole panel
+                               }
                        }
-               }
-       },
-       
-       // utilities
-       _setCopyStatus: function(copy){
+               }, args));
+
+               connect.connect(anim, "beforeBegin", function(){
+                       o = s.overflow;
+                       s.overflow = "hidden";
+                       s.display = "";
+               });
+               var fini = function(){
+                       s.overflow = o;
+                       s.height = "auto";
+                       s.display = "none";
+               };
+               connect.connect(anim, "onStop", fini);
+               connect.connect(anim, "onEnd", fini);
+
+               return anim; // dojo.Animation
+       };
+
+       coreFx.slideTo = /*===== dojo.fx.slideTo = =====*/ function(/*Object*/ args){
                // summary:
-               //              changes the copy status
-               // copy: Boolean
-               //              the copy status
-               this.copy = copy;
-               this.source._markDndStatus(this.copy);
-               this.updateAvatar();
-               dojo.removeClass(dojo.body(), "dojoDnd" + (this.copy ? "Move" : "Copy"));
-               dojo.addClass(dojo.body(), "dojoDnd" + (this.copy ? "Copy" : "Move"));
-       }
-});
+               //              Slide a node to a new top/left position
+               //
+               // description:
+               //              Returns an animation that will slide "node"
+               //              defined in args Object from its current position to
+               //              the position defined by (args.left, args.top).
+               //
+               // args: Object
+               //              A hash-map of standard `dojo.Animation` constructor properties
+               //              (such as easing: node: duration: and so on). Special args members
+               //              are `top` and `left`, which indicate the new position to slide to.
+               //
+               // example:
+               //      |       .slideTo({ node: node, left:"40", top:"50", units:"px" }).play()
 
-// dojo.dnd._manager:
-//             The manager singleton variable. Can be overwritten if needed.
-dojo.dnd._manager = null;
+               var node = args.node = dom.byId(args.node),
+                       top = null, left = null;
+
+               var init = (function(n){
+                       return function(){
+                               var cs = domStyle.getComputedStyle(n);
+                               var pos = cs.position;
+                               top = (pos == 'absolute' ? n.offsetTop : parseInt(cs.top) || 0);
+                               left = (pos == 'absolute' ? n.offsetLeft : parseInt(cs.left) || 0);
+                               if(pos != 'absolute' && pos != 'relative'){
+                                       var ret = geom.position(n, true);
+                                       top = ret.y;
+                                       left = ret.x;
+                                       n.style.position="absolute";
+                                       n.style.top=top+"px";
+                                       n.style.left=left+"px";
+                               }
+                       };
+               })(node);
+               init();
+
+               var anim = baseFx.animateProperty(lang.mixin({
+                       properties: {
+                               top: args.top || 0,
+                               left: args.left || 0
+                       }
+               }, args));
+               connect.connect(anim, "beforeBegin", anim, init);
+
+               return anim; // dojo.Animation
+       };
+
+       return coreFx;
+});
 
-dojo.dnd.manager = function(){
+},
+'dijit/_DialogMixin':function(){
+define("dijit/_DialogMixin", [
+       "dojo/_base/declare", // declare
+       "./a11y"        // _getTabNavigable
+], function(declare, a11y){
+
+       // module:
+       //              dijit/_DialogMixin
        // summary:
-       //              Returns the current DnD manager.  Creates one if it is not created yet.
-       if(!dojo.dnd._manager){
-               dojo.dnd._manager = new dojo.dnd.Manager();
-       }
-       return dojo.dnd._manager;       // Object
-};
+       //              _DialogMixin provides functions useful to Dialog and TooltipDialog
 
-}
+       return declare("dijit._DialogMixin", null, {
+               // summary:
+               //              This provides functions useful to Dialog and TooltipDialog
+
+               execute: function(/*Object*/ /*===== formContents =====*/){
+                       // summary:
+                       //              Callback when the user hits the submit button.
+                       //              Override this method to handle Dialog execution.
+                       // description:
+                       //              After the user has pressed the submit button, the Dialog
+                       //              first calls onExecute() to notify the container to hide the
+                       //              dialog and restore focus to wherever it used to be.
+                       //
+                       //              *Then* this method is called.
+                       // type:
+                       //              callback
+               },
+
+               onCancel: function(){
+                       // summary:
+                       //          Called when user has pressed the Dialog's cancel button, to notify container.
+                       // description:
+                       //          Developer shouldn't override or connect to this method;
+                       //              it's a private communication device between the TooltipDialog
+                       //              and the thing that opened it (ex: `dijit.form.DropDownButton`)
+                       // type:
+                       //              protected
+               },
+
+               onExecute: function(){
+                       // summary:
+                       //          Called when user has pressed the dialog's OK button, to notify container.
+                       // description:
+                       //          Developer shouldn't override or connect to this method;
+                       //              it's a private communication device between the TooltipDialog
+                       //              and the thing that opened it (ex: `dijit.form.DropDownButton`)
+                       // type:
+                       //              protected
+               },
 
-if(!dojo._hasResource["dijit.tree.dndSource"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dijit.tree.dndSource"] = true;
-dojo.provide("dijit.tree.dndSource");
+               _onSubmit: function(){
+                       // summary:
+                       //              Callback when user hits submit button
+                       // type:
+                       //              protected
+                       this.onExecute();       // notify container that we are about to execute
+                       this.execute(this.get('value'));
+               },
 
+               _getFocusItems: function(){
+                       // summary:
+                       //              Finds focusable items in dialog,
+                       //              and sets this._firstFocusItem and this._lastFocusItem
+                       // tags:
+                       //              protected
 
+                       var elems = a11y._getTabNavigable(this.containerNode);
+                       this._firstFocusItem = elems.lowest || elems.first || this.closeButtonNode || this.domNode;
+                       this._lastFocusItem = elems.last || elems.highest || this._firstFocusItem;
+               }
+       });
+});
 
+},
+'dijit/Tree':function(){
+require({cache:{
+'url:dijit/templates/TreeNode.html':"<div class=\"dijitTreeNode\" role=\"presentation\"\n\t><div data-dojo-attach-point=\"rowNode\" class=\"dijitTreeRow\" role=\"presentation\" data-dojo-attach-event=\"onmouseenter:_onMouseEnter, onmouseleave:_onMouseLeave, onclick:_onClick, ondblclick:_onDblClick\"\n\t\t><img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"expandoNode\" class=\"dijitTreeExpando\" role=\"presentation\"\n\t\t/><span data-dojo-attach-point=\"expandoNodeText\" class=\"dijitExpandoText\" role=\"presentation\"\n\t\t></span\n\t\t><span data-dojo-attach-point=\"contentNode\"\n\t\t\tclass=\"dijitTreeContent\" role=\"presentation\">\n\t\t\t<img src=\"${_blankGif}\" alt=\"\" data-dojo-attach-point=\"iconNode\" class=\"dijitIcon dijitTreeIcon\" role=\"presentation\"\n\t\t\t/><span data-dojo-attach-point=\"labelNode\" class=\"dijitTreeLabel\" role=\"treeitem\" tabindex=\"-1\" aria-selected=\"false\" data-dojo-attach-event=\"onfocus:_onLabelFocus\"></span>\n\t\t</span\n\t></div>\n\t<div data-dojo-attach-point=\"containerNode\" class=\"dijitTreeContainer\" role=\"presentation\" style=\"display: none;\"></div>\n</div>\n",
+'url:dijit/templates/Tree.html':"<div class=\"dijitTree dijitTreeContainer\" role=\"tree\"\n\tdata-dojo-attach-event=\"onkeypress:_onKeyPress\">\n\t<div class=\"dijitInline dijitTreeIndent\" style=\"position: absolute; top: -9999px\" data-dojo-attach-point=\"indentDetector\"></div>\n</div>\n"}});
+define("dijit/Tree", [
+       "dojo/_base/array", // array.filter array.forEach array.map
+       "dojo/_base/connect",   // connect.isCopyKey()
+       "dojo/cookie", // cookie
+       "dojo/_base/declare", // declare
+       "dojo/_base/Deferred", // Deferred
+       "dojo/DeferredList", // DeferredList
+       "dojo/dom", // dom.isDescendant
+       "dojo/dom-class", // domClass.add domClass.remove domClass.replace domClass.toggle
+       "dojo/dom-geometry", // domGeometry.setMarginBox domGeometry.position
+       "dojo/dom-style",// domStyle.set
+       "dojo/_base/event", // event.stop
+       "dojo/fx", // fxUtils.wipeIn fxUtils.wipeOut
+       "dojo/_base/kernel", // kernel.deprecated
+       "dojo/keys",    // arrows etc.
+       "dojo/_base/lang", // lang.getObject lang.mixin lang.hitch
+       "dojo/topic",
+       "./focus",
+       "./registry",   // registry.getEnclosingWidget(), manager.defaultDuration
+       "./_base/manager",      // manager.getEnclosingWidget(), manager.defaultDuration
+       "./_Widget",
+       "./_TemplatedMixin",
+       "./_Container",
+       "./_Contained",
+       "./_CssStateMixin",
+       "dojo/text!./templates/TreeNode.html",
+       "dojo/text!./templates/Tree.html",
+       "./tree/TreeStoreModel",
+       "./tree/ForestStoreModel",
+       "./tree/_dndSelector"
+], function(array, connect, cookie, declare, Deferred, DeferredList,
+                       dom, domClass, domGeometry, domStyle, event, fxUtils, kernel, keys, lang, topic,
+                       focus, registry, manager, _Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin,
+                       treeNodeTemplate, treeTemplate, TreeStoreModel, ForestStoreModel, _dndSelector){
 
 /*=====
-dijit.tree.__SourceArgs = function(){
-       // summary:
-       //              A dict of parameters for Tree source configuration.
-       // isSource: Boolean?
-       //              Can be used as a DnD source. Defaults to true.
-       // accept: String[]
-       //              List of accepted types (text strings) for a target; defaults to
-       //              ["text", "treeNode"]
-       // copyOnly: Boolean?
-       //              Copy items, if true, use a state of Ctrl key otherwise,
-       // dragThreshold: Number
-       //              The move delay in pixels before detecting a drag; 0 by default
-       // betweenThreshold: Integer
-       //              Distance from upper/lower edge of node to allow drop to reorder nodes
-       this.isSource = isSource;
-       this.accept = accept;
-       this.autoSync = autoSync;
-       this.copyOnly = copyOnly;
-       this.dragThreshold = dragThreshold;
-       this.betweenThreshold = betweenThreshold;
-}
+       var _Widget = dijit._Widget;
+       var _TemplatedMixin = dijit._TemplatedMixin;
+       var _CssStateMixin = dijit._CssStateMixin;
+       var _Container = dijit._Container;
+       var _Contained = dijit._Contained;
 =====*/
 
-dojo.declare("dijit.tree.dndSource", dijit.tree._dndSelector, {
+// module:
+//             dijit/Tree
+// summary:
+//             dijit.Tree widget, and internal dijit._TreeNode widget
+
+
+var TreeNode = declare(
+       "dijit._TreeNode",
+       [_Widget, _TemplatedMixin, _Container, _Contained, _CssStateMixin],
+{
        // summary:
-       //              Handles drag and drop operations (as a source or a target) for `dijit.Tree`
+       //              Single node within a tree.   This class is used internally
+       //              by Tree and should not be accessed directly.
+       // tags:
+       //              private
 
-       // isSource: [private] Boolean
-       //              Can be used as a DnD source.
-       isSource: true,
+       // item: [const] Item
+       //              the dojo.data entry this tree represents
+       item: null,
+
+       // isTreeNode: [protected] Boolean
+       //              Indicates that this is a TreeNode.   Used by `dijit.Tree` only,
+       //              should not be accessed directly.
+       isTreeNode: true,
+
+       // label: String
+       //              Text of this tree node
+       label: "",
+       _setLabelAttr: {node: "labelNode", type: "innerText"},
+
+       // isExpandable: [private] Boolean
+       //              This node has children, so show the expando node (+ sign)
+       isExpandable: null,
+
+       // isExpanded: [readonly] Boolean
+       //              This node is currently expanded (ie, opened)
+       isExpanded: false,
 
-       // accept: String[]
-       //              List of accepted types (text strings) for the Tree; defaults to
-       //              ["text"]
-       accept: ["text", "treeNode"],
+       // state: [private] String
+       //              Dynamic loading-related stuff.
+       //              When an empty folder node appears, it is "UNCHECKED" first,
+       //              then after dojo.data query it becomes "LOADING" and, finally "LOADED"
+       state: "UNCHECKED",
 
-       // copyOnly: [private] Boolean
-       //              Copy items, if true, use a state of Ctrl key otherwise
-       copyOnly: false,
+       templateString: treeNodeTemplate,
 
-       // dragThreshold: Number
-       //              The move delay in pixels before detecting a drag; 5 by default
-       dragThreshold: 5,
+       baseClass: "dijitTreeNode",
 
-       // betweenThreshold: Integer
-       //              Distance from upper/lower edge of node to allow drop to reorder nodes
-       betweenThreshold: 0,
+       // For hover effect for tree node, and focus effect for label
+       cssStateNodes: {
+               rowNode: "dijitTreeRow",
+               labelNode: "dijitTreeLabel"
+       },
 
-       constructor: function(/*dijit.Tree*/ tree, /*dijit.tree.__SourceArgs*/ params){
-               // summary:
-               //              a constructor of the Tree DnD Source
-               // tags:
-               //              private
-               if(!params){ params = {}; }
-               dojo.mixin(this, params);
-               this.isSource = typeof params.isSource == "undefined" ? true : params.isSource;
-               var type = params.accept instanceof Array ? params.accept : ["text", "treeNode"];
-               this.accept = null;
-               if(type.length){
-                       this.accept = {};
-                       for(var i = 0; i < type.length; ++i){
-                               this.accept[type[i]] = 1;
-                       }
-               }
+       // Tooltip is defined in _WidgetBase but we need to handle the mapping to DOM here
+       _setTooltipAttr: {node: "rowNode", type: "attribute", attribute: "title"},
 
-               // class-specific variables
-               this.isDragging = false;
-               this.mouseDown = false;
-               this.targetAnchor = null;       // DOMNode corresponding to the currently moused over TreeNode
-               this.targetBox = null;  // coordinates of this.targetAnchor
-               this.dropPosition = ""; // whether mouse is over/after/before this.targetAnchor
-               this._lastX = 0;
-               this._lastY = 0;
+       buildRendering: function(){
+               this.inherited(arguments);
 
-               // states
-               this.sourceState = "";
-               if(this.isSource){
-                       dojo.addClass(this.node, "dojoDndSource");
-               }
-               this.targetState = "";
-               if(this.accept){
-                       dojo.addClass(this.node, "dojoDndTarget");
-               }
+               // set expand icon for leaf
+               this._setExpando();
 
-               // set up events
-               this.topics = [
-                       dojo.subscribe("/dnd/source/over", this, "onDndSourceOver"),
-                       dojo.subscribe("/dnd/start", this, "onDndStart"),
-                       dojo.subscribe("/dnd/drop", this, "onDndDrop"),
-                       dojo.subscribe("/dnd/cancel", this, "onDndCancel")
-               ];
-       },
+               // set icon and label class based on item
+               this._updateItemClasses(this.item);
 
-       // methods
-       checkAcceptance: function(source, nodes){
-               // summary:
-               //              Checks if the target can accept nodes from this source
-               // source: dijit.tree.dndSource
-               //              The source which provides items
-               // nodes: DOMNode[]
-               //              Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
-               //              source is a dijit.Tree.
-               // tags:
-               //              extension
-               return true;    // Boolean
-       },
+               if(this.isExpandable){
+                       this.labelNode.setAttribute("aria-expanded", this.isExpanded);
+               }
 
-       copyState: function(keyPressed){
-               // summary:
-               //              Returns true, if we need to copy items, false to move.
-               //              It is separated to be overwritten dynamically, if needed.
-               // keyPressed: Boolean
-               //              The "copy" control key was pressed
-               // tags:
-               //              protected
-               return this.copyOnly || keyPressed;     // Boolean
-       },
-       destroy: function(){
-               // summary:
-               //              Prepares the object to be garbage-collected.
-               this.inherited("destroy",arguments);
-               dojo.forEach(this.topics, dojo.unsubscribe);
-               this.targetAnchor = null;
+               //aria-selected should be false on all selectable elements.
+               this.setSelected(false);
        },
 
-       _onDragMouse: function(e){
+       _setIndentAttr: function(indent){
                // summary:
-               //              Helper method for processing onmousemove/onmouseover events while drag is in progress.
-               //              Keeps track of current drop target.
-
-               var m = dojo.dnd.manager(),
-                       oldTarget = this.targetAnchor,                  // the DOMNode corresponding to TreeNode mouse was previously over
-                       newTarget = this.current,                               // DOMNode corresponding to TreeNode mouse is currently over
-                       newTargetWidget = this.currentWidget,   // the TreeNode itself
-                       oldDropPosition = this.dropPosition;    // the previous drop position (over/before/after)
+               //              Tell this node how many levels it should be indented
+               // description:
+               //              0 for top level nodes, 1 for their children, 2 for their
+               //              grandchildren, etc.
 
-               // calculate if user is indicating to drop the dragged node before, after, or over
-               // (i.e., to become a child of) the target node
-               var newDropPosition = "Over";
-               if(newTarget && this.betweenThreshold > 0){
-                       // If mouse is over a new TreeNode, then get new TreeNode's position and size
-                       if(!this.targetBox || oldTarget != newTarget){
-                               this.targetBox = dojo.position(newTarget, true);
-                       }
-                       if((e.pageY - this.targetBox.y) <= this.betweenThreshold){
-                               newDropPosition = "Before";
-                       }else if((e.pageY - this.targetBox.y) >= (this.targetBox.h - this.betweenThreshold)){
-                               newDropPosition = "After";
-                       }
-               }
+               // Math.max() is to prevent negative padding on hidden root node (when indent == -1)
+               var pixels = (Math.max(indent, 0) * this.tree._nodePixelIndent) + "px";
 
-               if(newTarget != oldTarget || newDropPosition != oldDropPosition){
-                       if(oldTarget){
-                               this._removeItemClass(oldTarget, oldDropPosition);
-                       }
-                       if(newTarget){
-                               this._addItemClass(newTarget, newDropPosition);
-                       }
+               domStyle.set(this.domNode, "backgroundPosition",        pixels + " 0px");
+               domStyle.set(this.rowNode, this.isLeftToRight() ? "paddingLeft" : "paddingRight", pixels);
 
-                       // Check if it's ok to drop the dragged node on/before/after the target node.
-                       if(!newTarget){
-                               m.canDrop(false);
-                       }else if(newTargetWidget == this.tree.rootNode && newDropPosition != "Over"){
-                               // Can't drop before or after tree's root node; the dropped node would just disappear (at least visually)
-                               m.canDrop(false);
-                       }else if(m.source == this && (newTarget.id in this.selection)){
-                               // Guard against dropping onto yourself (TODO: guard against dropping onto your descendant, #7140)
-                               m.canDrop(false);
-                       }else if(this.checkItemAcceptance(newTarget, m.source, newDropPosition.toLowerCase())
-                                       && !this._isParentChildDrop(m.source, newTarget)){
-                               m.canDrop(true);
-                       }else{
-                               m.canDrop(false);
-                       }
+               array.forEach(this.getChildren(), function(child){
+                       child.set("indent", indent+1);
+               });
 
-                       this.targetAnchor = newTarget;
-                       this.dropPosition = newDropPosition;
-               }
+               this._set("indent", indent);
        },
 
-       onMouseMove: function(e){
+       markProcessing: function(){
                // summary:
-               //              Called for any onmousemove events over the Tree
-               // e: Event
-               //              onmousemouse event
+               //              Visually denote that tree is loading data, etc.
                // tags:
                //              private
-               if(this.isDragging && this.targetState == "Disabled"){ return; }
-               this.inherited(arguments);
-               var m = dojo.dnd.manager();
-               if(this.isDragging){
-                       this._onDragMouse(e);
-               }else{
-                       if(this.mouseDown && this.isSource &&
-                                (Math.abs(e.pageX-this._lastX)>=this.dragThreshold || Math.abs(e.pageY-this._lastY)>=this.dragThreshold)){
-                               var n = this.getSelectedNodes();
-                               var nodes=[];
-                               for(var i in n){
-                                       nodes.push(n[i]);
-                               }
-                               if(nodes.length){
-                                       m.startDrag(this, nodes, this.copyState(dojo.isCopyKey(e)));
-                               }
-                       }
-               }
+               this.state = "LOADING";
+               this._setExpando(true);
        },
 
-       onMouseDown: function(e){
+       unmarkProcessing: function(){
                // summary:
-               //              Event processor for onmousedown
-               // e: Event
-               //              onmousedown event
+               //              Clear markup from markProcessing() call
                // tags:
                //              private
-               this.mouseDown = true;
-               this.mouseButton = e.button;
-               this._lastX = e.pageX;
-               this._lastY = e.pageY;
-               this.inherited("onMouseDown",arguments);
+               this._setExpando(false);
        },
 
-       onMouseUp: function(e){
+       _updateItemClasses: function(item){
                // summary:
-               //              Event processor for onmouseup
-               // e: Event
-               //              onmouseup event
+               //              Set appropriate CSS classes for icon and label dom node
+               //              (used to allow for item updates to change respective CSS)
                // tags:
                //              private
-               if(this.mouseDown){
-                       this.mouseDown = false;
-                       this.inherited("onMouseUp",arguments);
+               var tree = this.tree, model = tree.model;
+               if(tree._v10Compat && item === model.root){
+                       // For back-compat with 1.0, need to use null to specify root item (TODO: remove in 2.0)
+                       item = null;
                }
+               this._applyClassAndStyle(item, "icon", "Icon");
+               this._applyClassAndStyle(item, "label", "Label");
+               this._applyClassAndStyle(item, "row", "Row");
        },
 
-       onMouseOut: function(){
+       _applyClassAndStyle: function(item, lower, upper){
                // summary:
-               //              Event processor for when mouse is moved away from a TreeNode
+               //              Set the appropriate CSS classes and styles for labels, icons and rows.
+               //
+               // item:
+               //              The data item.
+               //
+               // lower:
+               //              The lower case attribute to use, e.g. 'icon', 'label' or 'row'.
+               //
+               // upper:
+               //              The upper case attribute to use, e.g. 'Icon', 'Label' or 'Row'.
+               //
                // tags:
                //              private
-               this.inherited(arguments);
-               this._unmarkTargetAnchor();
-       },
 
-       checkItemAcceptance: function(target, source, position){
-               // summary:
-               //              Stub function to be overridden if one wants to check for the ability to drop at the node/item level
-               // description:
-               //              In the base case, this is called to check if target can become a child of source.
-               //              When betweenThreshold is set, position="before" or "after" means that we
-               //              are asking if the source node can be dropped before/after the target node.
-               // target: DOMNode
-               //              The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
-               //              Use dijit.getEnclosingWidget(target) to get the TreeNode.
-               // source: dijit.tree.dndSource
-               //              The (set of) nodes we are dropping
-               // position: String
-               //              "over", "before", or "after"
-               // tags:
-               //              extension
-               return true;
-       },
+               var clsName = "_" + lower + "Class";
+               var nodeName = lower + "Node";
+               var oldCls = this[clsName];
 
-       // topic event processors
-       onDndSourceOver: function(source){
+               this[clsName] = this.tree["get" + upper + "Class"](item, this.isExpanded);
+               domClass.replace(this[nodeName], this[clsName] || "", oldCls || "");
+
+               domStyle.set(this[nodeName], this.tree["get" + upper + "Style"](item, this.isExpanded) || {});
+       },
+
+       _updateLayout: function(){
                // summary:
-               //              Topic event processor for /dnd/source/over, called when detected a current source.
-               // source: Object
-               //              The dijit.tree.dndSource / dojo.dnd.Source which has the mouse over it
+               //              Set appropriate CSS classes for this.domNode
                // tags:
                //              private
-               if(this != source){
-                       this.mouseDown = false;
-                       this._unmarkTargetAnchor();
-               }else if(this.isDragging){
-                       var m = dojo.dnd.manager();
-                       m.canDrop(false);
+               var parent = this.getParent();
+               if(!parent || !parent.rowNode || parent.rowNode.style.display == "none"){
+                       /* if we are hiding the root node then make every first level child look like a root node */
+                       domClass.add(this.domNode, "dijitTreeIsRoot");
+               }else{
+                       domClass.toggle(this.domNode, "dijitTreeIsLast", !this.getNextSibling());
                }
        },
-       onDndStart: function(source, nodes, copy){
+
+       _setExpando: function(/*Boolean*/ processing){
                // summary:
-               //              Topic event processor for /dnd/start, called to initiate the DnD operation
-               // source: Object
-               //              The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
-               // nodes: DomNode[]
-               //              The list of transferred items, dndTreeNode nodes if dragging from a Tree
-               // copy: Boolean
-               //              Copy items, if true, move items otherwise
+               //              Set the right image for the expando node
                // tags:
                //              private
 
-               if(this.isSource){
-                       this._changeState("Source", this == source ? (copy ? "Copied" : "Moved") : "");
+               var styles = ["dijitTreeExpandoLoading", "dijitTreeExpandoOpened",
+                                               "dijitTreeExpandoClosed", "dijitTreeExpandoLeaf"],
+                       _a11yStates = ["*","-","+","*"],
+                       idx = processing ? 0 : (this.isExpandable ?     (this.isExpanded ? 1 : 2) : 3);
+
+               // apply the appropriate class to the expando node
+               domClass.replace(this.expandoNode, styles[idx], styles);
+
+               // provide a non-image based indicator for images-off mode
+               this.expandoNodeText.innerHTML = _a11yStates[idx];
+
+       },
+
+       expand: function(){
+               // summary:
+               //              Show my children
+               // returns:
+               //              Deferred that fires when expansion is complete
+
+               // If there's already an expand in progress or we are already expanded, just return
+               if(this._expandDeferred){
+                       return this._expandDeferred;            // dojo.Deferred
                }
-               var accepted = this.checkAcceptance(source, nodes);
 
-               this._changeState("Target", accepted ? "" : "Disabled");
+               // cancel in progress collapse operation
+               this._wipeOut && this._wipeOut.stop();
 
-               if(this == source){
-                       dojo.dnd.manager().overSource(this);
+               // All the state information for when a node is expanded, maybe this should be
+               // set when the animation completes instead
+               this.isExpanded = true;
+               this.labelNode.setAttribute("aria-expanded", "true");
+               if(this.tree.showRoot || this !== this.tree.rootNode){
+                       this.containerNode.setAttribute("role", "group");
+               }
+               domClass.add(this.contentNode,'dijitTreeContentExpanded');
+               this._setExpando();
+               this._updateItemClasses(this.item);
+               if(this == this.tree.rootNode){
+                       this.tree.domNode.setAttribute("aria-expanded", "true");
                }
 
-               this.isDragging = true;
+               var def,
+                       wipeIn = fxUtils.wipeIn({
+                               node: this.containerNode, duration: manager.defaultDuration,
+                               onEnd: function(){
+                                       def.callback(true);
+                               }
+                       });
+
+               // Deferred that fires when expand is complete
+               def = (this._expandDeferred = new Deferred(function(){
+                       // Canceller
+                       wipeIn.stop();
+               }));
+
+               wipeIn.play();
+
+               return def;             // dojo.Deferred
        },
 
-       itemCreator: function(/*DomNode[]*/ nodes, target, /*dojo.dnd.Source*/ source){
+       collapse: function(){
                // summary:
-               //              Returns objects passed to `Tree.model.newItem()` based on DnD nodes
-               //              dropped onto the tree.   Developer must override this method to enable
-               //              dropping from external sources onto this Tree, unless the Tree.model's items
-               //              happen to look like {id: 123, name: "Apple" } with no other attributes.
-               // description:
-               //              For each node in nodes[], which came from source, create a hash of name/value
-               //              pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
-               // returns: Object[]
-               //              Array of name/value hashes for each new item to be added to the Tree, like:
-               // |    [
-               // |            { id: 123, label: "apple", foo: "bar" },
-               // |            { id: 456, label: "pear", zaz: "bam" }
-               // |    ]
-               // tags:
-               //              extension
+               //              Collapse this node (if it's expanded)
 
-               // TODO: for 2.0 refactor so itemCreator() is called once per drag node, and
-               // make signature itemCreator(sourceItem, node, target) (or similar).
+               if(!this.isExpanded){ return; }
 
-               return dojo.map(nodes, function(node){
-                       return {
-                               "id": node.id,
-                               "name": node.textContent || node.innerText || ""
-                       };
-               }); // Object[]
+               // cancel in progress expand operation
+               if(this._expandDeferred){
+                       this._expandDeferred.cancel();
+                       delete this._expandDeferred;
+               }
+
+               this.isExpanded = false;
+               this.labelNode.setAttribute("aria-expanded", "false");
+               if(this == this.tree.rootNode){
+                       this.tree.domNode.setAttribute("aria-expanded", "false");
+               }
+               domClass.remove(this.contentNode,'dijitTreeContentExpanded');
+               this._setExpando();
+               this._updateItemClasses(this.item);
+
+               if(!this._wipeOut){
+                       this._wipeOut = fxUtils.wipeOut({
+                               node: this.containerNode, duration: manager.defaultDuration
+                       });
+               }
+               this._wipeOut.play();
        },
 
-       onDndDrop: function(source, nodes, copy){
-               // summary:
-               //              Topic event processor for /dnd/drop, called to finish the DnD operation.
-               // description:
-               //              Updates data store items according to where node was dragged from and dropped
-               //              to.   The tree will then respond to those data store updates and redraw itself.
-               // source: Object
-               //              The dijit.tree.dndSource / dojo.dnd.Source which is providing the items
-               // nodes: DomNode[]
-               //              The list of transferred items, dndTreeNode nodes if dragging from a Tree
-               // copy: Boolean
-               //              Copy items, if true, move items otherwise
-               // tags:
-               //              protected
-               if(this.containerState == "Over"){
-                       var tree = this.tree,
-                               model = tree.model,
-                               target = this.targetAnchor,
-                               requeryRoot = false;    // set to true iff top level items change
+       // indent: Integer
+       //              Levels from this node to the root node
+       indent: 0,
 
-                       this.isDragging = false;
+       setChildItems: function(/* Object[] */ items){
+               // summary:
+               //              Sets the child items of this node, removing/adding nodes
+               //              from current children to match specified items[] array.
+               //              Also, if this.persist == true, expands any children that were previously
+               //              opened.
+               // returns:
+               //              Deferred object that fires after all previously opened children
+               //              have been expanded again (or fires instantly if there are no such children).
 
-                       // Compute the new parent item
-                       var targetWidget = dijit.getEnclosingWidget(target);
-                       var newParentItem;
-                       var insertIndex;
-                       newParentItem = (targetWidget && targetWidget.item) || tree.item;
-                       if(this.dropPosition == "Before" || this.dropPosition == "After"){
-                               // TODO: if there is no parent item then disallow the drop.
-                               // Actually this should be checked during onMouseMove too, to make the drag icon red.
-                               newParentItem = (targetWidget.getParent() && targetWidget.getParent().item) || tree.item;
-                               // Compute the insert index for reordering
-                               insertIndex = targetWidget.getIndexInParent();
-                               if(this.dropPosition == "After"){
-                                       insertIndex = targetWidget.getIndexInParent() + 1;
-                               }
-                       }else{
-                               newParentItem = (targetWidget && targetWidget.item) || tree.item;
-                       }
+               var tree = this.tree,
+                       model = tree.model,
+                       defs = [];      // list of deferreds that need to fire before I am complete
 
-                       // If necessary, use this variable to hold array of hashes to pass to model.newItem()
-                       // (one entry in the array for each dragged node).
-                       var newItemsParams;
 
-                       dojo.forEach(nodes, function(node, idx){
-                               // dojo.dnd.Item representing the thing being dropped.
-                               // Don't confuse the use of item here (meaning a DnD item) with the
-                               // uses below where item means dojo.data item.
-                               var sourceItem = source.getItem(node.id);
+               // Orphan all my existing children.
+               // If items contains some of the same items as before then we will reattach them.
+               // Don't call this.removeChild() because that will collapse the tree etc.
+               array.forEach(this.getChildren(), function(child){
+                       _Container.prototype.removeChild.call(this, child);
+               }, this);
 
-                               // Information that's available if the source is another Tree
-                               // (possibly but not necessarily this tree, possibly but not
-                               // necessarily the same model as this Tree)
-                               if(dojo.indexOf(sourceItem.type, "treeNode") != -1){
-                                       var childTreeNode = sourceItem.data,
-                                               childItem = childTreeNode.item,
-                                               oldParentItem = childTreeNode.getParent().item;
-                               }
+               this.state = "LOADED";
 
-                               if(source == this){
-                                       // This is a node from my own tree, and we are moving it, not copying.
-                                       // Remove item from old parent's children attribute.
-                                       // TODO: dijit.tree.dndSelector should implement deleteSelectedNodes()
-                                       // and this code should go there.
+               if(items && items.length > 0){
+                       this.isExpandable = true;
 
-                                       if(typeof insertIndex == "number"){
-                                               if(newParentItem == oldParentItem && childTreeNode.getIndexInParent() < insertIndex){
-                                                       insertIndex -= 1;
+                       // Create _TreeNode widget for each specified tree node, unless one already
+                       // exists and isn't being used (presumably it's from a DnD move and was recently
+                       // released
+                       array.forEach(items, function(item){
+                               var id = model.getIdentity(item),
+                                       existingNodes = tree._itemNodesMap[id],
+                                       node;
+                               if(existingNodes){
+                                       for(var i=0;i<existingNodes.length;i++){
+                                               if(existingNodes[i] && !existingNodes[i].getParent()){
+                                                       node = existingNodes[i];
+                                                       node.set('indent', this.indent+1);
+                                                       break;
                                                }
                                        }
-                                       model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
-                               }else if(model.isItem(childItem)){
-                                       // Item from same model
-                                       // (maybe we should only do this branch if the source is a tree?)
-                                       model.pasteItem(childItem, oldParentItem, newParentItem, copy, insertIndex);
-                               }else{
-                                       // Get the hash to pass to model.newItem().  A single call to
-                                       // itemCreator() returns an array of hashes, one for each drag source node.
-                                       if(!newItemsParams){
-                                               newItemsParams = this.itemCreator(nodes, target, source);
+                               }
+                               if(!node){
+                                       node = this.tree._createTreeNode({
+                                                       item: item,
+                                                       tree: tree,
+                                                       isExpandable: model.mayHaveChildren(item),
+                                                       label: tree.getLabel(item),
+                                                       tooltip: tree.getTooltip(item),
+                                                       dir: tree.dir,
+                                                       lang: tree.lang,
+                                                       textDir: tree.textDir,
+                                                       indent: this.indent + 1
+                                               });
+                                       if(existingNodes){
+                                               existingNodes.push(node);
+                                       }else{
+                                               tree._itemNodesMap[id] = [node];
                                        }
+                               }
+                               this.addChild(node);
 
-                                       // Create new item in the tree, based on the drag source.
-                                       model.newItem(newItemsParams[idx], newParentItem, insertIndex);
+                               // If node was previously opened then open it again now (this may trigger
+                               // more data store accesses, recursively)
+                               if(this.tree.autoExpand || this.tree._state(node)){
+                                       defs.push(tree._expandNode(node));
                                }
                        }, this);
 
-                       // Expand the target node (if it's currently collapsed) so the user can see
-                       // where their node was dropped.   In particular since that node is still selected.
-                       this.tree._expandNode(targetWidget);
-               }
-               this.onDndCancel();
+                       // note that updateLayout() needs to be called on each child after
+                       // _all_ the children exist
+                       array.forEach(this.getChildren(), function(child){
+                               child._updateLayout();
+                       });
+               }else{
+                       this.isExpandable=false;
+               }
+
+               if(this._setExpando){
+                       // change expando to/from dot or + icon, as appropriate
+                       this._setExpando(false);
+               }
+
+               // Set leaf icon or folder icon, as appropriate
+               this._updateItemClasses(this.item);
+
+               // On initial tree show, make the selected TreeNode as either the root node of the tree,
+               // or the first child, if the root node is hidden
+               if(this == tree.rootNode){
+                       var fc = this.tree.showRoot ? this : this.getChildren()[0];
+                       if(fc){
+                               fc.setFocusable(true);
+                               tree.lastFocused = fc;
+                       }else{
+                               // fallback: no nodes in tree so focus on Tree <div> itself
+                               tree.domNode.setAttribute("tabIndex", "0");
+                       }
+               }
+
+               return new DeferredList(defs);  // dojo.Deferred
+       },
+
+       getTreePath: function(){
+               var node = this;
+               var path = [];
+               while(node && node !== this.tree.rootNode){
+                               path.unshift(node.item);
+                               node = node.getParent();
+               }
+               path.unshift(this.tree.rootNode.item);
+
+               return path;
+       },
+
+       getIdentity: function(){
+               return this.tree.model.getIdentity(this.item);
+       },
+
+       removeChild: function(/* treeNode */ node){
+               this.inherited(arguments);
+
+               var children = this.getChildren();
+               if(children.length == 0){
+                       this.isExpandable = false;
+                       this.collapse();
+               }
+
+               array.forEach(children, function(child){
+                               child._updateLayout();
+               });
+       },
+
+       makeExpandable: function(){
+               // summary:
+               //              if this node wasn't already showing the expando node,
+               //              turn it into one and call _setExpando()
+
+               // TODO: hmm this isn't called from anywhere, maybe should remove it for 2.0
+
+               this.isExpandable = true;
+               this._setExpando(false);
        },
 
-       onDndCancel: function(){
+       _onLabelFocus: function(){
                // summary:
-               //              Topic event processor for /dnd/cancel, called to cancel the DnD operation
+               //              Called when this row is focused (possibly programatically)
+               //              Note that we aren't using _onFocus() builtin to dijit
+               //              because it's called when focus is moved to a descendant TreeNode.
                // tags:
                //              private
-               this._unmarkTargetAnchor();
-               this.isDragging = false;
-               this.mouseDown = false;
-               delete this.mouseButton;
-               this._changeState("Source", "");
-               this._changeState("Target", "");
+               this.tree._onNodeFocus(this);
        },
 
-       // When focus moves in/out of the entire Tree
-       onOverEvent: function(){
+       setSelected: function(/*Boolean*/ selected){
                // summary:
-               //              This method is called when mouse is moved over our container (like onmouseenter)
+               //              A Tree has a (single) currently selected node.
+               //              Mark that this node is/isn't that currently selected node.
+               // description:
+               //              In particular, setting a node as selected involves setting tabIndex
+               //              so that when user tabs to the tree, focus will go to that node (only).
+               this.labelNode.setAttribute("aria-selected", selected);
+               domClass.toggle(this.rowNode, "dijitTreeRowSelected", selected);
+       },
+
+       setFocusable: function(/*Boolean*/ selected){
+               // summary:
+               //              A Tree has a (single) node that's focusable.
+               //              Mark that this node is/isn't that currently focsuable node.
+               // description:
+               //              In particular, setting a node as selected involves setting tabIndex
+               //              so that when user tabs to the tree, focus will go to that node (only).
+
+               this.labelNode.setAttribute("tabIndex", selected ? "0" : "-1");
+       },
+
+       _onClick: function(evt){
+               // summary:
+               //              Handler for onclick event on a node
                // tags:
                //              private
-               this.inherited(arguments);
-               dojo.dnd.manager().overSource(this);
+               this.tree._onClick(this, evt);
        },
-       onOutEvent: function(){
+       _onDblClick: function(evt){
                // summary:
-               //              This method is called when mouse is moved out of our container (like onmouseleave)
+               //              Handler for ondblclick event on a node
                // tags:
                //              private
-               this._unmarkTargetAnchor();
-               var m = dojo.dnd.manager();
-               if(this.isDragging){
-                       m.canDrop(false);
-               }
-               m.outSource(this);
-
-               this.inherited(arguments);
+               this.tree._onDblClick(this, evt);
        },
 
-       _isParentChildDrop: function(source, targetRow){
+       _onMouseEnter: function(evt){
                // summary:
-               //              Checks whether the dragged items are parent rows in the tree which are being
-               //              dragged into their own children.
-               //
-               // source:
-               //              The DragSource object.
-               //
-               // targetRow:
-               //              The tree row onto which the dragged nodes are being dropped.
-               //
+               //              Handler for onmouseenter event on a node
                // tags:
                //              private
-
-               // If the dragged object is not coming from the tree this widget belongs to,
-               // it cannot be invalid.
-               if(!source.tree || source.tree != this.tree){
-                       return false;
-               }
-
-
-               var root = source.tree.domNode;
-               var ids = {};
-               for(var x in source.selection){
-                       ids[source.selection[x].parentNode.id] = true;
-               }
-
-               var node = targetRow.parentNode;
-
-               // Iterate up the DOM hierarchy from the target drop row,
-               // checking of any of the dragged nodes have the same ID.
-               while(node != root && (!node.id || !ids[node.id])){
-                       node = node.parentNode;
-               }
-
-               return node.id && ids[node.id];
+               this.tree._onNodeMouseEnter(this, evt);
        },
 
-       _unmarkTargetAnchor: function(){
+       _onMouseLeave: function(evt){
                // summary:
-               //              Removes hover class of the current target anchor
+               //              Handler for onmouseenter event on a node
                // tags:
                //              private
-               if(!this.targetAnchor){ return; }
-               this._removeItemClass(this.targetAnchor, this.dropPosition);
-               this.targetAnchor = null;
-               this.targetBox = null;
-               this.dropPosition = null;
+               this.tree._onNodeMouseLeave(this, evt);
        },
 
-       _markDndStatus: function(copy){
-               // summary:
-               //              Changes source's state based on "copy" status
-               this._changeState("Source", copy ? "Copied" : "Moved");
+       _setTextDirAttr: function(textDir){
+               if(textDir &&((this.textDir != textDir) || !this._created)){
+                       this._set("textDir", textDir);
+                       this.applyTextDir(this.labelNode, this.labelNode.innerText || this.labelNode.textContent || "");
+                       array.forEach(this.getChildren(), function(childNode){
+                               childNode.set("textDir", textDir);
+                       }, this);
+               }
        }
 });
 
-}
-
-if(!dojo._hasResource["dojo.data.ItemFileReadStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.data.ItemFileReadStore"] = true;
-dojo.provide("dojo.data.ItemFileReadStore");
-
+var Tree = declare("dijit.Tree", [_Widget, _TemplatedMixin], {
+       // summary:
+       //              This widget displays hierarchical data from a store.
 
+       // store: [deprecated] String||dojo.data.Store
+       //              Deprecated.  Use "model" parameter instead.
+       //              The store to get data to display in the tree.
+       store: null,
 
+       // model: dijit.Tree.model
+       //              Interface to read tree data, get notifications of changes to tree data,
+       //              and for handling drop operations (i.e drag and drop onto the tree)
+       model: null,
 
+       // query: [deprecated] anything
+       //              Deprecated.  User should specify query to the model directly instead.
+       //              Specifies datastore query to return the root item or top items for the tree.
+       query: null,
 
-dojo.declare("dojo.data.ItemFileReadStore", null,{
-       //      summary:
-       //              The ItemFileReadStore implements the dojo.data.api.Read API and reads
-       //              data from JSON files that have contents in this format --
-       //              { items: [
-       //                      { name:'Kermit', color:'green', age:12, friends:['Gonzo', {_reference:{name:'Fozzie Bear'}}]},
-       //                      { name:'Fozzie Bear', wears:['hat', 'tie']},
-       //                      { name:'Miss Piggy', pets:'Foo-Foo'}
-       //              ]}
-       //              Note that it can also contain an 'identifer' property that specified which attribute on the items 
-       //              in the array of items that acts as the unique identifier for that item.
-       //
-       constructor: function(/* Object */ keywordParameters){
-               //      summary: constructor
-               //      keywordParameters: {url: String}
-               //      keywordParameters: {data: jsonObject}
-               //      keywordParameters: {typeMap: object)
-               //              The structure of the typeMap object is as follows:
-               //              {
-               //                      type0: function || object,
-               //                      type1: function || object,
-               //                      ...
-               //                      typeN: function || object
-               //              }
-               //              Where if it is a function, it is assumed to be an object constructor that takes the 
-               //              value of _value as the initialization parameters.  If it is an object, then it is assumed
-               //              to be an object of general form:
-               //              {
-               //                      type: function, //constructor.
-               //                      deserialize:    function(value) //The function that parses the value and constructs the object defined by type appropriately.
-               //              }
-       
-               this._arrayOfAllItems = [];
-               this._arrayOfTopLevelItems = [];
-               this._loadFinished = false;
-               this._jsonFileUrl = keywordParameters.url;
-               this._ccUrl = keywordParameters.url;
-               this.url = keywordParameters.url;
-               this._jsonData = keywordParameters.data;
-               this.data = null;
-               this._datatypeMap = keywordParameters.typeMap || {};
-               if(!this._datatypeMap['Date']){
-                       //If no default mapping for dates, then set this as default.
-                       //We use the dojo.date.stamp here because the ISO format is the 'dojo way'
-                       //of generically representing dates.
-                       this._datatypeMap['Date'] = {
-                                                                                       type: Date,
-                                                                                       deserialize: function(value){
-                                                                                               return dojo.date.stamp.fromISOString(value);
-                                                                                       }
-                                                                               };
-               }
-               this._features = {'dojo.data.api.Read':true, 'dojo.data.api.Identity':true};
-               this._itemsByIdentity = null;
-               this._storeRefPropName = "_S"; // Default name for the store reference to attach to every item.
-               this._itemNumPropName = "_0"; // Default Item Id for isItem to attach to every item.
-               this._rootItemPropName = "_RI"; // Default Item Id for isItem to attach to every item.
-               this._reverseRefMap = "_RRM"; // Default attribute for constructing a reverse reference map for use with reference integrity
-               this._loadInProgress = false; //Got to track the initial load to prevent duelling loads of the dataset.
-               this._queuedFetches = [];
-               if(keywordParameters.urlPreventCache !== undefined){
-                       this.urlPreventCache = keywordParameters.urlPreventCache?true:false;
-               }
-               if(keywordParameters.hierarchical !== undefined){
-                       this.hierarchical = keywordParameters.hierarchical?true:false;
-               }
-               if(keywordParameters.clearOnClose){
-                       this.clearOnClose = true;
-               }
-               if("failOk" in keywordParameters){
-                       this.failOk = keywordParameters.failOk?true:false;
-               }
-       },
-       
-       url: "",        // use "" rather than undefined for the benefit of the parser (#3539)
+       // label: [deprecated] String
+       //              Deprecated.  Use dijit.tree.ForestStoreModel directly instead.
+       //              Used in conjunction with query parameter.
+       //              If a query is specified (rather than a root node id), and a label is also specified,
+       //              then a fake root node is created and displayed, with this label.
+       label: "",
 
-       //Internal var, crossCheckUrl.  Used so that setting either url or _jsonFileUrl, can still trigger a reload
-       //when clearOnClose and close is used.
-       _ccUrl: "",
+       // showRoot: [const] Boolean
+       //              Should the root node be displayed, or hidden?
+       showRoot: true,
 
-       data: null,     // define this so that the parser can populate it
+       // childrenAttr: [deprecated] String[]
+       //              Deprecated.   This information should be specified in the model.
+       //              One ore more attributes that holds children of a tree node
+       childrenAttr: ["children"],
 
-       typeMap: null, //Define so parser can populate.
-       
-       //Parameter to allow users to specify if a close call should force a reload or not.
-       //By default, it retains the old behavior of not clearing if close is called.  But
-       //if set true, the store will be reset to default state.  Note that by doing this,
-       //all item handles will become invalid and a new fetch must be issued.
-       clearOnClose: false,
+       // paths: String[][] or Item[][]
+       //              Full paths from rootNode to selected nodes expressed as array of items or array of ids.
+       //              Since setting the paths may be asynchronous (because ofwaiting on dojo.data), set("paths", ...)
+       //              returns a Deferred to indicate when the set is complete.
+       paths: [],
 
-       //Parameter to allow specifying if preventCache should be passed to the xhrGet call or not when loading data from a url.  
-       //Note this does not mean the store calls the server on each fetch, only that the data load has preventCache set as an option.
-       //Added for tracker: #6072
-       urlPreventCache: false,
-       
-       //Parameter for specifying that it is OK for the xhrGet call to fail silently.
-       failOk: false,
+       // path: String[] or Item[]
+       //      Backward compatible singular variant of paths.
+       path: [],
 
-       //Parameter to indicate to process data from the url as hierarchical 
-       //(data items can contain other data items in js form).  Default is true 
-       //for backwards compatibility.  False means only root items are processed 
-       //as items, all child objects outside of type-mapped objects and those in 
-       //specific reference format, are left straight JS data objects.
-       hierarchical: true,
+       // selectedItems: [readonly] Item[]
+       //              The currently selected items in this tree.
+       //              This property can only be set (via set('selectedItems', ...)) when that item is already
+       //              visible in the tree.   (I.e. the tree has already been expanded to show that node.)
+       //              Should generally use `paths` attribute to set the selected items instead.
+       selectedItems: null,
 
-       _assertIsItem: function(/* item */ item){
-               //      summary:
-               //              This function tests whether the item passed in is indeed an item in the store.
-               //      item: 
-               //              The item to test for being contained by the store.
-               if(!this.isItem(item)){ 
-                       throw new Error("dojo.data.ItemFileReadStore: Invalid item argument.");
-               }
-       },
+       // selectedItem: [readonly] Item
+       //      Backward compatible singular variant of selectedItems.
+       selectedItem: null,
 
-       _assertIsAttribute: function(/* attribute-name-string */ attribute){
-               //      summary:
-               //              This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
-               //      attribute: 
-               //              The attribute to test for being contained by the store.
-               if(typeof attribute !== "string"){ 
-                       throw new Error("dojo.data.ItemFileReadStore: Invalid attribute argument.");
-               }
-       },
+       // openOnClick: Boolean
+       //              If true, clicking a folder node's label will open it, rather than calling onClick()
+       openOnClick: false,
 
-       getValue: function(     /* item */ item, 
-                                               /* attribute-name-string */ attribute, 
-                                               /* value? */ defaultValue){
-               //      summary: 
-               //              See dojo.data.api.Read.getValue()
-               var values = this.getValues(item, attribute);
-               return (values.length > 0)?values[0]:defaultValue; // mixed
-       },
+       // openOnDblClick: Boolean
+       //              If true, double-clicking a folder node's label will open it, rather than calling onDblClick()
+       openOnDblClick: false,
 
-       getValues: function(/* item */ item, 
-                                               /* attribute-name-string */ attribute){
-               //      summary: 
-               //              See dojo.data.api.Read.getValues()
+       templateString: treeTemplate,
 
-               this._assertIsItem(item);
-               this._assertIsAttribute(attribute);
-               // Clone it before returning.  refs: #10474
-               return (item[attribute] || []).slice(0); // Array
-       },
+       // persist: Boolean
+       //              Enables/disables use of cookies for state saving.
+       persist: true,
 
-       getAttributes: function(/* item */ item){
-               //      summary: 
-               //              See dojo.data.api.Read.getAttributes()
-               this._assertIsItem(item);
-               var attributes = [];
-               for(var key in item){
-                       // Save off only the real item attributes, not the special id marks for O(1) isItem.
-                       if((key !== this._storeRefPropName) && (key !== this._itemNumPropName) && (key !== this._rootItemPropName) && (key !== this._reverseRefMap)){
-                               attributes.push(key);
-                       }
-               }
-               return attributes; // Array
-       },
+       // autoExpand: Boolean
+       //              Fully expand the tree on load.   Overrides `persist`.
+       autoExpand: false,
 
-       hasAttribute: function( /* item */ item,
-                                                       /* attribute-name-string */ attribute){
-               //      summary: 
-               //              See dojo.data.api.Read.hasAttribute()
-               this._assertIsItem(item);
-               this._assertIsAttribute(attribute);
-               return (attribute in item);
-       },
+       // dndController: [protected] Function|String
+       //              Class to use as as the dnd controller.  Specifying this class enables DnD.
+       //              Generally you should specify this as dijit.tree.dndSource.
+       //      Setting of dijit.tree._dndSelector handles selection only (no actual DnD).
+       dndController: _dndSelector,
 
-       containsValue: function(/* item */ item, 
-                                                       /* attribute-name-string */ attribute, 
-                                                       /* anything */ value){
-               //      summary: 
-               //              See dojo.data.api.Read.containsValue()
-               var regexp = undefined;
-               if(typeof value === "string"){
-                       regexp = dojo.data.util.filter.patternToRegExp(value, false);
-               }
-               return this._containsValue(item, attribute, value, regexp); //boolean.
-       },
+       // parameters to pull off of the tree and pass on to the dndController as its params
+       dndParams: ["onDndDrop","itemCreator","onDndCancel","checkAcceptance", "checkItemAcceptance", "dragThreshold", "betweenThreshold"],
 
-       _containsValue: function(       /* item */ item, 
-                                                               /* attribute-name-string */ attribute, 
-                                                               /* anything */ value,
-                                                               /* RegExp?*/ regexp){
-               //      summary: 
-               //              Internal function for looking at the values contained by the item.
-               //      description: 
-               //              Internal function for looking at the values contained by the item.  This 
-               //              function allows for denoting if the comparison should be case sensitive for
-               //              strings or not (for handling filtering cases where string case should not matter)
-               //      
-               //      item:
-               //              The data item to examine for attribute values.
-               //      attribute:
-               //              The attribute to inspect.
-               //      value:  
-               //              The value to match.
-               //      regexp:
-               //              Optional regular expression generated off value if value was of string type to handle wildcarding.
-               //              If present and attribute values are string, then it can be used for comparison instead of 'value'
-               return dojo.some(this.getValues(item, attribute), function(possibleValue){
-                       if(possibleValue !== null && !dojo.isObject(possibleValue) && regexp){
-                               if(possibleValue.toString().match(regexp)){
-                                       return true; // Boolean
-                               }
-                       }else if(value === possibleValue){
-                               return true; // Boolean
-                       }
-               });
-       },
+       //declare the above items so they can be pulled from the tree's markup
 
-       isItem: function(/* anything */ something){
-               //      summary: 
-               //              See dojo.data.api.Read.isItem()
-               if(something && something[this._storeRefPropName] === this){
-                       if(this._arrayOfAllItems[something[this._itemNumPropName]] === something){
-                               return true;
-                       }
-               }
-               return false; // Boolean
-       },
+       // onDndDrop: [protected] Function
+       //              Parameter to dndController, see `dijit.tree.dndSource.onDndDrop`.
+       //              Generally this doesn't need to be set.
+       onDndDrop: null,
 
-       isItemLoaded: function(/* anything */ something){
-               //      summary: 
-               //              See dojo.data.api.Read.isItemLoaded()
-               return this.isItem(something); //boolean
+       /*=====
+       itemCreator: function(nodes, target, source){
+               // summary:
+               //              Returns objects passed to `Tree.model.newItem()` based on DnD nodes
+               //              dropped onto the tree.   Developer must override this method to enable
+               //              dropping from external sources onto this Tree, unless the Tree.model's items
+               //              happen to look like {id: 123, name: "Apple" } with no other attributes.
+               // description:
+               //              For each node in nodes[], which came from source, create a hash of name/value
+               //              pairs to be passed to Tree.model.newItem().  Returns array of those hashes.
+               // nodes: DomNode[]
+               //              The DOMNodes dragged from the source container
+               // target: DomNode
+               //              The target TreeNode.rowNode
+               // source: dojo.dnd.Source
+               //              The source container the nodes were dragged from, perhaps another Tree or a plain dojo.dnd.Source
+               // returns: Object[]
+               //              Array of name/value hashes for each new item to be added to the Tree, like:
+               // |    [
+               // |            { id: 123, label: "apple", foo: "bar" },
+               // |            { id: 456, label: "pear", zaz: "bam" }
+               // |    ]
+               // tags:
+               //              extension
+               return [{}];
        },
+       =====*/
+       itemCreator: null,
 
-       loadItem: function(/* object */ keywordArgs){
-               //      summary: 
-               //              See dojo.data.api.Read.loadItem()
-               this._assertIsItem(keywordArgs.item);
-       },
+       // onDndCancel: [protected] Function
+       //              Parameter to dndController, see `dijit.tree.dndSource.onDndCancel`.
+       //              Generally this doesn't need to be set.
+       onDndCancel: null,
 
-       getFeatures: function(){
-               //      summary: 
-               //              See dojo.data.api.Read.getFeatures()
-               return this._features; //Object
+/*=====
+       checkAcceptance: function(source, nodes){
+               // summary:
+               //              Checks if the Tree itself can accept nodes from this source
+               // source: dijit.tree._dndSource
+               //              The source which provides items
+               // nodes: DOMNode[]
+               //              Array of DOM nodes corresponding to nodes being dropped, dijitTreeRow nodes if
+               //              source is a dijit.Tree.
+               // tags:
+               //              extension
+               return true;    // Boolean
        },
+=====*/
+       checkAcceptance: null,
 
-       getLabel: function(/* item */ item){
-               //      summary: 
-               //              See dojo.data.api.Read.getLabel()
-               if(this._labelAttr && this.isItem(item)){
-                       return this.getValue(item,this._labelAttr); //String
-               }
-               return undefined; //undefined
+/*=====
+       checkItemAcceptance: function(target, source, position){
+               // summary:
+               //              Stub function to be overridden if one wants to check for the ability to drop at the node/item level
+               // description:
+               //              In the base case, this is called to check if target can become a child of source.
+               //              When betweenThreshold is set, position="before" or "after" means that we
+               //              are asking if the source node can be dropped before/after the target node.
+               // target: DOMNode
+               //              The dijitTreeRoot DOM node inside of the TreeNode that we are dropping on to
+               //              Use dijit.getEnclosingWidget(target) to get the TreeNode.
+               // source: dijit.tree.dndSource
+               //              The (set of) nodes we are dropping
+               // position: String
+               //              "over", "before", or "after"
+               // tags:
+               //              extension
+               return true;    // Boolean
        },
+=====*/
+       checkItemAcceptance: null,
 
-       getLabelAttributes: function(/* item */ item){
-               //      summary: 
-               //              See dojo.data.api.Read.getLabelAttributes()
-               if(this._labelAttr){
-                       return [this._labelAttr]; //array
-               }
-               return null; //null
-       },
+       // dragThreshold: Integer
+       //              Number of pixels mouse moves before it's considered the start of a drag operation
+       dragThreshold: 5,
 
-       _fetchItems: function(  /* Object */ keywordArgs, 
-                                                       /* Function */ findCallback, 
-                                                       /* Function */ errorCallback){
-               //      summary: 
-               //              See dojo.data.util.simpleFetch.fetch()
-               var self = this,
-                   filter = function(requestArgs, arrayOfItems){
-                       var items = [],
-                           i, key;
-                       if(requestArgs.query){
-                               var value,
-                                   ignoreCase = requestArgs.queryOptions ? requestArgs.queryOptions.ignoreCase : false;
+       // betweenThreshold: Integer
+       //              Set to a positive value to allow drag and drop "between" nodes.
+       //
+       //              If during DnD mouse is over a (target) node but less than betweenThreshold
+       //              pixels from the bottom edge, dropping the the dragged node will make it
+       //              the next sibling of the target node, rather than the child.
+       //
+       //              Similarly, if mouse is over a target node but less that betweenThreshold
+       //              pixels from the top edge, dropping the dragged node will make it
+       //              the target node's previous sibling rather than the target node's child.
+       betweenThreshold: 0,
 
-                               //See if there are any string values that can be regexp parsed first to avoid multiple regexp gens on the
-                               //same value for each item examined.  Much more efficient.
-                               var regexpList = {};
-                               for(key in requestArgs.query){
-                                       value = requestArgs.query[key];
-                                       if(typeof value === "string"){
-                                               regexpList[key] = dojo.data.util.filter.patternToRegExp(value, ignoreCase);
-                                       }else if(value instanceof RegExp){
-                                               regexpList[key] = value;
-                                       }
-                               }
-                               for(i = 0; i < arrayOfItems.length; ++i){
-                                       var match = true;
-                                       var candidateItem = arrayOfItems[i];
-                                       if(candidateItem === null){
-                                               match = false;
-                                       }else{
-                                               for(key in requestArgs.query){
-                                                       value = requestArgs.query[key];
-                                                       if(!self._containsValue(candidateItem, key, value, regexpList[key])){
-                                                               match = false;
-                                                       }
-                                               }
-                                       }
-                                       if(match){
-                                               items.push(candidateItem);
-                                       }
-                               }
-                               findCallback(items, requestArgs);
-                       }else{
-                               // We want a copy to pass back in case the parent wishes to sort the array. 
-                               // We shouldn't allow resort of the internal list, so that multiple callers 
-                               // can get lists and sort without affecting each other.  We also need to
-                               // filter out any null values that have been left as a result of deleteItem()
-                               // calls in ItemFileWriteStore.
-                               for(i = 0; i < arrayOfItems.length; ++i){
-                                       var item = arrayOfItems[i];
-                                       if(item !== null){
-                                               items.push(item);
-                                       }
-                               }
-                               findCallback(items, requestArgs);
-                       }
-               };
+       // _nodePixelIndent: Integer
+       //              Number of pixels to indent tree nodes (relative to parent node).
+       //              Default is 19 but can be overridden by setting CSS class dijitTreeIndent
+       //              and calling resize() or startup() on tree after it's in the DOM.
+       _nodePixelIndent: 19,
 
-               if(this._loadFinished){
-                       filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
-               }else{
-                       //Do a check on the JsonFileUrl and crosscheck it.
-                       //If it doesn't match the cross-check, it needs to be updated
-                       //This allows for either url or _jsonFileUrl to he changed to
-                       //reset the store load location.  Done this way for backwards 
-                       //compatibility.  People use _jsonFileUrl (even though officially
-                       //private.
-                       if(this._jsonFileUrl !== this._ccUrl){
-                               dojo.deprecated("dojo.data.ItemFileReadStore: ", 
-                                       "To change the url, set the url property of the store," +
-                                       " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-                               this._ccUrl = this._jsonFileUrl;
-                               this.url = this._jsonFileUrl;
-                       }else if(this.url !== this._ccUrl){
-                               this._jsonFileUrl = this.url;
-                               this._ccUrl = this.url;
-                       }
+       _publish: function(/*String*/ topicName, /*Object*/ message){
+               // summary:
+               //              Publish a message for this widget/topic
+               topic.publish(this.id, lang.mixin({tree: this, event: topicName}, message || {}));      // publish
+       },
+
+       postMixInProperties: function(){
+               this.tree = this;
 
-                       //See if there was any forced reset of data.
-                       if(this.data != null && this._jsonData == null){
-                               this._jsonData = this.data;
-                               this.data = null;
-                       }
+               if(this.autoExpand){
+                       // There's little point in saving opened/closed state of nodes for a Tree
+                       // that initially opens all it's nodes.
+                       this.persist = false;
+               }
 
-                       if(this._jsonFileUrl){
-                               //If fetches come in before the loading has finished, but while
-                               //a load is in progress, we have to defer the fetching to be 
-                               //invoked in the callback.
-                               if(this._loadInProgress){
-                                       this._queuedFetches.push({args: keywordArgs, filter: filter});
-                               }else{
-                                       this._loadInProgress = true;
-                                       var getArgs = {
-                                                       url: self._jsonFileUrl, 
-                                                       handleAs: "json-comment-optional",
-                                                       preventCache: this.urlPreventCache,
-                                                       failOk: this.failOk
-                                               };
-                                       var getHandler = dojo.xhrGet(getArgs);
-                                       getHandler.addCallback(function(data){
-                                               try{
-                                                       self._getItemsFromLoadedData(data);
-                                                       self._loadFinished = true;
-                                                       self._loadInProgress = false;
-                                                       
-                                                       filter(keywordArgs, self._getItemsArray(keywordArgs.queryOptions));
-                                                       self._handleQueuedFetches();
-                                               }catch(e){
-                                                       self._loadFinished = true;
-                                                       self._loadInProgress = false;
-                                                       errorCallback(e, keywordArgs);
-                                               }
-                                       });
-                                       getHandler.addErrback(function(error){
-                                               self._loadInProgress = false;
-                                               errorCallback(error, keywordArgs);
-                                       });
+               this._itemNodesMap={};
 
-                                       //Wire up the cancel to abort of the request
-                                       //This call cancel on the deferred if it hasn't been called
-                                       //yet and then will chain to the simple abort of the
-                                       //simpleFetch keywordArgs
-                                       var oldAbort = null;
-                                       if(keywordArgs.abort){
-                                               oldAbort = keywordArgs.abort;
-                                       }
-                                       keywordArgs.abort = function(){
-                                               var df = getHandler;
-                                               if(df && df.fired === -1){
-                                                       df.cancel();
-                                                       df = null;
-                                               }
-                                               if(oldAbort){
-                                                       oldAbort.call(keywordArgs);
-                                               }
-                                       };
-                               }
-                       }else if(this._jsonData){
-                               try{
-                                       this._loadFinished = true;
-                                       this._getItemsFromLoadedData(this._jsonData);
-                                       this._jsonData = null;
-                                       filter(keywordArgs, this._getItemsArray(keywordArgs.queryOptions));
-                               }catch(e){
-                                       errorCallback(e, keywordArgs);
-                               }
-                       }else{
-                               errorCallback(new Error("dojo.data.ItemFileReadStore: No JSON source data was provided as either URL or a nested Javascript object."), keywordArgs);
-                       }
+               if(!this.cookieName && this.id){
+                       this.cookieName = this.id + "SaveStateCookie";
                }
+
+               this._loadDeferred = new Deferred();
+
+               this.inherited(arguments);
        },
 
-       _handleQueuedFetches: function(){
-               //      summary: 
-               //              Internal function to execute delayed request in the store.
-               //Execute any deferred fetches now.
-               if(this._queuedFetches.length > 0){
-                       for(var i = 0; i < this._queuedFetches.length; i++){
-                               var fData = this._queuedFetches[i],
-                                   delayedQuery = fData.args,
-                                   delayedFilter = fData.filter;
-                               if(delayedFilter){
-                                       delayedFilter(delayedQuery, this._getItemsArray(delayedQuery.queryOptions)); 
-                               }else{
-                                       this.fetchItemByIdentity(delayedQuery);
+       postCreate: function(){
+               this._initState();
+
+               // Create glue between store and Tree, if not specified directly by user
+               if(!this.model){
+                       this._store2model();
+               }
+
+               // monitor changes to items
+               this.connect(this.model, "onChange", "_onItemChange");
+               this.connect(this.model, "onChildrenChange", "_onItemChildrenChange");
+               this.connect(this.model, "onDelete", "_onItemDelete");
+
+               this._load();
+
+               this.inherited(arguments);
+
+               if(this.dndController){
+                       if(lang.isString(this.dndController)){
+                               this.dndController = lang.getObject(this.dndController);
+                       }
+                       var params={};
+                       for(var i=0; i<this.dndParams.length;i++){
+                               if(this[this.dndParams[i]]){
+                                       params[this.dndParams[i]] = this[this.dndParams[i]];
                                }
                        }
-                       this._queuedFetches = [];
+                       this.dndController = new this.dndController(this, params);
                }
        },
 
-       _getItemsArray: function(/*object?*/queryOptions){
-               //      summary: 
-               //              Internal function to determine which list of items to search over.
-               //      queryOptions: The query options parameter, if any.
-               if(queryOptions && queryOptions.deep){
-                       return this._arrayOfAllItems; 
+       _store2model: function(){
+               // summary:
+               //              User specified a store&query rather than model, so create model from store/query
+               this._v10Compat = true;
+               kernel.deprecated("Tree: from version 2.0, should specify a model object rather than a store/query");
+
+               var modelParams = {
+                       id: this.id + "_ForestStoreModel",
+                       store: this.store,
+                       query: this.query,
+                       childrenAttrs: this.childrenAttr
+               };
+
+               // Only override the model's mayHaveChildren() method if the user has specified an override
+               if(this.params.mayHaveChildren){
+                       modelParams.mayHaveChildren = lang.hitch(this, "mayHaveChildren");
                }
-               return this._arrayOfTopLevelItems;
-       },
 
-       close: function(/*dojo.data.api.Request || keywordArgs || null */ request){
-                //     summary: 
-                //             See dojo.data.api.Read.close()
-                if(this.clearOnClose && 
-                       this._loadFinished && 
-                       !this._loadInProgress){
-                        //Reset all internalsback to default state.  This will force a reload
-                        //on next fetch.  This also checks that the data or url param was set 
-                        //so that the store knows it can get data.  Without one of those being set,
-                        //the next fetch will trigger an error.
+               if(this.params.getItemChildren){
+                       modelParams.getChildren = lang.hitch(this, function(item, onComplete, onError){
+                               this.getItemChildren((this._v10Compat && item === this.model.root) ? null : item, onComplete, onError);
+                       });
+               }
+               this.model = new ForestStoreModel(modelParams);
 
-                        if(((this._jsonFileUrl == "" || this._jsonFileUrl == null) && 
-                                (this.url == "" || this.url == null)
-                               ) && this.data == null){
-                                console.debug("dojo.data.ItemFileReadStore: WARNING!  Data reload " +
-                                       " information has not been provided." + 
-                                       "  Please set 'url' or 'data' to the appropriate value before" +
-                                       " the next fetch");
-                        }
-                        this._arrayOfAllItems = [];
-                        this._arrayOfTopLevelItems = [];
-                        this._loadFinished = false;
-                        this._itemsByIdentity = null;
-                        this._loadInProgress = false;
-                        this._queuedFetches = [];
-                }
+               // For backwards compatibility, the visibility of the root node is controlled by
+               // whether or not the user has specified a label
+               this.showRoot = Boolean(this.label);
        },
 
-       _getItemsFromLoadedData: function(/* Object */ dataObject){
-               //      summary:
-               //              Function to parse the loaded data into item format and build the internal items array.
-               //      description:
-               //              Function to parse the loaded data into item format and build the internal items array.
-               //
-               //      dataObject:
-               //              The JS data object containing the raw data to convery into item format.
-               //
-               //      returns: array
-               //              Array of items in store item format.
-               
-               // First, we define a couple little utility functions...
-               var addingArrays = false,
-                   self = this;
-               
-               function valueIsAnItem(/* anything */ aValue){
-                       // summary:
-                       //              Given any sort of value that could be in the raw json data,
-                       //              return true if we should interpret the value as being an
-                       //              item itself, rather than a literal value or a reference.
-                       // example:
-                       //      |       false == valueIsAnItem("Kermit");
-                       //      |       false == valueIsAnItem(42);
-                       //      |       false == valueIsAnItem(new Date());
-                       //      |       false == valueIsAnItem({_type:'Date', _value:'May 14, 1802'});
-                       //      |       false == valueIsAnItem({_reference:'Kermit'});
-                       //      |       true == valueIsAnItem({name:'Kermit', color:'green'});
-                       //      |       true == valueIsAnItem({iggy:'pop'});
-                       //      |       true == valueIsAnItem({foo:42});
-                       var isItem = (
-                               (aValue !== null) &&
-                               (typeof aValue === "object") &&
-                               (!dojo.isArray(aValue) || addingArrays) &&
-                               (!dojo.isFunction(aValue)) &&
-                               (aValue.constructor == Object || dojo.isArray(aValue)) &&
-                               (typeof aValue._reference === "undefined") && 
-                               (typeof aValue._type === "undefined") && 
-                               (typeof aValue._value === "undefined") &&
-                               self.hierarchical
-                       );
-                       return isItem;
-               }
-               
-               function addItemAndSubItemsToArrayOfAllItems(/* Item */ anItem){
-                       self._arrayOfAllItems.push(anItem);
-                       for(var attribute in anItem){
-                               var valueForAttribute = anItem[attribute];
-                               if(valueForAttribute){
-                                       if(dojo.isArray(valueForAttribute)){
-                                               var valueArray = valueForAttribute;
-                                               for(var k = 0; k < valueArray.length; ++k){
-                                                       var singleValue = valueArray[k];
-                                                       if(valueIsAnItem(singleValue)){
-                                                               addItemAndSubItemsToArrayOfAllItems(singleValue);
-                                                       }
-                                               }
-                                       }else{
-                                               if(valueIsAnItem(valueForAttribute)){
-                                                       addItemAndSubItemsToArrayOfAllItems(valueForAttribute);
-                                               }
-                                       }
+       onLoad: function(){
+               // summary:
+               //              Called when tree finishes loading and expanding.
+               // description:
+               //              If persist == true the loading may encompass many levels of fetches
+               //              from the data store, each asynchronous.   Waits for all to finish.
+               // tags:
+               //              callback
+       },
+
+       _load: function(){
+               // summary:
+               //              Initial load of the tree.
+               //              Load root node (possibly hidden) and it's children.
+               this.model.getRoot(
+                       lang.hitch(this, function(item){
+                               var rn = (this.rootNode = this.tree._createTreeNode({
+                                       item: item,
+                                       tree: this,
+                                       isExpandable: true,
+                                       label: this.label || this.getLabel(item),
+                                       textDir: this.textDir,
+                                       indent: this.showRoot ? 0 : -1
+                               }));
+                               if(!this.showRoot){
+                                       rn.rowNode.style.display="none";
+                                       // if root is not visible, move tree role to the invisible
+                                       // root node's containerNode, see #12135
+                                       this.domNode.setAttribute("role", "presentation");
+
+                                       rn.labelNode.setAttribute("role", "presentation");
+                                       rn.containerNode.setAttribute("role", "tree");
+                               }
+                               this.domNode.appendChild(rn.domNode);
+                               var identity = this.model.getIdentity(item);
+                               if(this._itemNodesMap[identity]){
+                                       this._itemNodesMap[identity].push(rn);
+                               }else{
+                                       this._itemNodesMap[identity] = [rn];
                                }
+
+                               rn._updateLayout();             // sets "dijitTreeIsRoot" CSS classname
+
+                               // load top level children and then fire onLoad() event
+                               this._expandNode(rn).addCallback(lang.hitch(this, function(){
+                                       this._loadDeferred.callback(true);
+                                       this.onLoad();
+                               }));
+                       }),
+                       function(err){
+                               console.error(this, ": error loading root: ", err);
                        }
-               }
+               );
+       },
+
+       getNodesByItem: function(/*Item or id*/ item){
+               // summary:
+               //              Returns all tree nodes that refer to an item
+               // returns:
+               //              Array of tree nodes that refer to passed item
 
-               this._labelAttr = dataObject.label;
+               if(!item){ return []; }
+               var identity = lang.isString(item) ? item : this.model.getIdentity(item);
+               // return a copy so widget don't get messed up by changes to returned array
+               return [].concat(this._itemNodesMap[identity]);
+       },
 
-               // We need to do some transformations to convert the data structure
-               // that we read from the file into a format that will be convenient
-               // to work with in memory.
+       _setSelectedItemAttr: function(/*Item or id*/ item){
+               this.set('selectedItems', [item]);
+       },
 
-               // Step 1: Walk through the object hierarchy and build a list of all items
-               var i,
-                   item;
-               this._arrayOfAllItems = [];
-               this._arrayOfTopLevelItems = dataObject.items;
+       _setSelectedItemsAttr: function(/*Items or ids*/ items){
+               // summary:
+               //              Select tree nodes related to passed items.
+               //              WARNING: if model use multi-parented items or desired tree node isn't already loaded
+               //              behavior is undefined. Use set('paths', ...) instead.
+               var tree = this;
+               this._loadDeferred.addCallback( lang.hitch(this, function(){
+                       var identities = array.map(items, function(item){
+                               return (!item || lang.isString(item)) ? item : tree.model.getIdentity(item);
+                       });
+                       var nodes = [];
+                       array.forEach(identities, function(id){
+                               nodes = nodes.concat(tree._itemNodesMap[id] || []);
+                       });
+                       this.set('selectedNodes', nodes);
+               }));
+       },
 
-               for(i = 0; i < this._arrayOfTopLevelItems.length; ++i){
-                       item = this._arrayOfTopLevelItems[i];
-                       if(dojo.isArray(item)){
-                               addingArrays = true;
-                       }
-                       addItemAndSubItemsToArrayOfAllItems(item);
-                       item[this._rootItemPropName]=true;
+       _setPathAttr: function(/*Item[] || String[]*/ path){
+               // summary:
+               //      Singular variant of _setPathsAttr
+               if(path.length){
+                       return this.set("paths", [path]);
+               }else{
+                       // Empty list is interpreted as "select nothing"
+                       return this.set("paths", []);
                }
+       },
 
-               // Step 2: Walk through all the attribute values of all the items, 
-               // and replace single values with arrays.  For example, we change this:
-               //              { name:'Miss Piggy', pets:'Foo-Foo'}
-               // into this:
-               //              { name:['Miss Piggy'], pets:['Foo-Foo']}
-               // 
-               // We also store the attribute names so we can validate our store  
-               // reference and item id special properties for the O(1) isItem
-               var allAttributeNames = {},
-                   key;
+       _setPathsAttr: function(/*Item[][] || String[][]*/ paths){
+               // summary:
+               //              Select the tree nodes identified by passed paths.
+               // paths:
+               //              Array of arrays of items or item id's
+               // returns:
+               //              Deferred to indicate when the set is complete
+               var tree = this;
 
-               for(i = 0; i < this._arrayOfAllItems.length; ++i){
-                       item = this._arrayOfAllItems[i];
-                       for(key in item){
-                               if(key !== this._rootItemPropName){
-                                       var value = item[key];
-                                       if(value !== null){
-                                               if(!dojo.isArray(value)){
-                                                       item[key] = [value];
-                                               }
-                                       }else{
-                                               item[key] = [null];
-                                       }
-                               }
-                               allAttributeNames[key]=key;
-                       }
-               }
+               // We may need to wait for some nodes to expand, so setting
+               // each path will involve a Deferred. We bring those deferreds
+               // together witha DeferredList.
+               return new DeferredList(array.map(paths, function(path){
+                       var d = new Deferred();
 
-               // Step 3: Build unique property names to use for the _storeRefPropName and _itemNumPropName
-               // This should go really fast, it will generally never even run the loop.
-               while(allAttributeNames[this._storeRefPropName]){
-                       this._storeRefPropName += "_";
-               }
-               while(allAttributeNames[this._itemNumPropName]){
-                       this._itemNumPropName += "_";
-               }
-               while(allAttributeNames[this._reverseRefMap]){
-                       this._reverseRefMap += "_";
-               }
+                       // normalize path to use identity
+                       path = array.map(path, function(item){
+                               return lang.isString(item) ? item : tree.model.getIdentity(item);
+                       });
 
-               // Step 4: Some data files specify an optional 'identifier', which is 
-               // the name of an attribute that holds the identity of each item. 
-               // If this data file specified an identifier attribute, then build a 
-               // hash table of items keyed by the identity of the items.
-               var arrayOfValues;
+                       if(path.length){
+                               // Wait for the tree to load, if it hasn't already.
+                               tree._loadDeferred.addCallback(function(){ selectPath(path, [tree.rootNode], d); });
+                       }else{
+                               d.errback("Empty path");
+                       }
+                       return d;
+               })).addCallback(setNodes);
 
-               var identifier = dataObject.identifier;
-               if(identifier){
-                       this._itemsByIdentity = {};
-                       this._features['dojo.data.api.Identity'] = identifier;
-                       for(i = 0; i < this._arrayOfAllItems.length; ++i){
-                               item = this._arrayOfAllItems[i];
-                               arrayOfValues = item[identifier];
-                               var identity = arrayOfValues[0];
-                               if(!this._itemsByIdentity[identity]){
-                                       this._itemsByIdentity[identity] = item;
+               function selectPath(path, nodes, def){
+                       // Traverse path; the next path component should be among "nodes".
+                       var nextPath = path.shift();
+                       var nextNode = array.filter(nodes, function(node){
+                               return node.getIdentity() == nextPath;
+                       })[0];
+                       if(!!nextNode){
+                               if(path.length){
+                                       tree._expandNode(nextNode).addCallback(function(){ selectPath(path, nextNode.getChildren(), def); });
                                }else{
-                                       if(this._jsonFileUrl){
-                                               throw new Error("dojo.data.ItemFileReadStore:  The json data as specified by: [" + this._jsonFileUrl + "] is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
-                                       }else if(this._jsonData){
-                                               throw new Error("dojo.data.ItemFileReadStore:  The json data provided by the creation arguments is malformed.  Items within the list have identifier: [" + identifier + "].  Value collided: [" + identity + "]");
-                                       }
+                                       //Successfully reached the end of this path
+                                       def.callback(nextNode);
                                }
+                       }else{
+                               def.errback("Could not expand path at " + nextPath);
                        }
-               }else{
-                       this._features['dojo.data.api.Identity'] = Number;
                }
 
-               // Step 5: Walk through all the items, and set each item's properties 
-               // for _storeRefPropName and _itemNumPropName, so that store.isItem() will return true.
-               for(i = 0; i < this._arrayOfAllItems.length; ++i){
-                       item = this._arrayOfAllItems[i];
-                       item[this._storeRefPropName] = this;
-                       item[this._itemNumPropName] = i;
+               function setNodes(newNodes){
+                       //After all expansion is finished, set the selection to
+                       //the set of nodes successfully found.
+                       tree.set("selectedNodes", array.map(
+                               array.filter(newNodes,function(x){return x[0];}),
+                               function(x){return x[1];}));
                }
+       },
 
-               // Step 6: We walk through all the attribute values of all the items,
-               // looking for type/value literals and item-references.
-               //
-               // We replace item-references with pointers to items.  For example, we change:
-               //              { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
-               // into this:
-               //              { name:['Kermit'], friends:[miss_piggy] } 
-               // (where miss_piggy is the object representing the 'Miss Piggy' item).
+       _setSelectedNodeAttr: function(node){
+               this.set('selectedNodes', [node]);
+       },
+       _setSelectedNodesAttr: function(nodes){
+               this._loadDeferred.addCallback( lang.hitch(this, function(){
+                       this.dndController.setSelection(nodes);
+               }));
+       },
+
+
+       ////////////// Data store related functions //////////////////////
+       // These just get passed to the model; they are here for back-compat
+
+       mayHaveChildren: function(/*dojo.data.Item*/ /*===== item =====*/){
+               // summary:
+               //              Deprecated.   This should be specified on the model itself.
                //
-               // We replace type/value pairs with typed-literals.  For example, we change:
-               //              { name:['Nelson Mandela'], born:[{_type:'Date', _value:'July 18, 1918'}] }
-               // into this:
-               //              { name:['Kermit'], born:(new Date('July 18, 1918')) } 
+               //              Overridable function to tell if an item has or may have children.
+               //              Controls whether or not +/- expando icon is shown.
+               //              (For efficiency reasons we may not want to check if an element actually
+               //              has children until user clicks the expando node)
+               // tags:
+               //              deprecated
+       },
+
+       getItemChildren: function(/*===== parentItem, onComplete =====*/){
+               // summary:
+               //              Deprecated.   This should be specified on the model itself.
                //
-               // We also generate the associate map for all items for the O(1) isItem function.
-               for(i = 0; i < this._arrayOfAllItems.length; ++i){
-                       item = this._arrayOfAllItems[i]; // example: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
-                       for(key in item){
-                               arrayOfValues = item[key]; // example: [{_reference:{name:'Miss Piggy'}}]
-                               for(var j = 0; j < arrayOfValues.length; ++j){
-                                       value = arrayOfValues[j]; // example: {_reference:{name:'Miss Piggy'}}
-                                       if(value !== null && typeof value == "object"){
-                                               if(("_type" in value) && ("_value" in value)){
-                                                       var type = value._type; // examples: 'Date', 'Color', or 'ComplexNumber'
-                                                       var mappingObj = this._datatypeMap[type]; // examples: Date, dojo.Color, foo.math.ComplexNumber, {type: dojo.Color, deserialize(value){ return new dojo.Color(value)}}
-                                                       if(!mappingObj){ 
-                                                               throw new Error("dojo.data.ItemFileReadStore: in the typeMap constructor arg, no object class was specified for the datatype '" + type + "'");
-                                                       }else if(dojo.isFunction(mappingObj)){
-                                                               arrayOfValues[j] = new mappingObj(value._value);
-                                                       }else if(dojo.isFunction(mappingObj.deserialize)){
-                                                               arrayOfValues[j] = mappingObj.deserialize(value._value);
-                                                       }else{
-                                                               throw new Error("dojo.data.ItemFileReadStore: Value provided in typeMap was neither a constructor, nor a an object with a deserialize function");
-                                                       }
-                                               }
-                                               if(value._reference){
-                                                       var referenceDescription = value._reference; // example: {name:'Miss Piggy'}
-                                                       if(!dojo.isObject(referenceDescription)){
-                                                               // example: 'Miss Piggy'
-                                                               // from an item like: { name:['Kermit'], friends:[{_reference:'Miss Piggy'}]}
-                                                               arrayOfValues[j] = this._getItemByIdentity(referenceDescription);
-                                                       }else{
-                                                               // example: {name:'Miss Piggy'}
-                                                               // from an item like: { name:['Kermit'], friends:[{_reference:{name:'Miss Piggy'}}] }
-                                                               for(var k = 0; k < this._arrayOfAllItems.length; ++k){
-                                                                       var candidateItem = this._arrayOfAllItems[k],
-                                                                           found = true;
-                                                                       for(var refKey in referenceDescription){
-                                                                               if(candidateItem[refKey] != referenceDescription[refKey]){ 
-                                                                                       found = false; 
-                                                                               }
-                                                                       }
-                                                                       if(found){ 
-                                                                               arrayOfValues[j] = candidateItem; 
-                                                                       }
-                                                               }
-                                                       }
-                                                       if(this.referenceIntegrity){
-                                                               var refItem = arrayOfValues[j];
-                                                               if(this.isItem(refItem)){
-                                                                       this._addReferenceToMap(refItem, item, key);
-                                                               }
-                                                       }
-                                               }else if(this.isItem(value)){
-                                                       //It's a child item (not one referenced through _reference).  
-                                                       //We need to treat this as a referenced item, so it can be cleaned up
-                                                       //in a write store easily.
-                                                       if(this.referenceIntegrity){
-                                                               this._addReferenceToMap(value, item, key);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               }
+               //              Overridable function that return array of child items of given parent item,
+               //              or if parentItem==null then return top items in tree
+               // tags:
+               //              deprecated
        },
 
-       _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
-                //     summary:
-                //             Method to add an reference map entry for an item and attribute.
-                //     description:
-                //             Method to add an reference map entry for an item and attribute.                  //
-                //     refItem:
-                //             The item that is referenced.
-                //     parentItem:
-                //             The item that holds the new reference to refItem.
-                //     attribute:
-                //             The attribute on parentItem that contains the new reference.
-                
-                //Stub function, does nothing.  Real processing is in ItemFileWriteStore.
+       ///////////////////////////////////////////////////////
+       // Functions for converting an item to a TreeNode
+       getLabel: function(/*dojo.data.Item*/ item){
+               // summary:
+               //              Overridable function to get the label for a tree node (given the item)
+               // tags:
+               //              extension
+               return this.model.getLabel(item);       // String
        },
 
-       getIdentity: function(/* item */ item){
-               //      summary: 
-               //              See dojo.data.api.Identity.getIdentity()
-               var identifier = this._features['dojo.data.api.Identity'];
-               if(identifier === Number){
-                       return item[this._itemNumPropName]; // Number
-               }else{
-                       var arrayOfValues = item[identifier];
-                       if(arrayOfValues){
-                               return arrayOfValues[0]; // Object || String
-                       }
-               }
-               return null; // null
+       getIconClass: function(/*dojo.data.Item*/ item, /*Boolean*/ opened){
+               // summary:
+               //              Overridable function to return CSS class name to display icon
+               // tags:
+               //              extension
+               return (!item || this.model.mayHaveChildren(item)) ? (opened ? "dijitFolderOpened" : "dijitFolderClosed") : "dijitLeaf"
+       },
+
+       getLabelClass: function(/*===== item, opened =====*/){
+               // summary:
+               //              Overridable function to return CSS class name to display label
+               // item: dojo.data.Item
+               // opened: Boolean
+               // returns: String
+               //              CSS class name
+               // tags:
+               //              extension
+       },
+
+       getRowClass: function(/*===== item, opened =====*/){
+               // summary:
+               //              Overridable function to return CSS class name to display row
+               // item: dojo.data.Item
+               // opened: Boolean
+               // returns: String
+               //              CSS class name
+               // tags:
+               //              extension
+       },
+
+       getIconStyle: function(/*===== item, opened =====*/){
+               // summary:
+               //              Overridable function to return CSS styles to display icon
+               // item: dojo.data.Item
+               // opened: Boolean
+               // returns: Object
+               //              Object suitable for input to dojo.style() like {backgroundImage: "url(...)"}
+               // tags:
+               //              extension
+       },
+
+       getLabelStyle: function(/*===== item, opened =====*/){
+               // summary:
+               //              Overridable function to return CSS styles to display label
+               // item: dojo.data.Item
+               // opened: Boolean
+               // returns:
+               //              Object suitable for input to dojo.style() like {color: "red", background: "green"}
+               // tags:
+               //              extension
+       },
+
+       getRowStyle: function(/*===== item, opened =====*/){
+               // summary:
+               //              Overridable function to return CSS styles to display row
+               // item: dojo.data.Item
+               // opened: Boolean
+               // returns:
+               //              Object suitable for input to dojo.style() like {background-color: "#bbb"}
+               // tags:
+               //              extension
        },
 
-       fetchItemByIdentity: function(/* Object */ keywordArgs){
-               //      summary: 
-               //              See dojo.data.api.Identity.fetchItemByIdentity()
+       getTooltip: function(/*dojo.data.Item*/ /*===== item =====*/){
+               // summary:
+               //              Overridable function to get the tooltip for a tree node (given the item)
+               // tags:
+               //              extension
+               return "";      // String
+       },
 
-               // Hasn't loaded yet, we have to trigger the load.
-               var item,
-                   scope;
-               if(!this._loadFinished){
-                       var self = this;
-                       //Do a check on the JsonFileUrl and crosscheck it.
-                       //If it doesn't match the cross-check, it needs to be updated
-                       //This allows for either url or _jsonFileUrl to he changed to
-                       //reset the store load location.  Done this way for backwards 
-                       //compatibility.  People use _jsonFileUrl (even though officially
-                       //private.
-                       if(this._jsonFileUrl !== this._ccUrl){
-                               dojo.deprecated("dojo.data.ItemFileReadStore: ", 
-                                       "To change the url, set the url property of the store," +
-                                       " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-                               this._ccUrl = this._jsonFileUrl;
-                               this.url = this._jsonFileUrl;
-                       }else if(this.url !== this._ccUrl){
-                               this._jsonFileUrl = this.url;
-                               this._ccUrl = this.url;
-                       }
-                       
-                       //See if there was any forced reset of data.
-                       if(this.data != null && this._jsonData == null){
-                               this._jsonData = this.data;
-                               this.data = null;
-                       }
+       /////////// Keyboard and Mouse handlers ////////////////////
 
-                       if(this._jsonFileUrl){
+       _onKeyPress: function(/*Event*/ e){
+               // summary:
+               //              Translates keypress events into commands for the controller
+               if(e.altKey){ return; }
+               var treeNode = registry.getEnclosingWidget(e.target);
+               if(!treeNode){ return; }
 
-                               if(this._loadInProgress){
-                                       this._queuedFetches.push({args: keywordArgs});
-                               }else{
-                                       this._loadInProgress = true;
-                                       var getArgs = {
-                                                       url: self._jsonFileUrl, 
-                                                       handleAs: "json-comment-optional",
-                                                       preventCache: this.urlPreventCache,
-                                                       failOk: this.failOk
-                                       };
-                                       var getHandler = dojo.xhrGet(getArgs);
-                                       getHandler.addCallback(function(data){
-                                               var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-                                               try{
-                                                       self._getItemsFromLoadedData(data);
-                                                       self._loadFinished = true;
-                                                       self._loadInProgress = false;
-                                                       item = self._getItemByIdentity(keywordArgs.identity);
-                                                       if(keywordArgs.onItem){
-                                                               keywordArgs.onItem.call(scope, item);
-                                                       }
-                                                       self._handleQueuedFetches();
-                                               }catch(error){
-                                                       self._loadInProgress = false;
-                                                       if(keywordArgs.onError){
-                                                               keywordArgs.onError.call(scope, error);
-                                                       }
-                                               }
-                                       });
-                                       getHandler.addErrback(function(error){
-                                               self._loadInProgress = false;
-                                               if(keywordArgs.onError){
-                                                       var scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-                                                       keywordArgs.onError.call(scope, error);
-                                               }
-                                       });
-                               }
+               var key = e.charOrCode;
+               if(typeof key == "string" && key != " "){       // handle printables (letter navigation)
+                       // Check for key navigation.
+                       if(!e.altKey && !e.ctrlKey && !e.shiftKey && !e.metaKey){
+                               this._onLetterKeyNav( { node: treeNode, key: key.toLowerCase() } );
+                               event.stop(e);
+                       }
+               }else{  // handle non-printables (arrow keys)
+                       // clear record of recent printables (being saved for multi-char letter navigation),
+                       // because "a", down-arrow, "b" shouldn't search for "ab"
+                       if(this._curSearch){
+                               clearTimeout(this._curSearch.timer);
+                               delete this._curSearch;
+                       }
 
-                       }else if(this._jsonData){
-                               // Passed in data, no need to xhr.
-                               self._getItemsFromLoadedData(self._jsonData);
-                               self._jsonData = null;
-                               self._loadFinished = true;
-                               item = self._getItemByIdentity(keywordArgs.identity);
-                               if(keywordArgs.onItem){
-                                       scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-                                       keywordArgs.onItem.call(scope, item);
-                               }
-                       } 
-               }else{
-                       // Already loaded.  We can just look it up and call back.
-                       item = this._getItemByIdentity(keywordArgs.identity);
-                       if(keywordArgs.onItem){
-                               scope = keywordArgs.scope?keywordArgs.scope:dojo.global;
-                               keywordArgs.onItem.call(scope, item);
+                       var map = this._keyHandlerMap;
+                       if(!map){
+                               // setup table mapping keys to events
+                               map = {};
+                               map[keys.ENTER]="_onEnterKey";
+                               //On WebKit based browsers, the combination ctrl-enter
+                               //does not get passed through. To allow accessible
+                               //multi-select on those browsers, the space key is
+                               //also used for selection.
+                               map[keys.SPACE]= map[" "] = "_onEnterKey";
+                               map[this.isLeftToRight() ? keys.LEFT_ARROW : keys.RIGHT_ARROW]="_onLeftArrow";
+                               map[this.isLeftToRight() ? keys.RIGHT_ARROW : keys.LEFT_ARROW]="_onRightArrow";
+                               map[keys.UP_ARROW]="_onUpArrow";
+                               map[keys.DOWN_ARROW]="_onDownArrow";
+                               map[keys.HOME]="_onHomeKey";
+                               map[keys.END]="_onEndKey";
+                               this._keyHandlerMap = map;
+                       }
+                       if(this._keyHandlerMap[key]){
+                               this[this._keyHandlerMap[key]]( { node: treeNode, item: treeNode.item, evt: e } );
+                               event.stop(e);
                        }
                }
        },
 
-       _getItemByIdentity: function(/* Object */ identity){
-               //      summary:
-               //              Internal function to look an item up by its identity map.
-               var item = null;
-               if(this._itemsByIdentity){
-                       item = this._itemsByIdentity[identity];
-               }else{
-                       item = this._arrayOfAllItems[identity];
-               }
-               if(item === undefined){
-                       item = null;
-               }
-               return item; // Object
+       _onEnterKey: function(/*Object*/ message){
+               this._publish("execute", { item: message.item, node: message.node } );
+               this.dndController.userSelect(message.node, connect.isCopyKey( message.evt ), message.evt.shiftKey);
+               this.onClick(message.item, message.node, message.evt);
        },
 
-       getIdentityAttributes: function(/* item */ item){
-               //      summary: 
-               //              See dojo.data.api.Identity.getIdentifierAttributes()
-                
-               var identifier = this._features['dojo.data.api.Identity'];
-               if(identifier === Number){
-                       // If (identifier === Number) it means getIdentity() just returns
-                       // an integer item-number for each item.  The dojo.data.api.Identity
-                       // spec says we need to return null if the identity is not composed 
-                       // of attributes 
-                       return null; // null
-               }else{
-                       return [identifier]; // Array
+       _onDownArrow: function(/*Object*/ message){
+               // summary:
+               //              down arrow pressed; get next visible node, set focus there
+               var node = this._getNextNode(message.node);
+               if(node && node.isTreeNode){
+                       this.focusNode(node);
                }
        },
-       
-       _forceLoad: function(){
-               //      summary: 
-               //              Internal function to force a load of the store if it hasn't occurred yet.  This is required
-               //              for specific functions to work properly.  
-               var self = this;
-               //Do a check on the JsonFileUrl and crosscheck it.
-               //If it doesn't match the cross-check, it needs to be updated
-               //This allows for either url or _jsonFileUrl to he changed to
-               //reset the store load location.  Done this way for backwards 
-               //compatibility.  People use _jsonFileUrl (even though officially
-               //private.
-               if(this._jsonFileUrl !== this._ccUrl){
-                       dojo.deprecated("dojo.data.ItemFileReadStore: ", 
-                               "To change the url, set the url property of the store," +
-                               " not _jsonFileUrl.  _jsonFileUrl support will be removed in 2.0");
-                       this._ccUrl = this._jsonFileUrl;
-                       this.url = this._jsonFileUrl;
-               }else if(this.url !== this._ccUrl){
-                       this._jsonFileUrl = this.url;
-                       this._ccUrl = this.url;
-               }
-
-               //See if there was any forced reset of data.
-               if(this.data != null && this._jsonData == null){
-                       this._jsonData = this.data;
-                       this.data = null;
-               }
-
-               if(this._jsonFileUrl){
-                               var getArgs = {
-                                       url: this._jsonFileUrl, 
-                                       handleAs: "json-comment-optional",
-                                       preventCache: this.urlPreventCache,
-                                       failOk: this.failOk,
-                                       sync: true
-                               };
-                       var getHandler = dojo.xhrGet(getArgs);
-                       getHandler.addCallback(function(data){
-                               try{
-                                       //Check to be sure there wasn't another load going on concurrently 
-                                       //So we don't clobber data that comes in on it.  If there is a load going on
-                                       //then do not save this data.  It will potentially clobber current data.
-                                       //We mainly wanted to sync/wait here.
-                                       //TODO:  Revisit the loading scheme of this store to improve multi-initial
-                                       //request handling.
-                                       if(self._loadInProgress !== true && !self._loadFinished){
-                                               self._getItemsFromLoadedData(data);
-                                               self._loadFinished = true;
-                                       }else if(self._loadInProgress){
-                                               //Okay, we hit an error state we can't recover from.  A forced load occurred
-                                               //while an async load was occurring.  Since we cannot block at this point, the best
-                                               //that can be managed is to throw an error.
-                                               throw new Error("dojo.data.ItemFileReadStore:  Unable to perform a synchronous load, an async load is in progress."); 
-                                       }
-                               }catch(e){
-                                       console.log(e);
-                                       throw e;
-                               }
-                       });
-                       getHandler.addErrback(function(error){
-                               throw error;
-                       });
-               }else if(this._jsonData){
-                       self._getItemsFromLoadedData(self._jsonData);
-                       self._jsonData = null;
-                       self._loadFinished = true;
-               } 
-       }
-});
-//Mix in the simple fetch implementation to this class.
-dojo.extend(dojo.data.ItemFileReadStore,dojo.data.util.simpleFetch);
-
-}
-
-if(!dojo._hasResource["dojo.data.ItemFileWriteStore"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
-dojo._hasResource["dojo.data.ItemFileWriteStore"] = true;
-dojo.provide("dojo.data.ItemFileWriteStore");
 
+       _onUpArrow: function(/*Object*/ message){
+               // summary:
+               //              Up arrow pressed; move to previous visible node
 
-dojo.declare("dojo.data.ItemFileWriteStore", dojo.data.ItemFileReadStore, {
-       constructor: function(/* object */ keywordParameters){
-               //      keywordParameters: {typeMap: object)
-               //              The structure of the typeMap object is as follows:
-               //              {
-               //                      type0: function || object,
-               //                      type1: function || object,
-               //                      ...
-               //                      typeN: function || object
-               //              }
-               //              Where if it is a function, it is assumed to be an object constructor that takes the 
-               //              value of _value as the initialization parameters.  It is serialized assuming object.toString()
-               //              serialization.  If it is an object, then it is assumed
-               //              to be an object of general form:
-               //              {
-               //                      type: function, //constructor.
-               //                      deserialize:    function(value) //The function that parses the value and constructs the object defined by type appropriately.
-               //                      serialize:      function(object) //The function that converts the object back into the proper file format form.
-               //              }
-
-               // ItemFileWriteStore extends ItemFileReadStore to implement these additional dojo.data APIs
-               this._features['dojo.data.api.Write'] = true;
-               this._features['dojo.data.api.Notification'] = true;
-               
-               // For keeping track of changes so that we can implement isDirty and revert
-               this._pending = {
-                       _newItems:{}, 
-                       _modifiedItems:{}, 
-                       _deletedItems:{}
-               };
+               var node = message.node;
 
-               if(!this._datatypeMap['Date'].serialize){
-                       this._datatypeMap['Date'].serialize = function(obj){
-                               return dojo.date.stamp.toISOString(obj, {zulu:true});
-                       };
+               // if younger siblings
+               var previousSibling = node.getPreviousSibling();
+               if(previousSibling){
+                       node = previousSibling;
+                       // if the previous node is expanded, dive in deep
+                       while(node.isExpandable && node.isExpanded && node.hasChildren()){
+                               // move to the last child
+                               var children = node.getChildren();
+                               node = children[children.length-1];
+                       }
+               }else{
+                       // if this is the first child, return the parent
+                       // unless the parent is the root of a tree with a hidden root
+                       var parent = node.getParent();
+                       if(!(!this.showRoot && parent === this.rootNode)){
+                               node = parent;
+                       }
                }
-               //Disable only if explicitly set to false.
-               if(keywordParameters && (keywordParameters.referenceIntegrity === false)){
-                       this.referenceIntegrity = false;
+
+               if(node && node.isTreeNode){
+                       this.focusNode(node);
                }
-
-               // this._saveInProgress is set to true, briefly, from when save() is first called to when it completes
-               this._saveInProgress = false;
        },
 
-       referenceIntegrity: true, //Flag that defaultly enabled reference integrity tracking.  This way it can also be disabled pogrammatially or declaratively.
+       _onRightArrow: function(/*Object*/ message){
+               // summary:
+               //              Right arrow pressed; go to child node
+               var node = message.node;
 
-       _assert: function(/* boolean */ condition){
-               if(!condition){
-                       throw new Error("assertion failed in ItemFileWriteStore");
+               // if not expanded, expand, else move to 1st child
+               if(node.isExpandable && !node.isExpanded){
+                       this._expandNode(node);
+               }else if(node.hasChildren()){
+                       node = node.getChildren()[0];
+                       if(node && node.isTreeNode){
+                               this.focusNode(node);
+                       }
                }
        },
 
-       _getIdentifierAttribute: function(){
-               var identifierAttribute = this.getFeatures()['dojo.data.api.Identity'];
-               // this._assert((identifierAttribute === Number) || (dojo.isString(identifierAttribute)));
-               return identifierAttribute;
-       },
-       
-       
-/* dojo.data.api.Write */
-
-       newItem: function(/* Object? */ keywordArgs, /* Object? */ parentInfo){
-               // summary: See dojo.data.api.Write.newItem()
-
-               this._assert(!this._saveInProgress);
+       _onLeftArrow: function(/*Object*/ message){
+               // summary:
+               //              Left arrow pressed.
+               //              If not collapsed, collapse, else move to parent.
 
-               if(!this._loadFinished){
-                       // We need to do this here so that we'll be able to find out what
-                       // identifierAttribute was specified in the data file.
-                       this._forceLoad();
-               }
+               var node = message.node;
 
-               if(typeof keywordArgs != "object" && typeof keywordArgs != "undefined"){
-                       throw new Error("newItem() was passed something other than an object");
-               }
-               var newIdentity = null;
-               var identifierAttribute = this._getIdentifierAttribute();
-               if(identifierAttribute === Number){
-                       newIdentity = this._arrayOfAllItems.length;
+               if(node.isExpandable && node.isExpanded){
+                       this._collapseNode(node);
                }else{
-                       newIdentity = keywordArgs[identifierAttribute];
-                       if(typeof newIdentity === "undefined"){
-                               throw new Error("newItem() was not passed an identity for the new item");
-                       }
-                       if(dojo.isArray(newIdentity)){
-                               throw new Error("newItem() was not passed an single-valued identity");
+                       var parent = node.getParent();
+                       if(parent && parent.isTreeNode && !(!this.showRoot && parent === this.rootNode)){
+                               this.focusNode(parent);
                        }
                }
-               
-               // make sure this identity is not already in use by another item, if identifiers were 
-               // defined in the file.  Otherwise it would be the item count, 
-               // which should always be unique in this case.
-               if(this._itemsByIdentity){
-                       this._assert(typeof this._itemsByIdentity[newIdentity] === "undefined");
-               }
-               this._assert(typeof this._pending._newItems[newIdentity] === "undefined");
-               this._assert(typeof this._pending._deletedItems[newIdentity] === "undefined");
-               
-               var newItem = {};
-               newItem[this._storeRefPropName] = this;         
-               newItem[this._itemNumPropName] = this._arrayOfAllItems.length;
-               if(this._itemsByIdentity){
-                       this._itemsByIdentity[newIdentity] = newItem;
-                       //We have to set the identifier now, otherwise we can't look it
-                       //up at calls to setValueorValues in parentInfo handling.
-                       newItem[identifierAttribute] = [newIdentity];
+       },
+
+       _onHomeKey: function(){
+               // summary:
+               //              Home key pressed; get first visible node, and set focus there
+               var node = this._getRootOrFirstNode();
+               if(node){
+                       this.focusNode(node);
                }
-               this._arrayOfAllItems.push(newItem);
+       },
 
-               //We need to construct some data for the onNew call too...
-               var pInfo = null;
-               
-               // Now we need to check to see where we want to assign this thingm if any.
-               if(parentInfo && parentInfo.parent && parentInfo.attribute){
-                       pInfo = {
-                               item: parentInfo.parent,
-                               attribute: parentInfo.attribute,
-                               oldValue: undefined
-                       };
+       _onEndKey: function(){
+               // summary:
+               //              End key pressed; go to last visible node.
 
-                       //See if it is multi-valued or not and handle appropriately
-                       //Generally, all attributes are multi-valued for this store
-                       //So, we only need to append if there are already values present.
-                       var values = this.getValues(parentInfo.parent, parentInfo.attribute);
-                       if(values && values.length > 0){
-                               var tempValues = values.slice(0, values.length);
-                               if(values.length === 1){
-                                       pInfo.oldValue = values[0];
-                               }else{
-                                       pInfo.oldValue = values.slice(0, values.length);
-                               }
-                               tempValues.push(newItem);
-                               this._setValueOrValues(parentInfo.parent, parentInfo.attribute, tempValues, false);
-                               pInfo.newValue = this.getValues(parentInfo.parent, parentInfo.attribute);
-                       }else{
-                               this._setValueOrValues(parentInfo.parent, parentInfo.attribute, newItem, false);
-                               pInfo.newValue = newItem;
-                       }
-               }else{
-                       //Toplevel item, add to both top list as well as all list.
-                       newItem[this._rootItemPropName]=true;
-                       this._arrayOfTopLevelItems.push(newItem);
-               }
-               
-               this._pending._newItems[newIdentity] = newItem;
-               
-               //Clone over the properties to the new item
-               for(var key in keywordArgs){
-                       if(key === this._storeRefPropName || key === this._itemNumPropName){
-                               // Bummer, the user is trying to do something like
-                               // newItem({_S:"foo"}).  Unfortunately, our superclass,
-                               // ItemFileReadStore, is already using _S in each of our items
-                               // to hold private info.  To avoid a naming collision, we 
-                               // need to move all our private info to some other property 
-                               // of all the items/objects.  So, we need to iterate over all
-                               // the items and do something like: 
-                               //    item.__S = item._S;
-                               //    item._S = undefined;
-                               // But first we have to make sure the new "__S" variable is 
-                               // not in use, which means we have to iterate over all the 
-                               // items checking for that.
-                               throw new Error("encountered bug in ItemFileWriteStore.newItem");
-                       }
-                       var value = keywordArgs[key];
-                       if(!dojo.isArray(value)){
-                               value = [value];
-                       }
-                       newItem[key] = value;
-                       if(this.referenceIntegrity){
-                               for(var i = 0; i < value.length; i++){
-                                       var val = value[i];
-                                       if(this.isItem(val)){
-                                               this._addReferenceToMap(val, newItem, key);
-                                       }
-                               }
-                       }
+               var node = this.rootNode;
+               while(node.isExpanded){
+                       var c = node.getChildren();
+                       node = c[c.length - 1];
                }
-               this.onNew(newItem, pInfo); // dojo.data.api.Notification call
-               return newItem; // item
-       },
-       
-       _removeArrayElement: function(/* Array */ array, /* anything */ element){
-               var index = dojo.indexOf(array, element);
-               if(index != -1){
-                       array.splice(index, 1);
-                       return true;
+
+               if(node && node.isTreeNode){
+                       this.focusNode(node);
                }
-               return false;
        },
-       
-       deleteItem: function(/* item */ item){
-               // summary: See dojo.data.api.Write.deleteItem()
-               this._assert(!this._saveInProgress);
-               this._assertIsItem(item);
 
-               // Remove this item from the _arrayOfAllItems, but leave a null value in place
-               // of the item, so as not to change the length of the array, so that in newItem() 
-               // we can still safely do: newIdentity = this._arrayOfAllItems.length;
-               var indexInArrayOfAllItems = item[this._itemNumPropName];
-               var identity = this.getIdentity(item);
+       // multiCharSearchDuration: Number
+       //              If multiple characters are typed where each keystroke happens within
+       //              multiCharSearchDuration of the previous keystroke,
+       //              search for nodes matching all the keystrokes.
+       //
+       //              For example, typing "ab" will search for entries starting with
+       //              "ab" unless the delay between "a" and "b" is greater than multiCharSearchDuration.
+       multiCharSearchDuration: 250,
 
-               //If we have reference integrity on, we need to do reference cleanup for the deleted item
-               if(this.referenceIntegrity){
-                       //First scan all the attributes of this items for references and clean them up in the map 
-                       //As this item is going away, no need to track its references anymore.
+       _onLetterKeyNav: function(message){
+               // summary:
+               //              Called when user presses a prinatable key; search for node starting with recently typed letters.
+               // message: Object
+               //              Like { node: TreeNode, key: 'a' } where key is the key the user pressed.
 
-                       //Get the attributes list before we generate the backup so it 
-                       //doesn't pollute the attributes list.
-                       var attributes = this.getAttributes(item);
+               // Branch depending on whether this key starts a new search, or modifies an existing search
+               var cs = this._curSearch;
+               if(cs){
+                       // We are continuing a search.  Ex: user has pressed 'a', and now has pressed
+                       // 'b', so we want to search for nodes starting w/"ab".
+                       cs.pattern = cs.pattern + message.key;
+                       clearTimeout(cs.timer);
+               }else{
+                       // We are starting a new search
+                       cs = this._curSearch = {
+                                       pattern: message.key,
+                                       startNode: message.node
+                       };
+               }
 
-                       //Backup the map, we'll have to restore it potentially, in a revert.
-                       if(item[this._reverseRefMap]){
-                               item["backup_" + this._reverseRefMap] = dojo.clone(item[this._reverseRefMap]);
-                       }
-                       
-                       //TODO:  This causes a reversion problem.  This list won't be restored on revert since it is
-                       //attached to the 'value'. item, not ours.  Need to back tese up somehow too.
-                       //Maybe build a map of the backup of the entries and attach it to the deleted item to be restored
-                       //later.  Or just record them and call _addReferenceToMap on them in revert.
-                       dojo.forEach(attributes, function(attribute){
-                               dojo.forEach(this.getValues(item, attribute), function(value){
-                                       if(this.isItem(value)){
-                                               //We have to back up all the references we had to others so they can be restored on a revert.
-                                               if(!item["backupRefs_" + this._reverseRefMap]){
-                                                       item["backupRefs_" + this._reverseRefMap] = [];
-                                               }
-                                               item["backupRefs_" + this._reverseRefMap].push({id: this.getIdentity(value), attr: attribute});
-                                               this._removeReferenceFromMap(value, item, attribute);
-                                       }
-                               }, this);
-                       }, this);
+               // set/reset timer to forget recent keystrokes
+               var self = this;
+               cs.timer = setTimeout(function(){
+                       delete self._curSearch;
+               }, this.multiCharSearchDuration);
 
-                       //Next, see if we have references to this item, if we do, we have to clean them up too.
-                       var references = item[this._reverseRefMap];
-                       if(references){
-                               //Look through all the items noted as references to clean them up.
-                               for(var itemId in references){
-                                       var containingItem = null;
-                                       if(this._itemsByIdentity){
-                                               containingItem = this._itemsByIdentity[itemId];
-                                       }else{
-                                               containingItem = this._arrayOfAllItems[itemId];
-                                       }
-                                       //We have a reference to a containing item, now we have to process the
-                                       //attributes and clear all references to the item being deleted.
-                                       if(containingItem){
-                                               for(var attribute in references[itemId]){
-                                                       var oldValues = this.getValues(containingItem, attribute) || [];
-                                                       var newValues = dojo.filter(oldValues, function(possibleItem){
-                                                               return !(this.isItem(possibleItem) && this.getIdentity(possibleItem) == identity);
-                                                       }, this);
-                                                       //Remove the note of the reference to the item and set the values on the modified attribute.
-                                                       this._removeReferenceFromMap(item, containingItem, attribute); 
-                                                       if(newValues.length < oldValues.length){
-                                                               this._setValueOrValues(containingItem, attribute, newValues, true);
-                                                       }
-                                               }
-                                       }
-                               }
+               // Navigate to TreeNode matching keystrokes [entered so far].
+               var node = cs.startNode;
+               do{
+                       node = this._getNextNode(node);
+                       //check for last node, jump to first node if necessary
+                       if(!node){
+                               node = this._getRootOrFirstNode();
+                       }
+               }while(node !== cs.startNode && (node.label.toLowerCase().substr(0, cs.pattern.length) != cs.pattern));
+               if(node && node.isTreeNode){
+                       // no need to set focus if back where we started
+                       if(node !== cs.startNode){
+                               this.focusNode(node);
                        }
                }
+       },
 
-               this._arrayOfAllItems[indexInArrayOfAllItems] = null;
+       isExpandoNode: function(node, widget){
+               // summary:
+               //              check whether a dom node is the expandoNode for a particular TreeNode widget
+               return dom.isDescendant(node, widget.expandoNode);
+       },
+       _onClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
+               // summary:
+               //              Translates click events into commands for the controller to process
 
-               item[this._storeRefPropName] = null;
-               if(this._itemsByIdentity){
-                       delete this._itemsByIdentity[identity];
+               var domElement = e.target,
+                       isExpandoClick = this.isExpandoNode(domElement, nodeWidget);
+
+               if( (this.openOnClick && nodeWidget.isExpandable) || isExpandoClick ){
+                       // expando node was clicked, or label of a folder node was clicked; open it
+                       if(nodeWidget.isExpandable){
+                               this._onExpandoClick({node:nodeWidget});
+                       }
+               }else{
+                       this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
+                       this.onClick(nodeWidget.item, nodeWidget, e);
+                       this.focusNode(nodeWidget);
                }
-               this._pending._deletedItems[identity] = item;
-               
-               //Remove from the toplevel items, if necessary...
-               if(item[this._rootItemPropName]){
-                       this._removeArrayElement(this._arrayOfTopLevelItems, item);
+               event.stop(e);
+       },
+       _onDblClick: function(/*TreeNode*/ nodeWidget, /*Event*/ e){
+               // summary:
+               //              Translates double-click events into commands for the controller to process
+
+               var domElement = e.target,
+                       isExpandoClick = (domElement == nodeWidget.expandoNode || domElement == nodeWidget.expandoNodeText);
+
+               if( (this.openOnDblClick && nodeWidget.isExpandable) ||isExpandoClick ){
+                       // expando node was clicked, or label of a folder node was clicked; open it
+                       if(nodeWidget.isExpandable){
+                               this._onExpandoClick({node:nodeWidget});
+                       }
+               }else{
+                       this._publish("execute", { item: nodeWidget.item, node: nodeWidget, evt: e } );
+                       this.onDblClick(nodeWidget.item, nodeWidget, e);
+                       this.focusNode(nodeWidget);
                }
-               this.onDelete(item); // dojo.data.api.Notification call
-               return true;
+               event.stop(e);
        },
 
-       setValue: function(/* item */ item, /* attribute-name-string */ attribute, /* almost anything */ value){
-               // summary: See dojo.data.api.Write.set()
-               return this._setValueOrValues(item, attribute, value, true); // boolean
+       _onExpandoClick: function(/*Object*/ message){
+               // summary:
+               //              User clicked the +/- icon; expand or collapse my children.
+               var node = message.node;
+
+               // If we are collapsing, we might be hiding the currently focused node.
+               // Also, clicking the expando node might have erased focus from the current node.
+               // For simplicity's sake just focus on the node with the expando.
+               this.focusNode(node);
+
+               if(node.isExpanded){
+                       this._collapseNode(node);
+               }else{
+                       this._expandNode(node);
+               }
        },
-       
-       setValues: function(/* item */ item, /* attribute-name-string */ attribute, /* array */ values){
-               // summary: See dojo.data.api.Write.setValues()
-               return this._setValueOrValues(item, attribute, values, true); // boolean
+
+       onClick: function(/*===== item, node, evt =====*/){
+               // summary:
+               //              Callback when a tree node is clicked
+               // item: dojo.data.Item
+               // node: TreeNode
+               // evt: Event
+               // tags:
+               //              callback
        },
-       
-       unsetAttribute: function(/* item */ item, /* attribute-name-string */ attribute){
-               // summary: See dojo.data.api.Write.unsetAttribute()
-               return this._setValueOrValues(item, attribute, [], true);
+       onDblClick: function(/*===== item, node, evt =====*/){
+               // summary:
+               //              Callback when a tree node is double-clicked
+               // item: dojo.data.Item
+               // node: TreeNode
+               // evt: Event
+               // tags:
+               //              callback
+       },
+       onOpen: function(/*===== item, node =====*/){
+               // summary:
+               //              Callback when a node is opened
+               // item: dojo.data.Item
+               // node: TreeNode
+               // tags:
+               //              callback
+       },
+       onClose: function(/*===== item, node =====*/){
+               // summary:
+               //              Callback when a node is closed
+               // item: dojo.data.Item
+               // node: TreeNode
+               // tags:
+               //              callback
        },
-       
-       _setValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute, /* anything */ newValueOrValues, /*boolean?*/ callOnSet){
-               this._assert(!this._saveInProgress);
-               
-               // Check for valid arguments
-               this._assertIsItem(item);
-               this._assert(dojo.isString(attribute));
-               this._assert(typeof newValueOrValues !== "undefined");
-
-               // Make sure the user isn't trying to change the item's identity
-               var identifierAttribute = this._getIdentifierAttribute();
-               if(attribute == identifierAttribute){
-                       throw new Error("ItemFileWriteStore does not have support for changing the value of an item's identifier.");
-               }
 
-               // To implement the Notification API, we need to make a note of what
-               // the old attribute value was, so that we can pass that info when
-               // we call the onSet method.
-               var oldValueOrValues = this._getValueOrValues(item, attribute);
+       _getNextNode: function(node){
+               // summary:
+               //              Get next visible node
 
-               var identity = this.getIdentity(item);
-               if(!this._pending._modifiedItems[identity]){
-                       // Before we actually change the item, we make a copy of it to 
-                       // record the original state, so that we'll be able to revert if 
-                       // the revert method gets called.  If the item has already been
-                       // modified then there's no need to do this now, since we already
-                       // have a record of the original state.                                         
-                       var copyOfItemState = {};
-                       for(var key in item){
-                               if((key === this._storeRefPropName) || (key === this._itemNumPropName) || (key === this._rootItemPropName)){
-                                       copyOfItemState[key] = item[key];
-                               }else if(key === this._reverseRefMap){
-                                       copyOfItemState[key] = dojo.clone(item[key]);
-                               }else{
-                                       copyOfItemState[key] = item[key].slice(0, item[key].length);
+               if(node.isExpandable && node.isExpanded && node.hasChildren()){
+                       // if this is an expanded node, get the first child
+                       return node.getChildren()[0];           // _TreeNode
+               }else{
+                       // find a parent node with a sibling
+                       while(node && node.isTreeNode){
+                               var returnNode = node.getNextSibling();
+                               if(returnNode){
+                                       return returnNode;              // _TreeNode
                                }
+                               node = node.getParent();
                        }
-                       // Now mark the item as dirty, and save the copy of the original state
-                       this._pending._modifiedItems[identity] = copyOfItemState;
+                       return null;
                }
-               
-               // Okay, now we can actually change this attribute on the item
-               var success = false;
-               
-               if(dojo.isArray(newValueOrValues) && newValueOrValues.length === 0){
-                       
-                       // If we were passed an empty array as the value, that counts
-                       // as "unsetting" the attribute, so we need to remove this 
-                       // attribute from the item.
-                       success = delete item[attribute];
-                       newValueOrValues = undefined; // used in the onSet Notification call below
+       },
 
-                       if(this.referenceIntegrity && oldValueOrValues){
-                               var oldValues = oldValueOrValues;
-                               if(!dojo.isArray(oldValues)){
-                                       oldValues = [oldValues];
-                               }
-                               for(var i = 0; i < oldValues.length; i++){
-                                       var value = oldValues[i];
-                                       if(this.isItem(value)){
-                                               this._removeReferenceFromMap(value, item, attribute);
-                                       }
-                               }
-                       }
-               }else{
-                       var newValueArray;
-                       if(dojo.isArray(newValueOrValues)){
-                               var newValues = newValueOrValues;
-                               // Unfortunately, it's not safe to just do this:
-                               //    newValueArray = newValues;
-                               // Instead, we need to copy the array, which slice() does very nicely.
-                               // This is so that our internal data structure won't  
-                               // get corrupted if the user mucks with the values array *after*
-                               // calling setValues().
-                               newValueArray = newValueOrValues.slice(0, newValueOrValues.length);
-                       }else{
-                               newValueArray = [newValueOrValues];
+       _getRootOrFirstNode: function(){
+               // summary:
+               //              Get first visible node
+               return this.showRoot ? this.rootNode : this.rootNode.getChildren()[0];
+       },
+
+       _collapseNode: function(/*_TreeNode*/ node){
+               // summary:
+               //              Called when the user has requested to collapse the node
+
+               if(node._expandNodeDeferred){
+                       delete node._expandNodeDeferred;
+               }
+
+               if(node.isExpandable){
+                       if(node.state == "LOADING"){
+                               // ignore clicks while we are in the process of loading data
+                               return;
                        }
 
-                       //We need to handle reference integrity if this is on. 
-                       //In the case of set, we need to see if references were added or removed
-                       //and update the reference tracking map accordingly.
-                       if(this.referenceIntegrity){
-                               if(oldValueOrValues){
-                                       var oldValues = oldValueOrValues;
-                                       if(!dojo.isArray(oldValues)){
-                                               oldValues = [oldValues];
-                                       }
-                                       //Use an associative map to determine what was added/removed from the list.
-                                       //Should be O(n) performant.  First look at all the old values and make a list of them
-                                       //Then for any item not in the old list, we add it.  If it was already present, we remove it.
-                                       //Then we pass over the map and any references left it it need to be removed (IE, no match in
-                                       //the new values list).
-                                       var map = {};
-                                       dojo.forEach(oldValues, function(possibleItem){
-                                               if(this.isItem(possibleItem)){
-                                                       var id = this.getIdentity(possibleItem);
-                                                       map[id.toString()] = true;
-                                               }
-                                       }, this);
-                                       dojo.forEach(newValueArray, function(possibleItem){
-                                               if(this.isItem(possibleItem)){
-                                                       var id = this.getIdentity(possibleItem);
-                                                       if(map[id.toString()]){
-                                                               delete map[id.toString()];
-                                                       }else{
-                                                               this._addReferenceToMap(possibleItem, item, attribute); 
-                                                       }
-                                               }
-                                       }, this);
-                                       for(var rId in map){
-                                               var removedItem;
-                                               if(this._itemsByIdentity){
-                                                       removedItem = this._itemsByIdentity[rId];
-                                               }else{
-                                                       removedItem = this._arrayOfAllItems[rId];
-                                               }
-                                               this._removeReferenceFromMap(removedItem, item, attribute);
-                                       }
-                               }else{
-                                       //Everything is new (no old values) so we have to just
-                                       //insert all the references, if any.
-                                       for(var i = 0; i < newValueArray.length; i++){
-                                               var value = newValueArray[i];
-                                               if(this.isItem(value)){
-                                                       this._addReferenceToMap(value, item, attribute);
-                                               }
+                       node.collapse();
+                       this.onClose(node.item, node);
+
+                       this._state(node, false);
+               }
+       },
+
+       _expandNode: function(/*_TreeNode*/ node, /*Boolean?*/ recursive){
+               // summary:
+               //              Called when the user has requested to expand the node
+               // recursive:
+               //              Internal flag used when _expandNode() calls itself, don't set.
+               // returns:
+               //              Deferred that fires when the node is loaded and opened and (if persist=true) all it's descendants
+               //              that were previously opened too
+
+               if(node._expandNodeDeferred && !recursive){
+                       // there's already an expand in progress (or completed), so just return
+                       return node._expandNodeDeferred;        // dojo.Deferred
+               }
+
+               var model = this.model,
+                       item = node.item,
+                       _this = this;
+
+               switch(node.state){
+                       case "UNCHECKED":
+                               // need to load all the children, and then expand
+                               node.markProcessing();
+
+                               // Setup deferred to signal when the load and expand are finished.
+                               // Save that deferred in this._expandDeferred as a flag that operation is in progress.
+                               var def = (node._expandNodeDeferred = new Deferred());
+
+                               // Get the children
+                               model.getChildren(
+                                       item,
+                                       function(items){
+                                               node.unmarkProcessing();
+
+                                               // Display the children and also start expanding any children that were previously expanded
+                                               // (if this.persist == true).   The returned Deferred will fire when those expansions finish.
+                                               var scid = node.setChildItems(items);
+
+                                               // Call _expandNode() again but this time it will just to do the animation (default branch).
+                                               // The returned Deferred will fire when the animation completes.
+                                               // TODO: seems like I can avoid recursion and just use a deferred to sequence the events?
+                                               var ed = _this._expandNode(node, true);
+
+                                               // After the above two tasks (setChildItems() and recursive _expandNode()) finish,
+                                               // signal that I am done.
+                                               scid.addCallback(function(){
+                                                       ed.addCallback(function(){
+                                                               def.callback();
+                                                       })
+                                               });
+                                       },
+                                       function(err){
+                                               console.error(_this, ": error loading root children: ", err);
                                        }
-                               }
-                       }
-                       item[attribute] = newValueArray;
-                       success = true;
-               }
+                               );
+                               break;
 
-               // Now we make the dojo.data.api.Notification call
-               if(callOnSet){
-                       this.onSet(item, attribute, oldValueOrValues, newValueOrValues); 
+                       default:        // "LOADED"
+                               // data is already loaded; just expand node
+                               def = (node._expandNodeDeferred = node.expand());
+
+                               this.onOpen(node.item, node);
+
+                               this._state(node, true);
                }
-               return success; // boolean
+
+               return def;     // dojo.Deferred
        },
 
-       _addReferenceToMap: function(/*item*/ refItem, /*item*/ parentItem, /*string*/ attribute){
-               //      summary:
-               //              Method to add an reference map entry for an item and attribute.
-               //      description:
-               //              Method to add an reference map entry for an item and attribute.                  //
-               //      refItem:
-               //              The item that is referenced.
-               //      parentItem:
-               //              The item that holds the new reference to refItem.
-               //      attribute:
-               //              The attribute on parentItem that contains the new reference.
-                
-               var parentId = this.getIdentity(parentItem);
-               var references = refItem[this._reverseRefMap];
+       ////////////////// Miscellaneous functions ////////////////
 
-               if(!references){
-                       references = refItem[this._reverseRefMap] = {};
-               }
-               var itemRef = references[parentId];
-               if(!itemRef){
-                       itemRef = references[parentId] = {};
-               }
-               itemRef[attribute] = true;
+       focusNode: function(/* _tree.Node */ node){
+               // summary:
+               //              Focus on the specified node (which must be visible)
+               // tags:
+               //              protected
+
+               // set focus so that the label will be voiced using screen readers
+               focus.focus(node.labelNode);
        },
 
-       _removeReferenceFromMap: function(/* item */ refItem, /* item */ parentItem, /*strin*/ attribute){
-               //      summary:
-               //              Method to remove an reference map entry for an item and attribute.
-               //      description:
-               //              Method to remove an reference map entry for an item and attribute.  This will
-               //              also perform cleanup on the map such that if there are no more references at all to 
-               //              the item, its reference object and entry are removed.
-               //
-               //      refItem:
-               //              The item that is referenced.
-               //      parentItem:
-               //              The item holding a reference to refItem.
-               //      attribute:
-               //              The attribute on parentItem that contains the reference.
-               var identity = this.getIdentity(parentItem);
-               var references = refItem[this._reverseRefMap];
-               var itemId;
-               if(references){
-                       for(itemId in references){
-                               if(itemId == identity){
-                                       delete references[itemId][attribute];
-                                       if(this._isEmpty(references[itemId])){
-                                               delete references[itemId];
-                                       }
-                               }
-                       }
-                       if(this._isEmpty(references)){
-                               delete refItem[this._reverseRefMap];
+       _onNodeFocus: function(/*dijit._Widget*/ node){
+               // summary:
+               //              Called when a TreeNode gets focus, either by user clicking
+               //              it, or programatically by arrow key handling code.
+               // description:
+               //              It marks that the current node is the selected one, and the previously
+               //              selected node no longer is.
+
+               if(node && node != this.lastFocused){
+                       if(this.lastFocused && !this.lastFocused._destroyed){
+                               // mark that the previously focsable node is no longer focusable
+                               this.lastFocused.setFocusable(false);
                        }
+
+                       // mark that the new node is the currently selected one
+                       node.setFocusable(true);
+                       this.lastFocused = node;
                }
        },
 
-       _dumpReferenceMap: function(){
-               //      summary:
-               //              Function to dump the reverse reference map of all items in the store for debug purposes.
-               //      description:
-               //              Function to dump the reverse reference map of all items in the store for debug purposes.
-               var i;
-               for(i = 0; i < this._arrayOfAllItems.length; i++){
-                       var item = this._arrayOfAllItems[i];
-                       if(item && item[this._reverseRefMap]){
-                               console.log("Item: [" + this.getIdentity(item) + "] is referenced by: " + dojo.toJson(item[this._reverseRefMap]));
-                       }
-               }
+       _onNodeMouseEnter: function(/*dijit._Widget*/ /*===== node =====*/){
+               // summary:
+               //              Called when mouse is over a node (onmouseenter event),
+               //              this is monitored by the DND code
        },
-       
-       _getValueOrValues: function(/* item */ item, /* attribute-name-string */ attribute){
-               var valueOrValues = undefined;
-               if(this.hasAttribute(item, attribute)){
-                       var valueArray = this.getValues(item, attribute);
-                       if(valueArray.length == 1){
-                               valueOrValues = valueArray[0];
-                       }else{
-                               valueOrValues = valueArray;
-                       }
-               }
-               return valueOrValues;
+
+       _onNodeMouseLeave: function(/*dijit._Widget*/ /*===== node =====*/){
+               // summary:
+               //              Called when mouse leaves a node (onmouseleave event),
+               //              this is monitored by the DND code
        },
-       
-       _flatten: function(/* anything */ value){
-               if(this.isItem(value)){
-                       var item = value;
-                       // Given an item, return an serializable object that provides a 
-                       // reference to the item.
-                       // For example, given kermit:
-                       //    var kermit = store.newItem({id:2, name:"Kermit"});
-                       // we want to return
-                       //    {_reference:2}
-                       var identity = this.getIdentity(item);
-                       var referenceObject = {_reference: identity};
-                       return referenceObject;
-               }else{
-                       if(typeof value === "object"){
-                               for(var type in this._datatypeMap){
-                                       var typeMap = this._datatypeMap[type];
-                                       if(dojo.isObject(typeMap) && !dojo.isFunction(typeMap)){
-                                               if(value instanceof typeMap.type){
-                                                       if(!typeMap.serialize){
-                                                               throw new Error("ItemFileWriteStore:  No serializer defined for type mapping: [" + type + "]");
-                                                       }
-                                                       return {_type: type, _value: typeMap.serialize(value)};
-                                               }
-                                       } else if(value instanceof typeMap){
-                                               //SImple mapping, therefore, return as a toString serialization.
-                                               return {_type: type, _value: value.toString()};
-                                       }
-                               }
-                       }
-                       return value;
+
+       //////////////// Events from the model //////////////////////////
+
+       _onItemChange: function(/*Item*/ item){
+               // summary:
+               //              Processes notification of a change to an item's scalar values like label
+               var model = this.model,
+                       identity = model.getIdentity(item),
+                       nodes = this._itemNodesMap[identity];
+
+               if(nodes){
+                       var label = this.getLabel(item),
+                               tooltip = this.getTooltip(item);
+                       array.forEach(nodes, function(node){
+                               node.set({
+                                       item: item,             // theoretically could be new JS Object representing same item
+                                       label: label,
+                                       tooltip: tooltip
+                               });
+                               node._updateItemClasses(item);
+                       });
                }
        },
-       
-       _getNewFileContentString: function(){
-               // summary: 
-               //              Generate a string that can be saved to a file.
-               //              The result should look similar to:
-               //              http://trac.dojotoolkit.org/browser/dojo/trunk/tests/data/countries.json
-               var serializableStructure = {};
-               
-               var identifierAttribute = this._getIdentifierAttribute();
-               if(identifierAttribute !== Number){
-                       serializableStructure.identifier = identifierAttribute;
-               }
-               if(this._labelAttr){
-                       serializableStructure.label = this._labelAttr;
+
+       _onItemChildrenChange: function(/*dojo.data.Item*/ parent, /*dojo.data.Item[]*/ newChildrenList){
+               // summary:
+               //              Processes notification of a change to an item's children
+               var model = this.model,
+                       identity = model.getIdentity(parent),
+                       parentNodes = this._itemNodesMap[identity];
+
+               if(parentNodes){
+                       array.forEach(parentNodes,function(parentNode){
+                               parentNode.setChildItems(newChildrenList);
+                       });
                }
-               serializableStructure.items = [];
-               for(var i = 0; i < this._arrayOfAllItems.length; ++i){
-                       var item = this._arrayOfAllItems[i];
-                       if(item !== null){
-                               var serializableItem = {};
-                               for(var key in item){
-                                       if(key !== this._storeRefPropName && key !== this._itemNumPropName && key !== this._reverseRefMap && key !== this._rootItemPropName){
-                                               var attribute = key;
-                                               var valueArray = this.getValues(item, attribute);
-                                               if(valueArray.length == 1){
-                                                       serializableItem[attribute] = this._flatten(valueArray[0]);
-                                               }else{
-                                                       var serializableArray = [];
-                                                       for(var j = 0; j < valueArray.length; ++j){
-                                                               serializableArray.push(this._flatten(valueArray[j]));
-                                                               serializableItem[attribute] = serializableArray;
-                                                       }
-                                               }
-                                       }
+       },
+
+       _onItemDelete: function(/*Item*/ item){
+               // summary:
+               //              Processes notification of a deletion of an item
+               var model = this.model,
+                       identity = model.getIdentity(item),
+                       nodes = this._itemNodesMap[identity];
+
+               if(nodes){
+                       array.forEach(nodes,function(node){
+                               // Remove node from set of selected nodes (if it's selected)
+                               this.dndController.removeTreeNode(node);
+
+                               var parent = node.getParent();
+                               if(parent){
+                                       // if node has not already been orphaned from a _onSetItem(parent, "children", ..) call...
+                                       parent.removeChild(node);
                                }
-                               serializableStructure.items.push(serializableItem);
-                       }
+                               node.destroyRecursive();
+                       }, this);
+                       delete this._itemNodesMap[identity];
                }
-               var prettyPrint = true;
-               return dojo.toJson(serializableStructure, prettyPrint);
        },
 
-       _isEmpty: function(something){
-               //      summary: 
-               //              Function to determine if an array or object has no properties or values.
-               //      something:
-               //              The array or object to examine.
-               var empty = true;
-               if(dojo.isObject(something)){
-                       var i;
-                       for(i in something){
-                               empty = false;
-                               break;
-                       }
-               }else if(dojo.isArray(something)){
-                       if(something.length > 0){
-                               empty = false;
-                       }
-               }
-               return empty; //boolean
-       },
-       
-       save: function(/* object */ keywordArgs){
-               // summary: See dojo.data.api.Write.save()
-               this._assert(!this._saveInProgress);
-               
-               // this._saveInProgress is set to true, briefly, from when save is first called to when it completes
-               this._saveInProgress = true;
-               
-               var self = this;
-               var saveCompleteCallback = function(){
-                       self._pending = {
-                               _newItems:{}, 
-                               _modifiedItems:{},
-                               _deletedItems:{}
-                       };
+       /////////////// Miscellaneous funcs
 
-                       self._saveInProgress = false; // must come after this._pending is cleared, but before any callbacks
-                       if(keywordArgs && keywordArgs.onComplete){
-                               var scope = keywordArgs.scope || dojo.global;
-                               keywordArgs.onComplete.call(scope);
-                       }
-               };
-               var saveFailedCallback = function(err){
-                       self._saveInProgress = false;
-                       if(keywordArgs && keywordArgs.onError){
-                               var scope = keywordArgs.scope || dojo.global;
-                               keywordArgs.onError.call(scope, err);
+       _initState: function(){
+               // summary:
+               //              Load in which nodes should be opened automatically
+               this._openedNodes = {};
+               if(this.persist && this.cookieName){
+                       var oreo = cookie(this.cookieName);
+                       if(oreo){
+                               array.forEach(oreo.split(','), function(item){
+                                       this._openedNodes[item] = true;
+                               }, this);
                        }
-               };
-               
-               if(this._saveEverything){
-                       var newFileContentString = this._getNewFileContentString();
-                       this._saveEverything(saveCompleteCallback, saveFailedCallback, newFileContentString);
-               }
-               if(this._saveCustom){
-                       this._saveCustom(saveCompleteCallback, saveFailedCallback);
-               }
-               if(!this._saveEverything && !this._saveCustom){
-                       // Looks like there is no user-defined save-handler function.
-                       // That's fine, it just means the datastore is acting as a "mock-write"
-                       // store -- changes get saved in memory but don't get saved to disk.
-                       saveCompleteCallback();
                }
        },
-       
-       revert: function(){
-               // summary: See dojo.data.api.Write.revert()
-               this._assert(!this._saveInProgress);
-
-               var identity;
-               for(identity in this._pending._modifiedItems){
-                       // find the original item and the modified item that replaced it
-                       var copyOfItemState = this._pending._modifiedItems[identity];
-                       var modifiedItem = null;
-                       if(this._itemsByIdentity){
-                               modifiedItem = this._itemsByIdentity[identity];
+       _state: function(node, expanded){
+               // summary:
+               //              Query or set expanded state for an node
+               if(!this.persist){
+                       return false;
+               }
+               var path = array.map(node.getTreePath(), function(item){
+                               return this.model.getIdentity(item);
+                       }, this).join("/");
+               if(arguments.length === 1){
+                       return this._openedNodes[path];
+               }else{
+                       if(expanded){
+                               this._openedNodes[path] = true;
                        }else{
-                               modifiedItem = this._arrayOfAllItems[identity];
+                               delete this._openedNodes[path];
                        }
-       
-                       // Restore the original item into a full-fledged item again, we want to try to 
-                       // keep the same object instance as if we don't it, causes bugs like #9022.
-                       copyOfItemState[this._storeRefPropName] = this;
-                       for(key in modifiedItem){
-                               delete modifiedItem[key];
+                       var ary = [];
+                       for(var id in this._openedNodes){
+                               ary.push(id);
                        }
-                       dojo.mixin(modifiedItem, copyOfItemState);
+                       cookie(this.cookieName, ary.join(","), {expires:365});
                }
-               var deletedItem;
-               for(identity in this._pending._deletedItems){
-                       deletedItem = this._pending._deletedItems[identity];
-                       deletedItem[this._storeRefPropName] = this;
-                       var index = deletedItem[this._itemNumPropName];
+       },
 
-                       //Restore the reverse refererence map, if any.
-                       if(deletedItem["backup_" + this._reverseRefMap]){
-                               deletedItem[this._reverseRefMap] = deletedItem["backup_" + this._reverseRefMap];
-                               delete deletedItem["backup_" + this._reverseRefMap];
-                       }
-                       this._arrayOfAllItems[index] = deletedItem;
-                       if(this._itemsByIdentity){
-                               this._itemsByIdentity[identity] = deletedItem;
-                       }
-                       if(deletedItem[this._rootItemPropName]){
-                               this._arrayOfTopLevelItems.push(deletedItem);
-                       }
+       destroy: function(){
+               if(this._curSearch){
+                       clearTimeout(this._curSearch.timer);
+                       delete this._curSearch;
                }
-               //We have to pass through it again and restore the reference maps after all the
-               //undeletes have occurred.
-               for(identity in this._pending._deletedItems){
-                       deletedItem = this._pending._deletedItems[identity];
-                       if(deletedItem["backupRefs_" + this._reverseRefMap]){
-                               dojo.forEach(deletedItem["backupRefs_" + this._reverseRefMap], function(reference){
-                                       var refItem;
-                                       if(this._itemsByIdentity){
-                                               refItem = this._itemsByIdentity[reference.id];
-                                       }else{
-                                               refItem = this._arrayOfAllItems[reference.id];
-                                       }
-                                       this._addReferenceToMap(refItem, deletedItem, reference.attr);
-                               }, this);
-                               delete deletedItem["backupRefs_" + this._reverseRefMap]; 
-                       }
+               if(this.rootNode){
+                       this.rootNode.destroyRecursive();
                }
-
-               for(identity in this._pending._newItems){
-                       var newItem = this._pending._newItems[identity];
-                       newItem[this._storeRefPropName] = null;
-                       // null out the new item, but don't change the array index so
-                       // so we can keep using _arrayOfAllItems.length.
-                       this._arrayOfAllItems[newItem[this._itemNumPropName]] = null;
-                       if(newItem[this._rootItemPropName]){
-                               this._removeArrayElement(this._arrayOfTopLevelItems, newItem);
-                       }
-                       if(this._itemsByIdentity){
-                               delete this._itemsByIdentity[identity];
-                       }
+               if(this.dndController && !lang.isString(this.dndController)){
+                       this.dndController.destroy();
                }
+               this.rootNode = null;
+               this.inherited(arguments);
+       },
 
-               this._pending = {
-                       _newItems:{}, 
-                       _modifiedItems:{}, 
-                       _deletedItems:{}
-               };
-               return true; // boolean
+       destroyRecursive: function(){
+               // A tree is treated as a leaf, not as a node with children (like a grid),
+               // but defining destroyRecursive for back-compat.
+               this.destroy();
        },
-       
-       isDirty: function(/* item? */ item){
-               // summary: See dojo.data.api.Write.isDirty()
-               if(item){
-                       // return true if the item is dirty
-                       var identity = this.getIdentity(item);
-                       return new Boolean(this._pending._newItems[identity] || 
-                               this._pending._modifiedItems[identity] ||
-                               this._pending._deletedItems[identity]).valueOf(); // boolean
-               }else{
-                       // return true if the store is dirty -- which means return true
-                       // if there are any new items, dirty items, or modified items
-                       if(!this._isEmpty(this._pending._newItems) || 
-                               !this._isEmpty(this._pending._modifiedItems) ||
-                               !this._isEmpty(this._pending._deletedItems)){
-                               return true;
-                       }
-                       return false; // boolean
+
+       resize: function(changeSize){
+               if(changeSize){
+                       domGeometry.setMarginBox(this.domNode, changeSize);
                }
-       },
 
-/* dojo.data.api.Notification */
+               // The only JS sizing involved w/tree is the indentation, which is specified
+               // in CSS and read in through this dummy indentDetector node (tree must be
+               // visible and attached to the DOM to read this)
+               this._nodePixelIndent = domGeometry.position(this.tree.indentDetector).w;
 
-       onSet: function(/* item */ item, 
-                                       /*attribute-name-string*/ attribute, 
-                                       /*object | array*/ oldValue,
-                                       /*object | array*/ newValue){
-               // summary: See dojo.data.api.Notification.onSet()
-               
-               // No need to do anything. This method is here just so that the 
-               // client code can connect observers to it.
+               if(this.tree.rootNode){
+                       // If tree has already loaded, then reset indent for all the nodes
+                       this.tree.rootNode.set('indent', this.showRoot ? 0 : -1);
+               }
        },
 
-       onNew: function(/* item */ newItem, /*object?*/ parentInfo){
-               // summary: See dojo.data.api.Notification.onNew()
-               
-               // No need to do anything. This method is here just so that the 
-               // client code can connect observers to it. 
+       _createTreeNode: function(/*Object*/ args){
+               // summary:
+               //              creates a TreeNode
+               // description:
+               //              Developers can override this method to define their own TreeNode class;
+               //              However it will probably be removed in a future release in favor of a way
+               //              of just specifying a widget for the label, rather than one that contains
+               //              the children too.
+               return new TreeNode(args);
        },
 
-       onDelete: function(/* item */ deletedItem){
-               // summary: See dojo.data.api.Notification.onDelete()
-               
-               // No need to do anything. This method is here just so that the 
-               // client code can connect observers to it. 
-       },
+       _setTextDirAttr: function(textDir){
+               if(textDir && this.textDir!= textDir){
+                       this._set("textDir",textDir);
+                       this.rootNode.set("textDir", textDir);
+               }
+       }
+});
 
-       close: function(/* object? */ request){
-                // summary:
-                //             Over-ride of base close function of ItemFileReadStore to add in check for store state.
-                // description:
-                //             Over-ride of base close function of ItemFileReadStore to add in check for store state.
-                //             If the store is still dirty (unsaved changes), then an error will be thrown instead of
-                //             clearing the internal state for reload from the url.
+Tree._TreeNode = TreeNode;     // for monkey patching
 
-                //Clear if not dirty ... or throw an error
-                if(this.clearOnClose){
-                        if(!this.isDirty()){
-                                this.inherited(arguments);
-                        }else{
-                                //Only throw an error if the store was dirty and we were loading from a url (cannot reload from url until state is saved).
-                                throw new Error("dojo.data.ItemFileWriteStore: There are unsaved changes present in the store.  Please save or revert the changes before invoking close.");
-                        }
-                }
-       }
+return Tree;
 });
 
-}
+},
+'dijit/form/_FormValueWidget':function(){
+define("dijit/form/_FormValueWidget", [
+       "dojo/_base/declare", // declare
+       "dojo/_base/sniff", // has("ie")
+       "./_FormWidget",
+       "./_FormValueMixin"
+], function(declare, has, _FormWidget, _FormValueMixin){
+
+/*=====
+var _FormWidget = dijit.form._FormWidget;
+var _FormValueMixin = dijit.form._FormValueMixin;
+=====*/
+
+// module:
+//             dijit/form/_FormValueWidget
+// summary:
+//             FormValueWidget
+
+
+return declare("dijit.form._FormValueWidget", [_FormWidget, _FormValueMixin],
+{
+       // summary:
+       //              Base class for widgets corresponding to native HTML elements such as <input> or <select> that have user changeable values.
+       // description:
+       //              Each _FormValueWidget represents a single input value, and has a (possibly hidden) <input> element,
+       //              to which it serializes it's input value, so that form submission (either normal submission or via FormBind?)
+       //              works as expected.
+
+       // Don't attempt to mixin the 'type', 'name' attributes here programatically -- they must be declared
+       // directly in the template as read by the parser in order to function. IE is known to specifically
+       // require the 'name' attribute at element creation time.  See #8484, #8660.
+
+       _layoutHackIE7: function(){
+               // summary:
+               //              Work around table sizing bugs on IE7 by forcing redraw
+
+               if(has("ie") == 7){ // fix IE7 layout bug when the widget is scrolled out of sight
+                       var domNode = this.domNode;
+                       var parent = domNode.parentNode;
+                       var pingNode = domNode.firstChild || domNode; // target node most unlikely to have a custom filter
+                       var origFilter = pingNode.style.filter; // save custom filter, most likely nothing
+                       var _this = this;
+                       while(parent && parent.clientHeight == 0){ // search for parents that haven't rendered yet
+                               (function ping(){
+                                       var disconnectHandle = _this.connect(parent, "onscroll",
+                                               function(){
+                                                       _this.disconnect(disconnectHandle); // only call once
+                                                       pingNode.style.filter = (new Date()).getMilliseconds(); // set to anything that's unique
+                                                       setTimeout(function(){ pingNode.style.filter = origFilter }, 0); // restore custom filter, if any
+                                               }
+                                       );
+                               })();
+                               parent = parent.parentNode;
+                       }
+               }
+       }
+});
 
+});
 
-dojo.i18n._preloadLocalizations("dojo.nls.tt-rss-layer", ["ROOT","ar","ca","cs","da","de","de-de","el","en","en-gb","en-us","es","es-es","fi","fi-fi","fr","fr-fr","he","he-il","hu","it","it-it","ja","ja-jp","ko","ko-kr","nb","nl","nl-nl","pl","pt","pt-br","pt-pt","ru","sk","sl","sv","th","tr","xx","zh","zh-cn","zh-tw"]);
+},
+'*now':function(r){r(['dojo/i18n!*preload*dojo/nls/tt-rss-layer*["ar","ca","cs","da","de-de","el","en-gb","en-us","es-es","fi-fi","fr-fr","he-il","hu","it-it","ja-jp","ko-kr","nl-nl","nb","pl","pt-br","pt-pt","ru","sk","sl","sv","th","tr","zh-tw","zh-cn","ROOT"]']);}
+}});
+define("dojo/tt-rss-layer", [], 1);