Yahoo! UI Library

Slider Widget 

Yahoo! UI Library > slider > Slider.js (source view)

/**
 * The Slider component is a UI control that enables the user to adjust 
 * values in a finite range along one or two axes. Typically, the Slider 
 * control is used in a web application as a rich, visual replacement 
 * for an input box that takes a number as input. The Slider control can 
 * also easily accommodate a second dimension, providing x,y output for 
 * a selection point chosen from a rectangular region.
 *
 * @module    slider
 * @title     Slider Widget
 * @namespace YAHOO.widget
 * @requires  yahoo,dom,dragdrop,event
 * @optional  animation
 */

/**
 * A DragDrop implementation that can be used as a background for a
 * slider.  It takes a reference to the thumb instance 
 * so it can delegate some of the events to it.  The goal is to make the 
 * thumb jump to the location on the background when the background is 
 * clicked.  
 *
 * @class Slider
 * @extends YAHOO.util.DragDrop
 * @uses YAHOO.util.EventProvider
 * @constructor
 * @param {String}      id     The id of the element linked to this instance
 * @param {String}      sGroup The group of related DragDrop items
 * @param {SliderThumb} oThumb The thumb for this slider
 * @param {String}      sType  The type of slider (horiz, vert, region)
 */
YAHOO.widget.Slider = function(sElementId, sGroup, oThumb, sType) {
    if (sElementId) {
        this.init(sElementId, sGroup, true);
        this.initSlider(sType);
        this.initThumb(oThumb);
    }
};

/**
 * Factory method for creating a horizontal slider
 * @method YAHOO.widget.Slider.getHorizSlider
 * @static
 * @param {String} sBGElId the id of the slider's background element
 * @param {String} sHandleElId the id of the thumb element
 * @param {int} iLeft the number of pixels the element can move left
 * @param {int} iRight the number of pixels the element can move right
 * @param {int} iTickSize optional parameter for specifying that the element 
 * should move a certain number pixels at a time.
 * @return {Slider} a horizontal slider control
 */
YAHOO.widget.Slider.getHorizSlider = 
    function (sBGElId, sHandleElId, iLeft, iRight, iTickSize) {
        return new YAHOO.widget.Slider(sBGElId, sBGElId, 
            new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 
                               iLeft, iRight, 0, 0, iTickSize), "horiz");
};

/**
 * Factory method for creating a vertical slider
 * @method YAHOO.widget.Slider.getVertSlider
 * @static
 * @param {String} sBGElId the id of the slider's background element
 * @param {String} sHandleElId the id of the thumb element
 * @param {int} iUp the number of pixels the element can move up
 * @param {int} iDown the number of pixels the element can move down
 * @param {int} iTickSize optional parameter for specifying that the element 
 * should move a certain number pixels at a time.
 * @return {Slider} a vertical slider control
 */
YAHOO.widget.Slider.getVertSlider = 
    function (sBGElId, sHandleElId, iUp, iDown, iTickSize) {
        return new YAHOO.widget.Slider(sBGElId, sBGElId, 
            new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 0, 0, 
                               iUp, iDown, iTickSize), "vert");
};

/**
 * Factory method for creating a slider region like the one in the color
 * picker example
 * @method YAHOO.widget.Slider.getSliderRegion
 * @static
 * @param {String} sBGElId the id of the slider's background element
 * @param {String} sHandleElId the id of the thumb element
 * @param {int} iLeft the number of pixels the element can move left
 * @param {int} iRight the number of pixels the element can move right
 * @param {int} iUp the number of pixels the element can move up
 * @param {int} iDown the number of pixels the element can move down
 * @param {int} iTickSize optional parameter for specifying that the element 
 * should move a certain number pixels at a time.
 * @return {Slider} a slider region control
 */
YAHOO.widget.Slider.getSliderRegion = 
    function (sBGElId, sHandleElId, iLeft, iRight, iUp, iDown, iTickSize) {
        return new YAHOO.widget.Slider(sBGElId, sBGElId, 
            new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, iLeft, iRight, 
                               iUp, iDown, iTickSize), "region");
};

