(function($){
 
    $.fn.extend({
         
        vspinner: function(options) {
 
            //Set the default values, use comma to separate the settings, example:
            var defaults = {
                min: 0,
                max : 100,
                step : 1
            }
            var keyCode = {
                	ALT: 18, BACKSPACE: 8,CAPS_LOCK: 20,COMMA: 188,COMMAND: 91,COMMAND_LEFT: 91,COMMAND_RIGHT: 93,CONTROL: 17,
                	DELETE: 46,DOWN: 40,END: 35,ENTER: 13,ESCAPE: 27,HOME: 36,INSERT: 45,LEFT: 37,MENU: 93,NUMPAD_ADD: 107,
                	NUMPAD_DECIMAL: 110,NUMPAD_DIVIDE: 111,NUMPAD_ENTER: 108,NUMPAD_MULTIPLY: 106,NUMPAD_SUBTRACT: 109,
                	PAGE_DOWN: 34,PAGE_UP: 33,PERIOD: 190,RIGHT: 39,SHIFT: 16,SPACE: 32,TAB: 9,UP: 38,WINDOWS: 91 // COMMAND
                };
            var sysKeys = [keyCode.UP, keyCode.DOWN, keyCode.RIGHT, keyCode.LEFT, keyCode.PAGE_UP, keyCode.PAGE_DOWN, keyCode.HOME, keyCode.END, keyCode.BACKSPACE, keyCode.DELETE, keyCode.TAB]
            
            var options =  $.extend(defaults, options);
            
            
            var doSpin = function(input,step) {
        		// shortcut
        		value = parseInt(input.val());
        			
        		if (isNaN(value)) {
        			if (step == 0 && !input.val())
        				return;
        			value = (step >= 0 ? input.min : input.max) || 0;
        		}
        		value = value + (step * input.step);
        		if (value<input.min)
        			value = input.min;
        		if (value>input.max)
        			value = input.max;
        		input.val(value);
        		
        		if (options.onSpin)
        			options.onSpin(value);
        	};
        	
        	var startSpin = function(input,step) {
        		doSpin(input,step);
        		input.timer = setInterval(function(){doSpin(input,step)}, 200);
        	};
        	
        	var stopSpin = function(input) {
        		if (input.timer) {
        			clearInterval(input.timer);
        			input.timer = 0;
        		}
        	};	
            
            var onMouse = function(btn,tag,down ) {
            	btn.removeClass(tag+(down?'NP':'P'));
            	btn.addClass(tag+(down?'P':'NP'));
            	
            };
            
            function invalidKey(keyCode, charCode) {
            	//F-Keys?
            	if (keyCode>=112 && keyCode<=123)
            		return false;
            	for (var i=0; i<sysKeys.length; i++) {
    				if (sysKeys[i] == keyCode) 
    					return false;
            	}
            	
    			var ch = String.fromCharCode(charCode || keyCode);
    				
    			if ((ch >= '0') && (ch <= '9') || (ch == '-')) 
    				return false;
    						
    			return true;
    		}
            
            
 
            return this.each(function() {
                var o = options;
//                alert(o.padding);
                
                var input = $(this);
                
                if (!input.vspinning) {
                	
                	input.vspinning = true;
               
	                var props = ['max','min','step']
	                for (var i=0; i<props.length; i++) {
	                	input[props[i]] = parseInt(input.attr(props[i]));
	                	if (isNaN(input[props[i]]))
	                		input[props[i]] = options[props[i]]
	                }
	                
	                
	                
	                input.wrap('<span class="vspinner" />')
	                var btns = input.parent().append('<span class="vbtns"/>').find('.vbtns')
	                btns.append('<a class="up upNP" ></a>')//style="opacity: 0;"
	                btns.append('<a class="down downNP"></a>')
	                btns.hide();
	                var iwidth = input.width();
	                btns.css('left',iwidth);
	                if ($.browser.msie && !options.ignoreIE) {
	                	var iheight = Math.max(15,input.height());
	                	btns.css('top',-iheight);
	                }
	                
	                btns.find('.up').mousedown(function() {
	                	onMouse($(this),'up',true);
	                	startSpin(input,options.step);
	                	
	                }).mouseup(function() {
	                	onMouse($(this),'up',false);
	                	stopSpin(input);
	                	
	                });	
	                
	                btns.find('.down').mousedown(function() {
	                	onMouse($(this),'down',true);
	                	startSpin(input,-options.step);
	                }).mouseup(function() {
	                	onMouse($(this),'down',false);
	                	stopSpin(input);
	                });	
	                
	                input.parent().mouseenter(function() {
	                	btns.fadeIn(300);
	                });
	                
	                input.parent().mouseleave(function() {
	                	btns.hide();
	                	onMouse(btns.find('.up'),'up',false);
	                	onMouse(btns.find('.down'),'down',false);
	                	stopSpin(input);
	                });
	                
	                input.keypress(function(e) {
	                	if (e.keyCode == keyCode.NUMPAD_ENTER || e.keyCode == keyCode.ENTER) 
	                		doSpin(input,0);
	                	else if (e.keyCode == keyCode.UP)
	                		doSpin(input,1);
	                	else if (e.keyCode == keyCode.DOWN)
	                		doSpin(input,-1);
	                	else if (invalidKey(e.keyCode, e.charCode))
	                		e.preventDefault();
	                });
	                
	                input.focusout(function() {
	               		doSpin(input,0);
	                });
                }
            });
        }
    });
     
})(jQuery);
