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

Last change on this file since 28780 was 28780, checked in by rvelices, 10 years ago

upgrade jquery ui from 1.10.1 to 1.10.4

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