/**
 * By default, animation is available if the animation library is detected.
 * @property YAHOO.widget.Slider.ANIM_AVAIL
 * @static
 * @type boolean
 */
YAHOO.widget.Slider.ANIM_AVAIL = true;

YAHOO.extend(YAHOO.widget.Slider, YAHOO.util.DragDrop, {

    /**
     * Initializes the slider.  Executed in the constructor
     * @method initSlider
     * @param {string} sType the type of slider (horiz, vert, region)
     */
    initSlider: function(sType) {

        /**
         * The type of the slider (horiz, vert, region)
         * @property type
         * @type string
         */
        this.type = sType;

        //this.removeInvalidHandleType("A");

        this.logger = new YAHOO.widget.LogWriter(this.toString());

        /**
         * Event the fires when the value of the control changes.  If 
         * the control is animated the event will fire every point
         * along the way.
         * @event change
         * @param {int} newOffset|x the new offset for normal sliders, or the new
         *                          x offset for region sliders
         * @param {int} y the number of pixels the thumb has moved on the y axis
         *                (region sliders only)
         */
        this.createEvent("change", this);

        /**
         * Event that fires at the beginning of a slider thumb move.
         * @event slideStart
         */
        this.createEvent("slideStart", this);

        /**
         * Event that fires at the end of a slider thumb move
         * @event slideEnd
         */
        this.createEvent("slideEnd", this);

        /**
         * Overrides the isTarget property in YAHOO.util.DragDrop
         * @property isTarget
         * @private
         */
        this.isTarget = false;
    
        /**
         * Flag that determines if the thumb will animate when moved
         * @property animate
         * @type boolean
         */
        this.animate = YAHOO.widget.Slider.ANIM_AVAIL;

        /**
         * Set to false to disable a background click thumb move
         * @property backgroundEnabled
         * @type boolean
         */
        this.backgroundEnabled = true;

        /**
         * Adjustment factor for tick animation, the more ticks, the
         * faster the animation (by default)
         * @property tickPause
         * @type int
         */
        this.tickPause = 40;

        /**
         * Enables the arrow, home and end keys, defaults to true.
         * @property enableKeys
         * @type boolean
         */
        this.enableKeys = true;

        /**
         * Specifies the number of pixels the arrow keys will move the slider.
         * Default is 25.
         * @property keyIncrement
         * @type int
         */
        this.keyIncrement = 20;

        /**
         * moveComplete is set to true when the slider has moved to its final
         * destination.  For animated slider, this value can be checked in 
         * the onChange handler to make it possible to execute logic only
         * when the move is complete rather than at all points along the way.
         *
         * @property moveComplete
         * @type Boolean
         */
        this.moveComplete = true;

        /**
         * If animation is configured, specifies the length of the animation
         * in seconds.
         * @property animationDuration
         * @type int
         * @default 0.2
         */
        this.animationDuration = 0.2;
    },

    /**
     * Initializes the slider's thumb. Executed in the constructor.
     * @method initThumb
     * @param {YAHOO.widget.SliderThumb} t the slider thumb
     */
    initThumb: function(t) {

        var self = this;

        /**
         * A YAHOO.widget.SliderThumb instance that we will use to 
         * reposition the thumb when the background is clicked
         * @property thumb
         * @type YAHOO.widget.SliderThumb
         */
        this.thumb = t;
        t.cacheBetweenDrags = true;

        // add handler for the handle onchange event
        t.onChange = function() { 
            self.handleThumbChange(); 
        };

        if (t._isHoriz && t.xTicks && t.xTicks.length) {
            this.tickPause = Math.round(360 / t.xTicks.length);
        } else if (t.yTicks && t.yTicks.length) {
            this.tickPause = Math.round(360 / t.yTicks.length);
        }

        this.logger.log("tickPause: " + this.tickPause);

        // delegate thumb methods
        t.onMouseDown = function () { return self.focus(); };
        t.onMouseUp = function() { self.thumbMouseUp(); };
        t.onDrag = function() { self.fireEvents(true); };
        t.onAvailable = function() { return self.setStartSliderState(); };

    },

    /**
     * Executed when the slider element is available
     * @method onAvailable
     */
    onAvailable: function() {
        var Event = YAHOO.util.Event;
        Event.on(this.id, "keydown",  this.handleKeyDown,  this, true);
        Event.on(this.id, "keypress", this.handleKeyPress, this, true);
    },
 
    /**
     * Executed when a keypress event happens with the control focused.
     * Prevents the default behavior for navigation keys.  The actual
     * logic for moving the slider thumb in response to a key event
     * happens in handleKeyDown.
     * @param {Event} e the keypress event
     */
    handleKeyPress: function(e) {
        if (this.enableKeys) {
            var Event = YAHOO.util.Event;
            var kc = Event.getCharCode(e);
            switch (kc) {
                case 0x25: // left
                case 0x26: // up
                case 0x27: // right
                case 0x28: // down
                case 0x24: // home
                case 0x23: // end
                    Event.preventDefault(e);
                    break;
                default:
            }
        }
    },

    /**
     * Executed when a keydown event happens with the control focused.
     * Updates the slider value and display when the keypress is an
     * arrow key, home, or end as long as enableKeys is set to true.
     * @param {Event} e the keydown event
     */
    handleKeyDown: function(e) {
        if (this.enableKeys) {
            var Event = YAHOO.util.Event;

            var kc = Event.getCharCode(e), t=this.thumb;
            var h=this.getXValue(),v=this.getYValue();

            var horiz = false;
            var changeValue = true;
            switch (kc) {

                // left
                case 0x25: h -= this.keyIncrement; break;

                // up
                case 0x26: v -= this.keyIncrement; break;

                // right
                case 0x27: h += this.keyIncrement; break;

                // down
                case 0x28: v += this.keyIncrement; break;

                // home
                case 0x24: h = t.leftConstraint;    
                           v = t.topConstraint;    
                           break;

                // end
                case 0x23: h = t.rightConstraint; 
                           v = t.bottomConstraint;    
                           break;

                default:   changeValue = false;
            }

            if (changeValue) {
                if (t._isRegion) {
                    this.setRegionValue(h, v, true);
                } else {
                    var newVal = (t._isHoriz) ? h : v;
                    this.setValue(newVal, true);
                }
                Event.stopEvent(e);
            }

        }
    },

    /**
     * Initialization that sets up the value offsets once the elements are ready
     * @method setStartSliderState
     */
    setStartSliderState: function() {

        this.logger.log("Fixing state");

        this.setThumbCenterPoint();

        /**
         * The basline position of the background element, used
         * to determine if the background has moved since the last
         * operation.
         * @property baselinePos
         * @type [int, int]
         */
        this.baselinePos = YAHOO.util.Dom.getXY(this.getEl());

        this.thumb.startOffset = this.thumb.getOffsetFromParent(this.baselinePos);

        if (this.thumb._isRegion) {
            if (this.deferredSetRegionValue) {
                this.setRegionValue.apply(this, this.deferredSetRegionValue, true);
                this.deferredSetRegionValue = null;
            } else {
                this.setRegionValue(0, 0, true, true);
            }
        } else {
            if (this.deferredSetValue) {
                this.setValue.apply(this, this.deferredSetValue, true);
                this.deferredSetValue = null;
            } else {
                this.setValue(0, true, true);
            }
        }
    },

    /**
     * When the thumb is available, we cache the centerpoint of the element so
     * we can position the element correctly when the background is clicked
     * @method setThumbCenterPoint
     */
    setThumbCenterPoint: function() {

        var el = this.thumb.getEl();

        if (el) {
            /**
             * The center of the slider element is stored so we can 
             * place it in the correct position when the background is clicked.
             * @property thumbCenterPoint
             * @type {"x": int, "y": int}
             */
            this.thumbCenterPoint = { 
                    x: parseInt(el.offsetWidth/2, 10), 
                    y: parseInt(el.offsetHeight/2, 10) 
            };
        }

    },

    /**
     * Locks the slider, overrides YAHOO.util.DragDrop
     * @method lock
     */
    lock: function() {
        this.logger.log("locking");
        this.thumb.lock();
        this.locked = true;
    },

    /**
     * Unlocks the slider, overrides YAHOO.util.DragDrop
     * @method unlock
     */
    unlock: function() {
        this.logger.log("unlocking");
        this.thumb.unlock();
        this.locked = false;
    },

    /**
     * Handles mouseup event on the slider background
     * @method thumbMouseUp
     * @private
     */
    thumbMouseUp: function() {
        this.logger.log("bg mouseup");
        if (!this.isLocked() && !this.moveComplete) {
            this.endMove();
        }

    },

    /**
     * Returns a reference to this slider's thumb
     * @method getThumb
     * @return {SliderThumb} this slider's thumb
     */
    getThumb: function() {
        return this.thumb;
    },

    /**
     * Try to focus the element when clicked so we can add
     * accessibility features
     * @method focus
     * @private
     */
    focus: function() {
        this.logger.log("focus");

        // Focus the background element if possible
        var el = this.getEl();

        if (el.focus) {
            try {
                el.focus();
            } catch(e) {
                // Prevent permission denied unhandled exception in FF that can
                // happen when setting focus while another element is handling
                // the blur.  @TODO this is still writing to the error log 
                // (unhandled error) in FF1.5 with strict error checking on.
            }
        }

        this.verifyOffset();

        if (this.isLocked()) {
            return false;
        } else {
            this.onSlideStart();
            return true;
        }
    },

    /**
     * Event that fires when the value of the slider has changed
     * @method onChange
     * @param {int} firstOffset the number of pixels the thumb has moved
     * from its start position. Normal horizontal and vertical sliders will only
     * have the firstOffset.  Regions will have both, the first is the horizontal
     * offset, the second the vertical.
     * @param {int} secondOffset the y offset for region sliders
     * @deprecated use instance.subscribe("change") instead
     */
    onChange: function (firstOffset, secondOffset) { 
        /* override me */ 
        this.logger.log("onChange: " + firstOffset + ", " + secondOffset);
    },

    /**
     * Event that fires when the at the beginning of the slider thumb move
     * @method onSlideStart
     * @deprecated use instance.subscribe("slideStart") instead
     */
    onSlideStart: function () { 
        /* override me */ 
        this.logger.log("onSlideStart");
    },

    /**
     * Event that fires at the end of a slider thumb move
     * @method onSliderEnd
     * @deprecated use instance.subscribe("slideEnd") instead
     */
    onSlideEnd: function () { 
        /* override me */ 
        this.logger.log("onSlideEnd");
    },

    /**
     * Returns the slider's thumb offset from the start position
     * @method getValue
     * @return {int} the current value
     */
    getValue: function () { 
        return this.thumb.getValue();
    },

    /**
     * Returns the slider's thumb X offset from the start position
     * @method getXValue
     * @return {int} the current horizontal offset
     */
    getXValue: function () { 
        return this.thumb.getXValue();
    },

    /**
     * Returns the slider's thumb Y offset from the start position
     * @method getYValue
     * @return {int} the current vertical offset
     */
    getYValue: function () { 
        return this.thumb.getYValue();
    },

    /**
     * Internal handler for the slider thumb's onChange event
     * @method handleThumbChange
     * @private
     */
    handleThumbChange: function () { 
        var t = this.thumb;
        if (t._isRegion) {
            t.onChange(t.getXValue(), t.getYValue());
            this.fireEvent("change", { x: t.getXValue(), y: t.getYValue() } );
        } else {
            t.onChange(t.getValue());
            this.fireEvent("change", t.getValue());
        }

    },

    /**
     * Provides a way to set the value of the slider in code.
     * @method setValue
     * @param {int} newOffset the number of pixels the thumb should be
     * positioned away from the initial start point 
     * @param {boolean} skipAnim set to true to disable the animation
     * for this move action (but not others).
     * @param {boolean} force ignore the locked setting and set value anyway
     * @return {boolean} true if the move was performed, false if it failed
     */
    setValue: function(newOffset, skipAnim, force) {
        this.logger.log("setValue " + newOffset);

        if (!this.thumb.available) {
            this.logger.log("defer setValue until after onAvailble");
            this.deferredSetValue = arguments;
            return false;
        }

        if (this.isLocked() && !force) {
            this.logger.log("Can't set the value, the control is locked");
            return false;
        }

        if ( isNaN(newOffset) ) {
            this.logger.log("setValue, Illegal argument: " + newOffset);
            return false;
        }

        var t = this.thumb;
        var newX, newY;
        this.verifyOffset(true);
        if (t._isRegion) {
            return false;
        } else if (t._isHoriz) {
            this.onSlideStart();
            // this.fireEvent("slideStart");
            newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
            this.moveThumb(newX, t.initPageY, skipAnim);
        } else {
            this.onSlideStart();
            // this.fireEvent("slideStart");
            newY = t.initPageY + newOffset + this.thumbCenterPoint.y;
            this.moveThumb(t.initPageX, newY, skipAnim);
        }

        return true;
    },

    /**
     * Provides a way to set the value of the region slider in code.
     * @method setRegionValue
     * @param {int} newOffset the number of pixels the thumb should be
     * positioned away from the initial start point (x axis for region)
     * @param {int} newOffset2 the number of pixels the thumb should be
     * positioned away from the initial start point (y axis for region)
     * @param {boolean} skipAnim set to true to disable the animation
     * for this move action (but not others).
     * @param {boolean} force ignore the locked setting and set value anyway
     * @return {boolean} true if the move was performed, false if it failed
     */
    setRegionValue: function(newOffset, newOffset2, skipAnim, force) {

        if (!this.thumb.available) {
            this.logger.log("defer setRegionValue until after onAvailble");
            this.deferredSetRegionValue = arguments;
            return false;
        }

        if (this.isLocked() && !force) {
            this.logger.log("Can't set the value, the control is locked");
            return false;
        }

        if ( isNaN(newOffset) ) {
            this.logger.log("setRegionValue, Illegal argument: " + newOffset);
            return false;
        }

        var t = this.thumb;
        if (t._isRegion) {
            this.onSlideStart();
            var newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
            var newY = t.initPageY + newOffset2 + this.thumbCenterPoint.y;
            this.moveThumb(newX, newY, skipAnim);
            return true;
        }

        return false;

    },

    /**
     * Checks the background position element position.  If it has moved from the
     * baseline position, the constraints for the thumb are reset
     * @param checkPos {boolean} check the position instead of using cached value
     * @method verifyOffset
     * @return {boolean} True if the offset is the same as the baseline.
     */
    verifyOffset: function(checkPos) {

        var newPos = YAHOO.util.Dom.getXY(this.getEl());
        //var newPos = [this.initPageX, this.initPageY];

        this.logger.log("newPos: " + newPos, "warn");

        if (newPos[0] != this.baselinePos[0] || newPos[1] != this.baselinePos[1]) {
            this.logger.log("background moved, resetting constraints");
            this.thumb.resetConstraints();
            this.baselinePos = newPos;
            return false;
        }

        return true;
    },

    /**
     * Move the associated slider moved to a timeout to try to get around the 
     * mousedown stealing moz does when I move the slider element between the 
     * cursor and the background during the mouseup event
     * @method moveThumb
     * @param {int} x the X coordinate of the click
     * @param {int} y the Y coordinate of the click
     * @param {boolean} skipAnim don't animate if the move happend onDrag
     * @private
     */
    moveThumb: function(x, y, skipAnim) {

        // this.logger.log("move thumb", "warn");

        var t = this.thumb;
        var self = this;

        if (!t.available) {
            this.logger.log("thumb is not available yet, aborting move");
            return;
        }

        this.logger.log("move thumb, x: "  + x + ", y: " + y);

        // this.verifyOffset();

        t.setDelta(this.thumbCenterPoint.x, this.thumbCenterPoint.y);

        var _p = t.getTargetCoord(x, y);
        var p = [_p.x, _p.y];


        this.fireEvent("slideStart");

        if (this.animate && YAHOO.widget.Slider.ANIM_AVAIL && t._graduated && !skipAnim) {
            this.logger.log("graduated");
            // this.thumb._animating = true;
            this.lock();

            // cache the current thumb pos
            this.curCoord = YAHOO.util.Dom.getXY(this.thumb.getEl());

            setTimeout( function() { self.moveOneTick(p); }, this.tickPause );

        } else if (this.animate && YAHOO.widget.Slider.ANIM_AVAIL && !skipAnim) {
            this.logger.log("animating to " + p);

            // this.thumb._animating = true;
            this.lock();

            var oAnim = new YAHOO.util.Motion( 
                    t.id, { points: { to: p } }, 
                    this.animationDuration, 
                    YAHOO.util.Easing.easeOut );

            oAnim.onComplete.subscribe( function() { self.endMove(); } );
            oAnim.animate();
        } else {
            t.setDragElPos(x, y);
            // this.fireEvents();
            this.endMove();
        }
    },

    /**
     * Move the slider one tick mark towards its final coordinate.  Used
     * for the animation when tick marks are defined
     * @method moveOneTick
     * @param {int[]} the destination coordinate
     * @private
     */
    moveOneTick: function(finalCoord) {

        var t = this.thumb, tmp;


        // redundant call to getXY since we set the position most of time prior 
        // to getting here.  Moved to this.curCoord
        //var curCoord = YAHOO.util.Dom.getXY(t.getEl());

        // alignElWithMouse caches position in lastPageX, lastPageY .. doesn't work
        //var curCoord = [this.lastPageX, this.lastPageY];

        // var thresh = Math.min(t.tickSize + (Math.floor(t.tickSize/2)), 10);
        // var thresh = 10;
        // var thresh = t.tickSize + (Math.floor(t.tickSize/2));

        var nextCoord = null;

        if (t._isRegion) {
            nextCoord = this._getNextX(this.curCoord, finalCoord);
            var tmpX = (nextCoord) ? nextCoord[0] : this.curCoord[0];
            nextCoord = this._getNextY([tmpX, this.curCoord[1]], finalCoord);

        } else if (t._isHoriz) {
            nextCoord = this._getNextX(this.curCoord, finalCoord);
        } else {
            nextCoord = this._getNextY(this.curCoord, finalCoord);
        }

        this.logger.log("moveOneTick: " + 
                " finalCoord: " + finalCoord +
                " this.curCoord: " + this.curCoord +
                " nextCoord: " + nextCoord);

        if (nextCoord) {

            // cache the position
            this.curCoord = nextCoord;

            // move to the next coord
            // YAHOO.util.Dom.setXY(t.getEl(), nextCoord);

            // var el = t.getEl();
            // YAHOO.util.Dom.setStyle(el, "left", (nextCoord[0] + this.thumb.deltaSetXY[0]) + "px");
            // YAHOO.util.Dom.setStyle(el, "top",  (nextCoord[1] + this.thumb.deltaSetXY[1]) + "px");

            this.thumb.alignElWithMouse(t.getEl(), nextCoord[0], nextCoord[1]);
            
            // check if we are in the final position, if not make a recursive call
            if (!(nextCoord[0] == finalCoord[0] && nextCoord[1] == finalCoord[1])) {
                var self = this;
                setTimeout(function() { self.moveOneTick(finalCoord); }, 
                        this.tickPause);
            } else {
                this.endMove();
            }
        } else {
            this.endMove();
        }

        //this.tickPause = Math.round(this.tickPause/2);
    },

    /**
     * Returns the next X tick value based on the current coord and the target coord.
     * @method _getNextX
     * @private
     */
    _getNextX: function(curCoord, finalCoord) {
        this.logger.log("getNextX: " + curCoord + ", " + finalCoord);
        var t = this.thumb;
        var thresh;
        var tmp = [];
        var nextCoord = null;
        if (curCoord[0] > finalCoord[0]) {
            thresh = t.tickSize - this.thumbCenterPoint.x;
            tmp = t.getTargetCoord( curCoord[0] - thresh, curCoord[1] );
            nextCoord = [tmp.x, tmp.y];
        } else if (curCoord[0] < finalCoord[0]) {
            thresh = t.tickSize + this.thumbCenterPoint.x;
            tmp = t.getTargetCoord( curCoord[0] + thresh, curCoord[1] );
            nextCoord = [tmp.x, tmp.y];
        } else {
            // equal, do nothing
        }

        return nextCoord;
    },

    /**
     * Returns the next Y tick value based on the current coord and the target coord.
     * @method _getNextY
     * @private
     */
    _getNextY: function(curCoord, finalCoord) {
        var t = this.thumb;
        var thresh;
        var tmp = [];
        var nextCoord = null;

        if (curCoord[1] > finalCoord[1]) {
            thresh = t.tickSize - this.thumbCenterPoint.y;
            tmp = t.getTargetCoord( curCoord[0], curCoord[1] - thresh );
            nextCoord = [tmp.x, tmp.y];
        } else if (curCoord[1] < finalCoord[1]) {
            thresh = t.tickSize + this.thumbCenterPoint.y;
            tmp = t.getTargetCoord( curCoord[0], curCoord[1] + thresh );
            nextCoord = [tmp.x, tmp.y];
        } else {
            // equal, do nothing
        }

        return nextCoord;
    },

    /**
     * Resets the constraints before moving the thumb.
     * @method b4MouseDown
     * @private
     */
    b4MouseDown: function(e) {
        this.thumb.autoOffset();
        this.thumb.resetConstraints();
    },


    /**
     * Handles the mousedown event for the slider background
     * @method onMouseDown
     * @private
     */
    onMouseDown: function(e) {
        // this.resetConstraints(true);
        // this.thumb.resetConstraints(true);

        if (! this.isLocked() && this.backgroundEnabled) {
            var x = YAHOO.util.Event.getPageX(e);
            var y = YAHOO.util.Event.getPageY(e);
            this.logger.log("bg mousedown: " + x + "," + y);

            this.focus();
            this.moveThumb(x, y);
        }
        
    },

    /**
     * Handles the onDrag event for the slider background
     * @method onDrag
     * @private
     */
    onDrag: function(e) {
        if (! this.isLocked()) {
            var x = YAHOO.util.Event.getPageX(e);
            var y = YAHOO.util.Event.getPageY(e);
            this.moveThumb(x, y, true);
        }
    },

    /**
     * Fired when the slider movement ends
     * @method endMove
     * @private
     */
    endMove: function () {
        // this._animating = false;
        this.unlock();
        this.moveComplete = true;
        this.fireEvents();
    },

    /**
     * Fires the change event if the value has been changed.  Ignored if we are in
     * the middle of an animation as the event will fire when the animation is
     * complete
     * @method fireEvents
     * @param {boolean} thumbEvent set to true if this event is fired from an event
     *                  that occurred on the thumb.  If it is, the state of the
     *                  thumb dd object should be correct.  Otherwise, the event
     *                  originated on the background, so the thumb state needs to
     *                  be refreshed before proceeding.
     * @private
     */
    fireEvents: function (thumbEvent) {

        var t = this.thumb;
        // this.logger.log("FireEvents: " + t._isRegion);

        if (!thumbEvent) {
            t.cachePosition();
        }

        if (! this.isLocked()) {
            if (t._isRegion) {
                this.logger.log("region");
                var newX = t.getXValue();
                var newY = t.getYValue();

                if (newX != this.previousX || newY != this.previousY) {
                    // this.logger.log("Firing onchange");
                    this.onChange(newX, newY);
                    this.fireEvent("change", { x: newX, y: newY });
                }

                this.previousX = newX;
                this.previousY = newY;

            } else {
                var newVal = t.getValue();
                if (newVal != this.previousVal) {
                    this.logger.log("Firing onchange: " + newVal);
                    this.onChange( newVal );
                    this.fireEvent("change", newVal);
                }
                this.previousVal = newVal;
            }

            if (this.moveComplete) {
                this.onSlideEnd();
                this.fireEvent("slideEnd");
                this.moveComplete = false;
            }

        }
    },

    /**
     * Slider toString
     * @method toString
     * @return {string} string representation of the instance
     */
    toString: function () { 
        return ("Slider (" + this.type +") " + this.id);
    }

});

