[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 YUI.add('yui2-slider', function(Y) { 2 var YAHOO = Y.YUI2; 3 /* 4 Copyright (c) 2011, Yahoo! Inc. All rights reserved. 5 Code licensed under the BSD License: 6 http://developer.yahoo.com/yui/license.html 7 version: 2.9.0 8 */ 9 /** 10 * The Slider component is a UI control that enables the user to adjust 11 * values in a finite range along one or two axes. Typically, the Slider 12 * control is used in a web application as a rich, visual replacement 13 * for an input box that takes a number as input. The Slider control can 14 * also easily accommodate a second dimension, providing x,y output for 15 * a selection point chosen from a rectangular region. 16 * 17 * @module slider 18 * @title Slider Widget 19 * @namespace YAHOO.widget 20 * @requires yahoo,dom,dragdrop,event 21 * @optional animation 22 */ 23 (function () { 24 25 var getXY = YAHOO.util.Dom.getXY, 26 Event = YAHOO.util.Event, 27 _AS = Array.prototype.slice; 28 29 /** 30 * A DragDrop implementation that can be used as a background for a 31 * slider. It takes a reference to the thumb instance 32 * so it can delegate some of the events to it. The goal is to make the 33 * thumb jump to the location on the background when the background is 34 * clicked. 35 * 36 * @class Slider 37 * @extends YAHOO.util.DragDrop 38 * @uses YAHOO.util.EventProvider 39 * @constructor 40 * @param {String} id The id of the element linked to this instance 41 * @param {String} sGroup The group of related DragDrop items 42 * @param {SliderThumb} oThumb The thumb for this slider 43 * @param {String} sType The type of slider (horiz, vert, region) 44 */ 45 function Slider(sElementId, sGroup, oThumb, sType) { 46 47 Slider.ANIM_AVAIL = (!YAHOO.lang.isUndefined(YAHOO.util.Anim)); 48 49 if (sElementId) { 50 this.init(sElementId, sGroup, true); 51 this.initSlider(sType); 52 this.initThumb(oThumb); 53 } 54 } 55 56 YAHOO.lang.augmentObject(Slider,{ 57 /** 58 * Factory method for creating a horizontal slider 59 * @method YAHOO.widget.Slider.getHorizSlider 60 * @static 61 * @param {String} sBGElId the id of the slider's background element 62 * @param {String} sHandleElId the id of the thumb element 63 * @param {int} iLeft the number of pixels the element can move left 64 * @param {int} iRight the number of pixels the element can move right 65 * @param {int} iTickSize optional parameter for specifying that the element 66 * should move a certain number pixels at a time. 67 * @return {Slider} a horizontal slider control 68 */ 69 getHorizSlider : 70 function (sBGElId, sHandleElId, iLeft, iRight, iTickSize) { 71 return new Slider(sBGElId, sBGElId, 72 new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 73 iLeft, iRight, 0, 0, iTickSize), "horiz"); 74 }, 75 76 /** 77 * Factory method for creating a vertical slider 78 * @method YAHOO.widget.Slider.getVertSlider 79 * @static 80 * @param {String} sBGElId the id of the slider's background element 81 * @param {String} sHandleElId the id of the thumb element 82 * @param {int} iUp the number of pixels the element can move up 83 * @param {int} iDown the number of pixels the element can move down 84 * @param {int} iTickSize optional parameter for specifying that the element 85 * should move a certain number pixels at a time. 86 * @return {Slider} a vertical slider control 87 */ 88 getVertSlider : 89 function (sBGElId, sHandleElId, iUp, iDown, iTickSize) { 90 return new Slider(sBGElId, sBGElId, 91 new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 0, 0, 92 iUp, iDown, iTickSize), "vert"); 93 }, 94 95 /** 96 * Factory method for creating a slider region like the one in the color 97 * picker example 98 * @method YAHOO.widget.Slider.getSliderRegion 99 * @static 100 * @param {String} sBGElId the id of the slider's background element 101 * @param {String} sHandleElId the id of the thumb element 102 * @param {int} iLeft the number of pixels the element can move left 103 * @param {int} iRight the number of pixels the element can move right 104 * @param {int} iUp the number of pixels the element can move up 105 * @param {int} iDown the number of pixels the element can move down 106 * @param {int} iTickSize optional parameter for specifying that the element 107 * should move a certain number pixels at a time. 108 * @return {Slider} a slider region control 109 */ 110 getSliderRegion : 111 function (sBGElId, sHandleElId, iLeft, iRight, iUp, iDown, iTickSize) { 112 return new Slider(sBGElId, sBGElId, 113 new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, iLeft, iRight, 114 iUp, iDown, iTickSize), "region"); 115 }, 116 117 /** 118 * Constant for valueChangeSource, indicating that the user clicked or 119 * dragged the slider to change the value. 120 * @property Slider.SOURCE_UI_EVENT 121 * @final 122 * @static 123 * @default 1 124 */ 125 SOURCE_UI_EVENT : 1, 126 127 /** 128 * Constant for valueChangeSource, indicating that the value was altered 129 * by a programmatic call to setValue/setRegionValue. 130 * @property Slider.SOURCE_SET_VALUE 131 * @final 132 * @static 133 * @default 2 134 */ 135 SOURCE_SET_VALUE : 2, 136 137 /** 138 * Constant for valueChangeSource, indicating that the value was altered 139 * by hitting any of the supported keyboard characters. 140 * @property Slider.SOURCE_KEY_EVENT 141 * @final 142 * @static 143 * @default 2 144 */ 145 SOURCE_KEY_EVENT : 3, 146 147 /** 148 * By default, animation is available if the animation utility is detected. 149 * @property Slider.ANIM_AVAIL 150 * @static 151 * @type boolean 152 */ 153 ANIM_AVAIL : false 154 },true); 155 156 YAHOO.extend(Slider, YAHOO.util.DragDrop, { 157 158 /** 159 * Tracks the state of the mouse button to aid in when events are fired. 160 * 161 * @property _mouseDown 162 * @type boolean 163 * @default false 164 * @private 165 */ 166 _mouseDown : false, 167 168 /** 169 * Override the default setting of dragOnly to true. 170 * @property dragOnly 171 * @type boolean 172 * @default true 173 */ 174 dragOnly : true, 175 176 /** 177 * Initializes the slider. Executed in the constructor 178 * @method initSlider 179 * @param {string} sType the type of slider (horiz, vert, region) 180 */ 181 initSlider: function(sType) { 182 183 /** 184 * The type of the slider (horiz, vert, region) 185 * @property type 186 * @type string 187 */ 188 this.type = sType; 189 190 //this.removeInvalidHandleType("A"); 191 192 193 /** 194 * Event the fires when the value of the control changes. If 195 * the control is animated the event will fire every point 196 * along the way. 197 * @event change 198 * @param {int} newOffset|x the new offset for normal sliders, or the new 199 * x offset for region sliders 200 * @param {int} y the number of pixels the thumb has moved on the y axis 201 * (region sliders only) 202 */ 203 this.createEvent("change", this); 204 205 /** 206 * Event that fires at the beginning of a slider thumb move. 207 * @event slideStart 208 */ 209 this.createEvent("slideStart", this); 210 211 /** 212 * Event that fires at the end of a slider thumb move 213 * @event slideEnd 214 */ 215 this.createEvent("slideEnd", this); 216 217 /** 218 * Overrides the isTarget property in YAHOO.util.DragDrop 219 * @property isTarget 220 * @private 221 */ 222 this.isTarget = false; 223 224 /** 225 * Flag that determines if the thumb will animate when moved 226 * @property animate 227 * @type boolean 228 */ 229 this.animate = Slider.ANIM_AVAIL; 230 231 /** 232 * Set to false to disable a background click thumb move 233 * @property backgroundEnabled 234 * @type boolean 235 */ 236 this.backgroundEnabled = true; 237 238 /** 239 * Adjustment factor for tick animation, the more ticks, the 240 * faster the animation (by default) 241 * @property tickPause 242 * @type int 243 */ 244 this.tickPause = 40; 245 246 /** 247 * Enables the arrow, home and end keys, defaults to true. 248 * @property enableKeys 249 * @type boolean 250 */ 251 this.enableKeys = true; 252 253 /** 254 * Specifies the number of pixels the arrow keys will move the slider. 255 * Default is 20. 256 * @property keyIncrement 257 * @type int 258 */ 259 this.keyIncrement = 20; 260 261 /** 262 * moveComplete is set to true when the slider has moved to its final 263 * destination. For animated slider, this value can be checked in 264 * the onChange handler to make it possible to execute logic only 265 * when the move is complete rather than at all points along the way. 266 * Deprecated because this flag is only useful when the background is 267 * clicked and the slider is animated. If the user drags the thumb, 268 * the flag is updated when the drag is over ... the final onDrag event 269 * fires before the mouseup the ends the drag, so the implementer will 270 * never see it. 271 * 272 * @property moveComplete 273 * @type Boolean 274 * @deprecated use the slideEnd event instead 275 */ 276 this.moveComplete = true; 277 278 /** 279 * If animation is configured, specifies the length of the animation 280 * in seconds. 281 * @property animationDuration 282 * @type int 283 * @default 0.2 284 */ 285 this.animationDuration = 0.2; 286 287 /** 288 * Constant for valueChangeSource, indicating that the user clicked or 289 * dragged the slider to change the value. 290 * @property SOURCE_UI_EVENT 291 * @final 292 * @default 1 293 * @deprecated use static Slider.SOURCE_UI_EVENT 294 */ 295 this.SOURCE_UI_EVENT = 1; 296 297 /** 298 * Constant for valueChangeSource, indicating that the value was altered 299 * by a programmatic call to setValue/setRegionValue. 300 * @property SOURCE_SET_VALUE 301 * @final 302 * @default 2 303 * @deprecated use static Slider.SOURCE_SET_VALUE 304 */ 305 this.SOURCE_SET_VALUE = 2; 306 307 /** 308 * When the slider value changes, this property is set to identify where 309 * the update came from. This will be either 1, meaning the slider was 310 * clicked or dragged, or 2, meaning that it was set via a setValue() call. 311 * This can be used within event handlers to apply some of the logic only 312 * when dealing with one source or another. 313 * @property valueChangeSource 314 * @type int 315 * @since 2.3.0 316 */ 317 this.valueChangeSource = 0; 318 319 /** 320 * Indicates whether or not events will be supressed for the current 321 * slide operation 322 * @property _silent 323 * @type boolean 324 * @private 325 */ 326 this._silent = false; 327 328 /** 329 * Saved offset used to protect against NaN problems when slider is 330 * set to display:none 331 * @property lastOffset 332 * @type [int, int] 333 */ 334 this.lastOffset = [0,0]; 335 }, 336 337 /** 338 * Initializes the slider's thumb. Executed in the constructor. 339 * @method initThumb 340 * @param {YAHOO.widget.SliderThumb} t the slider thumb 341 */ 342 initThumb: function(t) { 343 344 var self = this; 345 346 /** 347 * A YAHOO.widget.SliderThumb instance that we will use to 348 * reposition the thumb when the background is clicked 349 * @property thumb 350 * @type YAHOO.widget.SliderThumb 351 */ 352 this.thumb = t; 353 354 t.cacheBetweenDrags = true; 355 356 if (t._isHoriz && t.xTicks && t.xTicks.length) { 357 this.tickPause = Math.round(360 / t.xTicks.length); 358 } else if (t.yTicks && t.yTicks.length) { 359 this.tickPause = Math.round(360 / t.yTicks.length); 360 } 361 362 363 // delegate thumb methods 364 t.onAvailable = function() { 365 return self.setStartSliderState(); 366 }; 367 t.onMouseDown = function () { 368 self._mouseDown = true; 369 return self.focus(); 370 }; 371 t.startDrag = function() { 372 self._slideStart(); 373 }; 374 t.onDrag = function() { 375 self.fireEvents(true); 376 }; 377 t.onMouseUp = function() { 378 self.thumbMouseUp(); 379 }; 380 381 }, 382 383 /** 384 * Executed when the slider element is available 385 * @method onAvailable 386 */ 387 onAvailable: function() { 388 this._bindKeyEvents(); 389 }, 390 391 /** 392 * Sets up the listeners for keydown and key press events. 393 * 394 * @method _bindKeyEvents 395 * @protected 396 */ 397 _bindKeyEvents : function () { 398 Event.on(this.id, "keydown", this.handleKeyDown, this, true); 399 Event.on(this.id, "keypress", this.handleKeyPress, this, true); 400 }, 401 402 /** 403 * Executed when a keypress event happens with the control focused. 404 * Prevents the default behavior for navigation keys. The actual 405 * logic for moving the slider thumb in response to a key event 406 * happens in handleKeyDown. 407 * @param {Event} e the keypress event 408 */ 409 handleKeyPress: function(e) { 410 if (this.enableKeys) { 411 var kc = Event.getCharCode(e); 412 413 switch (kc) { 414 case 0x25: // left 415 case 0x26: // up 416 case 0x27: // right 417 case 0x28: // down 418 case 0x24: // home 419 case 0x23: // end 420 Event.preventDefault(e); 421 break; 422 default: 423 } 424 } 425 }, 426 427 /** 428 * Executed when a keydown event happens with the control focused. 429 * Updates the slider value and display when the keypress is an 430 * arrow key, home, or end as long as enableKeys is set to true. 431 * @param {Event} e the keydown event 432 */ 433 handleKeyDown: function(e) { 434 if (this.enableKeys) { 435 var kc = Event.getCharCode(e), 436 t = this.thumb, 437 h = this.getXValue(), 438 v = this.getYValue(), 439 changeValue = true; 440 441 switch (kc) { 442 443 // left 444 case 0x25: h -= this.keyIncrement; break; 445 446 // up 447 case 0x26: v -= this.keyIncrement; break; 448 449 // right 450 case 0x27: h += this.keyIncrement; break; 451 452 // down 453 case 0x28: v += this.keyIncrement; break; 454 455 // home 456 case 0x24: h = t.leftConstraint; 457 v = t.topConstraint; 458 break; 459 460 // end 461 case 0x23: h = t.rightConstraint; 462 v = t.bottomConstraint; 463 break; 464 465 default: changeValue = false; 466 } 467 468 if (changeValue) { 469 if (t._isRegion) { 470 this._setRegionValue(Slider.SOURCE_KEY_EVENT, h, v, true); 471 } else { 472 this._setValue(Slider.SOURCE_KEY_EVENT, 473 (t._isHoriz ? h : v), true); 474 } 475 Event.stopEvent(e); 476 } 477 478 } 479 }, 480 481 /** 482 * Initialization that sets up the value offsets once the elements are ready 483 * @method setStartSliderState 484 */ 485 setStartSliderState: function() { 486 487 488 this.setThumbCenterPoint(); 489 490 /** 491 * The basline position of the background element, used 492 * to determine if the background has moved since the last 493 * operation. 494 * @property baselinePos 495 * @type [int, int] 496 */ 497 this.baselinePos = getXY(this.getEl()); 498 499 this.thumb.startOffset = this.thumb.getOffsetFromParent(this.baselinePos); 500 501 if (this.thumb._isRegion) { 502 if (this.deferredSetRegionValue) { 503 this._setRegionValue.apply(this, this.deferredSetRegionValue); 504 this.deferredSetRegionValue = null; 505 } else { 506 this.setRegionValue(0, 0, true, true, true); 507 } 508 } else { 509 if (this.deferredSetValue) { 510 this._setValue.apply(this, this.deferredSetValue); 511 this.deferredSetValue = null; 512 } else { 513 this.setValue(0, true, true, true); 514 } 515 } 516 }, 517 518 /** 519 * When the thumb is available, we cache the centerpoint of the element so 520 * we can position the element correctly when the background is clicked 521 * @method setThumbCenterPoint 522 */ 523 setThumbCenterPoint: function() { 524 525 var el = this.thumb.getEl(); 526 527 if (el) { 528 /** 529 * The center of the slider element is stored so we can 530 * place it in the correct position when the background is clicked. 531 * @property thumbCenterPoint 532 * @type {"x": int, "y": int} 533 */ 534 this.thumbCenterPoint = { 535 x: parseInt(el.offsetWidth/2, 10), 536 y: parseInt(el.offsetHeight/2, 10) 537 }; 538 } 539 540 }, 541 542 /** 543 * Locks the slider, overrides YAHOO.util.DragDrop 544 * @method lock 545 */ 546 lock: function() { 547 this.thumb.lock(); 548 this.locked = true; 549 }, 550 551 /** 552 * Unlocks the slider, overrides YAHOO.util.DragDrop 553 * @method unlock 554 */ 555 unlock: function() { 556 this.thumb.unlock(); 557 this.locked = false; 558 }, 559 560 /** 561 * Handles mouseup event on the thumb 562 * @method thumbMouseUp 563 * @private 564 */ 565 thumbMouseUp: function() { 566 this._mouseDown = false; 567 if (!this.isLocked()) { 568 this.endMove(); 569 } 570 571 }, 572 573 onMouseUp: function() { 574 this._mouseDown = false; 575 if (this.backgroundEnabled && !this.isLocked()) { 576 this.endMove(); 577 } 578 }, 579 580 /** 581 * Returns a reference to this slider's thumb 582 * @method getThumb 583 * @return {SliderThumb} this slider's thumb 584 */ 585 getThumb: function() { 586 return this.thumb; 587 }, 588 589 /** 590 * Try to focus the element when clicked so we can add 591 * accessibility features 592 * @method focus 593 * @private 594 */ 595 focus: function() { 596 this.valueChangeSource = Slider.SOURCE_UI_EVENT; 597 598 // Focus the background element if possible 599 var el = this.getEl(); 600 601 if (el.focus) { 602 try { 603 el.focus(); 604 } catch(e) { 605 // Prevent permission denied unhandled exception in FF that can 606 // happen when setting focus while another element is handling 607 // the blur. @TODO this is still writing to the error log 608 // (unhandled error) in FF1.5 with strict error checking on. 609 } 610 } 611 612 this.verifyOffset(); 613 614 return !this.isLocked(); 615 }, 616 617 /** 618 * Event that fires when the value of the slider has changed 619 * @method onChange 620 * @param {int} firstOffset the number of pixels the thumb has moved 621 * from its start position. Normal horizontal and vertical sliders will only 622 * have the firstOffset. Regions will have both, the first is the horizontal 623 * offset, the second the vertical. 624 * @param {int} secondOffset the y offset for region sliders 625 * @deprecated use instance.subscribe("change") instead 626 */ 627 onChange: function (firstOffset, secondOffset) { 628 /* override me */ 629 }, 630 631 /** 632 * Event that fires when the at the beginning of the slider thumb move 633 * @method onSlideStart 634 * @deprecated use instance.subscribe("slideStart") instead 635 */ 636 onSlideStart: function () { 637 /* override me */ 638 }, 639 640 /** 641 * Event that fires at the end of a slider thumb move 642 * @method onSliderEnd 643 * @deprecated use instance.subscribe("slideEnd") instead 644 */ 645 onSlideEnd: function () { 646 /* override me */ 647 }, 648 649 /** 650 * Returns the slider's thumb offset from the start position 651 * @method getValue 652 * @return {int} the current value 653 */ 654 getValue: function () { 655 return this.thumb.getValue(); 656 }, 657 658 /** 659 * Returns the slider's thumb X offset from the start position 660 * @method getXValue 661 * @return {int} the current horizontal offset 662 */ 663 getXValue: function () { 664 return this.thumb.getXValue(); 665 }, 666 667 /** 668 * Returns the slider's thumb Y offset from the start position 669 * @method getYValue 670 * @return {int} the current vertical offset 671 */ 672 getYValue: function () { 673 return this.thumb.getYValue(); 674 }, 675 676 /** 677 * Provides a way to set the value of the slider in code. 678 * 679 * @method setValue 680 * @param {int} newOffset the number of pixels the thumb should be 681 * positioned away from the initial start point 682 * @param {boolean} skipAnim set to true to disable the animation 683 * for this move action (but not others). 684 * @param {boolean} force ignore the locked setting and set value anyway 685 * @param {boolean} silent when true, do not fire events 686 * @return {boolean} true if the move was performed, false if it failed 687 */ 688 setValue: function() { 689 var args = _AS.call(arguments); 690 args.unshift(Slider.SOURCE_SET_VALUE); 691 return this._setValue.apply(this,args); 692 }, 693 694 /** 695 * Worker function to execute the value set operation. Accepts type of 696 * set operation in addition to the usual setValue params. 697 * 698 * @method _setValue 699 * @param source {int} what triggered the set (e.g. Slider.SOURCE_SET_VALUE) 700 * @param {int} newOffset the number of pixels the thumb should be 701 * positioned away from the initial start point 702 * @param {boolean} skipAnim set to true to disable the animation 703 * for this move action (but not others). 704 * @param {boolean} force ignore the locked setting and set value anyway 705 * @param {boolean} silent when true, do not fire events 706 * @return {boolean} true if the move was performed, false if it failed 707 * @protected 708 */ 709 _setValue: function(source, newOffset, skipAnim, force, silent) { 710 var t = this.thumb, newX, newY; 711 712 if (!t.available) { 713 this.deferredSetValue = arguments; 714 return false; 715 } 716 717 if (this.isLocked() && !force) { 718 return false; 719 } 720 721 if ( isNaN(newOffset) ) { 722 return false; 723 } 724 725 if (t._isRegion) { 726 return false; 727 } 728 729 730 this._silent = silent; 731 this.valueChangeSource = source || Slider.SOURCE_SET_VALUE; 732 733 t.lastOffset = [newOffset, newOffset]; 734 this.verifyOffset(); 735 736 this._slideStart(); 737 738 if (t._isHoriz) { 739 newX = t.initPageX + newOffset + this.thumbCenterPoint.x; 740 this.moveThumb(newX, t.initPageY, skipAnim); 741 } else { 742 newY = t.initPageY + newOffset + this.thumbCenterPoint.y; 743 this.moveThumb(t.initPageX, newY, skipAnim); 744 } 745 746 return true; 747 }, 748 749 /** 750 * Provides a way to set the value of the region slider in code. 751 * @method setRegionValue 752 * @param {int} newOffset the number of pixels the thumb should be 753 * positioned away from the initial start point (x axis for region) 754 * @param {int} newOffset2 the number of pixels the thumb should be 755 * positioned away from the initial start point (y axis for region) 756 * @param {boolean} skipAnim set to true to disable the animation 757 * for this move action (but not others). 758 * @param {boolean} force ignore the locked setting and set value anyway 759 * @param {boolean} silent when true, do not fire events 760 * @return {boolean} true if the move was performed, false if it failed 761 */ 762 setRegionValue : function () { 763 var args = _AS.call(arguments); 764 args.unshift(Slider.SOURCE_SET_VALUE); 765 return this._setRegionValue.apply(this,args); 766 }, 767 768 /** 769 * Worker function to execute the value set operation. Accepts type of 770 * set operation in addition to the usual setValue params. 771 * 772 * @method _setRegionValue 773 * @param source {int} what triggered the set (e.g. Slider.SOURCE_SET_VALUE) 774 * @param {int} newOffset the number of pixels the thumb should be 775 * positioned away from the initial start point (x axis for region) 776 * @param {int} newOffset2 the number of pixels the thumb should be 777 * positioned away from the initial start point (y axis for region) 778 * @param {boolean} skipAnim set to true to disable the animation 779 * for this move action (but not others). 780 * @param {boolean} force ignore the locked setting and set value anyway 781 * @param {boolean} silent when true, do not fire events 782 * @return {boolean} true if the move was performed, false if it failed 783 * @protected 784 */ 785 _setRegionValue: function(source, newOffset, newOffset2, skipAnim, force, silent) { 786 var t = this.thumb, newX, newY; 787 788 if (!t.available) { 789 this.deferredSetRegionValue = arguments; 790 return false; 791 } 792 793 if (this.isLocked() && !force) { 794 return false; 795 } 796 797 if ( isNaN(newOffset) ) { 798 return false; 799 } 800 801 if (!t._isRegion) { 802 return false; 803 } 804 805 this._silent = silent; 806 807 this.valueChangeSource = source || Slider.SOURCE_SET_VALUE; 808 809 t.lastOffset = [newOffset, newOffset2]; 810 this.verifyOffset(); 811 812 this._slideStart(); 813 814 newX = t.initPageX + newOffset + this.thumbCenterPoint.x; 815 newY = t.initPageY + newOffset2 + this.thumbCenterPoint.y; 816 this.moveThumb(newX, newY, skipAnim); 817 818 return true; 819 }, 820 821 /** 822 * Checks the background position element position. If it has moved from the 823 * baseline position, the constraints for the thumb are reset 824 * @method verifyOffset 825 * @return {boolean} True if the offset is the same as the baseline. 826 */ 827 verifyOffset: function() { 828 829 var xy = getXY(this.getEl()), 830 t = this.thumb; 831 832 if (!this.thumbCenterPoint || !this.thumbCenterPoint.x) { 833 this.setThumbCenterPoint(); 834 } 835 836 if (xy) { 837 838 839 if (xy[0] != this.baselinePos[0] || xy[1] != this.baselinePos[1]) { 840 841 // Reset background 842 this.setInitPosition(); 843 this.baselinePos = xy; 844 845 // Reset thumb 846 t.initPageX = this.initPageX + t.startOffset[0]; 847 t.initPageY = this.initPageY + t.startOffset[1]; 848 t.deltaSetXY = null; 849 this.resetThumbConstraints(); 850 851 return false; 852 } 853 } 854 855 return true; 856 }, 857 858 /** 859 * Move the associated slider moved to a timeout to try to get around the 860 * mousedown stealing moz does when I move the slider element between the 861 * cursor and the background during the mouseup event 862 * @method moveThumb 863 * @param {int} x the X coordinate of the click 864 * @param {int} y the Y coordinate of the click 865 * @param {boolean} skipAnim don't animate if the move happend onDrag 866 * @param {boolean} midMove set to true if this is not terminating 867 * the slider movement 868 * @private 869 */ 870 moveThumb: function(x, y, skipAnim, midMove) { 871 872 var t = this.thumb, 873 self = this, 874 p,_p,anim; 875 876 if (!t.available) { 877 return; 878 } 879 880 881 t.setDelta(this.thumbCenterPoint.x, this.thumbCenterPoint.y); 882 883 _p = t.getTargetCoord(x, y); 884 p = [Math.round(_p.x), Math.round(_p.y)]; 885 886 if (this.animate && t._graduated && !skipAnim) { 887 this.lock(); 888 889 // cache the current thumb pos 890 this.curCoord = getXY(this.thumb.getEl()); 891 this.curCoord = [Math.round(this.curCoord[0]), Math.round(this.curCoord[1])]; 892 893 setTimeout( function() { self.moveOneTick(p); }, this.tickPause ); 894 895 } else if (this.animate && Slider.ANIM_AVAIL && !skipAnim) { 896 897 this.lock(); 898 899 anim = new YAHOO.util.Motion( 900 t.id, { points: { to: p } }, 901 this.animationDuration, 902 YAHOO.util.Easing.easeOut ); 903 904 anim.onComplete.subscribe( function() { 905 self.unlock(); 906 if (!self._mouseDown) { 907 self.endMove(); 908 } 909 }); 910 anim.animate(); 911 912 } else { 913 t.setDragElPos(x, y); 914 if (!midMove && !this._mouseDown) { 915 this.endMove(); 916 } 917 } 918 }, 919 920 _slideStart: function() { 921 if (!this._sliding) { 922 if (!this._silent) { 923 this.onSlideStart(); 924 this.fireEvent("slideStart"); 925 } 926 this._sliding = true; 927 this.moveComplete = false; // for backward compatibility. Deprecated 928 } 929 }, 930 931 _slideEnd: function() { 932 if (this._sliding) { 933 // Reset state before firing slideEnd 934 var silent = this._silent; 935 this._sliding = false; 936 this.moveComplete = true; // for backward compatibility. Deprecated 937 this._silent = false; 938 if (!silent) { 939 this.onSlideEnd(); 940 this.fireEvent("slideEnd"); 941 } 942 } 943 }, 944 945 /** 946 * Move the slider one tick mark towards its final coordinate. Used 947 * for the animation when tick marks are defined 948 * @method moveOneTick 949 * @param {int[]} the destination coordinate 950 * @private 951 */ 952 moveOneTick: function(finalCoord) { 953 954 var t = this.thumb, 955 self = this, 956 nextCoord = null, 957 tmpX, tmpY; 958 959 if (t._isRegion) { 960 nextCoord = this._getNextX(this.curCoord, finalCoord); 961 tmpX = (nextCoord !== null) ? nextCoord[0] : this.curCoord[0]; 962 nextCoord = this._getNextY(this.curCoord, finalCoord); 963 tmpY = (nextCoord !== null) ? nextCoord[1] : this.curCoord[1]; 964 965 nextCoord = tmpX !== this.curCoord[0] || tmpY !== this.curCoord[1] ? 966 [ tmpX, tmpY ] : null; 967 } else if (t._isHoriz) { 968 nextCoord = this._getNextX(this.curCoord, finalCoord); 969 } else { 970 nextCoord = this._getNextY(this.curCoord, finalCoord); 971 } 972 973 974 if (nextCoord) { 975 976 // cache the position 977 this.curCoord = nextCoord; 978 979 // move to the next coord 980 this.thumb.alignElWithMouse(t.getEl(), nextCoord[0] + this.thumbCenterPoint.x, nextCoord[1] + this.thumbCenterPoint.y); 981 982 // check if we are in the final position, if not make a recursive call 983 if (!(nextCoord[0] == finalCoord[0] && nextCoord[1] == finalCoord[1])) { 984 setTimeout(function() { self.moveOneTick(finalCoord); }, 985 this.tickPause); 986 } else { 987 this.unlock(); 988 if (!this._mouseDown) { 989 this.endMove(); 990 } 991 } 992 } else { 993 this.unlock(); 994 if (!this._mouseDown) { 995 this.endMove(); 996 } 997 } 998 }, 999 1000 /** 1001 * Returns the next X tick value based on the current coord and the target coord. 1002 * @method _getNextX 1003 * @private 1004 */ 1005 _getNextX: function(curCoord, finalCoord) { 1006 var t = this.thumb, 1007 thresh, 1008 tmp = [], 1009 nextCoord = null; 1010 1011 if (curCoord[0] > finalCoord[0]) { 1012 thresh = t.tickSize - this.thumbCenterPoint.x; 1013 tmp = t.getTargetCoord( curCoord[0] - thresh, curCoord[1] ); 1014 nextCoord = [tmp.x, tmp.y]; 1015 } else if (curCoord[0] < finalCoord[0]) { 1016 thresh = t.tickSize + this.thumbCenterPoint.x; 1017 tmp = t.getTargetCoord( curCoord[0] + thresh, curCoord[1] ); 1018 nextCoord = [tmp.x, tmp.y]; 1019 } else { 1020 // equal, do nothing 1021 } 1022 1023 return nextCoord; 1024 }, 1025 1026 /** 1027 * Returns the next Y tick value based on the current coord and the target coord. 1028 * @method _getNextY 1029 * @private 1030 */ 1031 _getNextY: function(curCoord, finalCoord) { 1032 var t = this.thumb, 1033 thresh, 1034 tmp = [], 1035 nextCoord = null; 1036 1037 if (curCoord[1] > finalCoord[1]) { 1038 thresh = t.tickSize - this.thumbCenterPoint.y; 1039 tmp = t.getTargetCoord( curCoord[0], curCoord[1] - thresh ); 1040 nextCoord = [tmp.x, tmp.y]; 1041 } else if (curCoord[1] < finalCoord[1]) { 1042 thresh = t.tickSize + this.thumbCenterPoint.y; 1043 tmp = t.getTargetCoord( curCoord[0], curCoord[1] + thresh ); 1044 nextCoord = [tmp.x, tmp.y]; 1045 } else { 1046 // equal, do nothing 1047 } 1048 1049 return nextCoord; 1050 }, 1051 1052 /** 1053 * Resets the constraints before moving the thumb. 1054 * @method b4MouseDown 1055 * @private 1056 */ 1057 b4MouseDown: function(e) { 1058 if (!this.backgroundEnabled) { 1059 return false; 1060 } 1061 1062 this.thumb.autoOffset(); 1063 this.baselinePos = []; 1064 }, 1065 1066 /** 1067 * Handles the mousedown event for the slider background 1068 * @method onMouseDown 1069 * @private 1070 */ 1071 onMouseDown: function(e) { 1072 if (!this.backgroundEnabled || this.isLocked()) { 1073 return false; 1074 } 1075 1076 this._mouseDown = true; 1077 1078 var x = Event.getPageX(e), 1079 y = Event.getPageY(e); 1080 1081 1082 this.focus(); 1083 this._slideStart(); 1084 this.moveThumb(x, y); 1085 }, 1086 1087 /** 1088 * Handles the onDrag event for the slider background 1089 * @method onDrag 1090 * @private 1091 */ 1092 onDrag: function(e) { 1093 if (this.backgroundEnabled && !this.isLocked()) { 1094 var x = Event.getPageX(e), 1095 y = Event.getPageY(e); 1096 this.moveThumb(x, y, true, true); 1097 this.fireEvents(); 1098 } 1099 }, 1100 1101 /** 1102 * Fired when the slider movement ends 1103 * @method endMove 1104 * @private 1105 */ 1106 endMove: function () { 1107 this.unlock(); 1108 this.fireEvents(); 1109 this._slideEnd(); 1110 }, 1111 1112 /** 1113 * Resets the X and Y contraints for the thumb. Used in lieu of the thumb 1114 * instance's inherited resetConstraints because some logic was not 1115 * applicable. 1116 * @method resetThumbConstraints 1117 * @protected 1118 */ 1119 resetThumbConstraints: function () { 1120 var t = this.thumb; 1121 1122 t.setXConstraint(t.leftConstraint, t.rightConstraint, t.xTickSize); 1123 t.setYConstraint(t.topConstraint, t.bottomConstraint, t.xTickSize); 1124 }, 1125 1126 /** 1127 * Fires the change event if the value has been changed. Ignored if we are in 1128 * the middle of an animation as the event will fire when the animation is 1129 * complete 1130 * @method fireEvents 1131 * @param {boolean} thumbEvent set to true if this event is fired from an event 1132 * that occurred on the thumb. If it is, the state of the 1133 * thumb dd object should be correct. Otherwise, the event 1134 * originated on the background, so the thumb state needs to 1135 * be refreshed before proceeding. 1136 * @private 1137 */ 1138 fireEvents: function (thumbEvent) { 1139 1140 var t = this.thumb, newX, newY, newVal; 1141 1142 if (!thumbEvent) { 1143 t.cachePosition(); 1144 } 1145 1146 if (! this.isLocked()) { 1147 if (t._isRegion) { 1148 newX = t.getXValue(); 1149 newY = t.getYValue(); 1150 1151 if (newX != this.previousX || newY != this.previousY) { 1152 if (!this._silent) { 1153 this.onChange(newX, newY); 1154 this.fireEvent("change", { x: newX, y: newY }); 1155 } 1156 } 1157 1158 this.previousX = newX; 1159 this.previousY = newY; 1160 1161 } else { 1162 newVal = t.getValue(); 1163 if (newVal != this.previousVal) { 1164 if (!this._silent) { 1165 this.onChange( newVal ); 1166 this.fireEvent("change", newVal); 1167 } 1168 } 1169 this.previousVal = newVal; 1170 } 1171 1172 } 1173 }, 1174 1175 /** 1176 * Slider toString 1177 * @method toString 1178 * @return {string} string representation of the instance 1179 */ 1180 toString: function () { 1181 return ("Slider (" + this.type +") " + this.id); 1182 } 1183 1184 }); 1185 1186 YAHOO.lang.augmentProto(Slider, YAHOO.util.EventProvider); 1187 1188 YAHOO.widget.Slider = Slider; 1189 })(); 1190 /** 1191 * A drag and drop implementation to be used as the thumb of a slider. 1192 * @class SliderThumb 1193 * @extends YAHOO.util.DD 1194 * @constructor 1195 * @param {String} id the id of the slider html element 1196 * @param {String} sGroup the group of related DragDrop items 1197 * @param {int} iLeft the number of pixels the element can move left 1198 * @param {int} iRight the number of pixels the element can move right 1199 * @param {int} iUp the number of pixels the element can move up 1200 * @param {int} iDown the number of pixels the element can move down 1201 * @param {int} iTickSize optional parameter for specifying that the element 1202 * should move a certain number pixels at a time. 1203 */ 1204 YAHOO.widget.SliderThumb = function(id, sGroup, iLeft, iRight, iUp, iDown, iTickSize) { 1205 1206 if (id) { 1207 YAHOO.widget.SliderThumb.superclass.constructor.call(this, id, sGroup); 1208 1209 /** 1210 * The id of the thumbs parent HTML element (the slider background 1211 * element). 1212 * @property parentElId 1213 * @type string 1214 */ 1215 this.parentElId = sGroup; 1216 } 1217 1218 1219 1220 /** 1221 * Overrides the isTarget property in YAHOO.util.DragDrop 1222 * @property isTarget 1223 * @private 1224 */ 1225 this.isTarget = false; 1226 1227 /** 1228 * The tick size for this slider 1229 * @property tickSize 1230 * @type int 1231 * @private 1232 */ 1233 this.tickSize = iTickSize; 1234 1235 /** 1236 * Informs the drag and drop util that the offsets should remain when 1237 * resetting the constraints. This preserves the slider value when 1238 * the constraints are reset 1239 * @property maintainOffset 1240 * @type boolean 1241 * @private 1242 */ 1243 this.maintainOffset = true; 1244 1245 this.initSlider(iLeft, iRight, iUp, iDown, iTickSize); 1246 1247 /** 1248 * Turns off the autoscroll feature in drag and drop 1249 * @property scroll 1250 * @private 1251 */ 1252 this.scroll = false; 1253 1254 }; 1255 1256 YAHOO.extend(YAHOO.widget.SliderThumb, YAHOO.util.DD, { 1257 1258 /** 1259 * The (X and Y) difference between the thumb location and its parent 1260 * (the slider background) when the control is instantiated. 1261 * @property startOffset 1262 * @type [int, int] 1263 */ 1264 startOffset: null, 1265 1266 /** 1267 * Override the default setting of dragOnly to true. 1268 * @property dragOnly 1269 * @type boolean 1270 * @default true 1271 */ 1272 dragOnly : true, 1273 1274 /** 1275 * Flag used to figure out if this is a horizontal or vertical slider 1276 * @property _isHoriz 1277 * @type boolean 1278 * @private 1279 */ 1280 _isHoriz: false, 1281 1282 /** 1283 * Cache the last value so we can check for change 1284 * @property _prevVal 1285 * @type int 1286 * @private 1287 */ 1288 _prevVal: 0, 1289 1290 /** 1291 * The slider is _graduated if there is a tick interval defined 1292 * @property _graduated 1293 * @type boolean 1294 * @private 1295 */ 1296 _graduated: false, 1297 1298 1299 /** 1300 * Returns the difference between the location of the thumb and its parent. 1301 * @method getOffsetFromParent 1302 * @param {[int, int]} parentPos Optionally accepts the position of the parent 1303 * @type [int, int] 1304 */ 1305 getOffsetFromParent0: function(parentPos) { 1306 var myPos = YAHOO.util.Dom.getXY(this.getEl()), 1307 ppos = parentPos || YAHOO.util.Dom.getXY(this.parentElId); 1308 1309 return [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ]; 1310 }, 1311 1312 getOffsetFromParent: function(parentPos) { 1313 1314 var el = this.getEl(), newOffset, 1315 myPos,ppos,l,t,deltaX,deltaY,newLeft,newTop; 1316 1317 if (!this.deltaOffset) { 1318 1319 myPos = YAHOO.util.Dom.getXY(el); 1320 ppos = parentPos || YAHOO.util.Dom.getXY(this.parentElId); 1321 1322 newOffset = [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ]; 1323 1324 l = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); 1325 t = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); 1326 1327 deltaX = l - newOffset[0]; 1328 deltaY = t - newOffset[1]; 1329 1330 if (isNaN(deltaX) || isNaN(deltaY)) { 1331 } else { 1332 this.deltaOffset = [deltaX, deltaY]; 1333 } 1334 1335 } else { 1336 newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 ); 1337 newTop = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 ); 1338 1339 newOffset = [newLeft + this.deltaOffset[0], newTop + this.deltaOffset[1]]; 1340 } 1341 1342 return newOffset; 1343 }, 1344 1345 /** 1346 * Set up the slider, must be called in the constructor of all subclasses 1347 * @method initSlider 1348 * @param {int} iLeft the number of pixels the element can move left 1349 * @param {int} iRight the number of pixels the element can move right 1350 * @param {int} iUp the number of pixels the element can move up 1351 * @param {int} iDown the number of pixels the element can move down 1352 * @param {int} iTickSize the width of the tick interval. 1353 */ 1354 initSlider: function (iLeft, iRight, iUp, iDown, iTickSize) { 1355 this.initLeft = iLeft; 1356 this.initRight = iRight; 1357 this.initUp = iUp; 1358 this.initDown = iDown; 1359 1360 this.setXConstraint(iLeft, iRight, iTickSize); 1361 this.setYConstraint(iUp, iDown, iTickSize); 1362 1363 if (iTickSize && iTickSize > 1) { 1364 this._graduated = true; 1365 } 1366 1367 this._isHoriz = (iLeft || iRight); 1368 this._isVert = (iUp || iDown); 1369 this._isRegion = (this._isHoriz && this._isVert); 1370 1371 }, 1372 1373 /** 1374 * Clear's the slider's ticks 1375 * @method clearTicks 1376 */ 1377 clearTicks: function () { 1378 YAHOO.widget.SliderThumb.superclass.clearTicks.call(this); 1379 this.tickSize = 0; 1380 this._graduated = false; 1381 }, 1382 1383 1384 /** 1385 * Gets the current offset from the element's start position in 1386 * pixels. 1387 * @method getValue 1388 * @return {int} the number of pixels (positive or negative) the 1389 * slider has moved from the start position. 1390 */ 1391 getValue: function () { 1392 return (this._isHoriz) ? this.getXValue() : this.getYValue(); 1393 }, 1394 1395 /** 1396 * Gets the current X offset from the element's start position in 1397 * pixels. 1398 * @method getXValue 1399 * @return {int} the number of pixels (positive or negative) the 1400 * slider has moved horizontally from the start position. 1401 */ 1402 getXValue: function () { 1403 if (!this.available) { 1404 return 0; 1405 } 1406 var newOffset = this.getOffsetFromParent(); 1407 if (YAHOO.lang.isNumber(newOffset[0])) { 1408 this.lastOffset = newOffset; 1409 return (newOffset[0] - this.startOffset[0]); 1410 } else { 1411 return (this.lastOffset[0] - this.startOffset[0]); 1412 } 1413 }, 1414 1415 /** 1416 * Gets the current Y offset from the element's start position in 1417 * pixels. 1418 * @method getYValue 1419 * @return {int} the number of pixels (positive or negative) the 1420 * slider has moved vertically from the start position. 1421 */ 1422 getYValue: function () { 1423 if (!this.available) { 1424 return 0; 1425 } 1426 var newOffset = this.getOffsetFromParent(); 1427 if (YAHOO.lang.isNumber(newOffset[1])) { 1428 this.lastOffset = newOffset; 1429 return (newOffset[1] - this.startOffset[1]); 1430 } else { 1431 return (this.lastOffset[1] - this.startOffset[1]); 1432 } 1433 }, 1434 1435 /** 1436 * Thumb toString 1437 * @method toString 1438 * @return {string} string representation of the instance 1439 */ 1440 toString: function () { 1441 return "SliderThumb " + this.id; 1442 }, 1443 1444 /** 1445 * The onchange event for the handle/thumb is delegated to the YAHOO.widget.Slider 1446 * instance it belongs to. 1447 * @method onChange 1448 * @private 1449 */ 1450 onChange: function (x, y) { 1451 } 1452 1453 }); 1454 /** 1455 * A slider with two thumbs, one that represents the min value and 1456 * the other the max. Actually a composition of two sliders, both with 1457 * the same background. The constraints for each slider are adjusted 1458 * dynamically so that the min value of the max slider is equal or greater 1459 * to the current value of the min slider, and the max value of the min 1460 * slider is the current value of the max slider. 1461 * Constructor assumes both thumbs are positioned absolutely at the 0 mark on 1462 * the background. 1463 * 1464 * @namespace YAHOO.widget 1465 * @class DualSlider 1466 * @uses YAHOO.util.EventProvider 1467 * @constructor 1468 * @param {Slider} minSlider The Slider instance used for the min value thumb 1469 * @param {Slider} maxSlider The Slider instance used for the max value thumb 1470 * @param {int} range The number of pixels the thumbs may move within 1471 * @param {Array} initVals (optional) [min,max] Initial thumb placement 1472 */ 1473 (function () { 1474 1475 var Event = YAHOO.util.Event, 1476 YW = YAHOO.widget; 1477 1478 function DualSlider(minSlider, maxSlider, range, initVals) { 1479 1480 var self = this, 1481 ready = { min : false, max : false }, 1482 minThumbOnMouseDown, maxThumbOnMouseDown; 1483 1484 /** 1485 * A slider instance that keeps track of the lower value of the range. 1486 * <strong>read only</strong> 1487 * @property minSlider 1488 * @type Slider 1489 */ 1490 this.minSlider = minSlider; 1491 1492 /** 1493 * A slider instance that keeps track of the upper value of the range. 1494 * <strong>read only</strong> 1495 * @property maxSlider 1496 * @type Slider 1497 */ 1498 this.maxSlider = maxSlider; 1499 1500 /** 1501 * The currently active slider (min or max). <strong>read only</strong> 1502 * @property activeSlider 1503 * @type Slider 1504 */ 1505 this.activeSlider = minSlider; 1506 1507 /** 1508 * Is the DualSlider oriented horizontally or vertically? 1509 * <strong>read only</strong> 1510 * @property isHoriz 1511 * @type boolean 1512 */ 1513 this.isHoriz = minSlider.thumb._isHoriz; 1514 1515 //FIXME: this is horrible 1516 minThumbOnMouseDown = this.minSlider.thumb.onMouseDown; 1517 maxThumbOnMouseDown = this.maxSlider.thumb.onMouseDown; 1518 this.minSlider.thumb.onMouseDown = function() { 1519 self.activeSlider = self.minSlider; 1520 minThumbOnMouseDown.apply(this,arguments); 1521 }; 1522 this.maxSlider.thumb.onMouseDown = function () { 1523 self.activeSlider = self.maxSlider; 1524 maxThumbOnMouseDown.apply(this,arguments); 1525 }; 1526 1527 this.minSlider.thumb.onAvailable = function () { 1528 minSlider.setStartSliderState(); 1529 ready.min = true; 1530 if (ready.max) { 1531 self.fireEvent('ready',self); 1532 } 1533 }; 1534 this.maxSlider.thumb.onAvailable = function () { 1535 maxSlider.setStartSliderState(); 1536 ready.max = true; 1537 if (ready.min) { 1538 self.fireEvent('ready',self); 1539 } 1540 }; 1541 1542 // dispatch mousedowns to the active slider 1543 minSlider.onMouseDown = 1544 maxSlider.onMouseDown = function(e) { 1545 return this.backgroundEnabled && self._handleMouseDown(e); 1546 }; 1547 1548 // Fix the drag behavior so that only the active slider 1549 // follows the drag 1550 minSlider.onDrag = 1551 maxSlider.onDrag = function(e) { 1552 self._handleDrag(e); 1553 }; 1554 1555 // Likely only the minSlider's onMouseUp will be executed, but both are 1556 // overridden just to be safe 1557 minSlider.onMouseUp = 1558 maxSlider.onMouseUp = function (e) { 1559 self._handleMouseUp(e); 1560 }; 1561 1562 // Replace the _bindKeyEvents for the minSlider and remove that for the 1563 // maxSlider since they share the same bg element. 1564 minSlider._bindKeyEvents = function () { 1565 self._bindKeyEvents(this); 1566 }; 1567 maxSlider._bindKeyEvents = function () {}; 1568 1569 // The core events for each slider are handled so we can expose a single 1570 // event for when the event happens on either slider 1571 minSlider.subscribe("change", this._handleMinChange, minSlider, this); 1572 minSlider.subscribe("slideStart", this._handleSlideStart, minSlider, this); 1573 minSlider.subscribe("slideEnd", this._handleSlideEnd, minSlider, this); 1574 1575 maxSlider.subscribe("change", this._handleMaxChange, maxSlider, this); 1576 maxSlider.subscribe("slideStart", this._handleSlideStart, maxSlider, this); 1577 maxSlider.subscribe("slideEnd", this._handleSlideEnd, maxSlider, this); 1578 1579 /** 1580 * Event that fires when the slider is finished setting up 1581 * @event ready 1582 * @param {DualSlider} dualslider the DualSlider instance 1583 */ 1584 this.createEvent("ready", this); 1585 1586 /** 1587 * Event that fires when either the min or max value changes 1588 * @event change 1589 * @param {DualSlider} dualslider the DualSlider instance 1590 */ 1591 this.createEvent("change", this); 1592 1593 /** 1594 * Event that fires when one of the thumbs begins to move 1595 * @event slideStart 1596 * @param {Slider} activeSlider the moving slider 1597 */ 1598 this.createEvent("slideStart", this); 1599 1600 /** 1601 * Event that fires when one of the thumbs finishes moving 1602 * @event slideEnd 1603 * @param {Slider} activeSlider the moving slider 1604 */ 1605 this.createEvent("slideEnd", this); 1606 1607 // Validate initial values 1608 initVals = YAHOO.lang.isArray(initVals) ? initVals : [0,range]; 1609 initVals[0] = Math.min(Math.max(parseInt(initVals[0],10)|0,0),range); 1610 initVals[1] = Math.max(Math.min(parseInt(initVals[1],10)|0,range),0); 1611 // Swap initVals if min > max 1612 if (initVals[0] > initVals[1]) { 1613 initVals.splice(0,2,initVals[1],initVals[0]); 1614 } 1615 this.minVal = initVals[0]; 1616 this.maxVal = initVals[1]; 1617 1618 // Set values so initial assignment when the slider thumbs are ready will 1619 // use these values 1620 this.minSlider.setValue(this.minVal,true,true,true); 1621 this.maxSlider.setValue(this.maxVal,true,true,true); 1622 1623 } 1624 1625 DualSlider.prototype = { 1626 1627 /** 1628 * The current value of the min thumb. <strong>read only</strong>. 1629 * @property minVal 1630 * @type int 1631 */ 1632 minVal : -1, 1633 1634 /** 1635 * The current value of the max thumb. <strong>read only</strong>. 1636 * @property maxVal 1637 * @type int 1638 */ 1639 maxVal : -1, 1640 1641 /** 1642 * Pixel distance to maintain between thumbs. 1643 * @property minRange 1644 * @type int 1645 * @default 0 1646 */ 1647 minRange : 0, 1648 1649 /** 1650 * Executed when one of the sliders fires the slideStart event 1651 * @method _handleSlideStart 1652 * @private 1653 */ 1654 _handleSlideStart: function(data, slider) { 1655 this.fireEvent("slideStart", slider); 1656 }, 1657 1658 /** 1659 * Executed when one of the sliders fires the slideEnd event 1660 * @method _handleSlideEnd 1661 * @private 1662 */ 1663 _handleSlideEnd: function(data, slider) { 1664 this.fireEvent("slideEnd", slider); 1665 }, 1666 1667 /** 1668 * Overrides the onDrag method for both sliders 1669 * @method _handleDrag 1670 * @private 1671 */ 1672 _handleDrag: function(e) { 1673 YW.Slider.prototype.onDrag.call(this.activeSlider, e); 1674 }, 1675 1676 /** 1677 * Executed when the min slider fires the change event 1678 * @method _handleMinChange 1679 * @private 1680 */ 1681 _handleMinChange: function() { 1682 this.activeSlider = this.minSlider; 1683 this.updateValue(); 1684 }, 1685 1686 /** 1687 * Executed when the max slider fires the change event 1688 * @method _handleMaxChange 1689 * @private 1690 */ 1691 _handleMaxChange: function() { 1692 this.activeSlider = this.maxSlider; 1693 this.updateValue(); 1694 }, 1695 1696 /** 1697 * Set up the listeners for the keydown and keypress events. 1698 * 1699 * @method _bindKeyEvents 1700 * @protected 1701 */ 1702 _bindKeyEvents : function (slider) { 1703 Event.on(slider.id,'keydown', this._handleKeyDown, this,true); 1704 Event.on(slider.id,'keypress',this._handleKeyPress,this,true); 1705 }, 1706 1707 /** 1708 * Delegate event handling to the active Slider. See Slider.handleKeyDown. 1709 * 1710 * @method _handleKeyDown 1711 * @param e {Event} the mousedown DOM event 1712 * @protected 1713 */ 1714 _handleKeyDown : function (e) { 1715 this.activeSlider.handleKeyDown.apply(this.activeSlider,arguments); 1716 }, 1717 1718 /** 1719 * Delegate event handling to the active Slider. See Slider.handleKeyPress. 1720 * 1721 * @method _handleKeyPress 1722 * @param e {Event} the mousedown DOM event 1723 * @protected 1724 */ 1725 _handleKeyPress : function (e) { 1726 this.activeSlider.handleKeyPress.apply(this.activeSlider,arguments); 1727 }, 1728 1729 /** 1730 * Sets the min and max thumbs to new values. 1731 * @method setValues 1732 * @param min {int} Pixel offset to assign to the min thumb 1733 * @param max {int} Pixel offset to assign to the max thumb 1734 * @param skipAnim {boolean} (optional) Set to true to skip thumb animation. 1735 * Default false 1736 * @param force {boolean} (optional) ignore the locked setting and set 1737 * value anyway. Default false 1738 * @param silent {boolean} (optional) Set to true to skip firing change 1739 * events. Default false 1740 */ 1741 setValues : function (min, max, skipAnim, force, silent) { 1742 var mins = this.minSlider, 1743 maxs = this.maxSlider, 1744 mint = mins.thumb, 1745 maxt = maxs.thumb, 1746 self = this, 1747 done = { min : false, max : false }; 1748 1749 // Clear constraints to prevent animated thumbs from prematurely 1750 // stopping when hitting a constraint that's moving with the other 1751 // thumb. 1752 if (mint._isHoriz) { 1753 mint.setXConstraint(mint.leftConstraint,maxt.rightConstraint,mint.tickSize); 1754 maxt.setXConstraint(mint.leftConstraint,maxt.rightConstraint,maxt.tickSize); 1755 } else { 1756 mint.setYConstraint(mint.topConstraint,maxt.bottomConstraint,mint.tickSize); 1757 maxt.setYConstraint(mint.topConstraint,maxt.bottomConstraint,maxt.tickSize); 1758 } 1759 1760 // Set up one-time slideEnd callbacks to call updateValue when both 1761 // thumbs have been set 1762 this._oneTimeCallback(mins,'slideEnd',function () { 1763 done.min = true; 1764 if (done.max) { 1765 self.updateValue(silent); 1766 // Clean the slider's slideEnd events on a timeout since this 1767 // will be executed from inside the event's fire 1768 setTimeout(function () { 1769 self._cleanEvent(mins,'slideEnd'); 1770 self._cleanEvent(maxs,'slideEnd'); 1771 },0); 1772 } 1773 }); 1774 1775 this._oneTimeCallback(maxs,'slideEnd',function () { 1776 done.max = true; 1777 if (done.min) { 1778 self.updateValue(silent); 1779 // Clean both sliders' slideEnd events on a timeout since this 1780 // will be executed from inside one of the event's fire 1781 setTimeout(function () { 1782 self._cleanEvent(mins,'slideEnd'); 1783 self._cleanEvent(maxs,'slideEnd'); 1784 },0); 1785 } 1786 }); 1787 1788 // Must emit Slider slideEnd event to propagate to updateValue 1789 mins.setValue(min,skipAnim,force,false); 1790 maxs.setValue(max,skipAnim,force,false); 1791 }, 1792 1793 /** 1794 * Set the min thumb position to a new value. 1795 * @method setMinValue 1796 * @param min {int} Pixel offset for min thumb 1797 * @param skipAnim {boolean} (optional) Set to true to skip thumb animation. 1798 * Default false 1799 * @param force {boolean} (optional) ignore the locked setting and set 1800 * value anyway. Default false 1801 * @param silent {boolean} (optional) Set to true to skip firing change 1802 * events. Default false 1803 */ 1804 setMinValue : function (min, skipAnim, force, silent) { 1805 var mins = this.minSlider, 1806 self = this; 1807 1808 this.activeSlider = mins; 1809 1810 // Use a one-time event callback to delay the updateValue call 1811 // until after the slide operation is done 1812 self = this; 1813 this._oneTimeCallback(mins,'slideEnd',function () { 1814 self.updateValue(silent); 1815 // Clean the slideEnd event on a timeout since this 1816 // will be executed from inside the event's fire 1817 setTimeout(function () { self._cleanEvent(mins,'slideEnd'); }, 0); 1818 }); 1819 1820 mins.setValue(min, skipAnim, force); 1821 }, 1822 1823 /** 1824 * Set the max thumb position to a new value. 1825 * @method setMaxValue 1826 * @param max {int} Pixel offset for max thumb 1827 * @param skipAnim {boolean} (optional) Set to true to skip thumb animation. 1828 * Default false 1829 * @param force {boolean} (optional) ignore the locked setting and set 1830 * value anyway. Default false 1831 * @param silent {boolean} (optional) Set to true to skip firing change 1832 * events. Default false 1833 */ 1834 setMaxValue : function (max, skipAnim, force, silent) { 1835 var maxs = this.maxSlider, 1836 self = this; 1837 1838 this.activeSlider = maxs; 1839 1840 // Use a one-time event callback to delay the updateValue call 1841 // until after the slide operation is done 1842 this._oneTimeCallback(maxs,'slideEnd',function () { 1843 self.updateValue(silent); 1844 // Clean the slideEnd event on a timeout since this 1845 // will be executed from inside the event's fire 1846 setTimeout(function () { self._cleanEvent(maxs,'slideEnd'); }, 0); 1847 }); 1848 1849 maxs.setValue(max, skipAnim, force); 1850 }, 1851 1852 /** 1853 * Executed when one of the sliders is moved 1854 * @method updateValue 1855 * @param silent {boolean} (optional) Set to true to skip firing change 1856 * events. Default false 1857 * @private 1858 */ 1859 updateValue: function(silent) { 1860 var min = this.minSlider.getValue(), 1861 max = this.maxSlider.getValue(), 1862 changed = false, 1863 mint,maxt,dim,minConstraint,maxConstraint,thumbInnerWidth; 1864 1865 if (min != this.minVal || max != this.maxVal) { 1866 changed = true; 1867 1868 mint = this.minSlider.thumb; 1869 maxt = this.maxSlider.thumb; 1870 dim = this.isHoriz ? 'x' : 'y'; 1871 1872 thumbInnerWidth = this.minSlider.thumbCenterPoint[dim] + 1873 this.maxSlider.thumbCenterPoint[dim]; 1874 1875 // Establish barriers within the respective other thumb's edge, less 1876 // the minRange. Limit to the Slider's range in the case of 1877 // negative minRanges. 1878 minConstraint = Math.max(max-thumbInnerWidth-this.minRange,0); 1879 maxConstraint = Math.min(-min-thumbInnerWidth-this.minRange,0); 1880 1881 if (this.isHoriz) { 1882 minConstraint = Math.min(minConstraint,maxt.rightConstraint); 1883 1884 mint.setXConstraint(mint.leftConstraint,minConstraint, mint.tickSize); 1885 1886 maxt.setXConstraint(maxConstraint,maxt.rightConstraint, maxt.tickSize); 1887 } else { 1888 minConstraint = Math.min(minConstraint,maxt.bottomConstraint); 1889 mint.setYConstraint(mint.leftConstraint,minConstraint, mint.tickSize); 1890 1891 maxt.setYConstraint(maxConstraint,maxt.bottomConstraint, maxt.tickSize); 1892 } 1893 } 1894 1895 this.minVal = min; 1896 this.maxVal = max; 1897 1898 if (changed && !silent) { 1899 this.fireEvent("change", this); 1900 } 1901 }, 1902 1903 /** 1904 * A background click will move the slider thumb nearest to the click. 1905 * Override if you need different behavior. 1906 * @method selectActiveSlider 1907 * @param e {Event} the mousedown event 1908 * @private 1909 */ 1910 selectActiveSlider: function(e) { 1911 var min = this.minSlider, 1912 max = this.maxSlider, 1913 minLocked = min.isLocked() || !min.backgroundEnabled, 1914 maxLocked = max.isLocked() || !min.backgroundEnabled, 1915 Ev = YAHOO.util.Event, 1916 d; 1917 1918 if (minLocked || maxLocked) { 1919 this.activeSlider = minLocked ? max : min; 1920 } else { 1921 if (this.isHoriz) { 1922 d = Ev.getPageX(e)-min.thumb.initPageX-min.thumbCenterPoint.x; 1923 } else { 1924 d = Ev.getPageY(e)-min.thumb.initPageY-min.thumbCenterPoint.y; 1925 } 1926 1927 this.activeSlider = d*2 > max.getValue()+min.getValue() ? max : min; 1928 } 1929 }, 1930 1931 /** 1932 * Delegates the onMouseDown to the appropriate Slider 1933 * 1934 * @method _handleMouseDown 1935 * @param e {Event} mouseup event 1936 * @protected 1937 */ 1938 _handleMouseDown: function(e) { 1939 if (!e._handled && !this.minSlider._sliding && !this.maxSlider._sliding) { 1940 e._handled = true; 1941 this.selectActiveSlider(e); 1942 return YW.Slider.prototype.onMouseDown.call(this.activeSlider, e); 1943 } else { 1944 return false; 1945 } 1946 }, 1947 1948 /** 1949 * Delegates the onMouseUp to the active Slider 1950 * 1951 * @method _handleMouseUp 1952 * @param e {Event} mouseup event 1953 * @protected 1954 */ 1955 _handleMouseUp : function (e) { 1956 YW.Slider.prototype.onMouseUp.apply( 1957 this.activeSlider, arguments); 1958 }, 1959 1960 /** 1961 * Schedule an event callback that will execute once, then unsubscribe 1962 * itself. 1963 * @method _oneTimeCallback 1964 * @param o {EventProvider} Object to attach the event to 1965 * @param evt {string} Name of the event 1966 * @param fn {Function} function to execute once 1967 * @private 1968 */ 1969 _oneTimeCallback : function (o,evt,fn) { 1970 var sub = function () { 1971 // Unsubscribe myself 1972 o.unsubscribe(evt, sub); 1973 // Pass the event handler arguments to the one time callback 1974 fn.apply({},arguments); 1975 }; 1976 o.subscribe(evt,sub); 1977 }, 1978 1979 /** 1980 * Clean up the slideEnd event subscribers array, since each one-time 1981 * callback will be replaced in the event's subscribers property with 1982 * null. This will cause memory bloat and loss of performance. 1983 * @method _cleanEvent 1984 * @param o {EventProvider} object housing the CustomEvent 1985 * @param evt {string} name of the CustomEvent 1986 * @private 1987 */ 1988 _cleanEvent : function (o,evt) { 1989 var ce,i,len,j,subs,newSubs; 1990 1991 if (o.__yui_events && o.events[evt]) { 1992 for (i = o.__yui_events.length; i >= 0; --i) { 1993 if (o.__yui_events[i].type === evt) { 1994 ce = o.__yui_events[i]; 1995 break; 1996 } 1997 } 1998 if (ce) { 1999 subs = ce.subscribers; 2000 newSubs = []; 2001 j = 0; 2002 for (i = 0, len = subs.length; i < len; ++i) { 2003 if (subs[i]) { 2004 newSubs[j++] = subs[i]; 2005 } 2006 } 2007 ce.subscribers = newSubs; 2008 } 2009 } 2010 } 2011 2012 }; 2013 2014 YAHOO.lang.augmentProto(DualSlider, YAHOO.util.EventProvider); 2015 2016 2017 /** 2018 * Factory method for creating a horizontal dual-thumb slider 2019 * @for YAHOO.widget.Slider 2020 * @method YAHOO.widget.Slider.getHorizDualSlider 2021 * @static 2022 * @param {String} bg the id of the slider's background element 2023 * @param {String} minthumb the id of the min thumb 2024 * @param {String} maxthumb the id of the thumb thumb 2025 * @param {int} range the number of pixels the thumbs can move within 2026 * @param {int} iTickSize (optional) the element should move this many pixels 2027 * at a time 2028 * @param {Array} initVals (optional) [min,max] Initial thumb placement 2029 * @return {DualSlider} a horizontal dual-thumb slider control 2030 */ 2031 YW.Slider.getHorizDualSlider = 2032 function (bg, minthumb, maxthumb, range, iTickSize, initVals) { 2033 var mint = new YW.SliderThumb(minthumb, bg, 0, range, 0, 0, iTickSize), 2034 maxt = new YW.SliderThumb(maxthumb, bg, 0, range, 0, 0, iTickSize); 2035 2036 return new DualSlider( 2037 new YW.Slider(bg, bg, mint, "horiz"), 2038 new YW.Slider(bg, bg, maxt, "horiz"), 2039 range, initVals); 2040 }; 2041 2042 /** 2043 * Factory method for creating a vertical dual-thumb slider. 2044 * @for YAHOO.widget.Slider 2045 * @method YAHOO.widget.Slider.getVertDualSlider 2046 * @static 2047 * @param {String} bg the id of the slider's background element 2048 * @param {String} minthumb the id of the min thumb 2049 * @param {String} maxthumb the id of the thumb thumb 2050 * @param {int} range the number of pixels the thumbs can move within 2051 * @param {int} iTickSize (optional) the element should move this many pixels 2052 * at a time 2053 * @param {Array} initVals (optional) [min,max] Initial thumb placement 2054 * @return {DualSlider} a vertical dual-thumb slider control 2055 */ 2056 YW.Slider.getVertDualSlider = 2057 function (bg, minthumb, maxthumb, range, iTickSize, initVals) { 2058 var mint = new YW.SliderThumb(minthumb, bg, 0, 0, 0, range, iTickSize), 2059 maxt = new YW.SliderThumb(maxthumb, bg, 0, 0, 0, range, iTickSize); 2060 2061 return new YW.DualSlider( 2062 new YW.Slider(bg, bg, mint, "vert"), 2063 new YW.Slider(bg, bg, maxt, "vert"), 2064 range, initVals); 2065 }; 2066 2067 YAHOO.widget.DualSlider = DualSlider; 2068 2069 })(); 2070 YAHOO.register("slider", YAHOO.widget.Slider, {version: "2.9.0", build: "2800"}); 2071 2072 }, '2.9.0' ,{"requires": ["yui2-yahoo", "yui2-dom", "yui2-skin-sam-slider", "yui2-event", "yui2-dragdrop"], "optional": ["yui2-animation"]});
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |