PageRenderTime 76ms CodeModel.GetById 20ms app.highlight 44ms RepoModel.GetById 1ms app.codeStats 1ms

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

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

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