YAHOO.augment(YAHOO.widget.Slider, YAHOO.util.EventProvider);

Copyright © 2006 Yahoo! Inc. All rights reserved.
Download Mp3/Mp3 MusicTop Chartsdownload Guns N\ Roses music lyricdownload The Raconteurs music lyricdownload Nina Simone music lyricdownload The Cure music lyricdownload Pendulum music lyricdownload Barenaked Ladies music lyricdownload Spiritualized music lyricdownload The Beach Boys music lyricdownload Natasha Bedingfield music lyricdownload Def Leppard music lyricdownload Gabriella Cilmi music lyricdownload Red Hot Chili Peppers music lyricdownload Toby Keith music lyricdownload Nickelback music lyricdownload Flobots music lyricdownload Tom Waits music lyricdownload Sara Bareilles music lyricdownload Kanye West music lyricdownload Eric Clapton music lyricdownload Fleetwood Mac music lyricdownload Stevie Wonder music lyricdownload Elton John music lyricdownload Fleet Foxes music lyricdownload Sam Sparro music lyricdownload Depeche Mode music lyricsing

sing

once pair

pair

guide spring

spring

jump miss

miss

cat act

act

difficult gas

gas

down front

front

exercise ocean

ocean

differ listen

listen

look self

self

stretch subject

