<commit_before>(function (enyo, scope) {
	/**
	* Fires when the currently selected item changes.
	* 
	* @event moon.SimplePicker#onChange
	* @type {Object}
	* @property {enyo.Control} selected - A reference to the currently selected item.
	* @property {String} content - The content of the currently selected item.
	* @property {Number} index - The index of the currently selected item.
	* @public
	*/

	/**
	* {@link moon.SimplePicker} is a [control]{@link enyo.Control} that solicits a
	* choice from the user by cycling through a list of options. The picker's child
	* [components]{@link enyo.Component}, {@link moon.MarqueeText}
	* [objects]{@glossary Object} by default, become the options for the picker.
	*
	* ```javascript
	* {kind: 'moon.SimplePicker', onChange: 'changed', selectedIndex: 1, components: [
	*	{content: 'San Francisco'},
	*	{content: 'Boston'},
	*	{content: 'Tokyo'}
	* ]}
	* ```
	* 
	* The picker may be changed programmatically by calling
	* [previous()]{@link moon.SimplePicker#previous} or [next()]{@link moon.SimplePicker#next}, 
	* or by modifying the [selectedIndex]{@link moon.SimplePicker#selectedIndex} published 
	* property by calling `set('selectedIndex', <value>)`.
	*
	* The picker options may be modified programmatically in the standard manner, by calling
	* `createComponent().render()` or `destroy()`.
	*
	* ```javascript
	* // Add new items to picker
	* this.$.picker.createComponent({'New York'}).render();
	* this.$.picker.createComponent({'London'}).render();
	*
	* // Remove currently selected item from picker
	* this.$.picker.getSelected().destroy();
	* ```
	*
	* @class moon.SimplePicker
	* @extends enyo.Control
	* @mixes moon.MarqueeSupport
	* @ui
	* @public
	*/
	enyo.kind(
		/** @lends moon.SimplePicker.prototype */ {

		/**
		* @private
		*/
		name: 'moon.SimplePicker',

		/**
		* @private
		*/
		kind: 'enyo.Control',

		/**
		* @private
		*/
		classes: 'moon-simple-picker',

		/**
		* @private
		*/
		mixins: ['moon.MarqueeSupport'],

		/**
		* @private
		*/
		events: {
			onChange: ''
		},

		/**
		* @private
		* @lends moon.SimplePicker.prototype
		*/
		published: {

			/**
			* Reference to currently selected item, if any.
			*
			* @type {enyo.Control}
			* @default ''
			* @public
			*/
			selected: '',

			/**
			* Index of currently selected item, if any.
			*
			* @type {Number}
			* @default 0
			* @public
			*/
			selectedIndex: 0,

			/**
			* When `true`, picker transitions animate left/right.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			animate: true,

			/**
			* When `true`, buttons are shown as disabled and do not generate tap events.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			disabled: false,

			/**
			* When `true`, picker will wrap around from last item to first.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			wrap: false,

			/**
			* By default, {@link moon.SimplePicker} is an inline-block element;
			* setting `block: true` makes it a block element.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			block: false
		},

		/**
		* @private
		*/
		defaultKind:'moon.MarqueeText',

		/**
		* @private
		*/
		handlers: {
			onSpotlightFocused: 'scrollIntoView'
		},

		/**
		* @private
		*/
		components: [
			{name: 'buttonLeft',  kind: 'moon.IconButton', noBackground:true, classes: 'moon-simple-picker-button left', icon:'arrowlargeleft', onSpotlightKeyDown:'configureSpotlightHoldPulse', onSpotlightSelect: 'left', ondown: 'downLeft', onholdpulse:'left', defaultSpotlightDisappear: 'buttonRight'},
			{kind: 'enyo.Control', name: 'clientWrapper', classes:'moon-simple-picker-client-wrapper', components: [
				{kind: 'enyo.Control', name: 'client', classes: 'moon-simple-picker-client'}
			]},
			{name: 'buttonRight', kind: 'moon.IconButton', noBackground:true, classes: 'moon-simple-picker-button right', icon:'arrowlargeright', onSpotlightKeyDown:'configureSpotlightHoldPulse', onSpotlightSelect: 'right', ondown: 'downRight', onholdpulse:'right', defaultSpotlightDisappear: 'buttonLeft'}
		],

		/**
		* @private
		*/
		create: enyo.inherit(function (sup) {
			return function () {
				sup.apply(this, arguments);
				this.animateChanged();
				this.initializeActiveItem();
				this.disabledChanged();
				this.updateMarqueeDisable();
				this.blockChanged();
				this.showHideNavButtons();
			};
		}),

		/**
		* @private
		*/
		rendered: enyo.inherit(function (sup) {
			return function () {
				sup.apply(this, arguments);
				this.selectedIndexChanged();
			};
		}),

		/**
		* @private
		*/
		scrollIntoView: function() {
			this.bubble('onRequestScrollIntoView');
		},

		/**
		* @fires moon.SimplePicker#onChange
		* @private
		*/
		fireChangedEvent: function() {
			if (!this.generated) {
				return;
			}

			this.doChange({
				selected:   this.selected,
				content:    this.selected && this.selected.content,
				index:      this.selected && this.selectedIndex
			});
		},

		/**
		* @private
		*/
		blockChanged: function() {
			this.addRemoveClass('block', this.block);
		},

		/**
		* Shows/hides previous/next buttons based on current index.
		*
		* @private
		*/
		showHideNavButtons: function() {
			var index = this.getSelectedIndex(),
				maxIndex = this.getClientControls().length - 1;
			var prevButton = this.$.buttonLeft;
			var nextButton = this.$.buttonRight;

			if (this.disabled) {
				this.hideNavButton(prevButton);
				this.hideNavButton(nextButton);
			// Always show buttons if _this.wrap_ is _true_
			} else if (this.wrap) {
				this.showNavButton(prevButton);
				this.showNavButton(nextButton);
			// If we have one or less options, always show no buttons
			} else if (maxIndex <= 0) {
				this.hideNavButton(prevButton);
				this.hideNavButton(nextButton);
			// If we are on the first option, hide the left button
			} else if (index <= 0) {
				this.showNavButton(nextButton);
				this.hideNavButton(prevButton);
			// If we are on the last item, hide the right button
			} else if (index >= maxIndex) {
				this.showNavButton(prevButton);
				this.hideNavButton(nextButton);
			// Otherwise show both buttons
			} else {
				this.showNavButton(prevButton);
				this.showNavButton(nextButton);
			}
		},

		/**
		* @private
		*/
		destroy: function() {
			this.destroying = true;
			this.inherited(arguments);
		},

		/**
		* @private
		*/
		addControl: function(ctl) {
			this.inherited(arguments);
			var addedIdx = this.getClientControls().indexOf(ctl),
				selectedIdx = this.selectedIndex;
			if (this.generated) {
				if ((selectedIdx < 0) || (addedIdx < selectedIdx)) {
					this.setSelectedIndex(selectedIdx + 1);
				} else if (selectedIdx == addedIdx) {
					// Force change handler, since the currently selected item actually changed
					this.selectedIndexChanged();
				}
				this.showHideNavButtons();
			}
		},

		/**
		* @private
		*/
		removeControl: function(ctl) {
			if (!this.destroying) {
				var removedIdx = this.getClientControls().indexOf(ctl),
					selectedIdx = this.selectedIndex,
					wasLast = (removedIdx == this.getClientControls().length-1);

				this.inherited(arguments);

				// If removedIdx is -1, that means that the Control being removed is
				// not one of our picker items, so we don't need to update our state.
				// Probably, we're being torn down.
				if (removedIdx !== -1) {
					if ((removedIdx < selectedIdx) || ((selectedIdx == removedIdx) && wasLast)) {
						this.setSelectedIndex(selectedIdx - 1);
					} else if (selectedIdx == removedIdx) {
						// Force change handler, since the currently selected item actually changed
						this.selectedIndexChanged();
					}
					this.showHideNavButtons();
				}
			} else {
				this.inherited(arguments);
			}
		},

		/**
		* Hides passed-in [control]{@link enyo.Control} and disables {@glossary Spotlight}
		* functionality.
		*
		* @private
		*/
		hideNavButton: function(ctl) {
			ctl.setDisabled(true);
		},

		/**
		* Shows passed-in [control]{@link enyo.Control} and enables {@glossary Spotlight}
		* functionality.
		*
		* @private
		*/
		showNavButton: function(ctl) {
			ctl.setDisabled(false);
		},

		/**
		* @private
		*/
		disabledChanged: function() {
			this.$.client.addRemoveClass('disabled', this.disabled);
			if (this.generated) {
				this.showHideNavButtons();
			}
		},

		/**
		* @private
		*/
		animateChanged: function() {
			this.$.client.addRemoveClass('animated', this.animate);
		},

		/**
		* @private
		*/
		selectedChanged: function() {
			var idx = this.getClientControls().indexOf(this.selected);
			if (idx >= 0) {
				this.setSelectedIndex(idx);
			}
		},
		/*
		* When the picker is initialized, looks for any items with the `active` flag set to
		* `true`; if one is found, it is set as the currently selected item. This is done
		* without triggering an [onChange]{@link moon.SimplePicker#onChange} event, as
		* it happens during initialization.
		*
		* @private
		*/
		initializeActiveItem: function() {
			var i,
				controls = this.getClientControls();
			for (i = 0; i < controls.length; i++) {
				if (controls[i].active) {
					this.selectedIndex = i;
					this.selected = controls[i];
					return;
				}
			}
		},

		/**
		* @private
		*/
		selectedIndexChanged: function() {
			// FIXME: Accounting for issue with sub-pixels and setting a percentage transformation.
			// It appears that percentage transformations utilize the nearest whole-pixel value.
			if (!this._clientWidth) this._clientWidth = this.$.client.generated && this.$.client.hasNode().getBoundingClientRect().width;
			if (this.$.client.generated && this._clientWidth) { // correction for rounding (after we can measure the control width)
				enyo.dom.transform(this.$.client, {translateX: enyo.dom.unit(this.selectedIndex * this._clientWidth * -1, 'rem')});
			} else { // initial (rounded) transformation
				enyo.dom.transform(this.$.client, {translateX: (this.selectedIndex * -100) + '%'});
			}
			this.updateMarqueeDisable();
			this.setSelected(this.getClientControls()[this.selectedIndex]);
			this.fireChangedEvent();
			this.showHideNavButtons();
			this.startMarquee();
		},

		/**
		* @private
		*/
		updateMarqueeDisable: function() {
			this.stopMarquee();
			var i,
				c = this.getClientControls();
			for (i = 0; i < c.length; i++) {
				if (i == this.selectedIndex) {
					c[i].disabled = false;
				} else {
					c[i].disabled = true;
				}
			}
		},

		/**
		* @private
		*/
		left: function(sender, e) {
			if (e && e.sentHold) { return; }
			this.previous(sender, e);
		},

		/**
		* @private
		*/
		right: function(sender, e) {
			if (e && e.sentHold) { return; }
			this.next(sender, e);
		},

		/**
		* @private
		*/
		downLeft: function(sender, e) {
			e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			this.left(sender, e);
		},

		/**
		* @private
		*/
		downRight: function(sender, e) {
			e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			this.right(sender, e);
		},

		/**
		* @private
		*/
		configureSpotlightHoldPulse: function(sender, e) {
			if (e.keyCode === 13) {
				e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			}
		},

		/** 
		* Cycles the selected item to the one before the currently selected item. If chained from
		* an event, {@link Spotlight} hold pulse events will be canceled once the first item is
		* reached, unless [wrap]{@link moon.SimplePicker#wrap} is `true`. When calling this method
		* directly, no arguments are required.
		*
		* @param {Object} sender - (unused) Sender, if chained from event.
		* @param {Object} e - Event object, if chained from event.
		* @public
		*/
		previous: function(sender, e) {
			if (!this.disabled) {
				var idx = this.selectedIndex - 1;
				if (idx < 0) {
					idx = this.wrap ? this.getClientControls().length - 1 : 0;
				}
				if (!this.wrap && idx === 0 && e && e.cancelHoldPulse) {
					e.cancelHoldPulse();
				}
				this.setSelectedIndex(idx);
			}
		},

		/** 
		* Cycles the selected item to the one after the currently selected item. If chained from
		* an event, {@link Spotlight} hold pulse events will be canceled once the last item is
		* reached, unless [wrap]{@link moon.SimplePicker#wrap} is `true`. When calling this method
		* directly, no arguments are required.
		*
		* @param {Object} sender - (unused) Sender, if chained from event.
		* @param {Object} e - Event object, if chained from event.
		* @public
		*/
		next: function(sender, e) {
			if (!this.disabled) {
				var idx = this.selectedIndex + 1;
				if (idx > this.getClientControls().length - 1) {
					idx = this.wrap ? 0 : this.getClientControls().length - 1;
				}
				if (!this.wrap && idx === this.getClientControls().length - 1
					&& e && e.cancelHoldPulse) {
					e.cancelHoldPulse();
				}
				this.setSelectedIndex(idx);
			}
		}
	});

})(enyo, this);
<commit_msg>ENYO-752: Set position of initial value via transform.<commit_after>(function (enyo, scope) {
	/**
	* Fires when the currently selected item changes.
	* 
	* @event moon.SimplePicker#onChange
	* @type {Object}
	* @property {enyo.Control} selected - A reference to the currently selected item.
	* @property {String} content - The content of the currently selected item.
	* @property {Number} index - The index of the currently selected item.
	* @public
	*/

	/**
	* {@link moon.SimplePicker} is a [control]{@link enyo.Control} that solicits a
	* choice from the user by cycling through a list of options. The picker's child
	* [components]{@link enyo.Component}, {@link moon.MarqueeText}
	* [objects]{@glossary Object} by default, become the options for the picker.
	*
	* ```javascript
	* {kind: 'moon.SimplePicker', onChange: 'changed', selectedIndex: 1, components: [
	*	{content: 'San Francisco'},
	*	{content: 'Boston'},
	*	{content: 'Tokyo'}
	* ]}
	* ```
	* 
	* The picker may be changed programmatically by calling
	* [previous()]{@link moon.SimplePicker#previous} or [next()]{@link moon.SimplePicker#next}, 
	* or by modifying the [selectedIndex]{@link moon.SimplePicker#selectedIndex} published 
	* property by calling `set('selectedIndex', <value>)`.
	*
	* The picker options may be modified programmatically in the standard manner, by calling
	* `createComponent().render()` or `destroy()`.
	*
	* ```javascript
	* // Add new items to picker
	* this.$.picker.createComponent({'New York'}).render();
	* this.$.picker.createComponent({'London'}).render();
	*
	* // Remove currently selected item from picker
	* this.$.picker.getSelected().destroy();
	* ```
	*
	* @class moon.SimplePicker
	* @extends enyo.Control
	* @mixes moon.MarqueeSupport
	* @ui
	* @public
	*/
	enyo.kind(
		/** @lends moon.SimplePicker.prototype */ {

		/**
		* @private
		*/
		name: 'moon.SimplePicker',

		/**
		* @private
		*/
		kind: 'enyo.Control',

		/**
		* @private
		*/
		classes: 'moon-simple-picker',

		/**
		* @private
		*/
		mixins: ['moon.MarqueeSupport'],

		/**
		* @private
		*/
		events: {
			onChange: ''
		},

		/**
		* @private
		* @lends moon.SimplePicker.prototype
		*/
		published: {

			/**
			* Reference to currently selected item, if any.
			*
			* @type {enyo.Control}
			* @default ''
			* @public
			*/
			selected: '',

			/**
			* Index of currently selected item, if any.
			*
			* @type {Number}
			* @default 0
			* @public
			*/
			selectedIndex: 0,

			/**
			* When `true`, picker transitions animate left/right.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			animate: true,

			/**
			* When `true`, buttons are shown as disabled and do not generate tap events.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			disabled: false,

			/**
			* When `true`, picker will wrap around from last item to first.
			*
			* @type {Boolean}
			* @default true
			* @public
			*/
			wrap: false,

			/**
			* By default, {@link moon.SimplePicker} is an inline-block element;
			* setting `block: true` makes it a block element.
			*
			* @type {Boolean}
			* @default false
			* @public
			*/
			block: false
		},

		/**
		* @private
		*/
		defaultKind:'moon.MarqueeText',

		/**
		* @private
		*/
		handlers: {
			onSpotlightFocused: 'scrollIntoView'
		},

		/**
		* @private
		*/
		components: [
			{name: 'buttonLeft',  kind: 'moon.IconButton', noBackground:true, classes: 'moon-simple-picker-button left', icon:'arrowlargeleft', onSpotlightKeyDown:'configureSpotlightHoldPulse', onSpotlightSelect: 'left', ondown: 'downLeft', onholdpulse:'left', defaultSpotlightDisappear: 'buttonRight'},
			{kind: 'enyo.Control', name: 'clientWrapper', classes:'moon-simple-picker-client-wrapper', components: [
				{kind: 'enyo.Control', name: 'client', classes: 'moon-simple-picker-client'}
			]},
			{name: 'buttonRight', kind: 'moon.IconButton', noBackground:true, classes: 'moon-simple-picker-button right', icon:'arrowlargeright', onSpotlightKeyDown:'configureSpotlightHoldPulse', onSpotlightSelect: 'right', ondown: 'downRight', onholdpulse:'right', defaultSpotlightDisappear: 'buttonLeft'}
		],

		/**
		* @private
		*/
		create: enyo.inherit(function (sup) {
			return function () {
				sup.apply(this, arguments);
				this.animateChanged();
				this.initializeActiveItem();
				this.disabledChanged();
				this.selectedIndexChanged();
				this.updateMarqueeDisable();
				this.blockChanged();
				this.showHideNavButtons();
			};
		}),

		/**
		* @private
		*/
		rendered: enyo.inherit(function (sup) {
			return function () {
				sup.apply(this, arguments);
				this.selectedIndexChanged();
			};
		}),

		/**
		* @private
		*/
		scrollIntoView: function() {
			this.bubble('onRequestScrollIntoView');
		},

		/**
		* @fires moon.SimplePicker#onChange
		* @private
		*/
		fireChangedEvent: function() {
			if (!this.generated) {
				return;
			}

			this.doChange({
				selected:   this.selected,
				content:    this.selected && this.selected.content,
				index:      this.selected && this.selectedIndex
			});
		},

		/**
		* @private
		*/
		blockChanged: function() {
			this.addRemoveClass('block', this.block);
		},

		/**
		* Shows/hides previous/next buttons based on current index.
		*
		* @private
		*/
		showHideNavButtons: function() {
			var index = this.getSelectedIndex(),
				maxIndex = this.getClientControls().length - 1;
			var prevButton = this.$.buttonLeft;
			var nextButton = this.$.buttonRight;

			if (this.disabled) {
				this.hideNavButton(prevButton);
				this.hideNavButton(nextButton);
			// Always show buttons if _this.wrap_ is _true_
			} else if (this.wrap) {
				this.showNavButton(prevButton);
				this.showNavButton(nextButton);
			// If we have one or less options, always show no buttons
			} else if (maxIndex <= 0) {
				this.hideNavButton(prevButton);
				this.hideNavButton(nextButton);
			// If we are on the first option, hide the left button
			} else if (index <= 0) {
				this.showNavButton(nextButton);
				this.hideNavButton(prevButton);
			// If we are on the last item, hide the right button
			} else if (index >= maxIndex) {
				this.showNavButton(prevButton);
				this.hideNavButton(nextButton);
			// Otherwise show both buttons
			} else {
				this.showNavButton(prevButton);
				this.showNavButton(nextButton);
			}
		},

		/**
		* @private
		*/
		destroy: function() {
			this.destroying = true;
			this.inherited(arguments);
		},

		/**
		* @private
		*/
		addControl: function(ctl) {
			this.inherited(arguments);
			var addedIdx = this.getClientControls().indexOf(ctl),
				selectedIdx = this.selectedIndex;
			if (this.generated) {
				if ((selectedIdx < 0) || (addedIdx < selectedIdx)) {
					this.setSelectedIndex(selectedIdx + 1);
				} else if (selectedIdx == addedIdx) {
					// Force change handler, since the currently selected item actually changed
					this.selectedIndexChanged();
				}
				this.showHideNavButtons();
			}
		},

		/**
		* @private
		*/
		removeControl: function(ctl) {
			if (!this.destroying) {
				var removedIdx = this.getClientControls().indexOf(ctl),
					selectedIdx = this.selectedIndex,
					wasLast = (removedIdx == this.getClientControls().length-1);

				this.inherited(arguments);

				// If removedIdx is -1, that means that the Control being removed is
				// not one of our picker items, so we don't need to update our state.
				// Probably, we're being torn down.
				if (removedIdx !== -1) {
					if ((removedIdx < selectedIdx) || ((selectedIdx == removedIdx) && wasLast)) {
						this.setSelectedIndex(selectedIdx - 1);
					} else if (selectedIdx == removedIdx) {
						// Force change handler, since the currently selected item actually changed
						this.selectedIndexChanged();
					}
					this.showHideNavButtons();
				}
			} else {
				this.inherited(arguments);
			}
		},

		/**
		* Hides passed-in [control]{@link enyo.Control} and disables {@glossary Spotlight}
		* functionality.
		*
		* @private
		*/
		hideNavButton: function(ctl) {
			ctl.setDisabled(true);
		},

		/**
		* Shows passed-in [control]{@link enyo.Control} and enables {@glossary Spotlight}
		* functionality.
		*
		* @private
		*/
		showNavButton: function(ctl) {
			ctl.setDisabled(false);
		},

		/**
		* @private
		*/
		disabledChanged: function() {
			this.$.client.addRemoveClass('disabled', this.disabled);
			if (this.generated) {
				this.showHideNavButtons();
			}
		},

		/**
		* @private
		*/
		animateChanged: function() {
			this.$.client.addRemoveClass('animated', this.animate);
		},

		/**
		* @private
		*/
		selectedChanged: function() {
			var idx = this.getClientControls().indexOf(this.selected);
			if (idx >= 0) {
				this.setSelectedIndex(idx);
			}
		},
		/*
		* When the picker is initialized, looks for any items with the `active` flag set to
		* `true`; if one is found, it is set as the currently selected item. This is done
		* without triggering an [onChange]{@link moon.SimplePicker#onChange} event, as
		* it happens during initialization.
		*
		* @private
		*/
		initializeActiveItem: function() {
			var i,
				controls = this.getClientControls();
			for (i = 0; i < controls.length; i++) {
				if (controls[i].active) {
					this.selectedIndex = i;
					this.selected = controls[i];
					return;
				}
			}
		},

		/**
		* @private
		*/
		selectedIndexChanged: function() {
			// FIXME: Accounting for issue with sub-pixels and setting a percentage transformation.
			// It appears that percentage transformations utilize the nearest whole-pixel value.
			if (!this._clientWidth) this._clientWidth = this.$.client.generated && this.$.client.hasNode().getBoundingClientRect().width;
			if (this.$.client.generated && this._clientWidth) { // correction for rounding (after we can measure the control width)
				enyo.dom.transform(this.$.client, {translateX: enyo.dom.unit(this.selectedIndex * this._clientWidth * -1, 'rem')});
			} else { // initial (rounded) transformation
				enyo.dom.transform(this.$.client, {translateX: (this.selectedIndex * -100) + '%'});
			}
			this.updateMarqueeDisable();
			this.setSelected(this.getClientControls()[this.selectedIndex]);
			this.fireChangedEvent();
			this.showHideNavButtons();
			this.startMarquee();
		},

		/**
		* @private
		*/
		updateMarqueeDisable: function() {
			this.stopMarquee();
			var i,
				c = this.getClientControls();
			for (i = 0; i < c.length; i++) {
				if (i == this.selectedIndex) {
					c[i].disabled = false;
				} else {
					c[i].disabled = true;
				}
			}
		},

		/**
		* @private
		*/
		left: function(sender, e) {
			if (e && e.sentHold) { return; }
			this.previous(sender, e);
		},

		/**
		* @private
		*/
		right: function(sender, e) {
			if (e && e.sentHold) { return; }
			this.next(sender, e);
		},

		/**
		* @private
		*/
		downLeft: function(sender, e) {
			e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			this.left(sender, e);
		},

		/**
		* @private
		*/
		downRight: function(sender, e) {
			e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			this.right(sender, e);
		},

		/**
		* @private
		*/
		configureSpotlightHoldPulse: function(sender, e) {
			if (e.keyCode === 13) {
				e.configureHoldPulse({endHold: 'onLeave', delay: 300});
			}
		},

		/** 
		* Cycles the selected item to the one before the currently selected item. If chained from
		* an event, {@link Spotlight} hold pulse events will be canceled once the first item is
		* reached, unless [wrap]{@link moon.SimplePicker#wrap} is `true`. When calling this method
		* directly, no arguments are required.
		*
		* @param {Object} sender - (unused) Sender, if chained from event.
		* @param {Object} e - Event object, if chained from event.
		* @public
		*/
		previous: function(sender, e) {
			if (!this.disabled) {
				var idx = this.selectedIndex - 1;
				if (idx < 0) {
					idx = this.wrap ? this.getClientControls().length - 1 : 0;
				}
				if (!this.wrap && idx === 0 && e && e.cancelHoldPulse) {
					e.cancelHoldPulse();
				}
				this.setSelectedIndex(idx);
			}
		},

		/** 
		* Cycles the selected item to the one after the currently selected item. If chained from
		* an event, {@link Spotlight} hold pulse events will be canceled once the last item is
		* reached, unless [wrap]{@link moon.SimplePicker#wrap} is `true`. When calling this method
		* directly, no arguments are required.
		*
		* @param {Object} sender - (unused) Sender, if chained from event.
		* @param {Object} e - Event object, if chained from event.
		* @public
		*/
		next: function(sender, e) {
			if (!this.disabled) {
				var idx = this.selectedIndex + 1;
				if (idx > this.getClientControls().length - 1) {
					idx = this.wrap ? 0 : this.getClientControls().length - 1;
				}
				if (!this.wrap && idx === this.getClientControls().length - 1
					&& e && e.cancelHoldPulse) {
					e.cancelHoldPulse();
				}
				this.setSelectedIndex(idx);
			}
		}
	});

})(enyo, this);

{'fraction_non_alphanumeric': 0.14966964632724447, 'fraction_numerical': 0.0032258064516129032, 'mean_word_length': 3.099904397705545, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2322011', 'n_tokens_mistral': 9990, 'n_tokens_neox': 8266, 'n_words': 2056}