
/**
  * Prototype spin button / spin input / number field
  * @Author: wojciech.bajon@mail-from-google
  * @Version: 1.1
  * @reqire: (probably) Prototype 1.6.0.2
  * @basedOn: JQuerySpinBtn.js v1.3a http://www.softwareunity.com/sandbox/jqueryspinbtn/
  * Originally written by George Adamson, Software Unity (george.jquery@softwareunity.com) August 2006.
  * @license: MIT License
  * @Copyright (c) 2008 Wojciech Bajon
  */
  
/**
  * v1.1: reaction on pasate, keyboard function fixes, element from object, not form event
  */
  
  
if(typeof(Prototype) == "undefined")
  throw("spinbutton.js require  prototype library");



/*
 * Orginal: http://adomas.org/javascript-mouse-wheel/
 * prototype extension by "Frank Monnerjahn" <themonnie@gmail.com>
 */
Object.extend(Event, {
  wheel:function (ev){
    var delta = 0;
    if (!ev) ev = window.event;
    if (ev.wheelDelta) {
      delta = ev.wheelDelta/120; 
    } else if (ev.detail) { delta = -ev.detail/3;  }
    return Math.round(delta); //Safari Round
  }
});
/*
 * enf of extension 
 */ 

var SpinButton = Class.create({
    initialize: function(el){
      this.element = $(el);
      if(!this.element)
        return null;
      this.options = Object.extend(
        { ///default options
          min:null,
          max:null,
          step:1,
          page:10,
          spinClass:null,
          upClass:'up',
          downClass:'down',
          reset:Number(this.element.value),
          delay:500,
          interval:100,
          
          _btn_width: 20,
          _btn_height: 12,
          _direction: null,
          _delay: null,
          _repeat: null
        }, arguments[1] || { });
      
      if(this.options.spinClass)
        this.element.addClassName(this.options.spinClass);
      
      Event.observe(this.element,'mousemove',this.onMouseMove.bindAsEventListener(this));
      Event.observe(this.element,'mouseover',this.onMouseMove.bindAsEventListener(this));
      Event.observe(this.element,'mouseout',this.onMouseOut.bindAsEventListener(this));
      if(Prototype.Browser.Gecko){
        Event.observe(this.element,'DOMMouseScroll',this.mousewheel.bindAsEventListener(this),false);
        Event.observe(this.element,'input',this.onChange.bindAsEventListener(this));//FF_pasate
      }else{
        Event.observe(this.element,'mousewheel',this.mousewheel.bindAsEventListener(this),false);
      }
      if(Prototype.Browser.IE){
        Event.observe(this.element,'dblclick',this.onDblClick.bindAsEventListener(this));
        
        var self = this;
        var adjust = function() {
          self.adjustValue(self.options._direction * self.options.step);
        };
        this.element.onpaste= function(){setTimeout(adjust,0);};    
      }
      Event.observe(this.element,'mousedown',this.onMouseDown.bindAsEventListener(this));
      Event.observe(this.element,'mouseup',this.onMouseUp.bindAsEventListener(this));
      Event.observe(this.element,'keydown',this.onKeyDown.bindAsEventListener(this));
      Event.observe(this.element,'change',this.onChange.bindAsEventListener(this));
    },
    onDblClick:function(ev){
      this.adjustValue(this.options._direction * this.options.step);
    },
    onMouseUp:function(ev){
			// Cancel repeating adjustment
			window.clearInterval(this.options._repeat);
			window.clearTimeout(this.options._delay);
    },
    onMouseDown:function(ev){
      if (this.options._direction == 0)
        return;
      var self = this;
      var adjust = function() {
        self.adjustValue(self.options._direction * self.options.step);
      };
    
      adjust();
      
      // Initial delay before repeating adjustment
      self.options._delay = window.setTimeout(function() {
        adjust();
        // Repeat adjust at regular intervals
        self.options._repeat = window.setInterval(adjust, self.options.interval);
      }, self.options.delay);
    },
    onKeyDown:function(ev){
      switch(ev.keyCode){
				case Event.KEY_UP: 
              this.adjustValue(this.options.step); 
              Event.stop(ev); 
          break; 
				case Event.KEY_DOWN: 
              this.adjustValue(-this.options.step);
              Event.stop(ev); 
          break; 
				case Event.KEY_PAGEUP: 
              this.adjustValue(this.options.page);  
              Event.stop(ev);
          break; 
				case Event.KEY_PAGEDOWN:
              this.adjustValue(-this.options.page);
              Event.stop(ev); 
          break; 
			}
    },
    onChange:function(ev){
      this.adjustValue(0);
    },
    adjustValue: function(i){
      var v = (isNaN(this.element.value) ? this.options.reset : Number(this.element.value)) + Number(i);
      if (this.options.min !== null) v = Math.max(v, this.options.min);
      if (this.options.max !== null) v = Math.min(v, this.options.max);
      this.element.value = v;
    },
    onMouseMove:function(ev){
      var of = this.element.cumulativeOffset();// [left, top] 
      var direction = (Event.pointerX(ev) > of[0] + this.element.getWidth() - this.options._btn_width)
        ? ((Event.pointerY(ev) < of[1] + this.options._btn_height) ? 1 : -1) : 0;
        
        if (direction !== this.options._direction) {
        // Style up/down buttons:
        switch(direction){
          case 1: // Up arrow:
            this.element.removeClassName(this.options.downClass).addClassName(this.options.upClass);
            break;
          case -1: // Down arrow:
            this.element.removeClassName(this.options.upClass).addClassName(this.options.downClass);
            break;
          default: // Mouse is elsewhere in the textbox
            this.element.removeClassName(this.options.upClass).removeClassName(this.options.downClass);
        }
        this.options._direction = direction;
        }
    },
    onMouseOut: function(ev){
      this.element.removeClassName(this.options.upClass).removeClassName(this.options.downClass);
    },
    mousewheel:function(ev){
      if(Event.wheel(ev) >= 1)
        this.adjustValue(this.options.step);
      else if(Event.wheel(ev) <= -1)
        this.adjustValue(-this.options.step);
      Event.stop(ev);
    }
});
