Bug 20489 Configure illegal file characters https://bugzilla.wikimedia.org/show_bug...
[mediawiki.git] / js2 / mwEmbed / jquery / jquery.ui / ui / ui.slider.js
blobb1c1da666f8df9bf87e7dc4bd599594be93a5557
1 /*
2  * jQuery UI Slider 1.7.1
3  *
4  * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
5  * Dual licensed under the MIT (MIT-LICENSE.txt)
6  * and GPL (GPL-LICENSE.txt) licenses.
7  *
8  * http://docs.jquery.com/UI/Slider
9  *
10  * Depends:
11  *      ui.core.js
12  */
14 (function($) {
16 $.widget("ui.slider", $.extend({}, $.ui.mouse, {
18         _init: function() {
20                 var self = this, o = this.options;
21                 this._keySliding = false;
22                 this._handleIndex = null;
23                 this._detectOrientation();
24                 this._mouseInit();
26                 this.element
27                         .addClass("ui-slider"
28                                 + " ui-slider-" + this.orientation
29                                 + " ui-widget"
30                                 + " ui-widget-content"
31                                 + " ui-corner-all");
33                 this.range = $([]);
35                 if (o.range) {
37                         if (o.range === true) {
38                                 this.range = $('<div></div>');
39                                 if (!o.values) o.values = [this._valueMin(), this._valueMin()];
40                                 if (o.values.length && o.values.length != 2) {
41                                         o.values = [o.values[0], o.values[0]];
42                                 }
43                         } else {
44                                 this.range = $('<div></div>');
45                         }
47                         this.range
48                                 .appendTo(this.element)
49                                 .addClass("ui-slider-range");
51                         if (o.range == "min" || o.range == "max") {
52                                 this.range.addClass("ui-slider-range-" + o.range);
53                         }
55                         // note: this isn't the most fittingly semantic framework class for this element,
56                         // but worked best visually with a variety of themes
57                         this.range.addClass("ui-widget-header");
59                 }
61                 if ($(".ui-slider-handle", this.element).length == 0)
62                         $('<a href="#"></a>')
63                                 .appendTo(this.element)
64                                 .addClass("ui-slider-handle");
66                 if (o.values && o.values.length) {
67                         while ($(".ui-slider-handle", this.element).length < o.values.length)
68                                 $('<a href="#"></a>')
69                                         .appendTo(this.element)
70                                         .addClass("ui-slider-handle");
71                 }
73                 this.handles = $(".ui-slider-handle", this.element)
74                         .addClass("ui-state-default"
75                                 + " ui-corner-all");
77                 this.handle = this.handles.eq(0);
79                 this.handles.add(this.range).filter("a")
80                         .click(function(event) { event.preventDefault(); })
81                         .hover(function() { $(this).addClass('ui-state-hover'); }, function() { $(this).removeClass('ui-state-hover'); })
82                         .focus(function() { $(".ui-slider .ui-state-focus").removeClass('ui-state-focus'); $(this).addClass('ui-state-focus'); })
83                         .blur(function() { $(this).removeClass('ui-state-focus'); });
85                 this.handles.each(function(i) {
86                         $(this).data("index.ui-slider-handle", i);
87                 });
89                 this.handles.keydown(function(event) {
91                         var ret = true;
93                         var index = $(this).data("index.ui-slider-handle");
95                         if (self.options.disabled)
96                                 return;
98                         switch (event.keyCode) {
99                                 case $.ui.keyCode.HOME:
100                                 case $.ui.keyCode.END:
101                                 case $.ui.keyCode.UP:
102                                 case $.ui.keyCode.RIGHT:
103                                 case $.ui.keyCode.DOWN:
104                                 case $.ui.keyCode.LEFT:
105                                         ret = false;
106                                         if (!self._keySliding) {
107                                                 self._keySliding = true;
108                                                 $(this).addClass("ui-state-active");
109                                                 self._start(event, index);
110                                         }
111                                         break;
112                         }
114                         var curVal, newVal, step = self._step();
115                         if (self.options.values && self.options.values.length) {
116                                 curVal = newVal = self.values(index);
117                         } else {
118                                 curVal = newVal = self.value();
119                         }
121                         switch (event.keyCode) {
122                                 case $.ui.keyCode.HOME:
123                                         newVal = self._valueMin();
124                                         break;
125                                 case $.ui.keyCode.END:
126                                         newVal = self._valueMax();
127                                         break;
128                                 case $.ui.keyCode.UP:
129                                 case $.ui.keyCode.RIGHT:
130                                         if(curVal == self._valueMax()) return;
131                                         newVal = curVal + step;
132                                         break;
133                                 case $.ui.keyCode.DOWN:
134                                 case $.ui.keyCode.LEFT:
135                                         if(curVal == self._valueMin()) return;
136                                         newVal = curVal - step;
137                                         break;
138                         }
140                         self._slide(event, index, newVal);
142                         return ret;
144                 }).keyup(function(event) {
146                         var index = $(this).data("index.ui-slider-handle");
148                         if (self._keySliding) {
149                                 self._stop(event, index);
150                                 self._change(event, index);
151                                 self._keySliding = false;
152                                 $(this).removeClass("ui-state-active");
153                         }
155                 });
157                 this._refreshValue();
159         },
161         destroy: function() {
163                 this.handles.remove();
164                 this.range.remove();
166                 this.element
167                         .removeClass("ui-slider"
168                                 + " ui-slider-horizontal"
169                                 + " ui-slider-vertical"
170                                 + " ui-slider-disabled"
171                                 + " ui-widget"
172                                 + " ui-widget-content"
173                                 + " ui-corner-all")
174                         .removeData("slider")
175                         .unbind(".slider");
177                 this._mouseDestroy();
179         },
181         _mouseCapture: function(event) {
183                 var o = this.options;
185                 if (o.disabled)
186                         return false;
188                 this.elementSize = {
189                         width: this.element.outerWidth(),
190                         height: this.element.outerHeight()
191                 };
192                 this.elementOffset = this.element.offset();
194                 var position = { x: event.pageX, y: event.pageY };
195                 var normValue = this._normValueFromMouse(position);
197                 var distance = this._valueMax() - this._valueMin() + 1, closestHandle;
198                 var self = this, index;
199                 this.handles.each(function(i) {
200                         var thisDistance = Math.abs(normValue - self.values(i));
201                         if (distance > thisDistance) {
202                                 distance = thisDistance;
203                                 closestHandle = $(this);
204                                 index = i;
205                         }
206                 });
208                 // workaround for bug #3736 (if both handles of a range are at 0,
209                 // the first is always used as the one with least distance,
210                 // and moving it is obviously prevented by preventing negative ranges)
211                 if(o.range == true && this.values(1) == o.min) {
212                         closestHandle = $(this.handles[++index]);
213                 }
215                 this._start(event, index);
217                 self._handleIndex = index;
219                 closestHandle
220                         .addClass("ui-state-active")
221                         .focus();
222                 
223                 var offset = closestHandle.offset();
224                 var mouseOverHandle = !$(event.target).parents().andSelf().is('.ui-slider-handle');
225                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
226                         left: event.pageX - offset.left - (closestHandle.width() / 2),
227                         top: event.pageY - offset.top
228                                 - (closestHandle.height() / 2)
229                                 - (parseInt(closestHandle.css('borderTopWidth'),10) || 0)
230                                 - (parseInt(closestHandle.css('borderBottomWidth'),10) || 0)
231                                 + (parseInt(closestHandle.css('marginTop'),10) || 0)
232                 };
234                 normValue = this._normValueFromMouse(position);
235                 this._slide(event, index, normValue);
236                 return true;
238         },
240         _mouseStart: function(event) {
241                 return true;
242         },
244         _mouseDrag: function(event) {
246                 var position = { x: event.pageX, y: event.pageY };
247                 var normValue = this._normValueFromMouse(position);
248                 
249                 this._slide(event, this._handleIndex, normValue);
251                 return false;
253         },
255         _mouseStop: function(event) {
257                 this.handles.removeClass("ui-state-active");
258                 this._stop(event, this._handleIndex);
259                 this._change(event, this._handleIndex);
260                 this._handleIndex = null;
261                 this._clickOffset = null;
263                 return false;
265         },
266         
267         _detectOrientation: function() {
268                 this.orientation = this.options.orientation == 'vertical' ? 'vertical' : 'horizontal';
269         },
271         _normValueFromMouse: function(position) {
273                 var pixelTotal, pixelMouse;
274                 if ('horizontal' == this.orientation) {
275                         pixelTotal = this.elementSize.width;
276                         pixelMouse = position.x - this.elementOffset.left - (this._clickOffset ? this._clickOffset.left : 0);
277                 } else {
278                         pixelTotal = this.elementSize.height;
279                         pixelMouse = position.y - this.elementOffset.top - (this._clickOffset ? this._clickOffset.top : 0);
280                 }
282                 var percentMouse = (pixelMouse / pixelTotal);
283                 if (percentMouse > 1) percentMouse = 1;
284                 if (percentMouse < 0) percentMouse = 0;
285                 if ('vertical' == this.orientation)
286                         percentMouse = 1 - percentMouse;
288                 var valueTotal = this._valueMax() - this._valueMin(),
289                         valueMouse = percentMouse * valueTotal,
290                         valueMouseModStep = valueMouse % this.options.step,
291                         normValue = this._valueMin() + valueMouse - valueMouseModStep;
293                 if (valueMouseModStep > (this.options.step / 2))
294                         normValue += this.options.step;
296                 // Since JavaScript has problems with large floats, round
297                 // the final value to 5 digits after the decimal point (see #4124)
298                 return parseFloat(normValue.toFixed(5));
300         },
302         _start: function(event, index) {
303                 var uiHash = {
304                         handle: this.handles[index],
305                         value: this.value()
306                 };
307                 if (this.options.values && this.options.values.length) {
308                         uiHash.value = this.values(index)
309                         uiHash.values = this.values()
310                 }
311                 this._trigger("start", event, uiHash);
312         },
314         _slide: function(event, index, newVal) {
316                 var handle = this.handles[index];
318                 if (this.options.values && this.options.values.length) {
320                         var otherVal = this.values(index ? 0 : 1);
322                         if ((index == 0 && newVal >= otherVal) || (index == 1 && newVal <= otherVal))
323                                 newVal = otherVal;
325                         if (newVal != this.values(index)) {
326                                 var newValues = this.values();
327                                 newValues[index] = newVal;
328                                 // A slide can be canceled by returning false from the slide callback
329                                 var allowed = this._trigger("slide", event, {
330                                         handle: this.handles[index],
331                                         value: newVal,
332                                         values: newValues
333                                 });
334                                 var otherVal = this.values(index ? 0 : 1);
335                                 if (allowed !== false) {
336                                         this.values(index, newVal, ( event.type == 'mousedown' && this.options.animate ), true);
337                                 }
338                         }
340                 } else {
342                         if (newVal != this.value()) {
343                                 // A slide can be canceled by returning false from the slide callback
344                                 var allowed = this._trigger("slide", event, {
345                                         handle: this.handles[index],
346                                         value: newVal
347                                 });
348                                 if (allowed !== false) {
349                                         this._setData('value', newVal, ( event.type == 'mousedown' && this.options.animate ));
350                                 }
351                                         
352                         }
354                 }
356         },
358         _stop: function(event, index) {
359                 var uiHash = {
360                         handle: this.handles[index],
361                         value: this.value()
362                 };
363                 if (this.options.values && this.options.values.length) {
364                         uiHash.value = this.values(index)
365                         uiHash.values = this.values()
366                 }
367                 this._trigger("stop", event, uiHash);
368         },
370         _change: function(event, index) {
371                 var uiHash = {
372                         handle: this.handles[index],
373                         value: this.value()
374                 };
375                 if (this.options.values && this.options.values.length) {
376                         uiHash.value = this.values(index)
377                         uiHash.values = this.values()
378                 }
379                 this._trigger("change", event, uiHash);
380         },
382         value: function(newValue) {
384                 if (arguments.length) {
385                         this._setData("value", newValue);
386                         this._change(null, 0);
387                 }
389                 return this._value();
391         },
393         values: function(index, newValue, animated, noPropagation) {
395                 if (arguments.length > 1) {
396                         this.options.values[index] = newValue;
397                         this._refreshValue(animated);
398                         if(!noPropagation) this._change(null, index);
399                 }
401                 if (arguments.length) {
402                         if (this.options.values && this.options.values.length) {
403                                 return this._values(index);
404                         } else {
405                                 return this.value();
406                         }
407                 } else {
408                         return this._values();
409                 }
411         },
413         _setData: function(key, value, animated) {
415                 $.widget.prototype._setData.apply(this, arguments);
417                 switch (key) {
418                         case 'orientation':
420                                 this._detectOrientation();
421                                 
422                                 this.element
423                                         .removeClass("ui-slider-horizontal ui-slider-vertical")
424                                         .addClass("ui-slider-" + this.orientation);
425                                 this._refreshValue(animated);
426                                 break;
427                         case 'value':
428                                 this._refreshValue(animated);
429                                 break;
430                 }
432         },
434         _step: function() {
435                 var step = this.options.step;
436                 return step;
437         },
439         _value: function() {
441                 var val = this.options.value;
442                 if (val < this._valueMin()) val = this._valueMin();
443                 if (val > this._valueMax()) val = this._valueMax();
445                 return val;
447         },
449         _values: function(index) {
451                 if (arguments.length) {
452                         var val = this.options.values[index];
453                         if (val < this._valueMin()) val = this._valueMin();
454                         if (val > this._valueMax()) val = this._valueMax();
456                         return val;
457                 } else {
458                         return this.options.values;
459                 }
461         },
463         _valueMin: function() {
464                 var valueMin = this.options.min;
465                 return valueMin;
466         },
468         _valueMax: function() {
469                 var valueMax = this.options.max;
470                 return valueMax;
471         },
473         _refreshValue: function(animate) {
475                 var oRange = this.options.range, o = this.options, self = this;
477                 if (this.options.values && this.options.values.length) {
478                         var vp0, vp1;
479                         this.handles.each(function(i, j) {
480                                 var valPercent = (self.values(i) - self._valueMin()) / (self._valueMax() - self._valueMin()) * 100;
481                                 var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
482                                 $(this).stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
483                                 if (self.options.range === true) {
484                                         if (self.orientation == 'horizontal') {
485                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ left: valPercent + '%' }, o.animate);
486                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ width: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
487                                         } else {
488                                                 (i == 0) && self.range.stop(1,1)[animate ? 'animate' : 'css']({ bottom: (valPercent) + '%' }, o.animate);
489                                                 (i == 1) && self.range[animate ? 'animate' : 'css']({ height: (valPercent - lastValPercent) + '%' }, { queue: false, duration: o.animate });
490                                         }
491                                 }
492                                 lastValPercent = valPercent;
493                         });
494                 } else {
495                         var value = this.value(),
496                                 valueMin = this._valueMin(),
497                                 valueMax = this._valueMax(),
498                                 valPercent = valueMax != valueMin
499                                         ? (value - valueMin) / (valueMax - valueMin) * 100
500                                         : 0;
501                         var _set = {}; _set[self.orientation == 'horizontal' ? 'left' : 'bottom'] = valPercent + '%';
502                         this.handle.stop(1,1)[animate ? 'animate' : 'css'](_set, o.animate);
504                         (oRange == "min") && (this.orientation == "horizontal") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ width: valPercent + '%' }, o.animate);
505                         (oRange == "max") && (this.orientation == "horizontal") && this.range[animate ? 'animate' : 'css']({ width: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
506                         (oRange == "min") && (this.orientation == "vertical") && this.range.stop(1,1)[animate ? 'animate' : 'css']({ height: valPercent + '%' }, o.animate);
507                         (oRange == "max") && (this.orientation == "vertical") && this.range[animate ? 'animate' : 'css']({ height: (100 - valPercent) + '%' }, { queue: false, duration: o.animate });
508                 }
510         }
511         
512 }));
514 $.extend($.ui.slider, {
515         getter: "value values",
516         version: "1.7.1",
517         eventPrefix: "slide",
518         defaults: {
519                 animate: false,
520                 delay: 0,
521                 distance: 0,
522                 max: 100,
523                 min: 0,
524                 orientation: 'horizontal',
525                 range: false,
526                 step: 1,
527                 value: 0,
528                 values: null
529         }
532 })(jQuery);