simple_form_extension 1.3.19 → 1.3.20

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1e7907bb88ab31cbf0dc3f5b0e354e8a3d1dd0cb
4
- data.tar.gz: dcaaf0a5c20b1037a1cb2068e0e01a926e151665
3
+ metadata.gz: a756fb3beeb7c0b5800200896572b695d8c19426
4
+ data.tar.gz: 991f35fcaf7ccae388825bca31d7e1700469400e
5
5
  SHA512:
6
- metadata.gz: 8b738ce0dd70b0bdf4487842b8f7a912fc4ddffcf1b7a8a852683f4e4fd040d251e5eecf244edd6038b53b1d383c4d425faeb669d28e9fc37bfb6f73ad63ad7e
7
- data.tar.gz: f435ccac86f3182910428bc43fdc9c1a675f8698a3253dd1e174669cf880e1efe5c62428760c1c0aeadb0e1ae8e56c2b7722ce559fc3f5df6319d9c5b5cfe908
6
+ metadata.gz: 625a2fd54375d19bc17dabbd2a39f85de676ef04dc82c797c62fa61233f8dfc11373963b43f6945ab8d10084965922ab06306f479a585807769b4e183644d591
7
+ data.tar.gz: 9999f753d350c862966b2770c22eb44767ffadcc96f61ec4d5b9e548ce0ad96495689b182fdbd627622b705a15a620d0a4928941b5c40fb05a62abf903a7161f
@@ -13,6 +13,8 @@ module SimpleFormExtension
13
13
  end
14
14
  end
15
15
 
16
+ input_html_options[:data][:'slider-value'] ||= object.send(attribute_name)
17
+
16
18
  if options[:disabled]
17
19
  input_html_options[:data][:'slider-enabled'] = false
18
20
  end
@@ -1,3 +1,3 @@
1
1
  module SimpleFormExtension
2
- VERSION = "1.3.19"
2
+ VERSION = "1.3.20"
3
3
  end
@@ -1,3 +1,10 @@
1
+ /*! =======================================================
2
+ VERSION 6.1.8
3
+ ========================================================= */
4
+ "use strict";
5
+
6
+ function _typeof(obj) { return obj && typeof Symbol !== "undefined" && obj.constructor === Symbol ? "symbol" : typeof obj; }
7
+
1
8
  /*! =========================================================
2
9
  * bootstrap-slider.js
3
10
  *
@@ -24,36 +31,31 @@
24
31
  * limitations under the License.
25
32
  * ========================================================= */
26
33
 
27
-
28
34
  /**
29
35
  * Bridget makes jQuery widgets
30
36
  * v1.0.1
31
37
  * MIT license
32
38
  */
33
39
 
