text: define([
  	"dojo/_base/array", // array.forEach array.indexOf array.some
  	"dojo/cookie", // cookie
  	"dojo/_base/declare", // declare
  	"dojo/dom-class", // domClass.add domClass.replace
  	"dojo/dom-construct",
  	"dojo/has", // has("dijit-legacy-requires")
  	"dojo/_base/lang", // lang.extend
  	"dojo/on",
  	"dojo/ready",
  	"dojo/topic", // publish
  	"dojo/when",
  	"../registry", // registry.byId
  	"../_WidgetBase",
  	"./_LayoutWidget"
  ], function(array, cookie, declare, domClass, domConstruct, has, lang, on, ready, topic, when, registry, _WidgetBase, _LayoutWidget){
  
  	// module:
  	//		dijit/layout/StackContainer
  
  	// Back compat w/1.6, remove for 2.0
  	if(has("dijit-legacy-requires")){
  		ready(0, function(){
  			var requires = ["dijit/layout/StackController"];
  			require(requires);	// use indirection so modules not rolled into a build
  		});
  	}
  
  	var StackContainer = declare("dijit.layout.StackContainer", _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.
  		//
  		//		See `StackContainer.ChildWidgetProperties` for details on the properties that can be set on
  		//		children of a `StackContainer`.
  
  		// doLayout: Boolean
  		//		If true, change the size of my currently displayed child to match my size
  		doLayout: true,
  
  		// persist: Boolean
  		//		Remembers the selected child across sessions
  		persist: false,
  
  		baseClass: "dijitStackContainer",
  
  		/*=====
  		// selectedChildWidget: [readonly] dijit._Widget
  		//		References the currently selected child widget, if any.
  		//		Adjust selected child with selectChild() method.
  		selectedChildWidget: null,
  		=====*/
  
  		buildRendering: function(){
  			this.inherited(arguments);
  			domClass.add(this.domNode, "dijitLayoutContainer");
  		},
  
  		postCreate: function(){
  			this.inherited(arguments);
  			this.own(
  				on(this.domNode, "keydown", lang.hitch(this, "_onKeyDown"))
  			);
  		},
  
  		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;
  			}
  
  			// 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, textDir: this.textDir});
  
  			// 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(){
  			// Overrides _LayoutWidget.resize()
  			// 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.inherited(arguments);
  		},
  
  		_setupChild: function(/*dijit/_WidgetBase*/ child){
  			// Overrides _LayoutWidget._setupChild()
  
  			// For aria support, wrap child widget in a <div role="tabpanel">
  			var childNode = child.domNode,
  				wrapper = domConstruct.place(
  					"<div role='tabpanel' class='" + this.baseClass + "ChildWrapper dijitHidden'>",
  					child.domNode,
  					"replace"),
  				label = child["aria-label"] || child.title || child.label;
  			if(label){
  				// setAttribute() escapes special chars, and if() statement avoids setting aria-label="undefined"
  				wrapper.setAttribute("aria-label", label);
  			}
  			domConstruct.place(childNode, wrapper);
  			child._wrapper = wrapper;	// to set the aria-labelledby in StackController
  
  			this.inherited(arguments);
  
  			// child may have style="display: none" (at least our test cases do), so remove that
  			if(childNode.style.display == "none"){
  				childNode.style.display = "block";
  			}
  
  			// remove the title attribute so it doesn't show up when i hover over a node
  			child.domNode.removeAttribute("title");
  		},
  
  		addChild: function(/*dijit/_WidgetBase*/ 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/_WidgetBase*/ page){
  			// Overrides _Container.removeChild() to do layout and publish events
  
        var idx;
        if (typeof page === 'number') {
          idx = page;
          arguments[0] = this.getChildren()[page];
        } else {
          idx = array.indexOf(this.getChildren(), page);
        }
  
  			this.inherited(arguments);
  
  			// Remove the child widget wrapper we use to set aria roles.  This won't affect the page itself since it's
  			// already been detached from page._wrapper via the this.inherited(arguments) call above.
  			domConstruct.destroy(page._wrapper);
  			delete page._wrapper;
  
  			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);
  			}
  
  			// 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;
  			}
  
  			// 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[Math.max(idx - 1, 0)]);
  					}
  				}
  			}
  
  			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();
  			}
  		},
  
  		selectChild: function(/*dijit/_WidgetBase|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
  
  			var d;
  
  			page = registry.byId(page);
  
  			if(this.selectedChildWidget != page){
  				// Deselect old page and select new one
  				d = this._transition(page, this.selectedChildWidget, animate);
  				this._set("selectedChildWidget", page);
  				topic.publish(this.id + "-selectChild", page);	// publish
  
  				if(this.persist){
  					cookie(this.id + "_selectedChild", this.selectedChildWidget.id);
  				}
  			}
  
  			// d may be null, or a scalar like true.  Return a promise in all cases
  			return when(d || true);		// Promise
  		},
  
  		_transition: function(newWidget, oldWidget /*===== ,  animate =====*/){
  			// summary:
  			//		Hide the old widget and display the new widget.
  			//		Subclasses should override this.
  			// newWidget: dijit/_WidgetBase
  			//		The newly selected widget.
  			// oldWidget: dijit/_WidgetBase
  			//		The previously selected widget.
  			// animate: Boolean
  			//		Used by AccordionContainer to turn on/off slide effect.
  			// tags:
  			//		protected extension
  			if(oldWidget){
  				this._hideChild(oldWidget);
  			}
  			var d = this._showChild(newWidget);
  
  			// 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();
  				}
  			}
  
  			return d;	// If child has an href, promise that fires when the child's href finishes loading
  		},
  
  		_adjacent: function(/*Boolean*/ forward){
  			// summary:
  			//		Gets the next/previous child widget in this container from the current selection.
  
  			// TODO: remove for 2.0 if this isn't being used.   Otherwise, fix to skip disabled tabs.
  
  			var children = this.getChildren();
  			var index = array.indexOf(children, this.selectedChildWidget);
  			index += forward ? 1 : children.length - 1;
  			return children[ index % children.length ]; // dijit/_WidgetBase
  		},
  
  		forward: function(){
  			// summary:
  			//		Advance to next page.
  			return this.selectChild(this._adjacent(true), true);
  		},
  
  		back: function(){
  			// summary:
  			//		Go back to previous page.
  			return this.selectChild(this._adjacent(false), true);
  		},
  
  		_onKeyDown: function(e){
  			topic.publish(this.id + "-containerKeyDown", { e: e, page: this});	// publish
  		},
  
  		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();
  				}
  			}
  		},
  
  		_showChild: function(/*dijit/_WidgetBase*/ page){
  			// 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.
  			// 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);
  
  			if(page._wrapper){	// false if not started yet
  				domClass.replace(page._wrapper, "dijitVisible", "dijitHidden");
  			}
  
  			return (page._onShow && page._onShow()) || true;
  		},
  
  		_hideChild: function(/*dijit/_WidgetBase*/ page){
  			// summary:
  			//		Hide the specified child by changing it's CSS, and call _onHide() so
  			//		it's notified.
  			page._set("selected", false);
  
  			if(page._wrapper){	// false if not started yet
  				domClass.replace(page._wrapper, "dijitHidden", "dijitVisible");
  			}
  
  			page.onHide && page.onHide();
  		},
  
  		closeChild: function(/*dijit/_WidgetBase*/ 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 && page.onClose(this, page);
  			if(remove){
  				this.removeChild(page);
  				// makes sure we can clean up executeScripts in ContentPane onUnLoad
  				page.destroyRecursive();
  			}
  		},
  
  		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;
  		}
  	});
  
  	StackContainer.ChildWidgetProperties = {
  		// summary:
  		//		These properties can be specified for the children of a StackContainer.
  
  		// selected: Boolean
  		//		Specifies that this widget should be the initially displayed pane.
  		//		Note: to change the selected child use `dijit/layout/StackContainer.selectChild`
  		selected: false,
  
  		// disabled: Boolean
  		//		Specifies that the button to select this pane should be disabled.
  		//		Doesn't affect programmatic selection of the pane, nor does it deselect the pane if it is currently selected.
  		disabled: false,
  
  		// closable: Boolean
  		//		True if user can close (destroy) this child, such as (for example) clicking the X on the tab.
  		closable: false,
  
  		// iconClass: String
  		//		CSS Class specifying icon to use in label associated with this pane.
  		iconClass: "dijitNoIcon",
  
  		// showTitle: Boolean
  		//		When true, display title of this widget as tab label etc., rather than just using
  		//		icon specified in iconClass
  		showTitle: true
  	};
  
  	// 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.)
  	// This is for the benefit of the parser.   Remove for 2.0.  Also, hide from doc viewer.
  	lang.extend(_WidgetBase, /*===== {} || =====*/ StackContainer.ChildWidgetProperties);
  
  	return StackContainer;
  });
  