/* 
 * Spinbutton plugin for jQuery
 * http://www.softwareunity.com/jquery/JQuerySpinBtn/
 *
 * Adds bells and whistles to any ordinary textbox to
 * make it look and feel like a SpinButton Control.
 *
 * Copyright (c) 2006-2009 Software Unity Ltd
 * Dual licensed under the MIT and GPL licenses.
 * http://www.softwareunity.com/jquery/MIT-LICENSE.txt
 * http://www.softwareunity.com/jquery/GPL-LICENSE.txt
 *
 * Originally written by George Adamson, Software Unity (george.jquery@softwareunity.com) August 2006.
 * - Added min/max options
 * - Added step size option
 * - Added bigStep (page up/down) option
 *
 * Modifications made by Mark Gibson, (mgibson@designlinks.net) September 2006:
 * - Converted to jQuery plugin
 * - Allow limited or unlimited min/max values
 * - Allow custom class names, and add class to input element
 * - Removed global vars
 * - Reset (to original or through config) when invalid value entered
 * - Repeat whilst holding mouse button down (with initial pause, like keyboard repeat)
 * - Support mouse wheel in Firefox
 * - Fix double click in IE
 * - Refactored some code and renamed some vars
 *
 * Tested in IE6, Opera9, Firefox 1.5
 * v1.0  11 Aug 2006 - George Adamson	- First release
 * v1.1     Aug 2006 - George Adamson	- Minor enhancements
 * v1.2  27 Sep 2006 - Mark Gibson		- Major enhancements
 * v1.3a 28 Sep 2006 - George Adamson	- Minor enhancements

 Sample usage:

 // Create group of settings to initialise spinbutton(s). (Optional)
 var myOptions = {
 min: 0,						// Set lower limit.
 max: 100,					// Set upper limit.
 step: 1,					// Set increment size.
 spinClass: mySpinBtnClass,	// CSS class to style the spinbutton. (Class also specifies url of the up/down button image.)
 upClass: mySpinUpClass,		// CSS class for style when mouse over up button.
 downClass: mySpinDnClass	// CSS class for style when mouse over down button.
 }

 $(document).ready(function(){

 // Initialise INPUT element(s) as SpinButtons: (passing options if desired)
 $("#myInputElement").SpinButton(myOptions);

 });

 */



$.fn.SpinButton = function (options) {
    return this.each(function () {

        this.spinCfg = $.extend({}, $.fn.SpinButton.defaults, options);

        this.adjustValue = function (i) {
            var v = (isNaN(this.value) ? this.spinCfg.reset : Number(this.value)) + Number(i);
            if (this.spinCfg.min !== null) v = Math.max(v, this.spinCfg.min);
            if (this.spinCfg.max !== null) v = Math.min(v, this.spinCfg.max);
            var oldValue = this.value;
            this.value = v;
            this.spinCfg.valueChanged(this, { oldValue: oldValue, newValue: v });
        };

        $(this)
                .addClass(options && options.spinClass ? options.spinClass : 'spin-button')

                .mousemove(function (e) {
                    // Determine which button mouse is over, or not (spin direction):
                    var x = e.pageX || e.x;
                    var y = e.pageY || e.y;
                    var el = e.target || e.srcElement;


                    //alert(el.offsetWidth + " " + this.spinCfg._btn_width + " " + this.spinCfg._btn_height);


                    //alert($(el).position().top + " " + $(el).position().left);


                    //var p = { left: coord(el, 'offsetLeft'), top: coord(el, 'offsetTop') };
                    var p = $(el).offset();

                    
                    

                    var direction =
                    (x > p.left + el.offsetWidth - this.spinCfg._btn_width)
                            ? ((y < p.top + this.spinCfg._btn_height)
                                ? 1
                                : -1)
                            : 0;


                   // alert(direction);

                    if (direction !== this.spinCfg._direction) {
                        // Style up/down buttons:
                        switch (direction) {
                            case 1: // Up arrow:
                                $(this).removeClass(this.spinCfg.downClass).addClass(this.spinCfg.upClass);
                                break;
                            case -1: // Down arrow:
                                $(this).removeClass(this.spinCfg.upClass).addClass(this.spinCfg.downClass);
                                break;
                            default: // Mouse is elsewhere in the textbox
                                $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
                        }

                        // Set spin direction:
                        this.spinCfg._direction = direction;
                    }
                })

                .mouseout(function () {
                    // Reset up/down buttons to their normal appearance when mouse moves away:
                    $(this).removeClass(this.spinCfg.upClass).removeClass(this.spinCfg.downClass);
                    this.spinCfg._direction = null;
                })

                .mousedown(function (e) {
                    if (this.spinCfg._direction != 0) {
                        // Respond to click on one of the buttons:
                        var self = this;
                        var adjust = function () {
                            self.adjustValue(self.spinCfg._direction * self.spinCfg.step);
                        };

                        adjust();

                        // Initial delay before repeating adjustment
                        self.spinCfg._delay = window.setTimeout(function () {
                            adjust();
                            // Repeat adjust at regular intervals
                            self.spinCfg._repeat = window.setInterval(adjust, self.spinCfg.interval);
                        }, self.spinCfg.delay);
                    }
                })

                .mouseup(function (e) {
                    // Cancel repeating adjustment
                    window.clearInterval(this.spinCfg._repeat);
                    window.clearTimeout(this.spinCfg._delay);
                })

                .dblclick(function (e) {
                    if ($.browser.msie)
                        this.adjustValue(this.spinCfg._direction * this.spinCfg.step);
                })

                .keydown(function (e) {
                    // Respond to up/down arrow keys.
                    switch (e.keyCode) {
                        case 38: this.adjustValue(this.spinCfg.step);
                            break; // Up
                        case 40: this.adjustValue(-this.spinCfg.step);
                            break; // Down
                        case 33: this.adjustValue(this.spinCfg.page);
                            break; // PageUp
                        case 34: this.adjustValue(-this.spinCfg.page);
                            break; // PageDown
                    }
                })

                .bind("mousewheel", function (e) {
                    // Respond to mouse wheel in IE. (It returns up/dn motion in multiples of 120)
                    if (e.wheelDelta >= 120)
                        this.adjustValue(this.spinCfg.step);
                    else if (e.wheelDelta <= -120)
                        this.adjustValue(-this.spinCfg.step);

                    e.preventDefault();
                })

                .change(function (e) {
                    this.adjustValue(0);
                });

        if (this.addEventListener) {
            // Respond to mouse wheel in Firefox
            this.addEventListener('DOMMouseScroll', function (e) {
                if (e.detail > 0)
                    this.adjustValue(-this.spinCfg.step);
                else if (e.detail < 0)
                    this.adjustValue(this.spinCfg.step);

                e.preventDefault();
            }, false);
        }
    });

    function coord(el, prop) {
        var c = el[prop], b = document.body;

        while ((el = el.offsetParent) && (el != b)) {
            if (!$.browser.msie || (el.currentStyle.position != 'relative'))
                c += el[prop];
        }

        alert(c);

        return c;
    }
};

 $.fn.SpinButton.defaults = {             
            min: 0,
            max: 100,
            step: 1,
            page: 10,
            upClass: 'up',
            downClass: 'down',
            reset: 0,
            delay: 500,
            interval: 100,
            _btn_width: 20,
            _btn_height: 8,
            _direction: null,
            _delay: null,
            _repeat: null,
            valueChanged: function(sender, e) {}
 };