34
- (function(root, factory) {
35
- if(typeof define === "function" && define.amd) {
40
+ (function (factory) {
41
+ if (typeof define === "function" && define.amd) {
36
42
  define(["jquery"], factory);
37
- }
38
- else if(typeof module === "object" && module.exports) {
43
+ } else if ((typeof module === "undefined" ? "undefined" : _typeof(module)) === "object" && module.exports) {
39
44
  var jQuery;
40
45
  try {
41
46
  jQuery = require("jquery");
42
- }
43
- catch (err) {
47
+ } catch (err) {
44
48
  jQuery = null;
45
49
  }
46
50
  module.exports = factory(jQuery);
51
+ } else if (window) {
52
+ window.Slider = factory(window.jQuery);
47
53
  }
48
- else {
49
- root.Slider = factory(root.jQuery);
50
- }
51
- }(this, function($) {
54
+ })(function ($) {
52
55
  // Reference to Slider constructor
53
56
  var Slider;
54
57
 
55
-
56
- (function( $ ) {
58
+ (function ($) {
57
59
 
58
60
  'use strict';
59
61
 
@@ -65,167 +67,162 @@
65
67
 
66
68
  // -------------------------- definition -------------------------- //
67
69
 
68
- function defineBridget( $ ) {
70
+ function defineBridget($) {
69
71
 
70
72
  // bail if no jQuery
71
- if ( !$ ) {
73
+ if (!$) {
72
74
  return;
73
75
  }
74
76
 
75
77
  // -------------------------- addOptionMethod -------------------------- //
76
78
 
77
79
  /**
78
- * adds option method -> $().plugin('option', {...})
79
- * @param {Function} PluginClass - constructor class
80
- */
81
- function addOptionMethod( PluginClass ) {
80
+ * adds option method -> $().plugin('option', {...})
81
+ * @param {Function} PluginClass - constructor class
82
+ */
83
+ function addOptionMethod(PluginClass) {
82
84
  // don't overwrite original option method
83
- if ( PluginClass.prototype.option ) {
85
+ if (PluginClass.prototype.option) {
84
86
  return;
85
87
  }
86
88
 
87
89
  // option setter
88
- PluginClass.prototype.option = function( opts ) {
90
+ PluginClass.prototype.option = function (opts) {
89
91
  // bail out if not an object
90
- if ( !$.isPlainObject( opts ) ){
92
+ if (!$.isPlainObject(opts)) {
91
93
  return;
92
94
  }
93
- this.options = $.extend( true, this.options, opts );
95
+ this.options = $.extend(true, this.options, opts);
94
96
  };
95
97
  }
96
98
 
97
-
98
99
  // -------------------------- plugin bridge -------------------------- //
99
100
 
100
101
  // helper function for logging errors
101
102
  // $.error breaks jQuery chaining
102
- var logError = typeof console === 'undefined' ? noop :
103
- function( message ) {
104
- console.error( message );
105
- };
103
+ var logError = typeof console === 'undefined' ? noop : function (message) {
104
+ console.error(message);
105
+ };
106
106
 
107
107
  /**
108
- * jQuery plugin bridge, access methods like $elem.plugin('method')
109
- * @param {String} namespace - plugin name
110
- * @param {Function} PluginClass - constructor class
111
- */
112
- function bridge( namespace, PluginClass ) {
108
+ * jQuery plugin bridge, access methods like $elem.plugin('method')
109
+ * @param {String} namespace - plugin name
110
+ * @param {Function} PluginClass - constructor class
111
+ */
112
+ function bridge(namespace, PluginClass) {
113
113
  // add to jQuery fn namespace
114
- $.fn[ namespace ] = function( options ) {
115
- if ( typeof options === 'string' ) {
114
+ $.fn[namespace] = function (options) {
115
+ if (typeof options === 'string') {
116
116
  // call plugin method when first argument is a string
117
117
  // get arguments for method
118
- var args = slice.call( arguments, 1 );
118
+ var args = slice.call(arguments, 1);
119
119
 
120
- for ( var i=0, len = this.length; i < len; i++ ) {
120
+ for (var i = 0, len = this.length; i < len; i++) {
121
121
  var elem = this[i];
122
- var instance = $.data( elem, namespace );
123
- if ( !instance ) {
124
- logError( "cannot call methods on " + namespace + " prior to initialization; " +
125
- "attempted to call '" + options + "'" );
122
+ var instance = $.data(elem, namespace);
123
+ if (!instance) {
124
+ logError("cannot call methods on " + namespace + " prior to initialization; " + "attempted to call '" + options + "'");
126
125
  continue;
127
126
  }
128
- if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) {
129
- logError( "no such method '" + options + "' for " + namespace + " instance" );
127
+ if (!$.isFunction(instance[options]) || options.charAt(0) === '_') {
128
+ logError("no such method '" + options + "' for " + namespace + " instance");
130
129
  continue;
131
130
  }
132
131
 
133
132
  // trigger method with arguments
134
- var returnValue = instance[ options ].apply( instance, args);
133
+ var returnValue = instance[options].apply(instance, args);
135
134
 
136
135
  // break look and return first value if provided
137
- if ( returnValue !== undefined && returnValue !== instance) {
136
+ if (returnValue !== undefined && returnValue !== instance) {
138
137
  return returnValue;
139
138
  }
140
139
  }
141
140
  // return this if no return value
142
141
  return this;
143
142
  } else {
144
- var objects = this.map( function() {
145
- var instance = $.data( this, namespace );
146
- if ( instance ) {
143
+ var objects = this.map(function () {
144
+ var instance = $.data(this, namespace);
145
+ if (instance) {
147
146
  // apply options & init
148
- instance.option( options );
147
+ instance.option(options);
149
148
  instance._init();
150
149
  } else {
151
150
  // initialize new instance
152
- instance = new PluginClass( this, options );
153
- $.data( this, namespace, instance );
151
+ instance = new PluginClass(this, options);
152
+ $.data(this, namespace, instance);
154
153
  }
155
154
  return $(this);
156
155
  });
157
156
 
158
- if(!objects || objects.length > 1) {
157
+ if (!objects || objects.length > 1) {
159
158
  return objects;
160
159
  } else {
161
160
  return objects[0];
162
161
  }
163
162
  }
164
163
  };
165
-
166
164
  }
167
165
 
168
166
  // -------------------------- bridget -------------------------- //
169
167
 
170
168
  /**
171
- * converts a Prototypical class into a proper jQuery plugin
172
- * the class must have a ._init method
173
- * @param {String} namespace - plugin name, used in $().pluginName
174
- * @param {Function} PluginClass - constructor class
175
- */
176
- $.bridget = function( namespace, PluginClass ) {
177
- addOptionMethod( PluginClass );
178
- bridge( namespace, PluginClass );
169
+ * converts a Prototypical class into a proper jQuery plugin
170
+ * the class must have a ._init method
171
+ * @param {String} namespace - plugin name, used in $().pluginName
172
+ * @param {Function} PluginClass - constructor class
173
+ */
174
+ $.bridget = function (namespace, PluginClass) {
175
+ addOptionMethod(PluginClass);
176
+ bridge(namespace, PluginClass);
179
177
  };
180
178
 
181
179
  return $.bridget;
182
-
183
180
  }
184
181
 
185
- // get jquery from browser global
186
- defineBridget( $ );
187
-
188
- })( $ );
189
-
182
+ // get jquery from browser global
183
+ defineBridget($);
184
+ })($);
190
185
 
191
186
  /*************************************************
192
-
193
187
  BOOTSTRAP-SLIDER SOURCE CODE
194
-
195
188
  **************************************************/
196
189
 
197
- (function($) {
190
+ (function ($) {
198
191
 
199
192
  var ErrorMsgs = {
200
- formatInvalidInputErrorMsg : function(input) {
193
+ formatInvalidInputErrorMsg: function formatInvalidInputErrorMsg(input) {
201
194
  return "Invalid input value '" + input + "' passed in";
202
195
  },
203
- callingContextNotSliderInstance : "Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"
196
+ callingContextNotSliderInstance: "Calling context element does not have instance of Slider bound to it. Check your code to make sure the JQuery object returned from the call to the slider() initializer is calling the method"
204
197
  };
205
198
 
206
199
  var SliderScale = {
207
200
  linear: {
208
- toValue: function(percentage) {
209
- var rawValue = percentage/100 * (this.options.max - this.options.min);
201
+ toValue: function toValue(percentage) {
202
+ var rawValue = percentage / 100 * (this.options.max - this.options.min);
203
+ var shouldAdjustWithBase = true;
210
204
  if (this.options.ticks_positions.length > 0) {
211
- var minv, maxv, minp, maxp = 0;
212
- for (var i = 0; i < this.options.ticks_positions.length; i++) {
205
+ var minv,
206
+ maxv,
207
+ minp,
208
+ maxp = 0;
209
+ for (var i = 1; i < this.options.ticks_positions.length; i++) {
213
210
  if (percentage <= this.options.ticks_positions[i]) {
214
- minv = (i > 0) ? this.options.ticks[i-1] : 0;
215
- minp = (i > 0) ? this.options.ticks_positions[i-1] : 0;
211
+ minv = this.options.ticks[i - 1];
212
+ minp = this.options.ticks_positions[i - 1];
216
213
  maxv = this.options.ticks[i];
217
214
  maxp = this.options.ticks_positions[i];
218
215
 
219
216
  break;
220
217
  }
221
218
  }
222
- if (i > 0) {
223
- var partialPercentage = (percentage - minp) / (maxp - minp);
224
- rawValue = minv + partialPercentage * (maxv - minv);
225
- }
219
+ var partialPercentage = (percentage - minp) / (maxp - minp);
220
+ rawValue = minv + partialPercentage * (maxv - minv);
221
+ shouldAdjustWithBase = false;
226
222
  }
227
223
 
228
- var value = this.options.min + Math.round(rawValue / this.options.step) * this.options.step;
224
+ var adjustment = shouldAdjustWithBase ? this.options.min : 0;
225
+ var value = adjustment + Math.round(rawValue / this.options.step) * this.options.step;
229
226
  if (value < this.options.min) {
230
227
  return this.options.min;
231
228
  } else if (value > this.options.max) {
@@ -234,17 +231,20 @@
234
231
  return value;
235
232
  }
236
233
  },
237
- toPercentage: function(value) {
234
+ toPercentage: function toPercentage(value) {
238
235
  if (this.options.max === this.options.min) {
239
236
  return 0;
240
237
  }
241
238
 
242
239
  if (this.options.ticks_positions.length > 0) {
243
- var minv, maxv, minp, maxp = 0;
240
+ var minv,
241
+ maxv,
242
+ minp,
243
+ maxp = 0;
244
244
  for (var i = 0; i < this.options.ticks.length; i++) {
245
- if (value <= this.options.ticks[i]) {
246
- minv = (i > 0) ? this.options.ticks[i-1] : 0;
247
- minp = (i > 0) ? this.options.ticks_positions[i-1] : 0;
245
+ if (value <= this.options.ticks[i]) {
246
+ minv = i > 0 ? this.options.ticks[i - 1] : 0;
247
+ minp = i > 0 ? this.options.ticks_positions[i - 1] : 0;
248
248
  maxv = this.options.ticks[i];
249
249
  maxp = this.options.ticks_positions[i];
250
250
 
@@ -263,13 +263,13 @@
263
263
 
264
264
  logarithmic: {
265
265
  /* Based on http://stackoverflow.com/questions/846221/logarithmic-slider */
266
- toValue: function(percentage) {
267
- var min = (this.options.min === 0) ? 0 : Math.log(this.options.min);
266
+ toValue: function toValue(percentage) {
267
+ var min = this.options.min === 0 ? 0 : Math.log(this.options.min);
268
268
  var max = Math.log(this.options.max);
269
269
  var value = Math.exp(min + (max - min) * percentage / 100);
270
270
  value = this.options.min + Math.round((value - this.options.min) / this.options.step) * this.options.step;
271
271
  /* Rounding to the nearest step could exceed the min or
272
- * max, so clip to those values. */
272
+ * max, so clip to those values. */
273
273
  if (value < this.options.min) {
274
274
  return this.options.min;
275
275
  } else if (value > this.options.max) {
@@ -278,7 +278,7 @@
278
278
  return value;
279
279
  }
280
280
  },
281
- toPercentage: function(value) {
281
+ toPercentage: function toPercentage(value) {
282
282
  if (this.options.max === this.options.min) {
283
283
  return 0;
284
284
  } else {
@@ -291,67 +291,87 @@
291
291
  }
292
292
  };
293
293
 
294
-
295
294
  /*************************************************
296
-
297
295
  CONSTRUCTOR
298
-
299
296
  **************************************************/
300
- Slider = function(element, options) {
297
+ Slider = function (element, options) {
301
298
  createNewSlider.call(this, element, options);
302
299
  return this;
303
300
  };
304
301
 
305
302
  function createNewSlider(element, options) {
306
303
 
307
- if(typeof element === "string") {
304
+ /*
305
+ The internal state object is used to store data about the current 'state' of slider.
306
+ This includes values such as the `value`, `enabled`, etc...
307
+ */
308
+ this._state = {
309
+ value: null,
310
+ enabled: null,
311
+ offset: null,
312
+ size: null,
313
+ percentage: null,
314
+ inDrag: false,
315
+ over: false
316
+ };
317
+
318
+ if (typeof element === "string") {
308
319
  this.element = document.querySelector(element);
309
- } else if(element instanceof HTMLElement) {
320
+ } else if (element instanceof HTMLElement) {
310
321
  this.element = element;
311
322
  }
312
323
 
313
324
  /*************************************************
314
-
315
- Process Options
316
-
317
- **************************************************/
325
+ Process Options
326
+ **************************************************/
318
327
  options = options ? options : {};
319
328
  var optionTypes = Object.keys(this.defaultOptions);
320
329
 
321
- for(var i = 0; i < optionTypes.length; i++) {
330
+ for (var i = 0; i < optionTypes.length; i++) {
322
331
  var optName = optionTypes[i];
323
332
 
324
333
  // First check if an option was passed in via the constructor
325
334
  var val = options[optName];
326
335
  // If no data attrib, then check data atrributes
327
- val = (typeof val !== 'undefined') ? val : getDataAttrib(this.element, optName);
336
+ val = typeof val !== 'undefined' ? val : getDataAttrib(this.element, optName);
328
337
  // Finally, if nothing was specified, use the defaults
329
- val = (val !== null) ? val : this.defaultOptions[optName];
338
+ val = val !== null ? val : this.defaultOptions[optName];
330
339
 
331
340
  // Set all options on the instance of the Slider
332
- if(!this.options) {
341
+ if (!this.options) {
333
342
  this.options = {};
334
343
  }
335
344
  this.options[optName] = val;
336
345
  }
337
346
 
347
+ /*
348
+ Validate `tooltip_position` against 'orientation`
349
+ - if `tooltip_position` is incompatible with orientation, swith it to a default compatible with specified `orientation`
350
+ -- default for "vertical" -> "right"
351
+ -- default for "horizontal" -> "left"
352
+ */
353
+ if (this.options.orientation === "vertical" && (this.options.tooltip_position === "top" || this.options.tooltip_position === "bottom")) {
354
+
355
+ this.options.tooltip_position = "right";
356
+ } else if (this.options.orientation === "horizontal" && (this.options.tooltip_position === "left" || this.options.tooltip_position === "right")) {
357
+
358
+ this.options.tooltip_position = "top";
359
+ }
360
+
338
361
  function getDataAttrib(element, optName) {
339
362
  var dataName = "data-slider-" + optName.replace(/_/g, '-');
340
363
  var dataValString = element.getAttribute(dataName);
341
364
 
342
365
  try {
343
366
  return JSON.parse(dataValString);
344
- }
345
- catch(err) {
367
+ } catch (err) {
346
368
  return dataValString;
347
369
  }
348
370
  }
349
371
 
350
372
  /*************************************************
351
-
352
- Create Markup
353
-
354
- **************************************************/
373
+ Create Markup
374
+ **************************************************/
355
375
 
356
376
  var origWidth = this.element.style.width;
357
377
  var updateSlider = false;
@@ -383,14 +403,33 @@
383
403
 
384
404
  sliderMinHandle = document.createElement("div");
385
405
  sliderMinHandle.className = "slider-handle min-slider-handle";
406
+ sliderMinHandle.setAttribute('role', 'slider');
407
+ sliderMinHandle.setAttribute('aria-valuemin', this.options.min);
408
+ sliderMinHandle.setAttribute('aria-valuemax', this.options.max);
386
409
 
387
410
  sliderMaxHandle = document.createElement("div");
388
411
  sliderMaxHandle.className = "slider-handle max-slider-handle";
412
+ sliderMaxHandle.setAttribute('role', 'slider');
413
+ sliderMaxHandle.setAttribute('aria-valuemin', this.options.min);
414
+ sliderMaxHandle.setAttribute('aria-valuemax', this.options.max);
389
415
 
390
416
  sliderTrack.appendChild(sliderTrackLow);
391
417
  sliderTrack.appendChild(sliderTrackSelection);
392
418
  sliderTrack.appendChild(sliderTrackHigh);
393
419
 
420
+ /* Add aria-labelledby to handle's */
421
+ var isLabelledbyArray = Array.isArray(this.options.labelledby);
422
+ if (isLabelledbyArray && this.options.labelledby[0]) {
423
+ sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby[0]);
424
+ }
425
+ if (isLabelledbyArray && this.options.labelledby[1]) {
426
+ sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby[1]);
427
+ }
428
+ if (!isLabelledbyArray && this.options.labelledby) {
429
+ sliderMinHandle.setAttribute('aria-labelledby', this.options.labelledby);
430
+ sliderMaxHandle.setAttribute('aria-labelledby', this.options.labelledby);
431
+ }
432
+
394
433
  /* Create ticks */
395
434
  this.ticks = [];
396
435
  if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
@@ -415,16 +454,17 @@
415
454
 
416
455
  for (i = 0; i < this.options.ticks_labels.length; i++) {
417
456
  var label = document.createElement('div');
457
+ var noTickPositionsSpecified = this.options.ticks_positions.length === 0;
458
+ var tickLabelsIndex = this.options.reversed && noTickPositionsSpecified ? this.options.ticks_labels.length - (i + 1) : i;
418
459
  label.className = 'slider-tick-label';
419
- label.innerHTML = this.options.ticks_labels[i];
460
+ label.innerHTML = this.options.ticks_labels[tickLabelsIndex];
420
461
 
421
462
  this.tickLabels.push(label);
422
463
  this.tickLabelContainer.appendChild(label);
423
464
  }
424
465
  }
425
466
 
426
-
427
- var createAndAppendTooltipSubElements = function(tooltipElem) {
467
+ var createAndAppendTooltipSubElements = function createAndAppendTooltipSubElements(tooltipElem) {
428
468
  var arrow = document.createElement("div");
429
469
  arrow.className = "tooltip-arrow";
430
470
 
@@ -433,23 +473,24 @@
433
473
 
434
474
  tooltipElem.appendChild(arrow);
435
475
  tooltipElem.appendChild(inner);
436
-
437
476
  };
438
477
 
439
478
  /* Create tooltip elements */
440
479
  var sliderTooltip = document.createElement("div");
441
480
  sliderTooltip.className = "tooltip tooltip-main";
481
+ sliderTooltip.setAttribute('role', 'presentation');
442
482
  createAndAppendTooltipSubElements(sliderTooltip);
443
483
 
444
484
  var sliderTooltipMin = document.createElement("div");
445
485
  sliderTooltipMin.className = "tooltip tooltip-min";
486
+ sliderTooltipMin.setAttribute('role', 'presentation');
446
487
  createAndAppendTooltipSubElements(sliderTooltipMin);
447
488
 
448
489
  var sliderTooltipMax = document.createElement("div");
449
490
  sliderTooltipMax.className = "tooltip tooltip-max";
491
+ sliderTooltipMax.setAttribute('role', 'presentation');
450
492
  createAndAppendTooltipSubElements(sliderTooltipMax);
451
493
 
452
-
453
494
  /* Append components to sliderElem */
454
495
  this.sliderElem.appendChild(sliderTrack);
455
496
  this.sliderElem.appendChild(sliderTooltip);
@@ -467,20 +508,21 @@
467
508
  this.element.style.display = "none";
468
509
  }
469
510
  /* If JQuery exists, cache JQ references */
470
- if($) {
511
+ if ($) {
471
512
  this.$element = $(this.element);
472
513
  this.$sliderElem = $(this.sliderElem);
473
514
  }
474
515
 
475
516
  /*************************************************
476
-
477
- Setup
478
-
479
- **************************************************/
517
+ Setup
518
+ **************************************************/
480
519
  this.eventToCallbackMap = {};
481
520
  this.sliderElem.id = this.options.id;
482
521
 
483
- this.touchCapable = 'ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch);
522
+ this.touchCapable = 'ontouchstart' in window || window.DocumentTouch && document instanceof window.DocumentTouch;
523
+
524
+ this.touchX = 0;
525
+ this.touchY = 0;
484
526
 
485
527
  this.tooltip = this.sliderElem.querySelector('.tooltip-main');
486
528
  this.tooltipInner = this.tooltip.querySelector('.tooltip-inner');
@@ -489,7 +531,7 @@
489
531
  this.tooltipInner_min = this.tooltip_min.querySelector('.tooltip-inner');
490
532
 
491
533
  this.tooltip_max = this.sliderElem.querySelector('.tooltip-max');
492
- this.tooltipInner_max= this.tooltip_max.querySelector('.tooltip-inner');
534
+ this.tooltipInner_max = this.tooltip_max.querySelector('.tooltip-inner');
493
535
 
494
536
  if (SliderScale[this.options.scale]) {
495
537
  this.options.scale = SliderScale[this.options.scale];
@@ -504,20 +546,20 @@
504
546
  this._removeClass(this.tooltip_max, 'hide');
505
547
 
506
548
  // Undo existing inline styles for track
507
- ["left", "top", "width", "height"].forEach(function(prop) {
549
+ ["left", "top", "width", "height"].forEach(function (prop) {
508
550
  this._removeProperty(this.trackLow, prop);
509
551
  this._removeProperty(this.trackSelection, prop);
510
552
  this._removeProperty(this.trackHigh, prop);
511
553
  }, this);
512
554
 
513
555
  // Undo inline styles on handles
514
- [this.handle1, this.handle2].forEach(function(handle) {
556
+ [this.handle1, this.handle2].forEach(function (handle) {
515
557
  this._removeProperty(handle, 'left');
516
558
  this._removeProperty(handle, 'top');
517
559
  }, this);
518
560
 
519
561
  // Undo inline styles and classes on tooltips
520
- [this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function(tooltip) {
562
+ [this.tooltip, this.tooltip_min, this.tooltip_max].forEach(function (tooltip) {
521
563
  this._removeProperty(tooltip, 'left');
522
564
  this._removeProperty(tooltip, 'top');
523
565
  this._removeProperty(tooltip, 'margin-left');
@@ -528,51 +570,34 @@
528
570
  }, this);
529
571
  }
530
572
 
531
- if(this.options.orientation === 'vertical') {
532
- this._addClass(this.sliderElem,'slider-vertical');
533
-
573
+ if (this.options.orientation === 'vertical') {
574
+ this._addClass(this.sliderElem, 'slider-vertical');
534
575
  this.stylePos = 'top';
535
576
  this.mousePos = 'pageY';
536
577
  this.sizePos = 'offsetHeight';
537
-
538
- this._addClass(this.tooltip, 'right');
539
- this.tooltip.style.left = '100%';
540
-
541
- this._addClass(this.tooltip_min, 'right');
542
- this.tooltip_min.style.left = '100%';
543
-
544
- this._addClass(this.tooltip_max, 'right');
545
- this.tooltip_max.style.left = '100%';
546
578
  } else {
547
579
  this._addClass(this.sliderElem, 'slider-horizontal');
548
580
  this.sliderElem.style.width = origWidth;
549
-
550
581
  this.options.orientation = 'horizontal';
551
582
  this.stylePos = 'left';
552
583
  this.mousePos = 'pageX';
553
584
  this.sizePos = 'offsetWidth';
554
-
555
- this._addClass(this.tooltip, 'top');
556
- this.tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';
557
-
558
- this._addClass(this.tooltip_min, 'top');
559
- this.tooltip_min.style.top = -this.tooltip_min.outerHeight - 14 + 'px';
560
-
561
- this._addClass(this.tooltip_max, 'top');
562
- this.tooltip_max.style.top = -this.tooltip_max.outerHeight - 14 + 'px';
563
585
  }
564
-
586
+ this._setTooltipPosition();
565
587
  /* In case ticks are specified, overwrite the min and max bounds */
566
588
  if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
567
- this.options.max = Math.max.apply(Math, this.options.ticks);
568
- this.options.min = Math.min.apply(Math, this.options.ticks);
589
+ this.options.max = Math.max.apply(Math, this.options.ticks);
590
+ this.options.min = Math.min.apply(Math, this.options.ticks);
569
591
  }
570
592
 
571
593
  if (Array.isArray(this.options.value)) {
572
594
  this.options.range = true;
595
+ this._state.value = this.options.value;
573
596
  } else if (this.options.range) {
574
597
  // User wants a range, but value is not an array
575
- this.options.value = [this.options.value, this.options.max];
598
+ this._state.value = [this.options.value, this.options.max];
599
+ } else {
600
+ this._state.value = this.options.value;
576
601
  }
577
602
 
578
603
  this.trackLow = sliderTrackLow || this.trackLow;
@@ -609,15 +634,13 @@
609
634
  }
610
635
  }
611
636
 
612
- this.offset = this._offset(this.sliderElem);
613
- this.size = this.sliderElem[this.sizePos];
614
- this.setValue(this.options.value);
637
+ this._state.offset = this._offset(this.sliderElem);
638
+ this._state.size = this.sliderElem[this.sizePos];
639
+ this.setValue(this._state.value);
615
640
 
616
641
  /******************************************
617
-
618
- Bind Event Listeners
619
-
620
- ******************************************/
642
+ Bind Event Listeners
643
+ ******************************************/
621
644
 
622
645
  // Bind keyboard handlers
623
646
  this.handle1Keydown = this._keydown.bind(this, 0);
@@ -627,19 +650,26 @@
627
650
  this.handle2.addEventListener("keydown", this.handle2Keydown, false);
628
651
 
629
652
  this.mousedown = this._mousedown.bind(this);
653
+ this.touchstart = this._touchstart.bind(this);
654
+ this.touchmove = this._touchmove.bind(this);
655
+
630
656
  if (this.touchCapable) {
631
657
  // Bind touch handlers
632
- this.sliderElem.addEventListener("touchstart", this.mousedown, false);
658
+ this.sliderElem.addEventListener("touchstart", this.touchstart, false);
659
+ this.sliderElem.addEventListener("touchmove", this.touchmove, false);
633
660
  }
634
661
  this.sliderElem.addEventListener("mousedown", this.mousedown, false);
635
662
 
663
+ // Bind window handlers
664
+ this.resize = this._resize.bind(this);
665
+ window.addEventListener("resize", this.resize, false);
636
666
 
637
667
  // Bind tooltip-related handlers
638
- if(this.options.tooltip === 'hide') {
668
+ if (this.options.tooltip === 'hide') {
639
669
  this._addClass(this.tooltip, 'hide');
640
670
  this._addClass(this.tooltip_min, 'hide');
641
671
  this._addClass(this.tooltip_max, 'hide');
642
- } else if(this.options.tooltip === 'always') {
672
+ } else if (this.options.tooltip === 'always') {
643
673
  this._showTooltip();
644
674
  this._alwaysShowTooltip = true;
645
675
  } else {
@@ -656,31 +686,26 @@
656
686
  this.handle2.addEventListener("blur", this.hideTooltip, false);
657
687
  }
658
688
 
659
- if(this.options.enabled) {
689
+ if (this.options.enabled) {
660
690
  this.enable();
661
691
  } else {
662
692
  this.disable();
663
693
  }
664
694
  }
665
695
 
666
-
667
-
668
696
  /*************************************************
669
-
670
697
  INSTANCE PROPERTIES/METHODS
671
-
672
698
  - Any methods bound to the prototype are considered
673
- part of the plugin's `public` interface
674
-
699
+ part of the plugin's `public` interface
675
700
  **************************************************/
676
701
  Slider.prototype = {
677
- _init: function() {}, // NOTE: Must exist to support bridget
702
+ _init: function _init() {}, // NOTE: Must exist to support bridget
678
703
 
679
704
  constructor: Slider,
680
705
 
681
706
  defaultOptions: {
682
707
  id: "",
683
- min: 0,
708
+ min: 0,
684
709
  max: 10,
685
710
  step: 1,
686
711
  precision: 0,
@@ -693,7 +718,7 @@
693
718
  handle: 'round',
694
719
  reversed: false,
695
720
  enabled: true,
696
- formatter: function(val) {
721
+ formatter: function formatter(val) {
697
722
  if (Array.isArray(val)) {
698
723
  return val[0] + " : " + val[1];
699
724
  } else {
@@ -706,73 +731,72 @@
706
731
  ticks_labels: [],
707
732
  ticks_snap_bounds: 0,
708
733
  scale: 'linear',
709
- focus: false
734
+ focus: false,
735
+ tooltip_position: null,
736
+ labelledby: null
710
737
  },
711
738
 
712
- over: false,
713
-
714
- inDrag: false,
739
+ getElement: function getElement() {
740
+ return this.sliderElem;
741
+ },
715
742
 
716
- getValue: function() {
743
+ getValue: function getValue() {
717
744
  if (this.options.range) {
718
- return this.options.value;
745
+ return this._state.value;
746
+ } else {
747
+ return this._state.value[0];
719
748
  }
720
- return this.options.value[0];
721
749
  },
722
750
 
723
- setValue: function(val, triggerSlideEvent, triggerChangeEvent) {
751
+ setValue: function setValue(val, triggerSlideEvent, triggerChangeEvent) {
724
752
  if (!val) {
725
753
  val = 0;
726
754
  }
727
755
  var oldValue = this.getValue();
728
- this.options.value = this._validateInputValue(val);
756
+ this._state.value = this._validateInputValue(val);
729
757
  var applyPrecision = this._applyPrecision.bind(this);
730
758
 
731
759
  if (this.options.range) {
732
- this.options.value[0] = applyPrecision(this.options.value[0]);
733
- this.options.value[1] = applyPrecision(this.options.value[1]);
760
+ this._state.value[0] = applyPrecision(this._state.value[0]);
761
+ this._state.value[1] = applyPrecision(this._state.value[1]);
734
762
 
735
- this.options.value[0] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[0]));
736
- this.options.value[1] = Math.max(this.options.min, Math.min(this.options.max, this.options.value[1]));
763
+ this._state.value[0] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[0]));
764
+ this._state.value[1] = Math.max(this.options.min, Math.min(this.options.max, this._state.value[1]));
737
765
  } else {
738
- this.options.value = applyPrecision(this.options.value);
739
- this.options.value = [ Math.max(this.options.min, Math.min(this.options.max, this.options.value))];
766
+ this._state.value = applyPrecision(this._state.value);
767
+ this._state.value = [Math.max(this.options.min, Math.min(this.options.max, this._state.value))];
740
768
  this._addClass(this.handle2, 'hide');
741
769
  if (this.options.selection === 'after') {
742
- this.options.value[1] = this.options.max;
770
+ this._state.value[1] = this.options.max;
743
771
  } else {
744
- this.options.value[1] = this.options.min;
772
+ this._state.value[1] = this.options.min;
745
773
  }
746
774
  }
747
775
 
748
776
  if (this.options.max > this.options.min) {
749
- this.percentage = [
750
- this._toPercentage(this.options.value[0]),
751
- this._toPercentage(this.options.value[1]),
752
- this.options.step * 100 / (this.options.max - this.options.min)
753
- ];
777
+ this._state.percentage = [this._toPercentage(this._state.value[0]), this._toPercentage(this._state.value[1]), this.options.step * 100 / (this.options.max - this.options.min)];
754
778
  } else {
755
- this.percentage = [0, 0, 100];
779
+ this._state.percentage = [0, 0, 100];
756
780
  }
757
781
 
758
782
  this._layout();
759
- var newValue = this.options.range ? this.options.value : this.options.value[0];
783
+ var newValue = this.options.range ? this._state.value : this._state.value[0];
760
784
 
761
- if(triggerSlideEvent === true) {
785
+ this._setDataVal(newValue);
786
+ if (triggerSlideEvent === true) {
762
787
  this._trigger('slide', newValue);
763
788
  }
764
- if( (oldValue !== newValue) && (triggerChangeEvent === true) ) {
789
+ if (oldValue !== newValue && triggerChangeEvent === true) {
765
790
  this._trigger('change', {
766
791
  oldValue: oldValue,
767
792
  newValue: newValue
768
793
  });
769
794
  }
770
- this._setDataVal(newValue);
771
795
 
772
796
  return this;
773
797
  },
774
798
 
775
- destroy: function(){
799
+ destroy: function destroy() {
776
800
  // Remove event handlers on slider elements
777
801
  this._removeSliderEventHandlers();
778
802
 
@@ -788,14 +812,14 @@
788
812
  this.element.removeAttribute("data");
789
813
 
790
814
  // Remove JQuery handlers/data
791
- if($) {
815
+ if ($) {
792
816
  this._unbindJQueryEventHandlers();
793
817
  this.$element.removeData('slider');
794
818
  }
795
819
  },
796
820
 
797
- disable: function() {
798
- this.options.enabled = false;
821
+ disable: function disable() {
822
+ this._state.enabled = false;
799
823
  this.handle1.removeAttribute("tabindex");
800
824
  this.handle2.removeAttribute("tabindex");
801
825
  this._addClass(this.sliderElem, 'slider-disabled');
@@ -804,8 +828,8 @@
804
828
  return this;
805
829
  },
806
830
 
807
- enable: function() {
808
- this.options.enabled = true;
831
+ enable: function enable() {
832
+ this._state.enabled = true;
809
833
  this.handle1.setAttribute("tabindex", 0);
810
834
  this.handle2.setAttribute("tabindex", 0);
811
835
  this._removeClass(this.sliderElem, 'slider-disabled');
@@ -814,8 +838,8 @@
814
838
  return this;
815
839
  },
816
840
 
817
- toggle: function() {
818
- if(this.options.enabled) {
841
+ toggle: function toggle() {
842
+ if (this._state.enabled) {
819
843
  this.disable();
820
844
  } else {
821
845
  this.enable();
@@ -823,129 +847,164 @@
823
847
  return this;
824
848
  },
825
849
 
826
- isEnabled: function() {
827
- return this.options.enabled;
850
+ isEnabled: function isEnabled() {
851
+ return this._state.enabled;
828
852
  },
829
853
 
830
- on: function(evt, callback) {
854
+ on: function on(evt, callback) {
831
855
  this._bindNonQueryEventHandler(evt, callback);
832
856
  return this;
833
857
  },
834
858
 
835
- getAttribute: function(attribute) {
836
- if(attribute) {
859
+ off: function off(evt, callback) {
860
+ if ($) {
861
+ this.$element.off(evt, callback);
862
+ this.$sliderElem.off(evt, callback);
863
+ } else {
864
+ this._unbindNonQueryEventHandler(evt, callback);
865
+ }
866
+ },
867
+
868
+ getAttribute: function getAttribute(attribute) {
869
+ if (attribute) {
837
870
  return this.options[attribute];
838
871
  } else {
839
872
  return this.options;
840
873
  }
841
874
  },
842
875
 
843
- setAttribute: function(attribute, value) {
876
+ setAttribute: function setAttribute(attribute, value) {
844
877
  this.options[attribute] = value;
845
878
  return this;
846
879
  },
847
880
 
848
- refresh: function() {
881
+ refresh: function refresh() {
849
882
  this._removeSliderEventHandlers();
850
883
  createNewSlider.call(this, this.element, this.options);
851
- if($) {
884
+ if ($) {
852
885
  // Bind new instance of slider to the element
853
886
  $.data(this.element, 'slider', this);
854
887
  }
855
888
  return this;
856
889
  },
857
890
 
858
- relayout: function() {
891
+ relayout: function relayout() {
892
+ this._resize();
859
893
  this._layout();
860
894
  return this;
861
895
  },
862
896
 
863
897
  /******************************+
864
-
865
- HELPERS
866
-
867
- - Any method that is not part of the public interface.
868
- - Place it underneath this comment block and write its signature like so:
869
-
870
- _fnName : function() {...}
871
-
872
- ********************************/
873
- _removeSliderEventHandlers: function() {
874
- // Remove event listeners from handle1
898
+ HELPERS
899
+ - Any method that is not part of the public interface.
900
+ - Place it underneath this comment block and write its signature like so:
901
+ _fnName : function() {...}
902
+ ********************************/
903
+ _removeSliderEventHandlers: function _removeSliderEventHandlers() {
904
+ // Remove keydown event listeners
875
905
  this.handle1.removeEventListener("keydown", this.handle1Keydown, false);
876
- this.handle1.removeEventListener("focus", this.showTooltip, false);
877
- this.handle1.removeEventListener("blur", this.hideTooltip, false);
878
-
879
- // Remove event listeners from handle2
880
906
  this.handle2.removeEventListener("keydown", this.handle2Keydown, false);
881
- this.handle2.removeEventListener("focus", this.handle2Keydown, false);
882
- this.handle2.removeEventListener("blur", this.handle2Keydown, false);
907
+
908
+ if (this.showTooltip) {
909
+ this.handle1.removeEventListener("focus", this.showTooltip, false);
910
+ this.handle2.removeEventListener("focus", this.showTooltip, false);
911
+ }
912
+ if (this.hideTooltip) {
913
+ this.handle1.removeEventListener("blur", this.hideTooltip, false);
914
+ this.handle2.removeEventListener("blur", this.hideTooltip, false);
915
+ }
883
916
 
884
917
  // Remove event listeners from sliderElem
885
- this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false);
886
- this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false);
887
- this.sliderElem.removeEventListener("touchstart", this.mousedown, false);
918
+ if (this.showTooltip) {
919
+ this.sliderElem.removeEventListener("mouseenter", this.showTooltip, false);
920
+ }
921
+ if (this.hideTooltip) {
922
+ this.sliderElem.removeEventListener("mouseleave", this.hideTooltip, false);
923
+ }
924
+ this.sliderElem.removeEventListener("touchstart", this.touchstart, false);
925
+ this.sliderElem.removeEventListener("touchmove", this.touchmove, false);
888
926
  this.sliderElem.removeEventListener("mousedown", this.mousedown, false);
927
+
928
+ // Remove window event listener
929
+ window.removeEventListener("resize", this.resize, false);
889
930
  },
890
- _bindNonQueryEventHandler: function(evt, callback) {
891
- if(this.eventToCallbackMap[evt]===undefined) {
931
+ _bindNonQueryEventHandler: function _bindNonQueryEventHandler(evt, callback) {
932
+ if (this.eventToCallbackMap[evt] === undefined) {
892
933
  this.eventToCallbackMap[evt] = [];
893
934
  }
894
935
  this.eventToCallbackMap[evt].push(callback);
895
936
  },
896
- _cleanUpEventCallbacksMap: function() {
937
+ _unbindNonQueryEventHandler: function _unbindNonQueryEventHandler(evt, callback) {
938
+ var callbacks = this.eventToCallbackMap[evt];
939
+ if (callbacks !== undefined) {
940
+ for (var i = 0; i < callbacks.length; i++) {
941
+ if (callbacks[i] === callback) {
942
+ callbacks.splice(i, 1);
943
+ break;
944
+ }
945
+ }
946
+ }
947
+ },
948
+ _cleanUpEventCallbacksMap: function _cleanUpEventCallbacksMap() {
897
949
  var eventNames = Object.keys(this.eventToCallbackMap);
898
- for(var i = 0; i < eventNames.length; i++) {
950
+ for (var i = 0; i < eventNames.length; i++) {
899
951
  var eventName = eventNames[i];
900
952
  this.eventToCallbackMap[eventName] = null;
901
953
  }
902
954
  },
903
- _showTooltip: function() {
904
- if (this.options.tooltip_split === false ){
905
- this._addClass(this.tooltip, 'in');
906
- } else {
907
- this._addClass(this.tooltip_min, 'in');
908
- this._addClass(this.tooltip_max, 'in');
909
- }
910
- this.over = true;
955
+ _showTooltip: function _showTooltip() {
956
+ if (this.options.tooltip_split === false) {
957
+ this._addClass(this.tooltip, 'in');
958
+ this.tooltip_min.style.display = 'none';
959
+ this.tooltip_max.style.display = 'none';
960
+ } else {
961
+ this._addClass(this.tooltip_min, 'in');
962
+ this._addClass(this.tooltip_max, 'in');
963
+ this.tooltip.style.display = 'none';
964
+ }
965
+ this._state.over = true;
911
966
  },
912
- _hideTooltip: function() {
913
- if (this.inDrag === false && this.alwaysShowTooltip !== true) {
967
+ _hideTooltip: function _hideTooltip() {
968
+ if (this._state.inDrag === false && this.alwaysShowTooltip !== true) {
914
969
  this._removeClass(this.tooltip, 'in');
915
970
  this._removeClass(this.tooltip_min, 'in');
916
971
  this._removeClass(this.tooltip_max, 'in');
917
972
  }
918
- this.over = false;
973
+ this._state.over = false;
919
974
  },
920
- _layout: function() {
975
+ _layout: function _layout() {
921
976
  var positionPercentages;
922
977
 
923
- if(this.options.reversed) {
924
- positionPercentages = [ 100 - this.percentage[0], this.percentage[1] ];
978
+ if (this.options.reversed) {
979
+ positionPercentages = [100 - this._state.percentage[0], this.options.range ? 100 - this._state.percentage[1] : this._state.percentage[1]];
925
980
  } else {
926
- positionPercentages = [ this.percentage[0], this.percentage[1] ];
981
+ positionPercentages = [this._state.percentage[0], this._state.percentage[1]];
927
982
  }
928
983
 
929
- this.handle1.style[this.stylePos] = positionPercentages[0]+'%';
930
- this.handle2.style[this.stylePos] = positionPercentages[1]+'%';
984
+ this.handle1.style[this.stylePos] = positionPercentages[0] + '%';
985
+ this.handle1.setAttribute('aria-valuenow', this._state.value[0]);
986
+
987
+ this.handle2.style[this.stylePos] = positionPercentages[1] + '%';
988
+ this.handle2.setAttribute('aria-valuenow', this._state.value[1]);
931
989
 
932
990
  /* Position ticks and labels */
933
991
  if (Array.isArray(this.options.ticks) && this.options.ticks.length > 0) {
934
- var maxTickValue = Math.max.apply(Math, this.options.ticks);
935
- var minTickValue = Math.min.apply(Math, this.options.ticks);
936
992
 
937
993
  var styleSize = this.options.orientation === 'vertical' ? 'height' : 'width';
938
994
  var styleMargin = this.options.orientation === 'vertical' ? 'marginTop' : 'marginLeft';
939
- var labelSize = this.size / (this.options.ticks.length - 1);
995
+ var labelSize = this._state.size / (this.options.ticks.length - 1);
940
996
 
941
997
  if (this.tickLabelContainer) {
942
998
  var extraMargin = 0;
943
999
  if (this.options.ticks_positions.length === 0) {
944
- this.tickLabelContainer.style[styleMargin] = -labelSize/2 + 'px';
1000
+ if (this.options.orientation !== 'vertical') {
1001
+ this.tickLabelContainer.style[styleMargin] = -labelSize / 2 + 'px';
1002
+ }
1003
+
945
1004
  extraMargin = this.tickLabelContainer.offsetHeight;
946
1005
  } else {
947
1006
  /* Chidren are position absolute, calculate height by finding the max offsetHeight of a child */
948
- for (i = 0 ; i < this.tickLabelContainer.childNodes.length; i++) {
1007
+ for (i = 0; i < this.tickLabelContainer.childNodes.length; i++) {
949
1008
  if (this.tickLabelContainer.childNodes[i].offsetHeight > extraMargin) {
950
1009
  extraMargin = this.tickLabelContainer.childNodes[i].offsetHeight;
951
1010
  }
@@ -957,15 +1016,18 @@
957
1016
  }
958
1017
  for (var i = 0; i < this.options.ticks.length; i++) {
959
1018
 
960
- var percentage = this.options.ticks_positions[i] ||
961
- 100 * (this.options.ticks[i] - minTickValue) / (maxTickValue - minTickValue);
1019
+ var percentage = this.options.ticks_positions[i] || this._toPercentage(this.options.ticks[i]);
1020
+
1021
+ if (this.options.reversed) {
1022
+ percentage = 100 - percentage;
1023
+ }
962
1024
 
963
1025
  this.ticks[i].style[this.stylePos] = percentage + '%';
964
1026
 
965
1027
  /* Set class labels to denote whether ticks are in the selection */
966
1028
  this._removeClass(this.ticks[i], 'in-selection');
967
1029
  if (!this.options.range) {
968
- if (this.options.selection === 'after' && percentage >= positionPercentages[0]){
1030
+ if (this.options.selection === 'after' && percentage >= positionPercentages[0]) {
969
1031
  this._addClass(this.ticks[i], 'in-selection');
970
1032
  } else if (this.options.selection === 'before' && percentage <= positionPercentages[0]) {
971
1033
  this._addClass(this.ticks[i], 'in-selection');
@@ -977,54 +1039,24 @@
977
1039
  if (this.tickLabels[i]) {
978
1040
  this.tickLabels[i].style[styleSize] = labelSize + 'px';
979
1041
 
980
- if (this.options.ticks_positions[i] !== undefined) {
1042
+ if (this.options.orientation !== 'vertical' && this.options.ticks_positions[i] !== undefined) {
981
1043
  this.tickLabels[i].style.position = 'absolute';
982
- this.tickLabels[i].style[this.stylePos] = this.options.ticks_positions[i] + '%';
983
- this.tickLabels[i].style[styleMargin] = -labelSize/2 + 'px';
1044
+ this.tickLabels[i].style[this.stylePos] = percentage + '%';
1045
+ this.tickLabels[i].style[styleMargin] = -labelSize / 2 + 'px';
1046
+ } else if (this.options.orientation === 'vertical') {
1047
+ this.tickLabels[i].style['marginLeft'] = this.sliderElem.offsetWidth + 'px';
1048
+ this.tickLabelContainer.style['marginTop'] = this.sliderElem.offsetWidth / 2 * -1 + 'px';
984
1049
  }
985
1050
  }
986
1051
  }
987
1052
  }
988
1053
 
989
- if (this.options.orientation === 'vertical') {
990
- this.trackLow.style.top = '0';
991
- this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) +'%';
992
-
993
- this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) +'%';
994
- this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%';
995
-
996
- this.trackHigh.style.bottom = '0';
997
- this.trackHigh.style.height = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%';
998
- } else {
999
- this.trackLow.style.left = '0';
1000
- this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) +'%';
1001
-
1002
- this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) +'%';
1003
- this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) +'%';
1004
-
1005
- this.trackHigh.style.right = '0';
1006
- this.trackHigh.style.width = (100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1])) +'%';
1007
-
1008
- var offset_min = this.tooltip_min.getBoundingClientRect();
1009
- var offset_max = this.tooltip_max.getBoundingClientRect();
1010
-
1011
- if (offset_min.right > offset_max.left) {
1012
- this._removeClass(this.tooltip_max, 'top');
1013
- this._addClass(this.tooltip_max, 'bottom');
1014
- this.tooltip_max.style.top = 18 + 'px';
1015
- } else {
1016
- this._removeClass(this.tooltip_max, 'bottom');
1017
- this._addClass(this.tooltip_max, 'top');
1018
- this.tooltip_max.style.top = this.tooltip_min.style.top;
1019
- }
1020
- }
1021
-
1022
1054
  var formattedTooltipVal;
1023
1055
 
1024
1056
  if (this.options.range) {
1025
- formattedTooltipVal = this.options.formatter(this.options.value);
1057
+ formattedTooltipVal = this.options.formatter(this._state.value);
1026
1058
  this._setText(this.tooltipInner, formattedTooltipVal);
1027
- this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0])/2 + '%';
1059
+ this.tooltip.style[this.stylePos] = (positionPercentages[1] + positionPercentages[0]) / 2 + '%';
1028
1060
 
1029
1061
  if (this.options.orientation === 'vertical') {
1030
1062
  this._css(this.tooltip, 'margin-top', -this.tooltip.offsetHeight / 2 + 'px');
@@ -1038,10 +1070,10 @@
1038
1070
  this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');
1039
1071
  }
1040
1072
 
1041
- var innerTooltipMinText = this.options.formatter(this.options.value[0]);
1073
+ var innerTooltipMinText = this.options.formatter(this._state.value[0]);
1042
1074
  this._setText(this.tooltipInner_min, innerTooltipMinText);
1043
1075
 
1044
- var innerTooltipMaxText = this.options.formatter(this.options.value[1]);
1076
+ var innerTooltipMaxText = this.options.formatter(this._state.value[1]);
1045
1077
  this._setText(this.tooltipInner_max, innerTooltipMaxText);
1046
1078
 
1047
1079
  this.tooltip_min.style[this.stylePos] = positionPercentages[0] + '%';
@@ -1060,7 +1092,7 @@
1060
1092
  this._css(this.tooltip_max, 'margin-left', -this.tooltip_max.offsetWidth / 2 + 'px');
1061
1093
  }
1062
1094
  } else {
1063
- formattedTooltipVal = this.options.formatter(this.options.value[0]);
1095
+ formattedTooltipVal = this.options.formatter(this._state.value[0]);
1064
1096
  this._setText(this.tooltipInner, formattedTooltipVal);
1065
1097
 
1066
1098
  this.tooltip.style[this.stylePos] = positionPercentages[0] + '%';
@@ -1070,33 +1102,86 @@
1070
1102
  this._css(this.tooltip, 'margin-left', -this.tooltip.offsetWidth / 2 + 'px');
1071
1103
  }
1072
1104
  }
1105
+
1106
+ if (this.options.orientation === 'vertical') {
1107
+ this.trackLow.style.top = '0';
1108
+ this.trackLow.style.height = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1109
+
1110
+ this.trackSelection.style.top = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1111
+ this.trackSelection.style.height = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1112
+
1113
+ this.trackHigh.style.bottom = '0';
1114
+ this.trackHigh.style.height = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1115
+ } else {
1116
+ this.trackLow.style.left = '0';
1117
+ this.trackLow.style.width = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1118
+
1119
+ this.trackSelection.style.left = Math.min(positionPercentages[0], positionPercentages[1]) + '%';
1120
+ this.trackSelection.style.width = Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1121
+
1122
+ this.trackHigh.style.right = '0';
1123
+ this.trackHigh.style.width = 100 - Math.min(positionPercentages[0], positionPercentages[1]) - Math.abs(positionPercentages[0] - positionPercentages[1]) + '%';
1124
+
1125
+ var offset_min = this.tooltip_min.getBoundingClientRect();
1126
+ var offset_max = this.tooltip_max.getBoundingClientRect();
1127
+
1128
+ if (this.options.tooltip_position === 'bottom') {
1129
+ if (offset_min.right > offset_max.left) {
1130
+ this._removeClass(this.tooltip_max, 'bottom');
1131
+ this._addClass(this.tooltip_max, 'top');
1132
+ this.tooltip_max.style.top = '';
1133
+ this.tooltip_max.style.bottom = 22 + 'px';
1134
+ } else {
1135
+ this._removeClass(this.tooltip_max, 'top');
1136
+ this._addClass(this.tooltip_max, 'bottom');
1137
+ this.tooltip_max.style.top = this.tooltip_min.style.top;
1138
+ this.tooltip_max.style.bottom = '';
1139
+ }
1140
+ } else {
1141
+ if (offset_min.right > offset_max.left) {
1142
+ this._removeClass(this.tooltip_max, 'top');
1143
+ this._addClass(this.tooltip_max, 'bottom');
1144
+ this.tooltip_max.style.top = 18 + 'px';
1145
+ } else {
1146
+ this._removeClass(this.tooltip_max, 'bottom');
1147
+ this._addClass(this.tooltip_max, 'top');
1148
+ this.tooltip_max.style.top = this.tooltip_min.style.top;
1149
+ }
1150
+ }
1151
+ }
1152
+ },
1153
+ _resize: function _resize(ev) {
1154
+ /*jshint unused:false*/
1155
+ this._state.offset = this._offset(this.sliderElem);
1156
+ this._state.size = this.sliderElem[this.sizePos];
1157
+ this._layout();
1073
1158
  },
1074
- _removeProperty: function(element, prop) {
1159
+ _removeProperty: function _removeProperty(element, prop) {
1075
1160
  if (element.style.removeProperty) {
1076
- element.style.removeProperty(prop);
1161
+ element.style.removeProperty(prop);
1077
1162
  } else {
1078
- element.style.removeAttribute(prop);
1163
+ element.style.removeAttribute(prop);
1079
1164
  }
1080
1165
  },
1081
- _mousedown: function(ev) {
1082
- if(!this.options.enabled) {
1166
+ _mousedown: function _mousedown(ev) {
1167
+ if (!this._state.enabled) {
1083
1168
  return false;
1084
1169
  }
1085
1170
 
1086
- this.offset = this._offset(this.sliderElem);
1087
- this.size = this.sliderElem[this.sizePos];
1171
+ this._state.offset = this._offset(this.sliderElem);
1172
+ this._state.size = this.sliderElem[this.sizePos];
1088
1173
 
1089
1174
  var percentage = this._getPercentage(ev);
1090
1175
 
1091
1176
  if (this.options.range) {
1092
- var diff1 = Math.abs(this.percentage[0] - percentage);
1093
- var diff2 = Math.abs(this.percentage[1] - percentage);
1094
- this.dragged = (diff1 < diff2) ? 0 : 1;
1177
+ var diff1 = Math.abs(this._state.percentage[0] - percentage);
1178
+ var diff2 = Math.abs(this._state.percentage[1] - percentage);
1179
+ this._state.dragged = diff1 < diff2 ? 0 : 1;
1095
1180
  } else {
1096
- this.dragged = 0;
1181
+ this._state.dragged = 0;
1097
1182
  }
1098
1183
 
1099
- this.percentage[this.dragged] = this.options.reversed ? 100 - percentage : percentage;
1184
+ this._state.percentage[this._state.dragged] = percentage;
1100
1185
  this._layout();
1101
1186
 
1102
1187
  if (this.touchCapable) {
@@ -1104,10 +1189,10 @@
1104
1189
  document.removeEventListener("touchend", this.mouseup, false);
1105
1190
  }
1106
1191
 
1107
- if(this.mousemove){
1192
+ if (this.mousemove) {
1108
1193
  document.removeEventListener("mousemove", this.mousemove, false);
1109
1194
  }
1110
- if(this.mouseup){
1195
+ if (this.mouseup) {
1111
1196
  document.removeEventListener("mouseup", this.mouseup, false);
1112
1197
  }
1113
1198
 
@@ -1123,7 +1208,7 @@
1123
1208
  document.addEventListener("mousemove", this.mousemove, false);
1124
1209
  document.addEventListener("mouseup", this.mouseup, false);
1125
1210
 
1126
- this.inDrag = true;
1211
+ this._state.inDrag = true;
1127
1212
  var newValue = this._calculateValue();
1128
1213
 
1129
1214
  this._trigger('slideStart', newValue);
@@ -1134,32 +1219,44 @@
1134
1219
  this._pauseEvent(ev);
1135
1220
 
1136
1221
  if (this.options.focus) {
1137
- this._triggerFocusOnHandle(this.dragged);
1222
+ this._triggerFocusOnHandle(this._state.dragged);
1138
1223
  }
1139
1224
 
1140
1225
  return true;
1141
1226
  },
1142
- _triggerFocusOnHandle: function(handleIdx) {
1143
- if(handleIdx === 0) {
1227
+ _touchstart: function _touchstart(ev) {
1228
+ if (ev.changedTouches === undefined) {
1229
+ this._mousedown(ev);
1230
+ return;
1231
+ }
1232
+
1233
+ var touch = ev.changedTouches[0];
1234
+ this.touchX = touch.pageX;
1235
+ this.touchY = touch.pageY;
1236
+ },
1237
+ _triggerFocusOnHandle: function _triggerFocusOnHandle(handleIdx) {
1238
+ if (handleIdx === 0) {
1144
1239
  this.handle1.focus();
1145
1240
  }
1146
- if(handleIdx === 1) {
1241
+ if (handleIdx === 1) {
1147
1242
  this.handle2.focus();
1148
1243
  }
1149
1244
  },
1150
- _keydown: function(handleIdx, ev) {
1151
- if(!this.options.enabled) {
1245
+ _keydown: function _keydown(handleIdx, ev) {
1246
+ if (!this._state.enabled) {
1152
1247
  return false;
1153
1248
  }
1154
1249
 
1155
1250
  var dir;
1156
1251
  switch (ev.keyCode) {
1157
1252
  case 37: // left
1158
- case 40: // down
1253
+ case 40:
1254
+ // down
1159
1255
  dir = -1;
1160
1256
  break;
1161
1257
  case 39: // right
1162
- case 38: // up
1258
+ case 38:
1259
+ // up
1163
1260
  dir = 1;
1164
1261
  break;
1165
1262
  }
@@ -1169,50 +1266,49 @@
1169
1266
 
1170
1267
  // use natural arrow keys instead of from min to max
1171
1268
  if (this.options.natural_arrow_keys) {
1172
- var ifVerticalAndNotReversed = (this.options.orientation === 'vertical' && !this.options.reversed);
1173
- var ifHorizontalAndReversed = (this.options.orientation === 'horizontal' && this.options.reversed);
1269
+ var ifVerticalAndNotReversed = this.options.orientation === 'vertical' && !this.options.reversed;
1270
+ var ifHorizontalAndReversed = this.options.orientation === 'horizontal' && this.options.reversed;
1174
1271
 
1175
1272
  if (ifVerticalAndNotReversed || ifHorizontalAndReversed) {
1176
1273
  dir = -dir;
1177
1274
  }
1178
1275
  }
1179
1276
 
1180
- var val = this.options.value[handleIdx] + dir * this.options.step;
1277
+ var val = this._state.value[handleIdx] + dir * this.options.step;
1181
1278
  if (this.options.range) {
1182
- val = [ (!handleIdx) ? val : this.options.value[0],
1183
- ( handleIdx) ? val : this.options.value[1]];
1279
+ val = [!handleIdx ? val : this._state.value[0], handleIdx ? val : this._state.value[1]];
1184
1280
  }
1185
1281
 
1186
1282
  this._trigger('slideStart', val);
1187
1283
  this._setDataVal(val);
1188
1284
  this.setValue(val, true, true);
1189
1285
 
1190
- this._trigger('slideStop', val);
1191
1286
  this._setDataVal(val);
1287
+ this._trigger('slideStop', val);
1192
1288
  this._layout();
1193
1289
 
1194
1290
  this._pauseEvent(ev);
1195
1291
 
1196
1292
  return false;
1197
1293
  },
1198
- _pauseEvent: function(ev) {
1199
- if(ev.stopPropagation) {
1294
+ _pauseEvent: function _pauseEvent(ev) {
1295
+ if (ev.stopPropagation) {
1200
1296
  ev.stopPropagation();
1201
1297
  }
1202
- if(ev.preventDefault) {
1203
- ev.preventDefault();
1204
- }
1205
- ev.cancelBubble=true;
1206
- ev.returnValue=false;
1298
+ if (ev.preventDefault) {
1299
+ ev.preventDefault();
1300
+ }
1301
+ ev.cancelBubble = true;
1302
+ ev.returnValue = false;
1207
1303
  },
1208
- _mousemove: function(ev) {
1209
- if(!this.options.enabled) {
1304
+ _mousemove: function _mousemove(ev) {
1305
+ if (!this._state.enabled) {
1210
1306
  return false;
1211
1307
  }
1212
1308
 
1213
1309
  var percentage = this._getPercentage(ev);
1214
1310
  this._adjustPercentageForRangeSliders(percentage);
1215
- this.percentage[this.dragged] = this.options.reversed ? 100 - percentage : percentage;
1311
+ this._state.percentage[this._state.dragged] = percentage;
1216
1312
  this._layout();
1217
1313
 
1218
1314
  var val = this._calculateValue(true);
@@ -1220,19 +1316,43 @@
1220
1316
 
1221
1317
  return false;
1222
1318
  },
1223
- _adjustPercentageForRangeSliders: function(percentage) {
1319
+ _touchmove: function _touchmove(ev) {
1320
+ if (ev.changedTouches === undefined) {
1321
+ return;
1322
+ }
1323
+
1324
+ var touch = ev.changedTouches[0];
1325
+
1326
+ var xDiff = touch.pageX - this.touchX;
1327
+ var yDiff = touch.pageY - this.touchY;
1328
+
1329
+ if (!this._state.inDrag) {
1330
+ // Vertical Slider
1331
+ if (this.options.orientation === 'vertical' && xDiff <= 5 && xDiff >= -5 && (yDiff >= 15 || yDiff <= -15)) {
1332
+ this._mousedown(ev);
1333
+ }
1334
+ // Horizontal slider.
1335
+ else if (yDiff <= 5 && yDiff >= -5 && (xDiff >= 15 || xDiff <= -15)) {
1336
+ this._mousedown(ev);
1337
+ }
1338
+ }
1339
+ },
1340
+ _adjustPercentageForRangeSliders: function _adjustPercentageForRangeSliders(percentage) {
1224
1341
  if (this.options.range) {
1225
- if (this.dragged === 0 && this.percentage[1] < percentage) {
1226
- this.percentage[0] = this.percentage[1];
1227
- this.dragged = 1;
1228
- } else if (this.dragged === 1 && this.percentage[0] > percentage) {
1229
- this.percentage[1] = this.percentage[0];
1230
- this.dragged = 0;
1342
+ var precision = this._getNumDigitsAfterDecimalPlace(percentage);
1343
+ precision = precision ? precision - 1 : 0;
1344
+ var percentageWithAdjustedPrecision = this._applyToFixedAndParseFloat(percentage, precision);
1345
+ if (this._state.dragged === 0 && this._applyToFixedAndParseFloat(this._state.percentage[1], precision) < percentageWithAdjustedPrecision) {
1346
+ this._state.percentage[0] = this._state.percentage[1];
1347
+ this._state.dragged = 1;
1348
+ } else if (this._state.dragged === 1 && this._applyToFixedAndParseFloat(this._state.percentage[0], precision) > percentageWithAdjustedPrecision) {
1349
+ this._state.percentage[1] = this._state.percentage[0];
1350
+ this._state.dragged = 0;
1231
1351
  }
1232
1352
  }
1233
1353
  },
1234
- _mouseup: function() {
1235
- if(!this.options.enabled) {
1354
+ _mouseup: function _mouseup() {
1355
+ if (!this._state.enabled) {
1236
1356
  return false;
1237
1357
  }
1238
1358
  if (this.touchCapable) {
@@ -1240,36 +1360,36 @@
1240
1360
  document.removeEventListener("touchmove", this.mousemove, false);
1241
1361
  document.removeEventListener("touchend", this.mouseup, false);
1242
1362
  }
1243
- // Unbind mouse event handlers:
1244
- document.removeEventListener("mousemove", this.mousemove, false);
1245
- document.removeEventListener("mouseup", this.mouseup, false);
1363
+ // Unbind mouse event handlers:
1364
+ document.removeEventListener("mousemove", this.mousemove, false);
1365
+ document.removeEventListener("mouseup", this.mouseup, false);
1246
1366
 
1247
- this.inDrag = false;
1248
- if (this.over === false) {
1367
+ this._state.inDrag = false;
1368
+ if (this._state.over === false) {
1249
1369
  this._hideTooltip();
1250
1370
  }
1251
1371
  var val = this._calculateValue(true);
1252
1372
 
1253
1373
  this._layout();
1254
- this._trigger('slideStop', val);
1255
1374
  this._setDataVal(val);
1375
+ this._trigger('slideStop', val);
1256
1376
 
1257
1377
  return false;
1258
1378
  },
1259
- _calculateValue: function(snapToClosestTick) {
1379
+ _calculateValue: function _calculateValue(snapToClosestTick) {
1260
1380
  var val;
1261
1381
  if (this.options.range) {
1262
- val = [this.options.min,this.options.max];
1263
- if (this.percentage[0] !== 0){
1264
- val[0] = this._toValue(this.percentage[0]);
1265
- val[0] = this._applyPrecision(val[0]);
1266
- }
1267
- if (this.percentage[1] !== 100){
1268
- val[1] = this._toValue(this.percentage[1]);
1269
- val[1] = this._applyPrecision(val[1]);
1270
- }
1382
+ val = [this.options.min, this.options.max];
1383
+ if (this._state.percentage[0] !== 0) {
1384
+ val[0] = this._toValue(this._state.percentage[0]);
1385
+ val[0] = this._applyPrecision(val[0]);
1386
+ }
1387
+ if (this._state.percentage[1] !== 100) {
1388
+ val[1] = this._toValue(this._state.percentage[1]);
1389
+ val[1] = this._applyPrecision(val[1]);
1390
+ }
1271
1391
  } else {
1272
- val = this._toValue(this.percentage[0]);
1392
+ val = this._toValue(this._state.percentage[0]);
1273
1393
  val = parseFloat(val);
1274
1394
  val = this._applyPrecision(val);
1275
1395
  }
@@ -1289,79 +1409,85 @@
1289
1409
 
1290
1410
  return val;
1291
1411
  },
1292
- _applyPrecision: function(val) {
1412
+ _applyPrecision: function _applyPrecision(val) {
1293
1413
  var precision = this.options.precision || this._getNumDigitsAfterDecimalPlace(this.options.step);
1294
1414
  return this._applyToFixedAndParseFloat(val, precision);
1295
1415
  },
1296
- _getNumDigitsAfterDecimalPlace: function(num) {
1297
- var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
1298
- if (!match) { return 0; }
1416
+ _getNumDigitsAfterDecimalPlace: function _getNumDigitsAfterDecimalPlace(num) {
1417
+ var match = ('' + num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
1418
+ if (!match) {
1419
+ return 0;
1420
+ }
1299
1421
  return Math.max(0, (match[1] ? match[1].length : 0) - (match[2] ? +match[2] : 0));
1300
1422
  },
1301
- _applyToFixedAndParseFloat: function(num, toFixedInput) {
1423
+ _applyToFixedAndParseFloat: function _applyToFixedAndParseFloat(num, toFixedInput) {
1302
1424
  var truncatedNum = num.toFixed(toFixedInput);
1303
1425
  return parseFloat(truncatedNum);
1304
1426
  },
1305
1427
  /*
1306
- Credits to Mike Samuel for the following method!
1307
- Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number
1308
- */
1309
- _getPercentage: function(ev) {
1428
+ Credits to Mike Samuel for the following method!
1429
+ Source: http://stackoverflow.com/questions/10454518/javascript-how-to-retrieve-the-number-of-decimals-of-a-string-number
1430
+ */
1431
+ _getPercentage: function _getPercentage(ev) {
1310
1432
  if (this.touchCapable && (ev.type === 'touchstart' || ev.type === 'touchmove')) {
1311
1433
  ev = ev.touches[0];
1312
1434
  }
1313
1435
 
1314
1436
  var eventPosition = ev[this.mousePos];
1315
- var sliderOffset = this.offset[this.stylePos];
1437
+ var sliderOffset = this._state.offset[this.stylePos];
1316
1438
  var distanceToSlide = eventPosition - sliderOffset;
1317
1439
  // Calculate what percent of the length the slider handle has slid
1318
- var percentage = (distanceToSlide / this.size) * 100;
1319
- percentage = Math.round(percentage / this.percentage[2]) * this.percentage[2];
1440
+ var percentage = distanceToSlide / this._state.size * 100;
1441
+ percentage = Math.round(percentage / this._state.percentage[2]) * this._state.percentage[2];
1442
+ if (this.options.reversed) {
1443
+ percentage = 100 - percentage;
1444
+ }
1320
1445
 
1321
1446
  // Make sure the percent is within the bounds of the slider.
1322
1447
  // 0% corresponds to the 'min' value of the slide
1323
1448
  // 100% corresponds to the 'max' value of the slide
1324
1449
  return Math.max(0, Math.min(100, percentage));
1325
1450
  },
1326
- _validateInputValue: function(val) {
1451
+ _validateInputValue: function _validateInputValue(val) {
1327
1452
  if (typeof val === 'number') {
1328
1453
  return val;
1329
1454
  } else if (Array.isArray(val)) {
1330
1455
  this._validateArray(val);
1331
1456
  return val;
1332
1457
  } else {
1333
- throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(val) );
1458
+ throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(val));
1334
1459
  }
1335
1460
  },
1336
- _validateArray: function(val) {
1337
- for(var i = 0; i < val.length; i++) {
1338
- var input = val[i];
1339
- if (typeof input !== 'number') { throw new Error( ErrorMsgs.formatInvalidInputErrorMsg(input) ); }
1461
+ _validateArray: function _validateArray(val) {
1462
+ for (var i = 0; i < val.length; i++) {
1463
+ var input = val[i];
1464
+ if (typeof input !== 'number') {
1465
+ throw new Error(ErrorMsgs.formatInvalidInputErrorMsg(input));
1466
+ }
1340
1467
  }
1341
1468
  },
1342
- _setDataVal: function(val) {
1343
- var value = "value: '" + val + "'";
1344
- this.element.setAttribute('data', value);
1469
+ _setDataVal: function _setDataVal(val) {
1470
+ this.element.setAttribute('data-value', val);
1345
1471
  this.element.setAttribute('value', val);
1346
- this.element.value = val;
1472
+ this.element.value = val;
1347
1473
  },
1348
- _trigger: function(evt, val) {
1349
- val = (val || val === 0) ? val : undefined;
1474
+ _trigger: function _trigger(evt, val) {
1475
+ val = val || val === 0 ? val : undefined;
1350
1476
 
1351
1477
  var callbackFnArray = this.eventToCallbackMap[evt];
1352
- if(callbackFnArray && callbackFnArray.length) {
1353
- for(var i = 0; i < callbackFnArray.length; i++) {
1478
+ if (callbackFnArray && callbackFnArray.length) {
1479
+ for (var i = 0; i < callbackFnArray.length; i++) {
1354
1480
  var callbackFn = callbackFnArray[i];
1355
1481
  callbackFn(val);
1356
1482
  }
1357
1483
  }
1358
1484
 
1359
1485
  /* If JQuery exists, trigger JQuery events */
1360
- if($) {
1486
+ if ($) {
1361
1487
  this._triggerJQueryEvent(evt, val);
1362
1488
  }
1363
1489
  },
1364
- _triggerJQueryEvent: function(evt, val) {
1490
+ _triggerJQueryEvent: function _triggerJQueryEvent(evt, val) {
1365
1491
  var eventData = {
1366
1492
  type: evt,
1367
1493
  value: val
@@ -1369,22 +1495,22 @@
1369
1495
  this.$element.trigger(eventData);
1370
1496
  this.$sliderElem.trigger(eventData);
1371
1497
  },
1372
- _unbindJQueryEventHandlers: function() {
1498
+ _unbindJQueryEventHandlers: function _unbindJQueryEventHandlers() {
1373
1499
  this.$element.off();
1374
1500
  this.$sliderElem.off();
1375
1501
  },
1376
- _setText: function(element, text) {
1377
- if(typeof element.innerText !== "undefined") {
1378
- element.innerText = text;
1379
- } else if(typeof element.textContent !== "undefined") {
1502
+ _setText: function _setText(element, text) {
1503
+ if (typeof element.textContent !== "undefined") {
1380
1504
  element.textContent = text;
1505
+ } else if (typeof element.innerText !== "undefined") {
1506
+ element.innerText = text;
1381
1507
  }
1382
1508
  },
1383
- _removeClass: function(element, classString) {
1509
+ _removeClass: function _removeClass(element, classString) {
1384
1510
  var classes = classString.split(" ");
1385
1511
  var newClasses = element.className;
1386
1512
 
1387
- for(var i = 0; i < classes.length; i++) {
1513
+ for (var i = 0; i < classes.length; i++) {
1388
1514
  var classTag = classes[i];
1389
1515
  var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");
1390
1516
  newClasses = newClasses.replace(regex, " ");
@@ -1392,72 +1518,93 @@
1392
1518
 
1393
1519
  element.className = newClasses.trim();
1394
1520
  },
1395
- _addClass: function(element, classString) {
1521
+ _addClass: function _addClass(element, classString) {
1396
1522
  var classes = classString.split(" ");
1397
1523
  var newClasses = element.className;
1398
1524
 
1399
- for(var i = 0; i < classes.length; i++) {
1525
+ for (var i = 0; i < classes.length; i++) {
1400
1526
  var classTag = classes[i];
1401
1527
  var regex = new RegExp("(?:\\s|^)" + classTag + "(?:\\s|$)");
1402
1528
  var ifClassExists = regex.test(newClasses);
1403
1529
 
1404
- if(!ifClassExists) {
1530
+ if (!ifClassExists) {
1405
1531
  newClasses += " " + classTag;
1406
1532
  }
1407
1533
  }
1408
1534
 
1409
1535
  element.className = newClasses.trim();
1410
1536
  },
1411
- _offsetLeft: function(obj){
1412
- var offsetLeft = obj.offsetLeft;
1413
- while((obj = obj.offsetParent) && !isNaN(obj.offsetLeft)){
1414
- offsetLeft += obj.offsetLeft;
1415
- }
1416
- return offsetLeft;
1537
+ _offsetLeft: function _offsetLeft(obj) {
1538
+ return obj.getBoundingClientRect().left;
1417
1539
  },
1418
- _offsetTop: function(obj){
1540
+ _offsetTop: function _offsetTop(obj) {
1419
1541
  var offsetTop = obj.offsetTop;
1420
- while((obj = obj.offsetParent) && !isNaN(obj.offsetTop)){
1542
+ while ((obj = obj.offsetParent) && !isNaN(obj.offsetTop)) {
1421
1543
  offsetTop += obj.offsetTop;
1544
+ if (obj.tagName !== 'BODY') {
1545
+ offsetTop -= obj.scrollTop;
1546
+ }
1422
1547
  }
1423
1548
  return offsetTop;
1424
1549
  },
1425
- _offset: function (obj) {
1550
+ _offset: function _offset(obj) {
1426
1551
  return {
1427
1552
  left: this._offsetLeft(obj),
1428
1553
  top: this._offsetTop(obj)
1429
1554
  };
1430
- },
1431
- _css: function(elementRef, styleName, value) {
1432
- if ($) {
1433
- $.style(elementRef, styleName, value);
1434
- } else {
1435
- var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) {
1436
- return letter.toUpperCase();
1437
- });
1438
- elementRef.style[style] = value;
1439
- }
1440
1555
  },
1441
- _toValue: function(percentage) {
1556
+ _css: function _css(elementRef, styleName, value) {
1557
+ if ($) {
1558
+ $.style(elementRef, styleName, value);
1559
+ } else {
1560
+ var style = styleName.replace(/^-ms-/, "ms-").replace(/-([\da-z])/gi, function (all, letter) {
1561
+ return letter.toUpperCase();
1562
+ });
1563
+ elementRef.style[style] = value;
1564
+ }
1565
+ },
1566
+ _toValue: function _toValue(percentage) {
1442
1567
  return this.options.scale.toValue.apply(this, [percentage]);
1443
1568
  },
1444
- _toPercentage: function(value) {
1569
+ _toPercentage: function _toPercentage(value) {
1445
1570
  return this.options.scale.toPercentage.apply(this, [value]);
1571
+ },
1572
+ _setTooltipPosition: function _setTooltipPosition() {
1573
+ var tooltips = [this.tooltip, this.tooltip_min, this.tooltip_max];
1574
+ if (this.options.orientation === 'vertical') {
1575
+ var tooltipPos = this.options.tooltip_position || 'right';
1576
+ var oppositeSide = tooltipPos === 'left' ? 'right' : 'left';
1577
+ tooltips.forEach((function (tooltip) {
1578
+ this._addClass(tooltip, tooltipPos);
1579
+ tooltip.style[oppositeSide] = '100%';
1580
+ }).bind(this));
1581
+ } else if (this.options.tooltip_position === 'bottom') {
1582
+ tooltips.forEach((function (tooltip) {
1583
+ this._addClass(tooltip, 'bottom');
1584
+ tooltip.style.top = 22 + 'px';
1585
+ }).bind(this));
1586
+ } else {
1587
+ tooltips.forEach((function (tooltip) {
1588
+ this._addClass(tooltip, 'top');
1589
+ tooltip.style.top = -this.tooltip.outerHeight - 14 + 'px';
1590
+ }).bind(this));
1591
+ }
1446
1592
  }
1447
-
1448
1593
  };
1449
1594
 
1450
1595
  /*********************************
1451
-
1452
1596
  Attach to global namespace
1453
-
1454
1597
  *********************************/
1455
- if($) {
1598
+ if ($) {
1456
1599
  var namespace = $.fn.slider ? 'bootstrapSlider' : 'slider';
1457
1600
  $.bridget(namespace, Slider);
1458
- }
1459
1601
 
1460
- })( $ );
1602
+ // Auto-Register data-provide="slider" Elements
1603
+ $(function () {
1604
+ $("input[data-provide=slider]")[namespace]();
1605
+ });
1606
+ }
1607
+ })($);
1461
1608
 
1462
1609
  return Slider;
1463
- }));
1610
+ });