PageRenderTime 95ms CodeModel.GetById 12ms app.highlight 71ms RepoModel.GetById 1ms app.codeStats 0ms

/hippo/src/main/webapp/yui/slider/slider.js

http://hdbc.googlecode.com/
JavaScript | 2061 lines | 863 code | 288 blank | 910 comment | 155 complexity | 45389cd364aaa1719af38cddc9385088 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/*
   2Copyright (c) 2009, Yahoo! Inc. All rights reserved.
   3Code licensed under the BSD License:
   4http://developer.yahoo.net/yui/license.txt
   5version: 2.7.0
   6*/
   7/**
   8 * The Slider component is a UI control that enables the user to adjust 
   9 * values in a finite range along one or two axes. Typically, the Slider 
  10 * control is used in a web application as a rich, visual replacement 
  11 * for an input box that takes a number as input. The Slider control can 
  12 * also easily accommodate a second dimension, providing x,y output for 
  13 * a selection point chosen from a rectangular region.
  14 *
  15 * @module    slider
  16 * @title     Slider Widget
  17 * @namespace YAHOO.widget
  18 * @requires  yahoo,dom,dragdrop,event
  19 * @optional  animation
  20 */
  21 (function () {
  22
  23var getXY = YAHOO.util.Dom.getXY,
  24    Event = YAHOO.util.Event,
  25    _AS   = Array.prototype.slice;
  26
  27/**
  28 * A DragDrop implementation that can be used as a background for a
  29 * slider.  It takes a reference to the thumb instance 
  30 * so it can delegate some of the events to it.  The goal is to make the 
  31 * thumb jump to the location on the background when the background is 
  32 * clicked.  
  33 *
  34 * @class Slider
  35 * @extends YAHOO.util.DragDrop
  36 * @uses YAHOO.util.EventProvider
  37 * @constructor
  38 * @param {String}      id     The id of the element linked to this instance
  39 * @param {String}      sGroup The group of related DragDrop items
  40 * @param {SliderThumb} oThumb The thumb for this slider
  41 * @param {String}      sType  The type of slider (horiz, vert, region)
  42 */
  43function Slider(sElementId, sGroup, oThumb, sType) {
  44
  45    Slider.ANIM_AVAIL = (!YAHOO.lang.isUndefined(YAHOO.util.Anim));
  46
  47    if (sElementId) {
  48        this.init(sElementId, sGroup, true);
  49        this.initSlider(sType);
  50        this.initThumb(oThumb);
  51    }
  52}
  53
  54YAHOO.lang.augmentObject(Slider,{
  55    /**
  56     * Factory method for creating a horizontal slider
  57     * @method YAHOO.widget.Slider.getHorizSlider
  58     * @static
  59     * @param {String} sBGElId the id of the slider's background element
  60     * @param {String} sHandleElId the id of the thumb element
  61     * @param {int} iLeft the number of pixels the element can move left
  62     * @param {int} iRight the number of pixels the element can move right
  63     * @param {int} iTickSize optional parameter for specifying that the element 
  64     * should move a certain number pixels at a time.
  65     * @return {Slider} a horizontal slider control
  66     */
  67    getHorizSlider : 
  68        function (sBGElId, sHandleElId, iLeft, iRight, iTickSize) {
  69            return new Slider(sBGElId, sBGElId, 
  70                new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 
  71                                   iLeft, iRight, 0, 0, iTickSize), "horiz");
  72    },
  73
  74    /**
  75     * Factory method for creating a vertical slider
  76     * @method YAHOO.widget.Slider.getVertSlider
  77     * @static
  78     * @param {String} sBGElId the id of the slider's background element
  79     * @param {String} sHandleElId the id of the thumb element
  80     * @param {int} iUp the number of pixels the element can move up
  81     * @param {int} iDown the number of pixels the element can move down
  82     * @param {int} iTickSize optional parameter for specifying that the element 
  83     * should move a certain number pixels at a time.
  84     * @return {Slider} a vertical slider control
  85     */
  86    getVertSlider :
  87        function (sBGElId, sHandleElId, iUp, iDown, iTickSize) {
  88            return new Slider(sBGElId, sBGElId, 
  89                new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 0, 0, 
  90                                   iUp, iDown, iTickSize), "vert");
  91    },
  92
  93    /**
  94     * Factory method for creating a slider region like the one in the color
  95     * picker example
  96     * @method YAHOO.widget.Slider.getSliderRegion
  97     * @static
  98     * @param {String} sBGElId the id of the slider's background element
  99     * @param {String} sHandleElId the id of the thumb element
 100     * @param {int} iLeft the number of pixels the element can move left
 101     * @param {int} iRight the number of pixels the element can move right
 102     * @param {int} iUp the number of pixels the element can move up
 103     * @param {int} iDown the number of pixels the element can move down
 104     * @param {int} iTickSize optional parameter for specifying that the element 
 105     * should move a certain number pixels at a time.
 106     * @return {Slider} a slider region control
 107     */
 108    getSliderRegion : 
 109        function (sBGElId, sHandleElId, iLeft, iRight, iUp, iDown, iTickSize) {
 110            return new Slider(sBGElId, sBGElId, 
 111                new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, iLeft, iRight, 
 112                                   iUp, iDown, iTickSize), "region");
 113    },
 114
 115    /**
 116     * Constant for valueChangeSource, indicating that the user clicked or
 117     * dragged the slider to change the value.
 118     * @property Slider.SOURCE_UI_EVENT
 119     * @final
 120     * @static
 121     * @default 1
 122     */
 123    SOURCE_UI_EVENT : 1,
 124
 125    /**
 126     * Constant for valueChangeSource, indicating that the value was altered
 127     * by a programmatic call to setValue/setRegionValue.
 128     * @property Slider.SOURCE_SET_VALUE
 129     * @final
 130     * @static
 131     * @default 2
 132     */
 133    SOURCE_SET_VALUE : 2,
 134
 135    /**
 136     * Constant for valueChangeSource, indicating that the value was altered
 137     * by hitting any of the supported keyboard characters.
 138     * @property Slider.SOURCE_KEY_EVENT
 139     * @final
 140     * @static
 141     * @default 2
 142     */
 143    SOURCE_KEY_EVENT : 3,
 144
 145    /**
 146     * By default, animation is available if the animation utility is detected.
 147     * @property Slider.ANIM_AVAIL
 148     * @static
 149     * @type boolean
 150     */
 151    ANIM_AVAIL : false
 152},true);
 153
 154YAHOO.extend(Slider, YAHOO.util.DragDrop, {
 155
 156    /**
 157     * Tracks the state of the mouse button to aid in when events are fired.
 158     *
 159     * @property _mouseDown
 160     * @type boolean
 161     * @default false
 162     * @private
 163     */
 164    _mouseDown : false,
 165
 166    /**
 167     * Override the default setting of dragOnly to true.
 168     * @property dragOnly
 169     * @type boolean
 170     * @default true
 171     */
 172    dragOnly : true,
 173
 174    /**
 175     * Initializes the slider.  Executed in the constructor
 176     * @method initSlider
 177     * @param {string} sType the type of slider (horiz, vert, region)
 178     */
 179    initSlider: function(sType) {
 180
 181        /**
 182         * The type of the slider (horiz, vert, region)
 183         * @property type
 184         * @type string
 185         */
 186        this.type = sType;
 187
 188        //this.removeInvalidHandleType("A");
 189
 190
 191        /**
 192         * Event the fires when the value of the control changes.  If 
 193         * the control is animated the event will fire every point
 194         * along the way.
 195         * @event change
 196         * @param {int} newOffset|x the new offset for normal sliders, or the new
 197         *                          x offset for region sliders
 198         * @param {int} y the number of pixels the thumb has moved on the y axis
 199         *                (region sliders only)
 200         */
 201        this.createEvent("change", this);
 202
 203        /**
 204         * Event that fires at the beginning of a slider thumb move.
 205         * @event slideStart
 206         */
 207        this.createEvent("slideStart", this);
 208
 209        /**
 210         * Event that fires at the end of a slider thumb move
 211         * @event slideEnd
 212         */
 213        this.createEvent("slideEnd", this);
 214
 215        /**
 216         * Overrides the isTarget property in YAHOO.util.DragDrop
 217         * @property isTarget
 218         * @private
 219         */
 220        this.isTarget = false;
 221    
 222        /**
 223         * Flag that determines if the thumb will animate when moved
 224         * @property animate
 225         * @type boolean
 226         */
 227        this.animate = Slider.ANIM_AVAIL;
 228
 229        /**
 230         * Set to false to disable a background click thumb move
 231         * @property backgroundEnabled
 232         * @type boolean
 233         */
 234        this.backgroundEnabled = true;
 235
 236        /**
 237         * Adjustment factor for tick animation, the more ticks, the
 238         * faster the animation (by default)
 239         * @property tickPause
 240         * @type int
 241         */
 242        this.tickPause = 40;
 243
 244        /**
 245         * Enables the arrow, home and end keys, defaults to true.
 246         * @property enableKeys
 247         * @type boolean
 248         */
 249        this.enableKeys = true;
 250
 251        /**
 252         * Specifies the number of pixels the arrow keys will move the slider.
 253         * Default is 20.
 254         * @property keyIncrement
 255         * @type int
 256         */
 257        this.keyIncrement = 20;
 258
 259        /**
 260         * moveComplete is set to true when the slider has moved to its final
 261         * destination.  For animated slider, this value can be checked in 
 262         * the onChange handler to make it possible to execute logic only
 263         * when the move is complete rather than at all points along the way.
 264         * Deprecated because this flag is only useful when the background is
 265         * clicked and the slider is animated.  If the user drags the thumb,
 266         * the flag is updated when the drag is over ... the final onDrag event
 267         * fires before the mouseup the ends the drag, so the implementer will
 268         * never see it.
 269         *
 270         * @property moveComplete
 271         * @type Boolean
 272         * @deprecated use the slideEnd event instead
 273         */
 274        this.moveComplete = true;
 275
 276        /**
 277         * If animation is configured, specifies the length of the animation
 278         * in seconds.
 279         * @property animationDuration
 280         * @type int
 281         * @default 0.2
 282         */
 283        this.animationDuration = 0.2;
 284
 285        /**
 286         * Constant for valueChangeSource, indicating that the user clicked or
 287         * dragged the slider to change the value.
 288         * @property SOURCE_UI_EVENT
 289         * @final
 290         * @default 1
 291         * @deprecated use static Slider.SOURCE_UI_EVENT
 292         */
 293        this.SOURCE_UI_EVENT = 1;
 294
 295        /**
 296         * Constant for valueChangeSource, indicating that the value was altered
 297         * by a programmatic call to setValue/setRegionValue.
 298         * @property SOURCE_SET_VALUE
 299         * @final
 300         * @default 2
 301         * @deprecated use static Slider.SOURCE_SET_VALUE
 302         */
 303        this.SOURCE_SET_VALUE = 2;
 304
 305        /**
 306         * When the slider value changes, this property is set to identify where
 307         * the update came from.  This will be either 1, meaning the slider was
 308         * clicked or dragged, or 2, meaning that it was set via a setValue() call.
 309         * This can be used within event handlers to apply some of the logic only
 310         * when dealing with one source or another.
 311         * @property valueChangeSource
 312         * @type int
 313         * @since 2.3.0
 314         */
 315        this.valueChangeSource = 0;
 316
 317        /**
 318         * Indicates whether or not events will be supressed for the current
 319         * slide operation
 320         * @property _silent
 321         * @type boolean
 322         * @private
 323         */
 324        this._silent = false;
 325
 326        /**
 327         * Saved offset used to protect against NaN problems when slider is
 328         * set to display:none
 329         * @property lastOffset
 330         * @type [int, int]
 331         */
 332        this.lastOffset = [0,0];
 333    },
 334
 335    /**
 336     * Initializes the slider's thumb. Executed in the constructor.
 337     * @method initThumb
 338     * @param {YAHOO.widget.SliderThumb} t the slider thumb
 339     */
 340    initThumb: function(t) {
 341
 342        var self = this;
 343
 344        /**
 345         * A YAHOO.widget.SliderThumb instance that we will use to 
 346         * reposition the thumb when the background is clicked
 347         * @property thumb
 348         * @type YAHOO.widget.SliderThumb
 349         */
 350        this.thumb = t;
 351
 352        t.cacheBetweenDrags = true;
 353
 354        if (t._isHoriz && t.xTicks && t.xTicks.length) {
 355            this.tickPause = Math.round(360 / t.xTicks.length);
 356        } else if (t.yTicks && t.yTicks.length) {
 357            this.tickPause = Math.round(360 / t.yTicks.length);
 358        }
 359
 360
 361        // delegate thumb methods
 362        t.onAvailable = function() { 
 363                return self.setStartSliderState(); 
 364            };
 365        t.onMouseDown = function () { 
 366                self._mouseDown = true;
 367                return self.focus(); 
 368            };
 369        t.startDrag = function() { 
 370                self._slideStart(); 
 371            };
 372        t.onDrag = function() { 
 373                self.fireEvents(true); 
 374            };
 375        t.onMouseUp = function() { 
 376                self.thumbMouseUp(); 
 377            };
 378
 379    },
 380
 381    /**
 382     * Executed when the slider element is available
 383     * @method onAvailable
 384     */
 385    onAvailable: function() {
 386        this._bindKeyEvents();
 387    },
 388 
 389    /**
 390     * Sets up the listeners for keydown and key press events.
 391     *
 392     * @method _bindKeyEvents
 393     * @protected
 394     */
 395    _bindKeyEvents : function () {
 396        Event.on(this.id, "keydown",  this.handleKeyDown,  this, true);
 397        Event.on(this.id, "keypress", this.handleKeyPress, this, true);
 398    },
 399
 400    /**
 401     * Executed when a keypress event happens with the control focused.
 402     * Prevents the default behavior for navigation keys.  The actual
 403     * logic for moving the slider thumb in response to a key event
 404     * happens in handleKeyDown.
 405     * @param {Event} e the keypress event
 406     */
 407    handleKeyPress: function(e) {
 408        if (this.enableKeys) {
 409            var kc = Event.getCharCode(e);
 410
 411            switch (kc) {
 412                case 0x25: // left
 413                case 0x26: // up
 414                case 0x27: // right
 415                case 0x28: // down
 416                case 0x24: // home
 417                case 0x23: // end
 418                    Event.preventDefault(e);
 419                    break;
 420                default:
 421            }
 422        }
 423    },
 424
 425    /**
 426     * Executed when a keydown event happens with the control focused.
 427     * Updates the slider value and display when the keypress is an
 428     * arrow key, home, or end as long as enableKeys is set to true.
 429     * @param {Event} e the keydown event
 430     */
 431    handleKeyDown: function(e) {
 432        if (this.enableKeys) {
 433            var kc = Event.getCharCode(e),
 434                t  = this.thumb,
 435                h  = this.getXValue(),
 436                v  = this.getYValue(),
 437                changeValue = true;
 438
 439            switch (kc) {
 440
 441                // left
 442                case 0x25: h -= this.keyIncrement; break;
 443
 444                // up
 445                case 0x26: v -= this.keyIncrement; break;
 446
 447                // right
 448                case 0x27: h += this.keyIncrement; break;
 449
 450                // down
 451                case 0x28: v += this.keyIncrement; break;
 452
 453                // home
 454                case 0x24: h = t.leftConstraint;    
 455                           v = t.topConstraint;    
 456                           break;
 457
 458                // end
 459                case 0x23: h = t.rightConstraint; 
 460                           v = t.bottomConstraint;    
 461                           break;
 462
 463                default:   changeValue = false;
 464            }
 465
 466            if (changeValue) {
 467                if (t._isRegion) {
 468                    this._setRegionValue(Slider.SOURCE_KEY_EVENT, h, v, true);
 469                } else {
 470                    this._setValue(Slider.SOURCE_KEY_EVENT,
 471                        (t._isHoriz ? h : v), true);
 472                }
 473                Event.stopEvent(e);
 474            }
 475
 476        }
 477    },
 478
 479    /**
 480     * Initialization that sets up the value offsets once the elements are ready
 481     * @method setStartSliderState
 482     */
 483    setStartSliderState: function() {
 484
 485
 486        this.setThumbCenterPoint();
 487
 488        /**
 489         * The basline position of the background element, used
 490         * to determine if the background has moved since the last
 491         * operation.
 492         * @property baselinePos
 493         * @type [int, int]
 494         */
 495        this.baselinePos = getXY(this.getEl());
 496
 497        this.thumb.startOffset = this.thumb.getOffsetFromParent(this.baselinePos);
 498
 499        if (this.thumb._isRegion) {
 500            if (this.deferredSetRegionValue) {
 501                this._setRegionValue.apply(this, this.deferredSetRegionValue);
 502                this.deferredSetRegionValue = null;
 503            } else {
 504                this.setRegionValue(0, 0, true, true, true);
 505            }
 506        } else {
 507            if (this.deferredSetValue) {
 508                this._setValue.apply(this, this.deferredSetValue);
 509                this.deferredSetValue = null;
 510            } else {
 511                this.setValue(0, true, true, true);
 512            }
 513        }
 514    },
 515
 516    /**
 517     * When the thumb is available, we cache the centerpoint of the element so
 518     * we can position the element correctly when the background is clicked
 519     * @method setThumbCenterPoint
 520     */
 521    setThumbCenterPoint: function() {
 522
 523        var el = this.thumb.getEl();
 524
 525        if (el) {
 526            /**
 527             * The center of the slider element is stored so we can 
 528             * place it in the correct position when the background is clicked.
 529             * @property thumbCenterPoint
 530             * @type {"x": int, "y": int}
 531             */
 532            this.thumbCenterPoint = { 
 533                    x: parseInt(el.offsetWidth/2, 10), 
 534                    y: parseInt(el.offsetHeight/2, 10) 
 535            };
 536        }
 537
 538    },
 539
 540    /**
 541     * Locks the slider, overrides YAHOO.util.DragDrop
 542     * @method lock
 543     */
 544    lock: function() {
 545        this.thumb.lock();
 546        this.locked = true;
 547    },
 548
 549    /**
 550     * Unlocks the slider, overrides YAHOO.util.DragDrop
 551     * @method unlock
 552     */
 553    unlock: function() {
 554        this.thumb.unlock();
 555        this.locked = false;
 556    },
 557
 558    /**
 559     * Handles mouseup event on the thumb
 560     * @method thumbMouseUp
 561     * @private
 562     */
 563    thumbMouseUp: function() {
 564        this._mouseDown = false;
 565        if (!this.isLocked() && !this.moveComplete) {
 566            this.endMove();
 567        }
 568
 569    },
 570
 571    onMouseUp: function() {
 572        this._mouseDown = false;
 573        if (this.backgroundEnabled && !this.isLocked() && !this.moveComplete) {
 574            this.endMove();
 575        }
 576    },
 577
 578    /**
 579     * Returns a reference to this slider's thumb
 580     * @method getThumb
 581     * @return {SliderThumb} this slider's thumb
 582     */
 583    getThumb: function() {
 584        return this.thumb;
 585    },
 586
 587    /**
 588     * Try to focus the element when clicked so we can add
 589     * accessibility features
 590     * @method focus
 591     * @private
 592     */
 593    focus: function() {
 594        this.valueChangeSource = Slider.SOURCE_UI_EVENT;
 595
 596        // Focus the background element if possible
 597        var el = this.getEl();
 598
 599        if (el.focus) {
 600            try {
 601                el.focus();
 602            } catch(e) {
 603                // Prevent permission denied unhandled exception in FF that can
 604                // happen when setting focus while another element is handling
 605                // the blur.  @TODO this is still writing to the error log 
 606                // (unhandled error) in FF1.5 with strict error checking on.
 607            }
 608        }
 609
 610        this.verifyOffset();
 611
 612        return !this.isLocked();
 613    },
 614
 615    /**
 616     * Event that fires when the value of the slider has changed
 617     * @method onChange
 618     * @param {int} firstOffset the number of pixels the thumb has moved
 619     * from its start position. Normal horizontal and vertical sliders will only
 620     * have the firstOffset.  Regions will have both, the first is the horizontal
 621     * offset, the second the vertical.
 622     * @param {int} secondOffset the y offset for region sliders
 623     * @deprecated use instance.subscribe("change") instead
 624     */
 625    onChange: function (firstOffset, secondOffset) { 
 626        /* override me */ 
 627    },
 628
 629    /**
 630     * Event that fires when the at the beginning of the slider thumb move
 631     * @method onSlideStart
 632     * @deprecated use instance.subscribe("slideStart") instead
 633     */
 634    onSlideStart: function () { 
 635        /* override me */ 
 636    },
 637
 638    /**
 639     * Event that fires at the end of a slider thumb move
 640     * @method onSliderEnd
 641     * @deprecated use instance.subscribe("slideEnd") instead
 642     */
 643    onSlideEnd: function () { 
 644        /* override me */ 
 645    },
 646
 647    /**
 648     * Returns the slider's thumb offset from the start position
 649     * @method getValue
 650     * @return {int} the current value
 651     */
 652    getValue: function () { 
 653        return this.thumb.getValue();
 654    },
 655
 656    /**
 657     * Returns the slider's thumb X offset from the start position
 658     * @method getXValue
 659     * @return {int} the current horizontal offset
 660     */
 661    getXValue: function () { 
 662        return this.thumb.getXValue();
 663    },
 664
 665    /**
 666     * Returns the slider's thumb Y offset from the start position
 667     * @method getYValue
 668     * @return {int} the current vertical offset
 669     */
 670    getYValue: function () { 
 671        return this.thumb.getYValue();
 672    },
 673
 674    /**
 675     * Provides a way to set the value of the slider in code.
 676     *
 677     * @method setValue
 678     * @param {int} newOffset the number of pixels the thumb should be
 679     * positioned away from the initial start point 
 680     * @param {boolean} skipAnim set to true to disable the animation
 681     * for this move action (but not others).
 682     * @param {boolean} force ignore the locked setting and set value anyway
 683     * @param {boolean} silent when true, do not fire events
 684     * @return {boolean} true if the move was performed, false if it failed
 685     */
 686    setValue: function() {
 687        var args = _AS.call(arguments);
 688        args.unshift(Slider.SOURCE_SET_VALUE);
 689        return this._setValue.apply(this,args);
 690    },
 691
 692    /**
 693     * Worker function to execute the value set operation.  Accepts type of
 694     * set operation in addition to the usual setValue params.
 695     *
 696     * @method _setValue
 697     * @param source {int} what triggered the set (e.g. Slider.SOURCE_SET_VALUE)
 698     * @param {int} newOffset the number of pixels the thumb should be
 699     * positioned away from the initial start point 
 700     * @param {boolean} skipAnim set to true to disable the animation
 701     * for this move action (but not others).
 702     * @param {boolean} force ignore the locked setting and set value anyway
 703     * @param {boolean} silent when true, do not fire events
 704     * @return {boolean} true if the move was performed, false if it failed
 705     * @protected
 706     */
 707    _setValue: function(source, newOffset, skipAnim, force, silent) {
 708        var t = this.thumb, newX, newY;
 709
 710        if (!t.available) {
 711            this.deferredSetValue = arguments;
 712            return false;
 713        }
 714
 715        if (this.isLocked() && !force) {
 716            return false;
 717        }
 718
 719        if ( isNaN(newOffset) ) {
 720            return false;
 721        }
 722
 723        if (t._isRegion) {
 724            return false;
 725        }
 726
 727
 728        this._silent = silent;
 729        this.valueChangeSource = source || Slider.SOURCE_SET_VALUE;
 730
 731        t.lastOffset = [newOffset, newOffset];
 732        this.verifyOffset(true);
 733
 734        this._slideStart();
 735
 736        if (t._isHoriz) {
 737            newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
 738            this.moveThumb(newX, t.initPageY, skipAnim);
 739        } else {
 740            newY = t.initPageY + newOffset + this.thumbCenterPoint.y;
 741            this.moveThumb(t.initPageX, newY, skipAnim);
 742        }
 743
 744        return true;
 745    },
 746
 747    /**
 748     * Provides a way to set the value of the region slider in code.
 749     * @method setRegionValue
 750     * @param {int} newOffset the number of pixels the thumb should be
 751     * positioned away from the initial start point (x axis for region)
 752     * @param {int} newOffset2 the number of pixels the thumb should be
 753     * positioned away from the initial start point (y axis for region)
 754     * @param {boolean} skipAnim set to true to disable the animation
 755     * for this move action (but not others).
 756     * @param {boolean} force ignore the locked setting and set value anyway
 757     * @param {boolean} silent when true, do not fire events
 758     * @return {boolean} true if the move was performed, false if it failed
 759     */
 760    setRegionValue : function () {
 761        var args = _AS.call(arguments);
 762        args.unshift(Slider.SOURCE_SET_VALUE);
 763        return this._setRegionValue.apply(this,args);
 764    },
 765
 766    /**
 767     * Worker function to execute the value set operation.  Accepts type of
 768     * set operation in addition to the usual setValue params.
 769     *
 770     * @method _setRegionValue
 771     * @param source {int} what triggered the set (e.g. Slider.SOURCE_SET_VALUE)
 772     * @param {int} newOffset the number of pixels the thumb should be
 773     * positioned away from the initial start point (x axis for region)
 774     * @param {int} newOffset2 the number of pixels the thumb should be
 775     * positioned away from the initial start point (y axis for region)
 776     * @param {boolean} skipAnim set to true to disable the animation
 777     * for this move action (but not others).
 778     * @param {boolean} force ignore the locked setting and set value anyway
 779     * @param {boolean} silent when true, do not fire events
 780     * @return {boolean} true if the move was performed, false if it failed
 781     * @protected
 782     */
 783    _setRegionValue: function(source, newOffset, newOffset2, skipAnim, force, silent) {
 784        var t = this.thumb, newX, newY;
 785
 786        if (!t.available) {
 787            this.deferredSetRegionValue = arguments;
 788            return false;
 789        }
 790
 791        if (this.isLocked() && !force) {
 792            return false;
 793        }
 794
 795        if ( isNaN(newOffset) ) {
 796            return false;
 797        }
 798
 799        if (!t._isRegion) {
 800            return false;
 801        }
 802
 803        this._silent = silent;
 804
 805        this.valueChangeSource = source || Slider.SOURCE_SET_VALUE;
 806
 807        t.lastOffset = [newOffset, newOffset2];
 808        this.verifyOffset(true);
 809
 810        this._slideStart();
 811
 812        newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
 813        newY = t.initPageY + newOffset2 + this.thumbCenterPoint.y;
 814        this.moveThumb(newX, newY, skipAnim);
 815
 816        return true;
 817    },
 818
 819    /**
 820     * Checks the background position element position.  If it has moved from the
 821     * baseline position, the constraints for the thumb are reset
 822     * @param checkPos {boolean} check the position instead of using cached value
 823     * @method verifyOffset
 824     * @return {boolean} True if the offset is the same as the baseline.
 825     */
 826    verifyOffset: function(checkPos) {
 827
 828        var xy = getXY(this.getEl()),
 829            t  = this.thumb;
 830
 831        if (!this.thumbCenterPoint || !this.thumbCenterPoint.x) {
 832            this.setThumbCenterPoint();
 833        }
 834
 835        if (xy) {
 836
 837
 838            if (xy[0] != this.baselinePos[0] || xy[1] != this.baselinePos[1]) {
 839
 840                // Reset background
 841                this.setInitPosition();
 842                this.baselinePos = xy;
 843
 844                // Reset thumb
 845                t.initPageX = this.initPageX + t.startOffset[0];
 846                t.initPageY = this.initPageY + t.startOffset[1];
 847                t.deltaSetXY = null;
 848                this.resetThumbConstraints();
 849
 850                return false;
 851            }
 852        }
 853
 854        return true;
 855    },
 856
 857    /**
 858     * Move the associated slider moved to a timeout to try to get around the 
 859     * mousedown stealing moz does when I move the slider element between the 
 860     * cursor and the background during the mouseup event
 861     * @method moveThumb
 862     * @param {int} x the X coordinate of the click
 863     * @param {int} y the Y coordinate of the click
 864     * @param {boolean} skipAnim don't animate if the move happend onDrag
 865     * @param {boolean} midMove set to true if this is not terminating
 866     * the slider movement
 867     * @private
 868     */
 869    moveThumb: function(x, y, skipAnim, midMove) {
 870
 871        var t = this.thumb,
 872            self = this,
 873            p,_p,anim;
 874
 875        if (!t.available) {
 876            return;
 877        }
 878
 879
 880        t.setDelta(this.thumbCenterPoint.x, this.thumbCenterPoint.y);
 881
 882        _p = t.getTargetCoord(x, y);
 883        p = [Math.round(_p.x), Math.round(_p.y)];
 884
 885        if (this.animate && t._graduated && !skipAnim) {
 886            this.lock();
 887
 888            // cache the current thumb pos
 889            this.curCoord = getXY(this.thumb.getEl());
 890            this.curCoord = [Math.round(this.curCoord[0]), Math.round(this.curCoord[1])];
 891
 892            setTimeout( function() { self.moveOneTick(p); }, this.tickPause );
 893
 894        } else if (this.animate && Slider.ANIM_AVAIL && !skipAnim) {
 895
 896            this.lock();
 897
 898            anim = new YAHOO.util.Motion( 
 899                    t.id, { points: { to: p } }, 
 900                    this.animationDuration, 
 901                    YAHOO.util.Easing.easeOut );
 902
 903            anim.onComplete.subscribe( function() { 
 904                    self.unlock();
 905                    if (!self._mouseDown) {
 906                        self.endMove(); 
 907                    }
 908                });
 909            anim.animate();
 910
 911        } else {
 912            t.setDragElPos(x, y);
 913            if (!midMove && !this._mouseDown) {
 914                this.endMove();
 915            }
 916        }
 917    },
 918
 919    _slideStart: function() {
 920        if (!this._sliding) {
 921            if (!this._silent) {
 922                this.onSlideStart();
 923                this.fireEvent("slideStart");
 924            }
 925            this._sliding = true;
 926        }
 927    },
 928
 929    _slideEnd: function() {
 930        if (this._sliding && this.moveComplete) {
 931            // Reset state before firing slideEnd
 932            var silent = this._silent;
 933            this._sliding = false;
 934            this._silent = false;
 935            this.moveComplete = false;
 936            if (!silent) {
 937                this.onSlideEnd();
 938                this.fireEvent("slideEnd");
 939            }
 940        }
 941    },
 942
 943    /**
 944     * Move the slider one tick mark towards its final coordinate.  Used
 945     * for the animation when tick marks are defined
 946     * @method moveOneTick
 947     * @param {int[]} the destination coordinate
 948     * @private
 949     */
 950    moveOneTick: function(finalCoord) {
 951
 952        var t = this.thumb,
 953            self = this,
 954            nextCoord = null,
 955            tmpX, tmpY;
 956
 957        if (t._isRegion) {
 958            nextCoord = this._getNextX(this.curCoord, finalCoord);
 959            tmpX = (nextCoord !== null) ? nextCoord[0] : this.curCoord[0];
 960            nextCoord = this._getNextY(this.curCoord, finalCoord);
 961            tmpY = (nextCoord !== null) ? nextCoord[1] : this.curCoord[1];
 962
 963            nextCoord = tmpX !== this.curCoord[0] || tmpY !== this.curCoord[1] ?
 964                [ tmpX, tmpY ] : null;
 965        } else if (t._isHoriz) {
 966            nextCoord = this._getNextX(this.curCoord, finalCoord);
 967        } else {
 968            nextCoord = this._getNextY(this.curCoord, finalCoord);
 969        }
 970
 971
 972        if (nextCoord) {
 973
 974            // cache the position
 975            this.curCoord = nextCoord;
 976
 977            // move to the next coord
 978            this.thumb.alignElWithMouse(t.getEl(), nextCoord[0] + this.thumbCenterPoint.x, nextCoord[1] + this.thumbCenterPoint.y);
 979            
 980            // check if we are in the final position, if not make a recursive call
 981            if (!(nextCoord[0] == finalCoord[0] && nextCoord[1] == finalCoord[1])) {
 982                setTimeout(function() { self.moveOneTick(finalCoord); }, 
 983                        this.tickPause);
 984            } else {
 985                this.unlock();
 986                if (!this._mouseDown) {
 987                    this.endMove();
 988                }
 989            }
 990        } else {
 991            this.unlock();
 992            if (!this._mouseDown) {
 993                this.endMove();
 994            }
 995        }
 996    },
 997
 998    /**
 999     * Returns the next X tick value based on the current coord and the target coord.
1000     * @method _getNextX
1001     * @private
1002     */
1003    _getNextX: function(curCoord, finalCoord) {
1004        var t = this.thumb,
1005            thresh,
1006            tmp = [],
1007            nextCoord = null;
1008
1009        if (curCoord[0] > finalCoord[0]) {
1010            thresh = t.tickSize - this.thumbCenterPoint.x;
1011            tmp = t.getTargetCoord( curCoord[0] - thresh, curCoord[1] );
1012            nextCoord = [tmp.x, tmp.y];
1013        } else if (curCoord[0] < finalCoord[0]) {
1014            thresh = t.tickSize + this.thumbCenterPoint.x;
1015            tmp = t.getTargetCoord( curCoord[0] + thresh, curCoord[1] );
1016            nextCoord = [tmp.x, tmp.y];
1017        } else {
1018            // equal, do nothing
1019        }
1020
1021        return nextCoord;
1022    },
1023
1024    /**
1025     * Returns the next Y tick value based on the current coord and the target coord.
1026     * @method _getNextY
1027     * @private
1028     */
1029    _getNextY: function(curCoord, finalCoord) {
1030        var t = this.thumb,
1031            thresh,
1032            tmp = [],
1033            nextCoord = null;
1034
1035        if (curCoord[1] > finalCoord[1]) {
1036            thresh = t.tickSize - this.thumbCenterPoint.y;
1037            tmp = t.getTargetCoord( curCoord[0], curCoord[1] - thresh );
1038            nextCoord = [tmp.x, tmp.y];
1039        } else if (curCoord[1] < finalCoord[1]) {
1040            thresh = t.tickSize + this.thumbCenterPoint.y;
1041            tmp = t.getTargetCoord( curCoord[0], curCoord[1] + thresh );
1042            nextCoord = [tmp.x, tmp.y];
1043        } else {
1044            // equal, do nothing
1045        }
1046
1047        return nextCoord;
1048    },
1049
1050    /**
1051     * Resets the constraints before moving the thumb.
1052     * @method b4MouseDown
1053     * @private
1054     */
1055    b4MouseDown: function(e) {
1056        if (!this.backgroundEnabled) {
1057            return false;
1058        }
1059
1060        this.thumb.autoOffset();
1061        this.resetThumbConstraints();
1062    },
1063
1064    /**
1065     * Handles the mousedown event for the slider background
1066     * @method onMouseDown
1067     * @private
1068     */
1069    onMouseDown: function(e) {
1070        if (!this.backgroundEnabled || this.isLocked()) {
1071            return false;
1072        }
1073
1074        this._mouseDown = true;
1075
1076        var x = Event.getPageX(e),
1077            y = Event.getPageY(e);
1078
1079
1080        this.focus();
1081        this._slideStart();
1082        this.moveThumb(x, y);
1083    },
1084
1085    /**
1086     * Handles the onDrag event for the slider background
1087     * @method onDrag
1088     * @private
1089     */
1090    onDrag: function(e) {
1091        if (this.backgroundEnabled && !this.isLocked()) {
1092            var x = Event.getPageX(e),
1093                y = Event.getPageY(e);
1094            this.moveThumb(x, y, true, true);
1095            this.fireEvents();
1096        }
1097    },
1098
1099    /**
1100     * Fired when the slider movement ends
1101     * @method endMove
1102     * @private
1103     */
1104    endMove: function () {
1105        this.unlock();
1106        this.fireEvents();
1107        this.moveComplete = true;
1108        this._slideEnd();
1109    },
1110
1111    /**
1112     * Resets the X and Y contraints for the thumb.  Used in lieu of the thumb
1113     * instance's inherited resetConstraints because some logic was not
1114     * applicable.
1115     * @method resetThumbConstraints
1116     * @protected
1117     */
1118    resetThumbConstraints: function () {
1119        var t = this.thumb;
1120
1121        t.setXConstraint(t.leftConstraint, t.rightConstraint, t.xTickSize);
1122        t.setYConstraint(t.topConstraint, t.bottomConstraint, t.xTickSize);
1123    },
1124
1125    /**
1126     * Fires the change event if the value has been changed.  Ignored if we are in
1127     * the middle of an animation as the event will fire when the animation is
1128     * complete
1129     * @method fireEvents
1130     * @param {boolean} thumbEvent set to true if this event is fired from an event
1131     *                  that occurred on the thumb.  If it is, the state of the
1132     *                  thumb dd object should be correct.  Otherwise, the event
1133     *                  originated on the background, so the thumb state needs to
1134     *                  be refreshed before proceeding.
1135     * @private
1136     */
1137    fireEvents: function (thumbEvent) {
1138
1139        var t = this.thumb, newX, newY, newVal;
1140
1141        if (!thumbEvent) {
1142            t.cachePosition();
1143        }
1144
1145        if (! this.isLocked()) {
1146            if (t._isRegion) {
1147                newX = t.getXValue();
1148                newY = t.getYValue();
1149
1150                if (newX != this.previousX || newY != this.previousY) {
1151                    if (!this._silent) {
1152                        this.onChange(newX, newY);
1153                        this.fireEvent("change", { x: newX, y: newY });
1154                    }
1155                }
1156
1157                this.previousX = newX;
1158                this.previousY = newY;
1159
1160            } else {
1161                newVal = t.getValue();
1162                if (newVal != this.previousVal) {
1163                    if (!this._silent) {
1164                        this.onChange( newVal );
1165                        this.fireEvent("change", newVal);
1166                    }
1167                }
1168                this.previousVal = newVal;
1169            }
1170
1171        }
1172    },
1173
1174    /**
1175     * Slider toString
1176     * @method toString
1177     * @return {string} string representation of the instance
1178     */
1179    toString: function () { 
1180        return ("Slider (" + this.type +") " + this.id);
1181    }
1182
1183});
1184
1185YAHOO.lang.augmentProto(Slider, YAHOO.util.EventProvider);
1186
1187YAHOO.widget.Slider = Slider;
1188})();
1189/**
1190 * A drag and drop implementation to be used as the thumb of a slider.
1191 * @class SliderThumb
1192 * @extends YAHOO.util.DD
1193 * @constructor
1194 * @param {String} id the id of the slider html element
1195 * @param {String} sGroup the group of related DragDrop items
1196 * @param {int} iLeft the number of pixels the element can move left
1197 * @param {int} iRight the number of pixels the element can move right
1198 * @param {int} iUp the number of pixels the element can move up
1199 * @param {int} iDown the number of pixels the element can move down
1200 * @param {int} iTickSize optional parameter for specifying that the element 
1201 * should move a certain number pixels at a time.
1202 */
1203YAHOO.widget.SliderThumb = function(id, sGroup, iLeft, iRight, iUp, iDown, iTickSize) {
1204
1205    if (id) {
1206        YAHOO.widget.SliderThumb.superclass.constructor.call(this, id, sGroup);
1207
1208        /**
1209         * The id of the thumbs parent HTML element (the slider background 
1210         * element).
1211         * @property parentElId
1212         * @type string
1213         */
1214        this.parentElId = sGroup;
1215    }
1216
1217
1218
1219    /**
1220     * Overrides the isTarget property in YAHOO.util.DragDrop
1221     * @property isTarget
1222     * @private
1223     */
1224    this.isTarget = false;
1225
1226    /**
1227     * The tick size for this slider
1228     * @property tickSize
1229     * @type int
1230     * @private
1231     */
1232    this.tickSize = iTickSize;
1233
1234    /**
1235     * Informs the drag and drop util that the offsets should remain when
1236     * resetting the constraints.  This preserves the slider value when
1237     * the constraints are reset
1238     * @property maintainOffset
1239     * @type boolean
1240     * @private
1241     */
1242    this.maintainOffset = true;
1243
1244    this.initSlider(iLeft, iRight, iUp, iDown, iTickSize);
1245
1246    /**
1247     * Turns off the autoscroll feature in drag and drop
1248     * @property scroll
1249     * @private
1250     */
1251    this.scroll = false;
1252
1253}; 
1254
1255YAHOO.extend(YAHOO.widget.SliderThumb, YAHOO.util.DD, {
1256
1257    /**
1258     * The (X and Y) difference between the thumb location and its parent 
1259     * (the slider background) when the control is instantiated.
1260     * @property startOffset
1261     * @type [int, int]
1262     */
1263    startOffset: null,
1264
1265    /**
1266     * Override the default setting of dragOnly to true.
1267     * @property dragOnly
1268     * @type boolean
1269     * @default true
1270     */
1271    dragOnly : true,
1272
1273    /**
1274     * Flag used to figure out if this is a horizontal or vertical slider
1275     * @property _isHoriz
1276     * @type boolean
1277     * @private
1278     */
1279    _isHoriz: false,
1280
1281    /**
1282     * Cache the last value so we can check for change
1283     * @property _prevVal
1284     * @type int
1285     * @private
1286     */
1287    _prevVal: 0,
1288
1289    /**
1290     * The slider is _graduated if there is a tick interval defined
1291     * @property _graduated
1292     * @type boolean
1293     * @private
1294     */
1295    _graduated: false,
1296
1297
1298    /**
1299     * Returns the difference between the location of the thumb and its parent.
1300     * @method getOffsetFromParent
1301     * @param {[int, int]} parentPos Optionally accepts the position of the parent
1302     * @type [int, int]
1303     */
1304    getOffsetFromParent0: function(parentPos) {
1305        var myPos = YAHOO.util.Dom.getXY(this.getEl()),
1306            ppos  = parentPos || YAHOO.util.Dom.getXY(this.parentElId);
1307
1308        return [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ];
1309    },
1310
1311    getOffsetFromParent: function(parentPos) {
1312
1313        var el = this.getEl(), newOffset,
1314            myPos,ppos,l,t,deltaX,deltaY,newLeft,newTop;
1315
1316        if (!this.deltaOffset) {
1317
1318            myPos = YAHOO.util.Dom.getXY(el);
1319            ppos  = parentPos || YAHOO.util.Dom.getXY(this.parentElId);
1320
1321            newOffset = [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ];
1322
1323            l = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
1324            t = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
1325
1326            deltaX = l - newOffset[0];
1327            deltaY = t - newOffset[1];
1328
1329            if (isNaN(deltaX) || isNaN(deltaY)) {
1330            } else {
1331                this.deltaOffset = [deltaX, deltaY];
1332            }
1333
1334        } else {
1335            newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
1336            newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
1337
1338            newOffset  = [newLeft + this.deltaOffset[0], newTop + this.deltaOffset[1]];
1339        }
1340
1341        return newOffset;
1342    },
1343
1344    /**
1345     * Set up the slider, must be called in the constructor of all subclasses
1346     * @method initSlider
1347     * @param {int} iLeft the number of pixels the element can move left
1348     * @param {int} iRight the number of pixels the element can move right
1349     * @param {int} iUp the number of pixels the element can move up
1350     * @param {int} iDown the number of pixels the element can move down
1351     * @param {int} iTickSize the width of the tick interval.
1352     */
1353    initSlider: function (iLeft, iRight, iUp, iDown, iTickSize) {
1354        this.initLeft = iLeft;
1355        this.initRight = iRight;
1356        this.initUp = iUp;
1357        this.initDown = iDown;
1358
1359        this.setXConstraint(iLeft, iRight, iTickSize);
1360        this.setYConstraint(iUp, iDown, iTickSize);
1361
1362        if (iTickSize && iTickSize > 1) {
1363            this._graduated = true;
1364        }
1365
1366        this._isHoriz  = (iLeft || iRight); 
1367        this._isVert   = (iUp   || iDown);
1368        this._isRegion = (this._isHoriz && this._isVert); 
1369
1370    },
1371
1372    /**
1373     * Clear's the slider's ticks
1374     * @method clearTicks
1375     */
1376    clearTicks: function () {
1377        YAHOO.widget.SliderThumb.superclass.clearTicks.call(this);
1378        this.tickSize = 0;
1379        this._graduated = false;
1380    },
1381
1382
1383    /**
1384     * Gets the current offset from the element's start position in
1385     * pixels.
1386     * @method getValue
1387     * @return {int} the number of pixels (positive or negative) the
1388     * slider has moved from the start position.
1389     */
1390    getValue: function () {
1391        return (this._isHoriz) ? this.getXValue() : this.getYValue();
1392    },
1393
1394    /**
1395     * Gets the current X offset from the element's start position in
1396     * pixels.
1397     * @method getXValue
1398     * @return {int} the number of pixels (positive or negative) the
1399     * slider has moved horizontally from the start position.
1400     */
1401    getXValue: function () {
1402        if (!this.available) { 
1403            return 0; 
1404        }
1405        var newOffset = this.getOffsetFromParent();
1406        if (YAHOO.lang.isNumber(newOffset[0])) {
1407            this.lastOffset = newOffset;
1408            return (newOffset[0] - this.startOffset[0]);
1409        } else {
1410            return (this.lastOffset[0] - this.startOffset[0]);
1411        }
1412    },
1413
1414    /**
1415     * Gets the current Y offset from the element's start position in
1416     * pixels.
1417     * @method getYValue
1418     * @return {int} the number of pixels (positive or negative) the
1419     * slider has moved vertically from the start position.
1420     */
1421    getYValue: function () {
1422        if (!this.available) { 
1423            return 0; 
1424        }
1425        var newOffset = this.getOffsetFromParent();
1426        if (YAHOO.lang.isNumber(newOffset[1])) {
1427            this.lastOffset = newOffset;
1428            return (newOffset[1] - this.startOffset[1]);
1429        } else {
1430            return (this.lastOffset[1] - this.startOffset[1]);
1431        }
1432    },
1433
1434    /**
1435     * Thumb toString
1436     * @method toString
1437     * @return {string} string representation of the instance
1438     */
1439    toString: function () { 
1440        return "SliderThumb " + this.id;
1441    },
1442
1443    /**
1444     * The onchange event for the handle/thumb is delegated to the YAHOO.widget.Slider
1445     * instance it belongs to.
1446     * @method onChange
1447     * @private
1448     */
1449    onChange: function (x, y) { 
1450    }
1451
1452});
1453/**
1454 * A slider with two thumbs, one that represents the min value and 
1455 * the other the max.  Actually a composition of two sliders, both with
1456 * the same background.  The constraints for each slider are adjusted
1457 * dynamically so that the min value of the max slider is equal or greater
1458 * to the current value of the min slider, and the max value of the min
1459 * slider is the current value of the max slider.
1460 * Constructor assumes both thumbs are positioned absolutely at the 0 mark on
1461 * the background.
1462 *
1463 * @namespace YAHOO.widget
1464 * @class DualSlider
1465 * @uses YAHOO.util.EventProvider
1466 * @constructor
1467 * @param {Slider} minSlider The Slider instance used for the min value thumb
1468 * @param {Slider} maxSlider The Slider instance used for the max value thumb
1469 * @param {int}    range The number of pixels the thumbs may move within
1470 * @param {Array}  initVals (optional) [min,max] Initial thumb placement
1471 */
1472(function () {
1473
1474var Event = YAHOO.util.Event,
1475    YW = YAHOO.widget;
1476
1477function DualSlider(minSlider, maxSlider, range, initVals) {
1478
1479    var self  = this,
1480        ready = { min : false, max : false },
1481        minThumbOnMouseDown, maxThumbOnMouseDown;
1482
1483    /**
1484     * A slider instance that keeps track of the lower value of the range.
1485     * <strong>read only</strong>
1486     * @property minSlider
1487     * @type Slider
1488     */
1489    this.minSlider = minSlider;
1490
1491    /**
1492     * A slider instance that keeps track of the upper value of the range.
1493     * <strong>read only</strong>
1494     * @property maxSlider
1495     * @type Slider
1496     */
1497    this.maxSlider = maxSlider;
1498
1499    /**
1500     * The currently active slider (min or max). <strong>read only</strong>
1501     * @property activeSlider
1502     * @type Slider
1503     */
1504    this.activeSlider = minSlider;
1505
1506    /**
1507     * Is the DualSlider oriented horizontally or vertically?
1508     * <strong>read only</strong>
1509     * @property isHoriz
1510     * @type boolean
1511     */
1512    this.isHoriz = minSlider.thumb._isHoriz;
1513
1514    //FIXME: this is horrible
1515    minThumbOnMouseDown = this.minSlider.thumb.onMouseDown;
1516    maxThumbOnMouseDown = this.maxSlider.thumb.onMouseDown;
1517    this.minSlider.thumb.onMouseDown = function() {
1518        self.activeSlider = self.minSlider;
1519        minThumbOnMouseDown.apply(this,arguments);
1520    };
1521    this.maxSlider.thumb.onMouseDown = function () {
1522        self.activeSlider = self.maxSlider;
1523        maxThumbOnMouseDown.apply(this,arguments);
1524    };
1525
1526    this.minSlider.thumb.onAvailable = function () {
1527        minSlider.setStartSliderState();
1528        ready.min = true;
1529        if (ready.max) {
1530            self.fireEvent('ready',self);
1531        }
1532    };
1533    this.maxSlider.thumb.onAvailable = function () {
1534        maxSlider.setStartSliderState();
1535        ready.max = true;
1536        if (ready.min) {
1537            self.fireEvent('ready',self);
1538        }
1539    };
1540
1541    // dispatch mousedowns to the active slider
1542    minSlider.onMouseDown =
1543    maxSlider.onMouseDown = function(e) {
1544        return this.backgroundEnabled && self._handleMouseDown(e);
1545    };
1546
1547    // Fix the drag behavior so that only the active slider
1548    // follows the drag
1549    minSlider.onDrag =
1550    maxSlider.onDrag = function(e) {
1551        self._handleDrag(e);
1552    };
1553
1554    // Likely only the minSlider's onMouseUp will be executed, but both are
1555    // overridden just to be safe
1556    minSlider.onMouseUp =
1557    maxSlider.onMouseUp = function (e) {
1558        self._handleMouseUp(e);
1559    };
1560
1561    // Replace the _bindKeyEvents for the minSlider and remove that for the
1562    // maxSlider since they share the same bg element.
1563    minSlider._bindKeyEvents = function () {
1564        self._bindKeyEvents(this);
1565    };
1566    maxSlider._bindKeyEvents = function () {};
1567
1568    // The core events for each slider are handled so we can expose a single
1569    // event for when the event happens on either slider
1570    minSlider.subscribe("change", this._handleMinChange, minSlider, this);
1571    minSlider.subscribe("slideStart", this._handleSlideStart, minSlider, this);
1572    minSlider.subscribe("slideEnd", this._handleSlideEnd, minSlider, this);
1573
1574    maxSlider.subscribe("change", this._handleMaxChange, maxSlider, this);
1575    maxSlider.subscribe("slideStart", this._handleSlideStart, maxSlider, this);
1576    maxSlider.subscribe("slideEnd", this._handleSlideEnd, maxSlider, this);
1577
1578    /**
1579     * Event that fires when the slider is finished setting up
1580     * @event ready
1581     * @param {DualSlider} dualslider the DualSlider instance
1582     */
1583    this.createEvent("ready", this);
1584
1585    /**
1586     * Event that fires when either the min or max value changes
1587     * @event change
1588     * @param {DualSlider} dualslider the DualSlider instance
1589     */
1590    this.createEvent("change", this);
1591
1592    /**
1593     * Event that fires when one of the thumbs begins to move
1594     * @event slideStart
1595     * @param {Slider} activeSlider the moving slider
1596     */
1597    this.createEvent("slideStart", this);
1598
1599    /**
1600     * Event that fires when one of the thumbs finishes moving
1601     * @event slideEnd
1602     * @param {Slider} activeSlider the moving slider
1603     */
1604    this.createEvent("slideEnd", this);
1605
1606    // Validate initial values
1607    initVals = YAHOO.lang.isArray(initVals) ? initVals : [0,rang

Large files files are truncated, but you can click here to view the full file