subject

help book

book

quick black

black

win who

who

except protect

protect

ground arrange

arrange

nature fact

fact

grass dead

dead

sit school

school

pose there

there

twenty book

book

better joy

joy

eye eye

eye

station led

led

populate whose

whose

bread king

king

element off

off

children baby

baby

bed middle

middle

these sure

sure

company view

view

if beauty

beauty

nose sign

sign

art dad

dad

decimal flower

flower

east salt

salt

large eat

eat

among there

there

right thousand

thousand

radio friend

friend

character few

few

body enough

enough

sign remember

remember

any
Download Mp3/Mp3 MusicTop Chartsdownload Guns N\ Roses music lyricdownload The Raconteurs music lyricdownload Nina Simone music lyricdownload The Cure music lyricdownload Pendulum music lyricdownload Barenaked Ladies music lyricdownload Spiritualized music lyricdownload The Beach Boys music lyricdownload Natasha Bedingfield music lyricdownload Def Leppard music lyricdownload Gabriella Cilmi music lyricdownload Red Hot Chili Peppers music lyricdownload Toby Keith music lyricdownload Nickelback music lyricdownload Flobots music lyricdownload Tom Waits music lyricdownload Sara Bareilles music lyricdownload Kanye West music lyricdownload Eric Clapton music lyricdownload Fleetwood Mac music lyricdownload Stevie Wonder music lyricdownload Elton John music lyricdownload Fleet Foxes music lyricdownload Sam Sparro music lyricdownload Depeche Mode music lyricadult 3d vids tgp

adult 3d vids tgp

warm abnormal lum on vagina

abnormal lum on vagina

fat milfs russian free porn