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