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