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

Last change on this file since 18630 was 18630, checked in by rvelices, 12 years ago

feature 2771: upgrade jquery from 1.7.2 to 1.8.2 and jquery.ui from 1.8.16 to 1.9.0
Attention plugins: jquery ui effect script ids change when using combine_script because file names changed ...

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