text: define("dojox/mobile/SpinWheelSlot", [
  	"dojo/_base/declare",
  	"dojo/_base/window",
  	"dojo/dom-class",
  	"dojo/dom-construct",
  	"dijit/_Contained",
  	"dijit/_WidgetBase",
  	"./_ScrollableMixin"
  ], function(declare, win, domClass, domConstruct, Contained, WidgetBase, ScrollableMixin){
  
  /*=====
  	var Contained = dijit._Contained;
  	var WidgetBase = dijit._WidgetBase;
  	var ScrollableMixin = dojox.mobile._ScrollableMixin;
  =====*/
  
  	// module:
  	//		dojox/mobile/SpinWheelSlot
  	// summary:
  	//		A slot of a SpinWheel.
  
  	return declare("dojox.mobile.SpinWheelSlot", [WidgetBase, Contained, ScrollableMixin], {
  		// summary:
  		//		A slot of a SpinWheel.
  		// description:
  		//		SpinWheelSlot is a slot that is placed in the SpinWheel widget.
  
  		// items: Array
  		//		An array of array of key-label paris.
  		//		(e.g. [[0,"Jan"],[1,"Feb"],...] ) If key values for each label
  		//		are not necessary, labels can be used instead.
  		items: [],
  
  		// labels: Array
  		//		An array of labels to be displayed on the slot.
  		//		(e.g. ["Jan","Feb",...] ) This is a simplified version of the
  		//		items property.
  		labels: [],
  
  		// labelFrom: Number
  		//		The start value of display values of the slot. This parameter is
  		//		especially useful when slot has serial values.
  		labelFrom: 0,
  
  		// labelTo: Number
  		//		The end value of display values of the slot.
  		labelTo: 0,
  
  		// value: String
  		//		The initial value of the slot.
  		value: "",
  
  		/* internal properties */	
  		maxSpeed: 500,
  		minItems: 15,
  		centerPos: 0,
  		scrollBar: false,
  		constraint: false,
  		allowNestedScrolls: false,
  		androidWorkaroud: false, // disable workaround in SpinWheel
  
  		buildRendering: function(){
  			this.inherited(arguments);
  			domClass.add(this.domNode, "mblSpinWheelSlot");
  
  			var i, j, idx;
  			if(this.labelFrom !== this.labelTo){
  				this.labels = [];
  				for(i = this.labelFrom, idx = 0; i <= this.labelTo; i++, idx++){
  					this.labels[idx] = String(i);
  				}
  			}
  			if(this.labels.length > 0){
  				this.items = [];
  				for(i = 0; i < this.labels.length; i++){
  					this.items.push([i, this.labels[i]]);
  				}
  			}
  
  			this.containerNode = domConstruct.create("DIV", {className:"mblSpinWheelSlotContainer"});
  			this.containerNode.style.height
  				= (win.global.innerHeight||win.doc.documentElement.clientHeight) * 2 + "px"; // must bigger than the screen
  			this.panelNodes = [];
  			for(var k = 0; k < 3; k++){
  				this.panelNodes[k] = domConstruct.create("DIV", {className:"mblSpinWheelSlotPanel"});
  				var len = this.items.length;
  				var n = Math.ceil(this.minItems / len);
  				for(j = 0; j < n; j++){
  					for(i = 0; i < len; i++){
  						domConstruct.create("DIV", {
  							className: "mblSpinWheelSlotLabel",
  							name: this.items[i][0],
  							innerHTML: this._cv ? this._cv(this.items[i][1]) : this.items[i][1]
  						}, this.panelNodes[k]);
  					}
  				}
  				this.containerNode.appendChild(this.panelNodes[k]);
  			}
  			this.domNode.appendChild(this.containerNode);
  			this.touchNode = domConstruct.create("DIV", {className:"mblSpinWheelSlotTouch"}, this.domNode);
  			this.setSelectable(this.domNode, false);
  		},
  	
  		startup: function(){
  			this.inherited(arguments);
  			this.centerPos = this.getParent().centerPos;
  			var items = this.panelNodes[1].childNodes;
  			this._itemHeight = items[0].offsetHeight;
  			this.adjust();
  		},
  	
  		adjust: function(){
  			// summary:
  			//		Adjusts the position of slot panels.
  			var items = this.panelNodes[1].childNodes;
  			var adjustY;
  			for(var i = 0, len = items.length; i < len; i++){
  				var item = items[i];
  				if(item.offsetTop <= this.centerPos && this.centerPos < item.offsetTop + item.offsetHeight){
  					adjustY = this.centerPos - (item.offsetTop + Math.round(item.offsetHeight/2));
  					break;
  				}
  			}
  			var h = this.panelNodes[0].offsetHeight;
  			this.panelNodes[0].style.top = -h + adjustY + "px";
  			this.panelNodes[1].style.top = adjustY + "px";
  			this.panelNodes[2].style.top = h + adjustY + "px";
  		},
  	
  		setInitialValue: function(){
  			// summary:
  			//		Sets the initial value using this.value or the first item.
  			if(this.items.length > 0){
  				var val = (this.value !== "") ? this.value : this.items[0][1];
  				this.setValue(val);
  			}
  		},
  	
  		getCenterPanel: function(){
  			// summary:
  			//		Gets a panel that contains the currently selected item.
  			var pos = this.getPos();
  			for(var i = 0, len = this.panelNodes.length; i < len; i++){
  				var top = pos.y + this.panelNodes[i].offsetTop;
  				if(top <= this.centerPos && this.centerPos < top + this.panelNodes[i].offsetHeight){
  					return this.panelNodes[i];
  				}
  			}
  			return null;
  		},
  	
  		setColor: function(/*String*/value){
  			// summary:
  			//		Sets the color of the specified item as blue.
  			for(var i = 0, len = this.panelNodes.length; i < len; i++){
  				var items = this.panelNodes[i].childNodes;
  				for(var j = 0; j < items.length; j++){
  					if(items[j].innerHTML === String(value)){
  						domClass.add(items[j], "mblSpinWheelSlotLabelBlue");
  					}else{
  						domClass.remove(items[j], "mblSpinWheelSlotLabelBlue");
  					}
  				}
  			}
  		},
  	
  		disableValues: function(/*Array*/values){
  			// summary:
  			//		Makes the specified items grayed out.
  			for(var i = 0, len = this.panelNodes.length; i < len; i++){
  				var items = this.panelNodes[i].childNodes;
  				for(var j = 0; j < items.length; j++){
  					domClass.remove(items[j], "mblSpinWheelSlotLabelGray");
  					for(var k = 0; k < values.length; k++){
  						if(items[j].innerHTML === String(values[k])){
  							domClass.add(items[j], "mblSpinWheelSlotLabelGray");
  							break;
  						}
  					}
  				}
  			}
  		},
  	
  		getCenterItem: function(){
  			// summary:
  			//		Gets the currently selected item.
  			var pos = this.getPos();
  			var centerPanel = this.getCenterPanel();
  			if(centerPanel){
  				var top = pos.y + centerPanel.offsetTop;
  				var items = centerPanel.childNodes;
  				for(var i = 0, len = items.length; i < len; i++){
  					if(top + items[i].offsetTop <= this.centerPos && this.centerPos < top + items[i].offsetTop + items[i].offsetHeight){
  						return items[i];
  					}
  				}
  			}
  			return null;
  	
  		},
  	
  		getValue: function(){
  			// summary:
  			//		Gets the currently selected value.
  			var item = this.getCenterItem();
  			return (item && item.innerHTML);
  		},
  	
  		getKey: function(){
  			// summary:
  			//		Gets the key for the currently selected value.
  			return this.getCenterItem().getAttribute("name");
  		},
  	
  		setValue: function(newValue){
  			// summary:
  			//		Sets the newValue to this slot.
  			var idx0, idx1;
  			var curValue = this.getValue();
  			if(!curValue){
  				this._penddingValue = newValue;
  				return;
  			}
  			this._penddingValue = undefined;
  			var n = this.items.length;
  			for(var i = 0; i < n; i++){
  				if(this.items[i][1] === String(curValue)){
  					idx0 = i;
  				}
  				if(this.items[i][1] === String(newValue)){
  					idx1 = i;
  				}
  				if(idx0 !== undefined && idx1 !== undefined){
  					break;
  				}
  			}
  			var d = idx1 - (idx0 || 0);
  			var m;
  			if(d > 0){
  				m = (d < n - d) ? -d : n - d;
  			}else{
  				m = (-d < n + d) ? -d : -(n + d);
  			}
  			var to = this.getPos();
  			to.y += m * this._itemHeight;
  			this.slideTo(to, 1);
  		},
  	
  		getSpeed: function(){
  			// summary:
  			//		Overrides dojox.mobile.scrollable.getSpeed().
  			var y = 0, n = this._time.length;
  			var delta = (new Date()).getTime() - this.startTime - this._time[n - 1];
  			if(n >= 2 && delta < 200){
  				var dy = this._posY[n - 1] - this._posY[(n - 6) >= 0 ? n - 6 : 0];
  				var dt = this._time[n - 1] - this._time[(n - 6) >= 0 ? n - 6 : 0];
  				y = this.calcSpeed(dy, dt);
  			}
  			return {x:0, y:y};
  		},
  
  		calcSpeed: function(/*Number*/d, /*Number*/t){
  			// summary:
  			//		Overrides dojox.mobile.scrollable.calcSpeed().
  			var speed = this.inherited(arguments);
  			if(!speed){ return 0; }
  			var v = Math.abs(speed);
  			var ret = speed;
  			if(v > this.maxSpeed){
  				ret = this.maxSpeed*(speed/v);
  			}
  			return ret;
  		},
  	
  		adjustDestination: function(to, pos){
  			// summary:
  			//		Overrides dojox.mobile.scrollable.adjustDestination().
  			var h = this._itemHeight;
  			var j = to.y + Math.round(h/2);
  			var a = Math.abs(j);
  			var r = j >= 0 ? j % h : j % h + h;
  			to.y = j - r;
  		},
  	
  		resize: function(e){
  			if(this._penddingValue){
  				this.setValue(this._penddingValue);
  			}
  		},
  
  		slideTo: function(/*Object*/to, /*Number*/duration, /*String*/easing){
  			// summary:
  			//		Overrides dojox.mobile.scrollable.slideTo().
  			var pos = this.getPos();
  			var top = pos.y + this.panelNodes[1].offsetTop;
  			var bottom = top + this.panelNodes[1].offsetHeight;
  			var vh = this.domNode.parentNode.offsetHeight;
  			var t;
  			if(pos.y < to.y){ // going down
  				if(bottom > vh){
  					// move up the bottom panel
  					t = this.panelNodes[2];
  					t.style.top = this.panelNodes[0].offsetTop - this.panelNodes[0].offsetHeight + "px";
  					this.panelNodes[2] = this.panelNodes[1];
  					this.panelNodes[1] = this.panelNodes[0];
  					this.panelNodes[0] = t;
  				}
  			}else if(pos.y > to.y){ // going up
  				if(top < 0){
  					// move down the top panel
  					t = this.panelNodes[0];
  					t.style.top = this.panelNodes[2].offsetTop + this.panelNodes[2].offsetHeight + "px";
  					this.panelNodes[0] = this.panelNodes[1];
  					this.panelNodes[1] = this.panelNodes[2];
  					this.panelNodes[2] = t;
  				}
  			}
  			if(!this._initialized){
  				duration = 0; // to reduce flickers at start-up especially on android
  				this._initialized = true;
  			}else if(Math.abs(this._speed.y) < 40){
  				duration = 0.2;
  			}
  			this.inherited(arguments, [to, duration, easing]); // 2nd arg is to avoid excessive optimization by closure compiler
  		}
  	});
  });
  