/*
* jQuery UI Spinner @VERSION
*
* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT (MIT-LICENSE.txt)
* and GPL (GPL-LICENSE.txt) licenses.
*
* http://docs.jquery.com/UI/Spinner
*
* Depends:
*  ui.core.js
*/
(function($) {

	// shortcut constants
	var hover = 'ui-state-hover',
	active = 'ui-state-active',
	namespace = '.spinner',
	buttonRegex = /hide|auto|fast|slow|(\d+)/,
	buttonDefault = 'show',
	uiSpinnerClasses = 'ui-spinner ui-state-default ui-widget ui-widget-content ui-corner-all ';

	$.widget('ui.spinner', {
		_init: function() {
			this._initOptions();

			this.value(this._parse(this.element.val() || this.options.value));

			this._draw();

			this._mousewheel();

			if (this.options.buttons !== buttonDefault) {
				this.buttons.hide();
			}

			this._aria();
		},
		_initOptions: function() {
			var self = this,
			options = self.options;

			// check for precision in stepping and set _precision as internal
			var precision = parseInt(options.precision, 10);

			if (self._step().toString().indexOf('.') != -1 && precision === 0) {
				var s = self._step().toString();
				precision = s.slice(s.indexOf('.')+1, s.length).length;
			}

			// set currency options
			if (options.currency) {
				precision = 2;
				options.radix = 10;
				options.groupSeparator = options.groupSeparator || (options.radixPoint === ',' ? '' : ',');
			}
			options.precision = precision;
		},
		_draw: function() {
			var self = this,
			options = self.options;

			var uiSpinner = self.element
			.addClass('ui-spinner-input')
			.attr('autocomplete', 'off') // switch off autocomplete in opera
			.wrap(self._uiSpinnerHtml())
			.parent()
			// add buttons
			.append(self._buttonHtml())
			// add behaviours
			.hover(function() {
				if (!options.disabled) {
					$(this).addClass(hover);
				}
				self.hovered = true;
				self._hide(false);
			}, function() {
				$(this).removeClass(hover);
				self.hovered = false;
				self._hide(true);
			});

			// TODO: need a better way to exclude IE8 without resorting to $.browser.version
			// fix inline-block issues for IE. Since IE8 supports inline-block we need to exclude it.
			if (!$.support.opacity && uiSpinner.css('display') == 'inline-block' && $.browser.version < 8) {
				uiSpinner.css('display', 'inline');
			}

			// element bindings
			this.element
			// Give the spinner casing a unique id only if one exists in original input
			// - this should aid targetted customisations if a page contains multiple instances
			.attr('id', function(){
				if (this.id) {
					uiSpinner.attr('id', 'ui-spinner-'+ this.id);
				}
			})
			.bind('keydown'+namespace, function(event) {
				return self._start(event) ? self._keydown(event) : false;
			})
			.bind('keyup'+namespace, function(event) {
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
			})
			.bind('focus'+namespace, function() {
				uiSpinner.addClass(active);
				self.focused = true;
			})
			.bind('blur'+namespace, function(event) {
				self._value(self.element.val());
				if (!self.hovered) {
					uiSpinner.removeClass(active);
				}
				self.focused = false;
			});

			// force width if passed through options
			if (options.width) {
				this.element.width(options.width);
			}

			// disable spinner if element was already disabled
			if (options.disabled) {
				this.disable();
			}

			// button bindings
			this.buttons = uiSpinner.find('.ui-spinner-button')
			.bind('mousedown', function(event) {
				if (self._start(event) === false) {
					return false;
				}
//				self._repeat(null, $(this).hasClass('ui-spinner-up') ? 1 : -1, event);

				if (!self.options.disabled) {
					$(this).addClass(active);
					uiSpinner.addClass(active);
				}
			})
			.bind('mouseup', function(event) {
				if (self.counter == 1) {
					self._spin(($(this).hasClass('ui-spinner-up') ? 1 : -1) * self._step(), event);
				}
				if (self.spinning) {
					self._stop(event);
					self._change(event);
				}
				$(this).removeClass(active);
			})
			.hover(function() {
				if (!self.options.disabled) {
					$(this).addClass(hover);
				}
			}, function(event) {
				$(this).removeClass(active + ' ' + hover);
				if (self.timer && self.spinning) {
					self._stop(event);
					self._change(event);
				}
			});

			self.uiSpinner = uiSpinner;
		},
		_uiSpinnerHtml: function() {
			return '<div role="spinbutton" class="' + uiSpinnerClasses +
			(this.options.spinnerClass || '') +
			' ui-spinner-' + this.options.dir +
			'"></div>';
		},
		_buttonHtml: function() {
			return '<a class="ui-spinner-button ui-spinner-up ui-state-default ui-corner-t' + this.options.dir.substr(-1,1) +
			'"><span class="ui-icon ui-icon-triangle-1-n">&#9650;</span></a>' +
			'<a class="ui-spinner-button ui-spinner-down ui-state-default ui-corner-b' + this.options.dir.substr(-1,1) +
			'"><span class="ui-icon ui-icon-triangle-1-s">&#9660;</span></a>';
		},
		_start: function(event) {
			if (!this.spinning && this._trigger('start', event, { value: this.value()}) !== false) {
				if (!this.counter) {
					this.counter = 1;
				}
				this.spinning = true;
				return true;
			}
			return false
		},
		_spin: function(step, event) {

			if (this.options.disabled) {
				return;
			}
			if (!this.counter) {
				this.counter = 1;
			}

			var newVal = this._value() + step * (this.options.incremental && this.counter > 100
			? this.counter > 200
			? 100
			: 10
			: 1);

			// cancelable
			if (this._trigger('spin', event, { value: newVal }) !== false) {
				this._value(newVal);
				this.counter++;
			}

		},
		_stop: function(event) {
			this.counter = 0;
			if (this.timer) {
				window.clearInterval(this.timer);
			}
			this.element[0].focus();
			this.spinning = false;
			this._trigger('stop', event);
		},
		_change: function(event) {
			this._trigger('change', event);
		},
		_repeat: function(i, steps, event) {
			var self = this;
			i = i || 100;

			if (this.timer) {
				window.clearInterval(this.timer);
			}

			this.timer = window.setInterval(function() {
				self._repeat(self.options.incremental && self.counter > 20 ? 20 : i, steps, event);
			}, i);

			self._spin(steps*self._step(), event);
		},
		_keydown: function(event) {
			var o = this.options,
			KEYS = $.ui.keyCode;

			switch (event.keyCode) {
				case KEYS.UP: 			this._repeat(null, event.shiftKey ? o.page : 1, event); break;
				case KEYS.DOWN: 		this._repeat(null, event.shiftKey ? -o.page : -1, event); break;
				case KEYS.PAGE_UP: 		this._repeat(null, o.page, event); break;
				case KEYS.PAGE_DOWN: 	this._repeat(null, -o.page, event); break;

				case KEYS.HOME:
				case KEYS.END:
				if (event.shiftKey) {
					return true;
				}
				this._value(this['_' + (event.keyCode == KEYS.HOME ? 'min':'max')]());
				break;

				case KEYS.TAB:
				case KEYS.BACKSPACE:
				case KEYS.LEFT:
				case KEYS.RIGHT:
				case KEYS.PERIOD:
				case KEYS.NUMPAD_DECIMAL:
				case KEYS.NUMPAD_SUBTRACT:
				return true;

				case KEYS.ENTER:
				this.value(this.element.val());
				return true;

				default:
				if ((event.keyCode >= 96 && event.keyCode <= 105) || // numeric keypad 0-9
				(new RegExp('[' + this._validChars() + ']', 'i').test(String.fromCharCode(event.keyCode)))) {
					return true;
				};
			}

			return false;
		},
		_mousewheel: function() {
			var self = this;
			if ($.fn.mousewheel && self.options.mouseWheel) {
				this.element.mousewheel(function(event, delta) {
					delta = ($.browser.opera ? -delta / Math.abs(delta) : delta);
					if (!self._start(event)) {
						return false;
					}
					self._spin((delta > 0 ? 1 : -1) * self._step(), event);
					if (self.timeout) {
						window.clearTimeout(self.timeout);
					}
					self.timeout = window.setTimeout(function() {
						if (self.spinning) {
							self._stop(event);
							self._change(event);
						}
					}, 400);
					event.preventDefault();
				});
			}
		},
		_value: function(newVal) {
			if (!arguments.length) {
				return this._parse(this.element.val());
			}
			this._setData('value', newVal);
		},
		_getData: function(key) {
			switch (key) {
				case 'min':
				case 'max':
				case 'step':
				return this['_'+key]();
				break;
			}
			return $.widget.prototype._getData.call(this, key);
		},
		_setData: function(key, value) {

			var blnPos = this.element.val() >= value ?  false : true ;

			switch (key) {
				case 'value':

				value = this._parse(value);

				if (this._getData("usezero") === true)
				{


					if(blnPos === true)
					{
						if(value < this._min())
						{
							value = this._min();
						}
					}
					else
					{
						if(value < this._min())
						{
							value = 0;
						}
					}
				}
				else
				{
					if (value < this._min()) {
						value = this._min();
					}
				}

				if (value > this._max()) {
					value = this._max();
				}
				break;
				case 'spinnerClass':
				this.uiSpinner
				.removeClass(this.options.spinnerClass)
				.addClass(uiSpinnerClasses + value);
				break;
			}

			$.widget.prototype._setData.call(this, key, value);

			this._afterSetData(key, value);
			this._aria();
		},
		_afterSetData: function(key, value) {
			switch(key) {
				case 'buttons':
				this._hide('hide');
				break;
				case 'max':
				case 'min':
				case 'step':
				if (value != null) {
					// write attributes back to element if original exist
					if (this.element.attr(key)) {
						this.element.attr(key, value);
					}
				}
				break;
				case 'width':
				this.element.width(value);
				break;
				case 'precision':
				case 'value':
				this._format(this._parse(this.options.value));
				break;
			}
		},
		_aria: function() {
			this.uiSpinner
			&& this.uiSpinner
			.attr('aria-valuemin', this._min())
			.attr('aria-valuemax', this._max())
			.attr('aria-valuenow', this.value());
		},
		_validChars: function() {
			var radix = parseInt(this.options.radix);
			return '\\-\\' + this.options.radixPoint + (this.options.groupSeparator
			? '\\' + this.options.groupSeparator
			:'') + (radix < 10
			? '0-' + radix
			: '0-9' + (radix > 10
			? 'a-' + String.fromCharCode('a'.charCodeAt(0) + radix - 11)
			:''));
		},
		_parse: function(val) {
			if (typeof val == 'string') {
				if (this.options.groupSeparator) {
					val = val.replace(new RegExp('\\'+this.options.groupSeparator,'g'), '');
				}
				val = val.replace(new RegExp('[^' + this._validChars() + ']', 'gi'), '').split(this.options.radixPoint);
				result = parseInt(val[0] == '-' ? 0 : val[0] || 0, this.options.radix);
				if (val.length > 1) {
					result += parseInt(val[1], this.options.radix) / Math.pow(this.options.radix, val[1].length) *
					// must test first character of val[0] for minus sign because -0 is parsed as 0 in result
					(val[0].substr(0,1) == '-' ? -1 : 1);
				}
				val = result;
			}
			return isNaN(val) ? null : val;
		},
		_format: function(num) {
			var regex = /(\d+)(\d{3})/,
			options = this.options,
			sym = options.currency || '',
			dec = options.precision,
			radix = options.radix,
			group = options.groupSeparator,
			pt = options.radixPoint,
			neg = num < 0 ? '-' : '';

			for (
			num = (
			isNaN(num)
			? options.value
			: radix === 10
			? parseFloat(num, radix).toFixed(dec)
			: parseInt(num, radix)
			).toString(radix).replace('.', pt);
			regex.test(num) && group;
			num = num.replace(regex, '$1'+group+'$2')
			);

			result = num.replace('-','');
			while (options.padding && (result.length < options.padding)) {
				result = '0' + result;
			}
			this.element.val(neg + sym + result);
		},
		_hide: function(hide) {
			if (this.options.buttons === buttonDefault) {
				this.buttons.show();
				return;
			}

			if  (this.options.buttons === 'hide') {
				this.buttons.hide();
				return;
			}

			var self = this,
			speed = this.options.buttons === 'auto' ? 400 : this.options.buttons;

			if (this.timeout) {
				window.clearTimeout(this.timeout);
			}
			this.timeout = window.setTimeout(function() {
				self.buttons.animate({opacity: hide ? 'hide' : 'show'}, speed);
			}, 200);
		},
		_getOption: function(key, defaultValue) {
			return this._parse(this.options[key] !== null
			? this.options[key]
			: this.element.attr(key)
			? this.element.attr(key)
			: defaultValue);
		},
		_step: function(newVal) {
			if (!arguments.length) {
				return this._getOption('step', 1);
			}
			this._setData('step', newVal);
		},
		_min: function(newVal) {
			if (!arguments.length) {
				return this._getOption('min', -Number.MAX_VALUE);
			}
			this._setData('min', newVal);
		},
		_max: function(newVal) {
			if (!arguments.length) {
				return this._getOption('max', Number.MAX_VALUE);
			}
			this._setData('max', newVal);
		},


		destroy: function() {
			if ($.fn.mousewheel) {
				this.element.unmousewheel();
			}

			this.element
			.removeClass('ui-spinner-input')
			.removeAttr('disabled')
			.removeAttr('autocomplete')
			.removeData('spinner')
			.unbind(namespace);

			if (this.uiSpinner) {
				if (this.uiSpinner.parent()[0] != null) {
					this.uiSpinner.replaceWith(this.element);
				}
				else {
					return this.element.clone(true);
				}
			}
		},
		enable: function() {
			this.element
			.removeAttr('disabled')
			.siblings()
			.removeAttr('disabled')
			.parent()
			.removeClass('ui-spinner-disabled ui-state-disabled');
			this.options.disabled = false;
		},
		disable: function() {
			this.element
			.attr('disabled', true)
			.siblings()
			.attr('disabled', true)
			.parent()
			.addClass('ui-spinner-disabled ui-state-disabled');
			this.options.disabled = true;
		},
		value: function(newVal) {
			if (!arguments.length) {
				return this._value();
			}
			this._value(newVal);
		},
		stepUp: function(steps) {
			this._spin((steps || 1) * this._step(), null);
			return this;
		},
		stepDown: function(steps) {
			this._spin((steps || 1) * -this._step(), null);
			return this;
		},
		pageUp: function(pages) {
			return this.stepUp((pages || 1) * this.options.page);
		},
		pageDown: function(pages) {
			return this.stepDown((pages || 1) * this.options.page);
		}
	});

	$.extend($.ui.spinner, {
		version: "@VERSION",
		eventPrefix: "spin",
		defaults: {
			buttons: buttonDefault,
			currency: false,
			dir: 'ltr',
			groupSeparator: '',
			incremental: true,
			max: null,
			min: null,
			mouseWheel: true,
			padding: 0,
			page: 5,
			precision: 0,
			radix: 10,
			radixPoint: '.',
			spinnerClass: null,
			step: null,
			value: 0,
			usezero: false,
			width: false
		}
	});

})(jQuery);


