source: trunk/themes/default/js/ui/jquery.ui.slider.js @ 9172

Last change on this file since 9172 was 9172, checked in by patdenice, 13 years ago

Update jQuery to 1.5 and jQuery UI to 1.8.9

File size: 17.3 KB
Line 
1/*
2 * jQuery UI Slider 1.8.9
3 *
4 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
5 * Dual licensed under the MIT or GPL Version 2 licenses.
6 * http://jquery.org/license
7 *
8 * http://docs.jquery.com/UI/Slider
9 *
10 * Depends:
11 *      jquery.ui.core.js
12 *      jquery.ui.mouse.js
13 *      jquery.ui.widget.js
14 */
15(function( $, undefined ) {
16
17// number of pages in a slider
18// (how many times can you page up/down to go through the whole range)
19var numPages = 5;
20
21$.widget( "ui.slider", $.ui.mouse, {
22
23        widgetEventPrefix: "slide",
24
25        options: {
26                animate: false,
27                distance: 0,
28                max: 100,
29                min: 0,
30                orientation: "horizontal",
31                range: false,
32                step: 1,
33                value: 0,
34                values: null
35        },
36
37        _create: function() {
38                var self = this,
39                        o = this.options;
40
41                this._keySliding = false;
42                this._mouseSliding = false;
43                this._animateOff = true;
44                this._handleIndex = null;
45                this._detectOrientation();
46                this._mouseInit();
47
48                this.element
49                        .addClass( "ui-slider" +
50                                " ui-slider-" + this.orientation +
51                                " ui-widget" +
52                                " ui-widget-content" +
53                                " ui-corner-all" );
54               
55                if ( o.disabled ) {
56                        this.element.addClass( "ui-slider-disabled ui-disabled" );
57                }
58
59                this.range = $([]);
60
61                if ( o.range ) {
62                        if ( o.range === true ) {
63                                this.range = $( "<div></div>" );
64                                if ( !o.values ) {
65                                        o.values = [ this._valueMin(), this._valueMin() ];
66                                }
67                                if ( o.values.length && o.values.length !== 2 ) {
68                                        o.values = [ o.values[0], o.values[0] ];
69                                }
70                        } else {
71                                this.range = $( "<div></div>" );
72                        }
73
74                        this.range
75                                .appendTo( this.element )
76                                .addClass( "ui-slider-range" );
77
78                        if ( o.range === "min" || o.range === "max" ) {
79                                this.range.addClass( "ui-slider-range-" + o.range );
80                        }
81
82                        // note: this isn't the most fittingly semantic framework class for this element,
83                        // but worked best visually with a variety of themes
84                        this.range.addClass( "ui-widget-header" );
85                }
86
87                if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
88                        $( "<a href='#'></a>" )
89                                .appendTo( this.element )
90                                .addClass( "ui-slider-handle" );
91                }
92
93                if ( o.values && o.values.length ) {
94                        while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
95                                $( "<a href='#'></a>" )
96                                        .appendTo( this.element )
97                                        .addClass( "ui-slider-handle" );
98                        }
99                }
100
101                this.handles = $( ".ui-slider-handle", this.element )
102                        .addClass( "ui-state-default" +
103                                " ui-corner-all" );
104
105                this.handle = this.handles.eq( 0 );
106
107                this.handles.add( this.range ).filter( "a" )
108                        .click(function( event ) {
109                                event.preventDefault();
110                        })
111                        .hover(function() {
112                                if ( !o.disabled ) {
113                                        $( this ).addClass( "ui-state-hover" );
114                                }
115                        }, function() {
116                                $( this ).removeClass( "ui-state-hover" );
117                        })
118                        .focus(function() {
119                                if ( !o.disabled ) {
120                                        $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
121                                        $( this ).addClass( "ui-state-focus" );
122                                } else {
123                                        $( this ).blur();
124                                }
125                        })
126                        .blur(function() {
127                                $( this ).removeClass( "ui-state-focus" );
128                        });
129
130                this.handles.each(function( i ) {
131                        $( this ).data( "index.ui-slider-handle", i );
132                });
133
134                this.handles
135                        .keydown(function( event ) {
136                                var ret = true,
137                                        index = $( this ).data( "index.ui-slider-handle" ),
138                                        allowed,
139                                        curVal,
140                                        newVal,
141                                        step;
142       
143                                if ( self.options.disabled ) {
144                                        return;
145                                }
146       
147                                switch ( event.keyCode ) {
148                                        case $.ui.keyCode.HOME:
149                                        case $.ui.keyCode.END:
150                                        case $.ui.keyCode.PAGE_UP:
151                                        case $.ui.keyCode.PAGE_DOWN:
152                                        case $.ui.keyCode.UP:
153                                        case $.ui.keyCode.RIGHT:
154                                        case $.ui.keyCode.DOWN:
155                                        case $.ui.keyCode.LEFT:
156                                                ret = false;
157                                                if ( !self._keySliding ) {
158                                                        self._keySliding = true;
159                                                        $( this ).addClass( "ui-state-active" );
160                                                        allowed = self._start( event, index );
161                                                        if ( allowed === false ) {
162                                                                return;
163                                                        }
164                                                }
165                                                break;
166                                }
167       
168                                step = self.options.step;
169                                if ( self.options.values && self.options.values.length ) {
170                                        curVal = newVal = self.values( index );
171                                } else {
172                                        curVal = newVal = self.value();
173                                }
174       
175                                switch ( event.keyCode ) {
176                                        case $.ui.keyCode.HOME:
177                                                newVal = self._valueMin();
178                                                break;
179                                        case $.ui.keyCode.END:
180                                                newVal = self._valueMax();
181                                                break;
182                                        case $.ui.keyCode.PAGE_UP:
183                                                newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
184                                                break;
185                                        case $.ui.keyCode.PAGE_DOWN:
186                                                newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
187                                                break;
188                                        case $.ui.keyCode.UP:
189                                        case $.ui.keyCode.RIGHT:
190                                                if ( curVal === self._valueMax() ) {
191                                                        return;
192                                                }
193                                                newVal = self._trimAlignValue( curVal + step );
194                                                break;
195                                        case $.ui.keyCode.DOWN:
196                                        case $.ui.keyCode.LEFT:
197                                                if ( curVal === self._valueMin() ) {
198                                                        return;
199                                                }
200                                                newVal = self._trimAlignValue( curVal - step );
201                                                break;
202                                }
203       
204                                self._slide( event, index, newVal );
205       
206                                return ret;
207       
208                        })
209                        .keyup(function( event ) {
210                                var index = $( this ).data( "index.ui-slider-handle" );
211       
212                                if ( self._keySliding ) {
213                                        self._keySliding = false;
214                                        self._stop( event, index );
215                                        self._change( event, index );
216                                        $( this ).removeClass( "ui-state-active" );
217                                }
218       
219                        });
220
221                this._refreshValue();
222
223                this._animateOff = false;
224        },
225
226        destroy: function() {
227                this.handles.remove();
228                this.range.remove();
229
230                this.element
231                        .removeClass( "ui-slider" +
232                                " ui-slider-horizontal" +
233                                " ui-slider-vertical" +
234                                " ui-slider-disabled" +
235                                " ui-widget" +
236                                " ui-widget-content" +
237                                " ui-corner-all" )
238                        .removeData( "slider" )
239                        .unbind( ".slider" );
240
241                this._mouseDestroy();
242
243                return this;
244        },
245
246        _mouseCapture: function( event ) {
247                var o = this.options,
248                        position,
249                        normValue,
250                        distance,
251                        closestHandle,
252                        self,
253                        index,
254                        allowed,
255                        offset,
256                        mouseOverHandle;
257
258                if ( o.disabled ) {
259                        return false;
260                }
261
262                this.elementSize = {
263                        width: this.element.outerWidth(),
264                        height: this.element.outerHeight()
265                };
266                this.elementOffset = this.element.offset();
267
268                position = { x: event.pageX, y: event.pageY };
269                normValue = this._normValueFromMouse( position );
270                distance = this._valueMax() - this._valueMin() + 1;
271                self = this;
272                this.handles.each(function( i ) {
273                        var thisDistance = Math.abs( normValue - self.values(i) );
274                        if ( distance > thisDistance ) {
275                                distance = thisDistance;
276                                closestHandle = $( this );
277                                index = i;
278                        }
279                });
280
281                // workaround for bug #3736 (if both handles of a range are at 0,
282                // the first is always used as the one with least distance,
283                // and moving it is obviously prevented by preventing negative ranges)
284                if( o.range === true && this.values(1) === o.min ) {
285                        index += 1;
286                        closestHandle = $( this.handles[index] );
287                }
288
289                allowed = this._start( event, index );
290                if ( allowed === false ) {
291                        return false;
292                }
293                this._mouseSliding = true;
294
295                self._handleIndex = index;
296
297                closestHandle
298                        .addClass( "ui-state-active" )
299                        .focus();
300               
301                offset = closestHandle.offset();
302                mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
303                this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
304                        left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
305                        top: event.pageY - offset.top -
306                                ( closestHandle.height() / 2 ) -
307                                ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
308                                ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
309                                ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
310                };
311
312                if ( !this.handles.hasClass( "ui-state-hover" ) ) {
313                        this._slide( event, index, normValue );
314                }
315                this._animateOff = true;
316                return true;
317        },
318
319        _mouseStart: function( event ) {
320                return true;
321        },
322
323        _mouseDrag: function( event ) {
324                var position = { x: event.pageX, y: event.pageY },
325                        normValue = this._normValueFromMouse( position );
326               
327                this._slide( event, this._handleIndex, normValue );
328
329                return false;
330        },
331
332        _mouseStop: function( event ) {
333                this.handles.removeClass( "ui-state-active" );
334                this._mouseSliding = false;
335
336                this._stop( event, this._handleIndex );
337                this._change( event, this._handleIndex );
338
339                this._handleIndex = null;
340                this._clickOffset = null;
341                this._animateOff = false;
342
343                return false;
344        },
345       
346        _detectOrientation: function() {
347                this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
348        },
349
350        _normValueFromMouse: function( position ) {
351                var pixelTotal,
352                        pixelMouse,
353                        percentMouse,
354                        valueTotal,
355                        valueMouse;
356
357                if ( this.orientation === "horizontal" ) {
358                        pixelTotal = this.elementSize.width;
359                        pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
360                } else {
361                        pixelTotal = this.elementSize.height;
362                        pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
363                }
364
365                percentMouse = ( pixelMouse / pixelTotal );
366                if ( percentMouse > 1 ) {
367                        percentMouse = 1;
368                }
369                if ( percentMouse < 0 ) {
370                        percentMouse = 0;
371                }
372                if ( this.orientation === "vertical" ) {
373                        percentMouse = 1 - percentMouse;
374                }
375
376                valueTotal = this._valueMax() - this._valueMin();
377                valueMouse = this._valueMin() + percentMouse * valueTotal;
378
379                return this._trimAlignValue( valueMouse );
380        },
381
382        _start: function( event, index ) {
383                var uiHash = {
384                        handle: this.handles[ index ],
385                        value: this.value()
386                };
387                if ( this.options.values && this.options.values.length ) {
388                        uiHash.value = this.values( index );
389                        uiHash.values = this.values();
390                }
391                return this._trigger( "start", event, uiHash );
392        },
393
394        _slide: function( event, index, newVal ) {
395                var otherVal,
396                        newValues,
397                        allowed;
398
399                if ( this.options.values && this.options.values.length ) {
400                        otherVal = this.values( index ? 0 : 1 );
401
402                        if ( ( this.options.values.length === 2 && this.options.range === true ) && 
403                                        ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
404                                ) {
405                                newVal = otherVal;
406                        }
407
408                        if ( newVal !== this.values( index ) ) {
409                                newValues = this.values();
410                                newValues[ index ] = newVal;
411                                // A slide can be canceled by returning false from the slide callback
412                                allowed = this._trigger( "slide", event, {
413                                        handle: this.handles[ index ],
414                                        value: newVal,
415                                        values: newValues
416                                } );
417                                otherVal = this.values( index ? 0 : 1 );
418                                if ( allowed !== false ) {
419                                        this.values( index, newVal, true );
420                                }
421                        }
422                } else {
423                        if ( newVal !== this.value() ) {
424                                // A slide can be canceled by returning false from the slide callback
425                                allowed = this._trigger( "slide", event, {
426                                        handle: this.handles[ index ],
427                                        value: newVal
428                                } );
429                                if ( allowed !== false ) {
430                                        this.value( newVal );
431                                }
432                        }
433                }
434        },
435
436        _stop: function( event, index ) {
437                var uiHash = {
438                        handle: this.handles[ index ],
439                        value: this.value()
440                };
441                if ( this.options.values && this.options.values.length ) {
442                        uiHash.value = this.values( index );
443                        uiHash.values = this.values();
444                }
445
446                this._trigger( "stop", event, uiHash );
447        },
448
449        _change: function( event, index ) {
450                if ( !this._keySliding && !this._mouseSliding ) {
451                        var uiHash = {
452                                handle: this.handles[ index ],
453                                value: this.value()
454                        };
455                        if ( this.options.values && this.options.values.length ) {
456                                uiHash.value = this.values( index );
457                                uiHash.values = this.values();
458                        }
459
460                        this._trigger( "change", event, uiHash );
461                }
462        },
463
464        value: function( newValue ) {
465                if ( arguments.length ) {
466                        this.options.value = this._trimAlignValue( newValue );
467                        this._refreshValue();
468                        this._change( null, 0 );
469                }
470
471                return this._value();
472        },
473
474        values: function( index, newValue ) {
475                var vals,
476                        newValues,
477                        i;
478
479                if ( arguments.length > 1 ) {
480                        this.options.values[ index ] = this._trimAlignValue( newValue );
481                        this._refreshValue();
482                        this._change( null, index );
483                }
484
485                if ( arguments.length ) {
486                        if ( $.isArray( arguments[ 0 ] ) ) {
487                                vals = this.options.values;
488                                newValues = arguments[ 0 ];
489                                for ( i = 0; i < vals.length; i += 1 ) {
490                                        vals[ i ] = this._trimAlignValue( newValues[ i ] );
491                                        this._change( null, i );
492                                }
493                                this._refreshValue();
494                        } else {
495                                if ( this.options.values && this.options.values.length ) {
496                                        return this._values( index );
497                                } else {
498                                        return this.value();
499                                }
500                        }
501                } else {
502                        return this._values();
503                }
504        },
505
506        _setOption: function( key, value ) {
507                var i,
508                        valsLength = 0;
509
510                if ( $.isArray( this.options.values ) ) {
511                        valsLength = this.options.values.length;
512                }
513
514                $.Widget.prototype._setOption.apply( this, arguments );
515
516                switch ( key ) {
517                        case "disabled":
518                                if ( value ) {
519                                        this.handles.filter( ".ui-state-focus" ).blur();
520                                        this.handles.removeClass( "ui-state-hover" );
521                                        this.handles.attr( "disabled", "disabled" );
522                                        this.element.addClass( "ui-disabled" );
523                                } else {
524                                        this.handles.removeAttr( "disabled" );
525                                        this.element.removeClass( "ui-disabled" );
526                                }
527                                break;
528                        case "orientation":
529                                this._detectOrientation();
530                                this.element
531                                        .removeClass( "ui-slider-horizontal ui-slider-vertical" )
532                                        .addClass( "ui-slider-" + this.orientation );
533                                this._refreshValue();
534                                break;
535                        case "value":
536                                this._animateOff = true;
537                                this._refreshValue();
538                                this._change( null, 0 );
539                                this._animateOff = false;
540                                break;
541                        case "values":
542                                this._animateOff = true;
543                                this._refreshValue();
544                                for ( i = 0; i < valsLength; i += 1 ) {
545                                        this._change( null, i );
546                                }
547                                this._animateOff = false;
548                                break;
549                }
550        },
551
552        //internal value getter
553        // _value() returns value trimmed by min and max, aligned by step
554        _value: function() {
555                var val = this.options.value;
556                val = this._trimAlignValue( val );
557
558                return val;
559        },
560
561        //internal values getter
562        // _values() returns array of values trimmed by min and max, aligned by step
563        // _values( index ) returns single value trimmed by min and max, aligned by step
564        _values: function( index ) {
565                var val,
566                        vals,
567                        i;
568
569                if ( arguments.length ) {
570                        val = this.options.values[ index ];
571                        val = this._trimAlignValue( val );
572
573                        return val;
574                } else {
575                        // .slice() creates a copy of the array
576                        // this copy gets trimmed by min and max and then returned
577                        vals = this.options.values.slice();
578                        for ( i = 0; i < vals.length; i+= 1) {
579                                vals[ i ] = this._trimAlignValue( vals[ i ] );
580                        }
581
582                        return vals;
583                }
584        },
585       
586        // returns the step-aligned value that val is closest to, between (inclusive) min and max
587        _trimAlignValue: function( val ) {
588                if ( val <= this._valueMin() ) {
589                        return this._valueMin();
590                }
591                if ( val >= this._valueMax() ) {
592                        return this._valueMax();
593                }
594                var step = ( this.options.step > 0 ) ? this.options.step : 1,
595                        valModStep = (val - this._valueMin()) % step;
596                        alignValue = val - valModStep;
597
598                if ( Math.abs(valModStep) * 2 >= step ) {
599                        alignValue += ( valModStep > 0 ) ? step : ( -step );
600                }
601
602                // Since JavaScript has problems with large floats, round
603                // the final value to 5 digits after the decimal point (see #4124)
604                return parseFloat( alignValue.toFixed(5) );
605        },
606
607        _valueMin: function() {
608                return this.options.min;
609        },
610
611        _valueMax: function() {
612                return this.options.max;
613        },
614       
615        _refreshValue: function() {
616                var oRange = this.options.range,
617                        o = this.options,
618                        self = this,
619                        animate = ( !this._animateOff ) ? o.animate : false,
620                        valPercent,
621                        _set = {},
622                        lastValPercent,
623                        value,
624                        valueMin,
625                        valueMax;
626
627                if ( this.options.values && this.options.values.length ) {
628                        this.handles.each(function( i, j ) {
629                                valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
630                                _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
631                                $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
632                                if ( self.options.range === true ) {
633                                        if ( self.orientation === "horizontal" ) {
634                                                if ( i === 0 ) {
635                                                        self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
636                                                }
637                                                if ( i === 1 ) {
638                                                        self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
639                                                }
640                                        } else {
641                                                if ( i === 0 ) {
642                                                        self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
643                                                }
644                                                if ( i === 1 ) {
645                                                        self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
646                                                }
647                                        }
648                                }
649                                lastValPercent = valPercent;
650                        });
651                } else {
652                        value = this.value();
653                        valueMin = this._valueMin();
654                        valueMax = this._valueMax();
655                        valPercent = ( valueMax !== valueMin ) ?
656                                        ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
657                                        0;
658                        _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
659                        this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
660
661                        if ( oRange === "min" && this.orientation === "horizontal" ) {
662                                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
663                        }
664                        if ( oRange === "max" && this.orientation === "horizontal" ) {
665                                this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
666                        }
667                        if ( oRange === "min" && this.orientation === "vertical" ) {
668                                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
669                        }
670                        if ( oRange === "max" && this.orientation === "vertical" ) {
671                                this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
672                        }
673                }
674        }
675
676});
677
678$.extend( $.ui.slider, {
679        version: "1.8.9"
680});
681
682}(jQuery));
Note: See TracBrowser for help on using the repository browser.