Automatic installer.php lang files by installer_builder (20070726)
[moodle-linuxchix.git] / lib / yui / slider / slider-debug.js
blobbbfb11793b2f29d586aec701729459781919f26d
1 /*
2 Copyright (c) 2006, Yahoo! Inc. All rights reserved.
3 Code licensed under the BSD License:
4 http://developer.yahoo.net/yui/license.txt
5 version: 0.12.2
6 */
8 /**
9  * The Slider component is a UI control that enables the user to adjust 
10  * values in a finite range along one or two axes. Typically, the Slider 
11  * control is used in a web application as a rich, visual replacement 
12  * for an input box that takes a number as input. The Slider control can 
13  * also easily accommodate a second dimension, providing x,y output for 
14  * a selection point chosen from a rectangular region.
15  *
16  * @module    slider
17  * @title     Slider Widget
18  * @namespace YAHOO.widget
19  * @requires  yahoo,dom,dragdrop,event
20  * @optional  animation
21  */
23 /**
24  * A DragDrop implementation that can be used as a background for a
25  * slider.  It takes a reference to the thumb instance 
26  * so it can delegate some of the events to it.  The goal is to make the 
27  * thumb jump to the location on the background when the background is 
28  * clicked.  
29  *
30  * @class Slider
31  * @extends YAHOO.util.DragDrop
32  * @uses YAHOO.util.EventProvider
33  * @constructor
34  * @param {String}      id     The id of the element linked to this instance
35  * @param {String}      sGroup The group of related DragDrop items
36  * @param {SliderThumb} oThumb The thumb for this slider
37  * @param {String}      sType  The type of slider (horiz, vert, region)
38  */
39 YAHOO.widget.Slider = function(sElementId, sGroup, oThumb, sType) {
40     if (sElementId) {
41         this.init(sElementId, sGroup, true);
42         this.initSlider(sType);
43         this.initThumb(oThumb);
44     }
47 /**
48  * Factory method for creating a horizontal slider
49  * @method YAHOO.widget.Slider.getHorizSlider
50  * @static
51  * @param {String} sBGElId the id of the slider's background element
52  * @param {String} sHandleElId the id of the thumb element
53  * @param {int} iLeft the number of pixels the element can move left
54  * @param {int} iRight the number of pixels the element can move right
55  * @param {int} iTickSize optional parameter for specifying that the element 
56  * should move a certain number pixels at a time.
57  * @return {Slider} a horizontal slider control
58  */
59 YAHOO.widget.Slider.getHorizSlider = 
60     function (sBGElId, sHandleElId, iLeft, iRight, iTickSize) {
61         return new YAHOO.widget.Slider(sBGElId, sBGElId, 
62             new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 
63                                iLeft, iRight, 0, 0, iTickSize), "horiz");
66 /**
67  * Factory method for creating a vertical slider
68  * @method YAHOO.widget.Slider.getVertSlider
69  * @static
70  * @param {String} sBGElId the id of the slider's background element
71  * @param {String} sHandleElId the id of the thumb element
72  * @param {int} iUp the number of pixels the element can move up
73  * @param {int} iDown the number of pixels the element can move down
74  * @param {int} iTickSize optional parameter for specifying that the element 
75  * should move a certain number pixels at a time.
76  * @return {Slider} a vertical slider control
77  */
78 YAHOO.widget.Slider.getVertSlider = 
79     function (sBGElId, sHandleElId, iUp, iDown, iTickSize) {
80         return new YAHOO.widget.Slider(sBGElId, sBGElId, 
81             new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, 0, 0, 
82                                iUp, iDown, iTickSize), "vert");
85 /**
86  * Factory method for creating a slider region like the one in the color
87  * picker example
88  * @method YAHOO.widget.Slider.getSliderRegion
89  * @static
90  * @param {String} sBGElId the id of the slider's background element
91  * @param {String} sHandleElId the id of the thumb element
92  * @param {int} iLeft the number of pixels the element can move left
93  * @param {int} iRight the number of pixels the element can move right
94  * @param {int} iUp the number of pixels the element can move up
95  * @param {int} iDown the number of pixels the element can move down
96  * @param {int} iTickSize optional parameter for specifying that the element 
97  * should move a certain number pixels at a time.
98  * @return {Slider} a slider region control
99  */
100 YAHOO.widget.Slider.getSliderRegion = 
101     function (sBGElId, sHandleElId, iLeft, iRight, iUp, iDown, iTickSize) {
102         return new YAHOO.widget.Slider(sBGElId, sBGElId, 
103             new YAHOO.widget.SliderThumb(sHandleElId, sBGElId, iLeft, iRight, 
104                                iUp, iDown, iTickSize), "region");
108  * By default, animation is available if the animation library is detected.
109  * @property YAHOO.widget.Slider.ANIM_AVAIL
110  * @static
111  * @type boolean
112  */
113 YAHOO.widget.Slider.ANIM_AVAIL = true;
115 YAHOO.extend(YAHOO.widget.Slider, YAHOO.util.DragDrop, {
117     /**
118      * Initializes the slider.  Executed in the constructor
119      * @method initSlider
120      * @param {string} sType the type of slider (horiz, vert, region)
121      */
122     initSlider: function(sType) {
124         /**
125          * The type of the slider (horiz, vert, region)
126          * @property type
127          * @type string
128          */
129         this.type = sType;
131         //this.removeInvalidHandleType("A");
133         this.logger = new YAHOO.widget.LogWriter(this.toString());
135         /**
136          * Event the fires when the value of the control changes.  If 
137          * the control is animated the event will fire every point
138          * along the way.
139          * @event change
140          * @param {int} newOffset|x the new offset for normal sliders, or the new
141          *                          x offset for region sliders
142          * @param {int} y the number of pixels the thumb has moved on the y axis
143          *                (region sliders only)
144          */
145         this.createEvent("change", this);
147         /**
148          * Event that fires at the beginning of a slider thumb move.
149          * @event slideStart
150          */
151         this.createEvent("slideStart", this);
153         /**
154          * Event that fires at the end of a slider thumb move
155          * @event slideEnd
156          */
157         this.createEvent("slideEnd", this);
159         /**
160          * Overrides the isTarget property in YAHOO.util.DragDrop
161          * @property isTarget
162          * @private
163          */
164         this.isTarget = false;
165     
166         /**
167          * Flag that determines if the thumb will animate when moved
168          * @property animate
169          * @type boolean
170          */
171         this.animate = YAHOO.widget.Slider.ANIM_AVAIL;
173         /**
174          * Set to false to disable a background click thumb move
175          * @property backgroundEnabled
176          * @type boolean
177          */
178         this.backgroundEnabled = true;
180         /**
181          * Adjustment factor for tick animation, the more ticks, the
182          * faster the animation (by default)
183          * @property tickPause
184          * @type int
185          */
186         this.tickPause = 40;
188         /**
189          * Enables the arrow, home and end keys, defaults to true.
190          * @property enableKeys
191          * @type boolean
192          */
193         this.enableKeys = true;
195         /**
196          * Specifies the number of pixels the arrow keys will move the slider.
197          * Default is 25.
198          * @property keyIncrement
199          * @type int
200          */
201         this.keyIncrement = 20;
203         /**
204          * moveComplete is set to true when the slider has moved to its final
205          * destination.  For animated slider, this value can be checked in 
206          * the onChange handler to make it possible to execute logic only
207          * when the move is complete rather than at all points along the way.
208          *
209          * @property moveComplete
210          * @type Boolean
211          */
212         this.moveComplete = true;
214         /**
215          * If animation is configured, specifies the length of the animation
216          * in seconds.
217          * @property animationDuration
218          * @type int
219          * @default 0.2
220          */
221         this.animationDuration = 0.2;
222     },
224     /**
225      * Initializes the slider's thumb. Executed in the constructor.
226      * @method initThumb
227      * @param {YAHOO.widget.SliderThumb} t the slider thumb
228      */
229     initThumb: function(t) {
231         var self = this;
233         /**
234          * A YAHOO.widget.SliderThumb instance that we will use to 
235          * reposition the thumb when the background is clicked
236          * @property thumb
237          * @type YAHOO.widget.SliderThumb
238          */
239         this.thumb = t;
240         t.cacheBetweenDrags = true;
242         // add handler for the handle onchange event
243         t.onChange = function() { 
244             self.handleThumbChange(); 
245         };
247         if (t._isHoriz && t.xTicks && t.xTicks.length) {
248             this.tickPause = Math.round(360 / t.xTicks.length);
249         } else if (t.yTicks && t.yTicks.length) {
250             this.tickPause = Math.round(360 / t.yTicks.length);
251         }
253         this.logger.log("tickPause: " + this.tickPause);
255         // delegate thumb methods
256         t.onMouseDown = function () { return self.focus(); };
257         t.onMouseUp = function() { self.thumbMouseUp(); };
258         t.onDrag = function() { self.fireEvents(true); };
259         t.onAvailable = function() { return self.setStartSliderState(); };
261     },
263     /**
264      * Executed when the slider element is available
265      * @method onAvailable
266      */
267     onAvailable: function() {
268         var Event = YAHOO.util.Event;
269         Event.on(this.id, "keydown",  this.handleKeyDown,  this, true);
270         Event.on(this.id, "keypress", this.handleKeyPress, this, true);
271     },
273     /**
274      * Executed when a keypress event happens with the control focused.
275      * Prevents the default behavior for navigation keys.  The actual
276      * logic for moving the slider thumb in response to a key event
277      * happens in handleKeyDown.
278      * @param {Event} e the keypress event
279      */
280     handleKeyPress: function(e) {
281         if (this.enableKeys) {
282             var Event = YAHOO.util.Event;
283             var kc = Event.getCharCode(e);
284             switch (kc) {
285                 case 0x25: // left
286                 case 0x26: // up
287                 case 0x27: // right
288                 case 0x28: // down
289                 case 0x24: // home
290                 case 0x23: // end
291                     Event.preventDefault(e);
292                     break;
293                 default:
294             }
295         }
296     },
298     /**
299      * Executed when a keydown event happens with the control focused.
300      * Updates the slider value and display when the keypress is an
301      * arrow key, home, or end as long as enableKeys is set to true.
302      * @param {Event} e the keydown event
303      */
304     handleKeyDown: function(e) {
305         if (this.enableKeys) {
306             var Event = YAHOO.util.Event;
308             var kc = Event.getCharCode(e), t=this.thumb;
309             var h=this.getXValue(),v=this.getYValue();
311             var horiz = false;
312             var changeValue = true;
313             switch (kc) {
315                 // left
316                 case 0x25: h -= this.keyIncrement; break;
318                 // up
319                 case 0x26: v -= this.keyIncrement; break;
321                 // right
322                 case 0x27: h += this.keyIncrement; break;
324                 // down
325                 case 0x28: v += this.keyIncrement; break;
327                 // home
328                 case 0x24: h = t.leftConstraint;    
329                            v = t.topConstraint;    
330                            break;
332                 // end
333                 case 0x23: h = t.rightConstraint; 
334                            v = t.bottomConstraint;    
335                            break;
337                 default:   changeValue = false;
338             }
340             if (changeValue) {
341                 if (t._isRegion) {
342                     this.setRegionValue(h, v, true);
343                 } else {
344                     var newVal = (t._isHoriz) ? h : v;
345                     this.setValue(newVal, true);
346                 }
347                 Event.stopEvent(e);
348             }
350         }
351     },
353     /**
354      * Initialization that sets up the value offsets once the elements are ready
355      * @method setStartSliderState
356      */
357     setStartSliderState: function() {
359         this.logger.log("Fixing state");
361         this.setThumbCenterPoint();
363         /**
364          * The basline position of the background element, used
365          * to determine if the background has moved since the last
366          * operation.
367          * @property baselinePos
368          * @type [int, int]
369          */
370         this.baselinePos = YAHOO.util.Dom.getXY(this.getEl());
372         this.thumb.startOffset = this.thumb.getOffsetFromParent(this.baselinePos);
374         if (this.thumb._isRegion) {
375             if (this.deferredSetRegionValue) {
376                 this.setRegionValue.apply(this, this.deferredSetRegionValue, true);
377                 this.deferredSetRegionValue = null;
378             } else {
379                 this.setRegionValue(0, 0, true, true);
380             }
381         } else {
382             if (this.deferredSetValue) {
383                 this.setValue.apply(this, this.deferredSetValue, true);
384                 this.deferredSetValue = null;
385             } else {
386                 this.setValue(0, true, true);
387             }
388         }
389     },
391     /**
392      * When the thumb is available, we cache the centerpoint of the element so
393      * we can position the element correctly when the background is clicked
394      * @method setThumbCenterPoint
395      */
396     setThumbCenterPoint: function() {
398         var el = this.thumb.getEl();
400         if (el) {
401             /**
402              * The center of the slider element is stored so we can 
403              * place it in the correct position when the background is clicked.
404              * @property thumbCenterPoint
405              * @type {"x": int, "y": int}
406              */
407             this.thumbCenterPoint = { 
408                     x: parseInt(el.offsetWidth/2, 10), 
409                     y: parseInt(el.offsetHeight/2, 10) 
410             };
411         }
413     },
415     /**
416      * Locks the slider, overrides YAHOO.util.DragDrop
417      * @method lock
418      */
419     lock: function() {
420         this.logger.log("locking");
421         this.thumb.lock();
422         this.locked = true;
423     },
425     /**
426      * Unlocks the slider, overrides YAHOO.util.DragDrop
427      * @method unlock
428      */
429     unlock: function() {
430         this.logger.log("unlocking");
431         this.thumb.unlock();
432         this.locked = false;
433     },
435     /**
436      * Handles mouseup event on the slider background
437      * @method thumbMouseUp
438      * @private
439      */
440     thumbMouseUp: function() {
441         this.logger.log("bg mouseup");
442         if (!this.isLocked() && !this.moveComplete) {
443             this.endMove();
444         }
446     },
448     /**
449      * Returns a reference to this slider's thumb
450      * @method getThumb
451      * @return {SliderThumb} this slider's thumb
452      */
453     getThumb: function() {
454         return this.thumb;
455     },
457     /**
458      * Try to focus the element when clicked so we can add
459      * accessibility features
460      * @method focus
461      * @private
462      */
463     focus: function() {
464         this.logger.log("focus");
466         // Focus the background element if possible
467         var el = this.getEl();
469         if (el.focus) {
470             try {
471                 el.focus();
472             } catch(e) {
473                 // Prevent permission denied unhandled exception in FF that can
474                 // happen when setting focus while another element is handling
475                 // the blur.  @TODO this is still writing to the error log 
476                 // (unhandled error) in FF1.5 with strict error checking on.
477             }
478         }
480         this.verifyOffset();
482         if (this.isLocked()) {
483             return false;
484         } else {
485             this.onSlideStart();
486             return true;
487         }
488     },
490     /**
491      * Event that fires when the value of the slider has changed
492      * @method onChange
493      * @param {int} firstOffset the number of pixels the thumb has moved
494      * from its start position. Normal horizontal and vertical sliders will only
495      * have the firstOffset.  Regions will have both, the first is the horizontal
496      * offset, the second the vertical.
497      * @param {int} secondOffset the y offset for region sliders
498      * @deprecated use instance.subscribe("change") instead
499      */
500     onChange: function (firstOffset, secondOffset) { 
501         /* override me */ 
502         this.logger.log("onChange: " + firstOffset + ", " + secondOffset);
503     },
505     /**
506      * Event that fires when the at the beginning of the slider thumb move
507      * @method onSlideStart
508      * @deprecated use instance.subscribe("slideStart") instead
509      */
510     onSlideStart: function () { 
511         /* override me */ 
512         this.logger.log("onSlideStart");
513     },
515     /**
516      * Event that fires at the end of a slider thumb move
517      * @method onSliderEnd
518      * @deprecated use instance.subscribe("slideEnd") instead
519      */
520     onSlideEnd: function () { 
521         /* override me */ 
522         this.logger.log("onSlideEnd");
523     },
525     /**
526      * Returns the slider's thumb offset from the start position
527      * @method getValue
528      * @return {int} the current value
529      */
530     getValue: function () { 
531         return this.thumb.getValue();
532     },
534     /**
535      * Returns the slider's thumb X offset from the start position
536      * @method getXValue
537      * @return {int} the current horizontal offset
538      */
539     getXValue: function () { 
540         return this.thumb.getXValue();
541     },
543     /**
544      * Returns the slider's thumb Y offset from the start position
545      * @method getYValue
546      * @return {int} the current vertical offset
547      */
548     getYValue: function () { 
549         return this.thumb.getYValue();
550     },
552     /**
553      * Internal handler for the slider thumb's onChange event
554      * @method handleThumbChange
555      * @private
556      */
557     handleThumbChange: function () { 
558         var t = this.thumb;
559         if (t._isRegion) {
560             t.onChange(t.getXValue(), t.getYValue());
561             this.fireEvent("change", { x: t.getXValue(), y: t.getYValue() } );
562         } else {
563             t.onChange(t.getValue());
564             this.fireEvent("change", t.getValue());
565         }
567     },
569     /**
570      * Provides a way to set the value of the slider in code.
571      * @method setValue
572      * @param {int} newOffset the number of pixels the thumb should be
573      * positioned away from the initial start point 
574      * @param {boolean} skipAnim set to true to disable the animation
575      * for this move action (but not others).
576      * @param {boolean} force ignore the locked setting and set value anyway
577      * @return {boolean} true if the move was performed, false if it failed
578      */
579     setValue: function(newOffset, skipAnim, force) {
580         this.logger.log("setValue " + newOffset);
582         if (!this.thumb.available) {
583             this.logger.log("defer setValue until after onAvailble");
584             this.deferredSetValue = arguments;
585             return false;
586         }
588         if (this.isLocked() && !force) {
589             this.logger.log("Can't set the value, the control is locked");
590             return false;
591         }
593         if ( isNaN(newOffset) ) {
594             this.logger.log("setValue, Illegal argument: " + newOffset);
595             return false;
596         }
598         var t = this.thumb;
599         var newX, newY;
600         this.verifyOffset(true);
601         if (t._isRegion) {
602             return false;
603         } else if (t._isHoriz) {
604             this.onSlideStart();
605             // this.fireEvent("slideStart");
606             newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
607             this.moveThumb(newX, t.initPageY, skipAnim);
608         } else {
609             this.onSlideStart();
610             // this.fireEvent("slideStart");
611             newY = t.initPageY + newOffset + this.thumbCenterPoint.y;
612             this.moveThumb(t.initPageX, newY, skipAnim);
613         }
615         return true;
616     },
618     /**
619      * Provides a way to set the value of the region slider in code.
620      * @method setRegionValue
621      * @param {int} newOffset the number of pixels the thumb should be
622      * positioned away from the initial start point (x axis for region)
623      * @param {int} newOffset2 the number of pixels the thumb should be
624      * positioned away from the initial start point (y axis for region)
625      * @param {boolean} skipAnim set to true to disable the animation
626      * for this move action (but not others).
627      * @param {boolean} force ignore the locked setting and set value anyway
628      * @return {boolean} true if the move was performed, false if it failed
629      */
630     setRegionValue: function(newOffset, newOffset2, skipAnim, force) {
632         if (!this.thumb.available) {
633             this.logger.log("defer setRegionValue until after onAvailble");
634             this.deferredSetRegionValue = arguments;
635             return false;
636         }
638         if (this.isLocked() && !force) {
639             this.logger.log("Can't set the value, the control is locked");
640             return false;
641         }
643         if ( isNaN(newOffset) ) {
644             this.logger.log("setRegionValue, Illegal argument: " + newOffset);
645             return false;
646         }
648         var t = this.thumb;
649         if (t._isRegion) {
650             this.onSlideStart();
651             var newX = t.initPageX + newOffset + this.thumbCenterPoint.x;
652             var newY = t.initPageY + newOffset2 + this.thumbCenterPoint.y;
653             this.moveThumb(newX, newY, skipAnim);
654             return true;
655         }
657         return false;
659     },
661     /**
662      * Checks the background position element position.  If it has moved from the
663      * baseline position, the constraints for the thumb are reset
664      * @param checkPos {boolean} check the position instead of using cached value
665      * @method verifyOffset
666      * @return {boolean} True if the offset is the same as the baseline.
667      */
668     verifyOffset: function(checkPos) {
670         var newPos = YAHOO.util.Dom.getXY(this.getEl());
671         //var newPos = [this.initPageX, this.initPageY];
673         this.logger.log("newPos: " + newPos, "warn");
675         if (newPos[0] != this.baselinePos[0] || newPos[1] != this.baselinePos[1]) {
676             this.logger.log("background moved, resetting constraints");
677             this.thumb.resetConstraints();
678             this.baselinePos = newPos;
679             return false;
680         }
682         return true;
683     },
685     /**
686      * Move the associated slider moved to a timeout to try to get around the 
687      * mousedown stealing moz does when I move the slider element between the 
688      * cursor and the background during the mouseup event
689      * @method moveThumb
690      * @param {int} x the X coordinate of the click
691      * @param {int} y the Y coordinate of the click
692      * @param {boolean} skipAnim don't animate if the move happend onDrag
693      * @private
694      */
695     moveThumb: function(x, y, skipAnim) {
697         // this.logger.log("move thumb", "warn");
699         var t = this.thumb;
700         var self = this;
702         if (!t.available) {
703             this.logger.log("thumb is not available yet, aborting move");
704             return;
705         }
707         this.logger.log("move thumb, x: "  + x + ", y: " + y);
709         // this.verifyOffset();
711         t.setDelta(this.thumbCenterPoint.x, this.thumbCenterPoint.y);
713         var _p = t.getTargetCoord(x, y);
714         var p = [_p.x, _p.y];
717         this.fireEvent("slideStart");
719         if (this.animate && YAHOO.widget.Slider.ANIM_AVAIL && t._graduated && !skipAnim) {
720             this.logger.log("graduated");
721             // this.thumb._animating = true;
722             this.lock();
724             // cache the current thumb pos
725             this.curCoord = YAHOO.util.Dom.getXY(this.thumb.getEl());
727             setTimeout( function() { self.moveOneTick(p); }, this.tickPause );
729         } else if (this.animate && YAHOO.widget.Slider.ANIM_AVAIL && !skipAnim) {
730             this.logger.log("animating to " + p);
732             // this.thumb._animating = true;
733             this.lock();
735             var oAnim = new YAHOO.util.Motion( 
736                     t.id, { points: { to: p } }, 
737                     this.animationDuration, 
738                     YAHOO.util.Easing.easeOut );
740             oAnim.onComplete.subscribe( function() { self.endMove(); } );
741             oAnim.animate();
742         } else {
743             t.setDragElPos(x, y);
744             // this.fireEvents();
745             this.endMove();
746         }
747     },
749     /**
750      * Move the slider one tick mark towards its final coordinate.  Used
751      * for the animation when tick marks are defined
752      * @method moveOneTick
753      * @param {int[]} the destination coordinate
754      * @private
755      */
756     moveOneTick: function(finalCoord) {
758         var t = this.thumb, tmp;
761         // redundant call to getXY since we set the position most of time prior 
762         // to getting here.  Moved to this.curCoord
763         //var curCoord = YAHOO.util.Dom.getXY(t.getEl());
765         // alignElWithMouse caches position in lastPageX, lastPageY .. doesn't work
766         //var curCoord = [this.lastPageX, this.lastPageY];
768         // var thresh = Math.min(t.tickSize + (Math.floor(t.tickSize/2)), 10);
769         // var thresh = 10;
770         // var thresh = t.tickSize + (Math.floor(t.tickSize/2));
772         var nextCoord = null;
774         if (t._isRegion) {
775             nextCoord = this._getNextX(this.curCoord, finalCoord);
776             var tmpX = (nextCoord) ? nextCoord[0] : this.curCoord[0];
777             nextCoord = this._getNextY([tmpX, this.curCoord[1]], finalCoord);
779         } else if (t._isHoriz) {
780             nextCoord = this._getNextX(this.curCoord, finalCoord);
781         } else {
782             nextCoord = this._getNextY(this.curCoord, finalCoord);
783         }
785         this.logger.log("moveOneTick: " + 
786                 " finalCoord: " + finalCoord +
787                 " this.curCoord: " + this.curCoord +
788                 " nextCoord: " + nextCoord);
790         if (nextCoord) {
792             // cache the position
793             this.curCoord = nextCoord;
795             // move to the next coord
796             // YAHOO.util.Dom.setXY(t.getEl(), nextCoord);
798             // var el = t.getEl();
799             // YAHOO.util.Dom.setStyle(el, "left", (nextCoord[0] + this.thumb.deltaSetXY[0]) + "px");
800             // YAHOO.util.Dom.setStyle(el, "top",  (nextCoord[1] + this.thumb.deltaSetXY[1]) + "px");
802             this.thumb.alignElWithMouse(t.getEl(), nextCoord[0], nextCoord[1]);
803             
804             // check if we are in the final position, if not make a recursive call
805             if (!(nextCoord[0] == finalCoord[0] && nextCoord[1] == finalCoord[1])) {
806                 var self = this;
807                 setTimeout(function() { self.moveOneTick(finalCoord); }, 
808                         this.tickPause);
809             } else {
810                 this.endMove();
811             }
812         } else {
813             this.endMove();
814         }
816         //this.tickPause = Math.round(this.tickPause/2);
817     },
819     /**
820      * Returns the next X tick value based on the current coord and the target coord.
821      * @method _getNextX
822      * @private
823      */
824     _getNextX: function(curCoord, finalCoord) {
825         this.logger.log("getNextX: " + curCoord + ", " + finalCoord);
826         var t = this.thumb;
827         var thresh;
828         var tmp = [];
829         var nextCoord = null;
830         if (curCoord[0] > finalCoord[0]) {
831             thresh = t.tickSize - this.thumbCenterPoint.x;
832             tmp = t.getTargetCoord( curCoord[0] - thresh, curCoord[1] );
833             nextCoord = [tmp.x, tmp.y];
834         } else if (curCoord[0] < finalCoord[0]) {
835             thresh = t.tickSize + this.thumbCenterPoint.x;
836             tmp = t.getTargetCoord( curCoord[0] + thresh, curCoord[1] );
837             nextCoord = [tmp.x, tmp.y];
838         } else {
839             // equal, do nothing
840         }
842         return nextCoord;
843     },
845     /**
846      * Returns the next Y tick value based on the current coord and the target coord.
847      * @method _getNextY
848      * @private
849      */
850     _getNextY: function(curCoord, finalCoord) {
851         var t = this.thumb;
852         var thresh;
853         var tmp = [];
854         var nextCoord = null;
856         if (curCoord[1] > finalCoord[1]) {
857             thresh = t.tickSize - this.thumbCenterPoint.y;
858             tmp = t.getTargetCoord( curCoord[0], curCoord[1] - thresh );
859             nextCoord = [tmp.x, tmp.y];
860         } else if (curCoord[1] < finalCoord[1]) {
861             thresh = t.tickSize + this.thumbCenterPoint.y;
862             tmp = t.getTargetCoord( curCoord[0], curCoord[1] + thresh );
863             nextCoord = [tmp.x, tmp.y];
864         } else {
865             // equal, do nothing
866         }
868         return nextCoord;
869     },
871     /**
872      * Resets the constraints before moving the thumb.
873      * @method b4MouseDown
874      * @private
875      */
876     b4MouseDown: function(e) {
877         this.thumb.autoOffset();
878         this.thumb.resetConstraints();
879     },
882     /**
883      * Handles the mousedown event for the slider background
884      * @method onMouseDown
885      * @private
886      */
887     onMouseDown: function(e) {
888         // this.resetConstraints(true);
889         // this.thumb.resetConstraints(true);
891         if (! this.isLocked() && this.backgroundEnabled) {
892             var x = YAHOO.util.Event.getPageX(e);
893             var y = YAHOO.util.Event.getPageY(e);
894             this.logger.log("bg mousedown: " + x + "," + y);
896             this.focus();
897             this.moveThumb(x, y);
898         }
899         
900     },
902     /**
903      * Handles the onDrag event for the slider background
904      * @method onDrag
905      * @private
906      */
907     onDrag: function(e) {
908         if (! this.isLocked()) {
909             var x = YAHOO.util.Event.getPageX(e);
910             var y = YAHOO.util.Event.getPageY(e);
911             this.moveThumb(x, y, true);
912         }
913     },
915     /**
916      * Fired when the slider movement ends
917      * @method endMove
918      * @private
919      */
920     endMove: function () {
921         // this._animating = false;
922         this.unlock();
923         this.moveComplete = true;
924         this.fireEvents();
925     },
927     /**
928      * Fires the change event if the value has been changed.  Ignored if we are in
929      * the middle of an animation as the event will fire when the animation is
930      * complete
931      * @method fireEvents
932      * @param {boolean} thumbEvent set to true if this event is fired from an event
933      *                  that occurred on the thumb.  If it is, the state of the
934      *                  thumb dd object should be correct.  Otherwise, the event
935      *                  originated on the background, so the thumb state needs to
936      *                  be refreshed before proceeding.
937      * @private
938      */
939     fireEvents: function (thumbEvent) {
941         var t = this.thumb;
942         // this.logger.log("FireEvents: " + t._isRegion);
944         if (!thumbEvent) {
945             t.cachePosition();
946         }
948         if (! this.isLocked()) {
949             if (t._isRegion) {
950                 this.logger.log("region");
951                 var newX = t.getXValue();
952                 var newY = t.getYValue();
954                 if (newX != this.previousX || newY != this.previousY) {
955                     // this.logger.log("Firing onchange");
956                     this.onChange(newX, newY);
957                     this.fireEvent("change", { x: newX, y: newY });
958                 }
960                 this.previousX = newX;
961                 this.previousY = newY;
963             } else {
964                 var newVal = t.getValue();
965                 if (newVal != this.previousVal) {
966                     this.logger.log("Firing onchange: " + newVal);
967                     this.onChange( newVal );
968                     this.fireEvent("change", newVal);
969                 }
970                 this.previousVal = newVal;
971             }
973             if (this.moveComplete) {
974                 this.onSlideEnd();
975                 this.fireEvent("slideEnd");
976                 this.moveComplete = false;
977             }
979         }
980     },
982     /**
983      * Slider toString
984      * @method toString
985      * @return {string} string representation of the instance
986      */
987     toString: function () { 
988         return ("Slider (" + this.type +") " + this.id);
989     }
993 YAHOO.augment(YAHOO.widget.Slider, YAHOO.util.EventProvider);
996  * A drag and drop implementation to be used as the thumb of a slider.
997  * @class SliderThumb
998  * @extends YAHOO.util.DD
999  * @constructor
1000  * @param {String} id the id of the slider html element
1001  * @param {String} sGroup the group of related DragDrop items
1002  * @param {int} iLeft the number of pixels the element can move left
1003  * @param {int} iRight the number of pixels the element can move right
1004  * @param {int} iUp the number of pixels the element can move up
1005  * @param {int} iDown the number of pixels the element can move down
1006  * @param {int} iTickSize optional parameter for specifying that the element 
1007  * should move a certain number pixels at a time.
1008  */
1009 YAHOO.widget.SliderThumb = function(id, sGroup, iLeft, iRight, iUp, iDown, iTickSize) {
1011     if (id) {
1012         //this.init(id, sGroup);
1013         YAHOO.widget.SliderThumb.superclass.constructor.call(this, id, sGroup);
1015         /**
1016          * The id of the thumbs parent HTML element (the slider background 
1017          * element).
1018          * @property parentElId
1019          * @type string
1020          */
1021         this.parentElId = sGroup;
1022     }
1025     //this.removeInvalidHandleType("A");
1027     this.logger = new YAHOO.widget.LogWriter(this.toString());
1029     /**
1030      * Overrides the isTarget property in YAHOO.util.DragDrop
1031      * @property isTarget
1032      * @private
1033      */
1034     this.isTarget = false;
1036     /**
1037      * The tick size for this slider
1038      * @property tickSize
1039      * @type int
1040      * @private
1041      */
1042     this.tickSize = iTickSize;
1044     /**
1045      * Informs the drag and drop util that the offsets should remain when
1046      * resetting the constraints.  This preserves the slider value when
1047      * the constraints are reset
1048      * @property maintainOffset
1049      * @type boolean
1050      * @private
1051      */
1052     this.maintainOffset = true;
1054     this.initSlider(iLeft, iRight, iUp, iDown, iTickSize);
1056     /**
1057      * Turns off the autoscroll feature in drag and drop
1058      * @property scroll
1059      * @private
1060      */
1061     this.scroll = false;
1063 }; 
1065 YAHOO.extend(YAHOO.widget.SliderThumb, YAHOO.util.DD, {
1067     /**
1068      * The (X and Y) difference between the thumb location and its parent 
1069      * (the slider background) when the control is instantiated.
1070      * @property startOffset
1071      * @type [int, int]
1072      */
1073     startOffset: null,
1075     /**
1076      * Flag used to figure out if this is a horizontal or vertical slider
1077      * @property _isHoriz
1078      * @type boolean
1079      * @private
1080      */
1081     _isHoriz: false,
1083     /**
1084      * Cache the last value so we can check for change
1085      * @property _prevVal
1086      * @type int
1087      * @private
1088      */
1089     _prevVal: 0,
1091     /**
1092      * The slider is _graduated if there is a tick interval defined
1093      * @property _graduated
1094      * @type boolean
1095      * @private
1096      */
1097     _graduated: false,
1100     /**
1101      * Returns the difference between the location of the thumb and its parent.
1102      * @method getOffsetFromParent
1103      * @param {[int, int]} parentPos Optionally accepts the position of the parent
1104      * @type [int, int]
1105      */
1106     getOffsetFromParent0: function(parentPos) {
1107         var myPos = YAHOO.util.Dom.getXY(this.getEl());
1108         var ppos  = parentPos || YAHOO.util.Dom.getXY(this.parentElId);
1110         return [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ];
1111     },
1113     getOffsetFromParent: function(parentPos) {
1115         var el = this.getEl();
1117         if (!this.deltaOffset) {
1119             var myPos = YAHOO.util.Dom.getXY(el);
1120             var ppos  = parentPos || YAHOO.util.Dom.getXY(this.parentElId);
1122             var newOffset = [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ];
1124             var l = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
1125             var t = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
1127             var deltaX = l - newOffset[0];
1128             var deltaY = t - newOffset[1];
1130             if (isNaN(deltaX) || isNaN(deltaY)) {
1131                 this.logger.log("element does not have a position style def yet");
1132             } else {
1133                 this.deltaOffset = [deltaX, deltaY];
1134             }
1136         } else {
1137             var newLeft = parseInt( YAHOO.util.Dom.getStyle(el, "left"), 10 );
1138             var newTop  = parseInt( YAHOO.util.Dom.getStyle(el, "top" ), 10 );
1140             newOffset  = [newLeft + this.deltaOffset[0], newTop + this.deltaOffset[1]];
1141         }
1143         return newOffset;
1145         //return [ (myPos[0] - ppos[0]), (myPos[1] - ppos[1]) ];
1146     },
1148     /**
1149      * Set up the slider, must be called in the constructor of all subclasses
1150      * @method initSlider
1151      * @param {int} iLeft the number of pixels the element can move left
1152      * @param {int} iRight the number of pixels the element can move right
1153      * @param {int} iUp the number of pixels the element can move up
1154      * @param {int} iDown the number of pixels the element can move down
1155      * @param {int} iTickSize the width of the tick interval.
1156      */
1157     initSlider: function (iLeft, iRight, iUp, iDown, iTickSize) {
1160         //document these.  new for 0.12.1
1161         this.initLeft = iLeft;
1162         this.initRight = iRight;
1163         this.initUp = iUp;
1164         this.initDown = iDown;
1166         this.setXConstraint(iLeft, iRight, iTickSize);
1167         this.setYConstraint(iUp, iDown, iTickSize);
1169         if (iTickSize && iTickSize > 1) {
1170             this._graduated = true;
1171         }
1173         this._isHoriz  = (iLeft || iRight); 
1174         this._isVert   = (iUp   || iDown);
1175         this._isRegion = (this._isHoriz && this._isVert); 
1177     },
1179     /**
1180      * Clear's the slider's ticks
1181      * @method clearTicks
1182      */
1183     clearTicks: function () {
1184         YAHOO.widget.SliderThumb.superclass.clearTicks.call(this);
1185         this.tickSize = 0;
1186         this._graduated = false;
1187     },
1190     /**
1191      * Gets the current offset from the element's start position in
1192      * pixels.
1193      * @method getValue
1194      * @return {int} the number of pixels (positive or negative) the
1195      * slider has moved from the start position.
1196      */
1197     getValue: function () {
1198         if (!this.available) { return 0; }
1199         var val = (this._isHoriz) ? this.getXValue() : this.getYValue();
1200         //this.logger.log("getVal: " + val);
1201         return val;
1202     },
1204     /**
1205      * Gets the current X offset from the element's start position in
1206      * pixels.
1207      * @method getXValue
1208      * @return {int} the number of pixels (positive or negative) the
1209      * slider has moved horizontally from the start position.
1210      */
1211     getXValue: function () {
1212         if (!this.available) { return 0; }
1213         var newOffset = this.getOffsetFromParent();
1214         return (newOffset[0] - this.startOffset[0]);
1215     },
1217     /**
1218      * Gets the current Y offset from the element's start position in
1219      * pixels.
1220      * @method getYValue
1221      * @return {int} the number of pixels (positive or negative) the
1222      * slider has moved vertically from the start position.
1223      */
1224     getYValue: function () {
1225         if (!this.available) { return 0; }
1226         var newOffset = this.getOffsetFromParent();
1227         return (newOffset[1] - this.startOffset[1]);
1228     },
1230     /**
1231      * Thumb toString
1232      * @method toString
1233      * @return {string} string representation of the instance
1234      */
1235     toString: function () { 
1236         return "SliderThumb " + this.id;
1237     },
1239     /**
1240      * The onchange event for the handle/thumb is delegated to the YAHOO.widget.Slider
1241      * instance it belongs to.
1242      * @method onChange
1243      * @private
1244      */
1245     onChange: function (x, y) { 
1246     }
1250 if ("undefined" == typeof YAHOO.util.Anim) {
1251     YAHOO.widget.Slider.ANIM_AVAIL = false;