pghero 3.2.0 → 3.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/app/assets/javascripts/pghero/application.js +13 -12
- data/app/assets/javascripts/pghero/highlight.min.js +373 -0
- data/app/assets/javascripts/pghero/jquery.js +318 -197
- data/app/assets/javascripts/pghero/nouislider.js +676 -1066
- data/app/assets/stylesheets/pghero/application.css +6 -0
- data/app/assets/stylesheets/pghero/nouislider.css +4 -10
- data/app/controllers/pg_hero/home_controller.rb +30 -9
- data/app/helpers/pg_hero/home_helper.rb +2 -2
- data/app/views/layouts/pg_hero/application.html.erb +1 -1
- data/app/views/pg_hero/home/_query_stats_slider.html.erb +6 -6
- data/app/views/pg_hero/home/connections.html.erb +6 -6
- data/app/views/pg_hero/home/index.html.erb +3 -1
- data/app/views/pg_hero/home/relation_space.html.erb +1 -1
- data/app/views/pg_hero/home/show_query.html.erb +16 -12
- data/app/views/pg_hero/home/space.html.erb +44 -40
- data/app/views/pg_hero/home/system.html.erb +6 -6
- data/lib/generators/pghero/query_stats_generator.rb +1 -0
- data/lib/generators/pghero/space_stats_generator.rb +1 -0
- data/lib/pghero/engine.rb +1 -1
- data/lib/pghero/methods/basic.rb +5 -8
- data/lib/pghero/methods/connections.rb +4 -4
- data/lib/pghero/methods/constraints.rb +1 -1
- data/lib/pghero/methods/indexes.rb +8 -8
- data/lib/pghero/methods/kill.rb +1 -1
- data/lib/pghero/methods/maintenance.rb +3 -3
- data/lib/pghero/methods/queries.rb +2 -2
- data/lib/pghero/methods/query_stats.rb +16 -17
- data/lib/pghero/methods/replication.rb +2 -2
- data/lib/pghero/methods/sequences.rb +2 -2
- data/lib/pghero/methods/space.rb +15 -10
- data/lib/pghero/methods/suggested_indexes.rb +2 -2
- data/lib/pghero/methods/tables.rb +4 -5
- data/lib/pghero/version.rb +1 -1
- data/lib/pghero.rb +2 -0
- metadata +3 -3
- data/app/assets/javascripts/pghero/highlight.pack.js +0 -2
@@ -1,131 +1,116 @@
|
|
1
|
-
|
2
|
-
(
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
1
|
+
(function (global, factory) {
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.noUiSlider = {}));
|
5
|
+
})(this, (function (exports) { 'use strict';
|
6
|
+
|
7
|
+
exports.PipsMode = void 0;
|
8
|
+
(function (PipsMode) {
|
9
|
+
PipsMode["Range"] = "range";
|
10
|
+
PipsMode["Steps"] = "steps";
|
11
|
+
PipsMode["Positions"] = "positions";
|
12
|
+
PipsMode["Count"] = "count";
|
13
|
+
PipsMode["Values"] = "values";
|
14
|
+
})(exports.PipsMode || (exports.PipsMode = {}));
|
15
|
+
exports.PipsType = void 0;
|
16
|
+
(function (PipsType) {
|
17
|
+
PipsType[PipsType["None"] = -1] = "None";
|
18
|
+
PipsType[PipsType["NoValue"] = 0] = "NoValue";
|
19
|
+
PipsType[PipsType["LargeValue"] = 1] = "LargeValue";
|
20
|
+
PipsType[PipsType["SmallValue"] = 2] = "SmallValue";
|
21
|
+
})(exports.PipsType || (exports.PipsType = {}));
|
18
22
|
//region Helper Methods
|
19
|
-
|
20
23
|
function isValidFormatter(entry) {
|
21
|
-
return
|
24
|
+
return isValidPartialFormatter(entry) && typeof entry.from === "function";
|
25
|
+
}
|
26
|
+
function isValidPartialFormatter(entry) {
|
27
|
+
// partial formatters only need a to function and not a from function
|
28
|
+
return typeof entry === "object" && typeof entry.to === "function";
|
22
29
|
}
|
23
|
-
|
24
30
|
function removeElement(el) {
|
25
31
|
el.parentElement.removeChild(el);
|
26
32
|
}
|
27
|
-
|
28
33
|
function isSet(value) {
|
29
34
|
return value !== null && value !== undefined;
|
30
35
|
}
|
31
|
-
|
32
36
|
// Bindable version
|
33
37
|
function preventDefault(e) {
|
34
38
|
e.preventDefault();
|
35
39
|
}
|
36
|
-
|
37
40
|
// Removes duplicates from an array.
|
38
41
|
function unique(array) {
|
39
|
-
return array.filter(function(a) {
|
42
|
+
return array.filter(function (a) {
|
40
43
|
return !this[a] ? (this[a] = true) : false;
|
41
44
|
}, {});
|
42
45
|
}
|
43
|
-
|
44
46
|
// Round a value to the closest 'to'.
|
45
47
|
function closest(value, to) {
|
46
48
|
return Math.round(value / to) * to;
|
47
49
|
}
|
48
|
-
|
49
50
|
// Current position of an element relative to the document.
|
50
51
|
function offset(elem, orientation) {
|
51
52
|
var rect = elem.getBoundingClientRect();
|
52
53
|
var doc = elem.ownerDocument;
|
53
54
|
var docElem = doc.documentElement;
|
54
55
|
var pageOffset = getPageOffset(doc);
|
55
|
-
|
56
56
|
// getBoundingClientRect contains left scroll in Chrome on Android.
|
57
57
|
// I haven't found a feature detection that proves this. Worst case
|
58
58
|
// scenario on mis-match: the 'tap' feature on horizontal sliders breaks.
|
59
59
|
if (/webkit.*Chrome.*Mobile/i.test(navigator.userAgent)) {
|
60
60
|
pageOffset.x = 0;
|
61
61
|
}
|
62
|
-
|
63
|
-
return orientation
|
64
|
-
? rect.top + pageOffset.y - docElem.clientTop
|
65
|
-
: rect.left + pageOffset.x - docElem.clientLeft;
|
62
|
+
return orientation ? rect.top + pageOffset.y - docElem.clientTop : rect.left + pageOffset.x - docElem.clientLeft;
|
66
63
|
}
|
67
|
-
|
68
64
|
// Checks whether a value is numerical.
|
69
65
|
function isNumeric(a) {
|
70
66
|
return typeof a === "number" && !isNaN(a) && isFinite(a);
|
71
67
|
}
|
72
|
-
|
73
68
|
// Sets a class and removes it after [duration] ms.
|
74
69
|
function addClassFor(element, className, duration) {
|
75
70
|
if (duration > 0) {
|
76
71
|
addClass(element, className);
|
77
|
-
setTimeout(function() {
|
72
|
+
setTimeout(function () {
|
78
73
|
removeClass(element, className);
|
79
74
|
}, duration);
|
80
75
|
}
|
81
76
|
}
|
82
|
-
|
83
77
|
// Limits a value to 0 - 100
|
84
78
|
function limit(a) {
|
85
79
|
return Math.max(Math.min(a, 100), 0);
|
86
80
|
}
|
87
|
-
|
88
81
|
// Wraps a variable as an array, if it isn't one yet.
|
89
82
|
// Note that an input array is returned by reference!
|
90
83
|
function asArray(a) {
|
91
84
|
return Array.isArray(a) ? a : [a];
|
92
85
|
}
|
93
|
-
|
94
86
|
// Counts decimals
|
95
87
|
function countDecimals(numStr) {
|
96
88
|
numStr = String(numStr);
|
97
89
|
var pieces = numStr.split(".");
|
98
90
|
return pieces.length > 1 ? pieces[1].length : 0;
|
99
91
|
}
|
100
|
-
|
101
92
|
// http://youmightnotneedjquery.com/#add_class
|
102
93
|
function addClass(el, className) {
|
103
94
|
if (el.classList && !/\s/.test(className)) {
|
104
95
|
el.classList.add(className);
|
105
|
-
}
|
96
|
+
}
|
97
|
+
else {
|
106
98
|
el.className += " " + className;
|
107
99
|
}
|
108
100
|
}
|
109
|
-
|
110
101
|
// http://youmightnotneedjquery.com/#remove_class
|
111
102
|
function removeClass(el, className) {
|
112
103
|
if (el.classList && !/\s/.test(className)) {
|
113
104
|
el.classList.remove(className);
|
114
|
-
}
|
115
|
-
|
116
|
-
|
117
|
-
" "
|
118
|
-
);
|
105
|
+
}
|
106
|
+
else {
|
107
|
+
el.className = el.className.replace(new RegExp("(^|\\b)" + className.split(" ").join("|") + "(\\b|$)", "gi"), " ");
|
119
108
|
}
|
120
109
|
}
|
121
|
-
|
122
110
|
// https://plainjs.com/javascript/attributes/adding-removing-and-testing-for-classes-9/
|
123
111
|
function hasClass(el, className) {
|
124
|
-
return el.classList
|
125
|
-
? el.classList.contains(className)
|
126
|
-
: new RegExp("\\b" + className + "\\b").test(el.className);
|
112
|
+
return el.classList ? el.classList.contains(className) : new RegExp("\\b" + className + "\\b").test(el.className);
|
127
113
|
}
|
128
|
-
|
129
114
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollY#Notes
|
130
115
|
function getPageOffset(doc) {
|
131
116
|
var supportPageOffset = window.pageXOffset !== undefined;
|
@@ -140,13 +125,11 @@
|
|
140
125
|
: isCSS1Compat
|
141
126
|
? doc.documentElement.scrollTop
|
142
127
|
: doc.body.scrollTop;
|
143
|
-
|
144
128
|
return {
|
145
129
|
x: x,
|
146
|
-
y: y
|
130
|
+
y: y,
|
147
131
|
};
|
148
132
|
}
|
149
|
-
|
150
133
|
// we provide a function to compute constants instead
|
151
134
|
// of accessing window.* as soon as the module needs it
|
152
135
|
// so that we do not compute anything if not needed
|
@@ -155,424 +138,333 @@
|
|
155
138
|
// a prefix, which breaks compatibility with the IE10 implementation.
|
156
139
|
return window.navigator.pointerEnabled
|
157
140
|
? {
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
141
|
+
start: "pointerdown",
|
142
|
+
move: "pointermove",
|
143
|
+
end: "pointerup",
|
144
|
+
}
|
162
145
|
: window.navigator.msPointerEnabled
|
163
146
|
? {
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
147
|
+
start: "MSPointerDown",
|
148
|
+
move: "MSPointerMove",
|
149
|
+
end: "MSPointerUp",
|
150
|
+
}
|
168
151
|
: {
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
152
|
+
start: "mousedown touchstart",
|
153
|
+
move: "mousemove touchmove",
|
154
|
+
end: "mouseup touchend",
|
155
|
+
};
|
173
156
|
}
|
174
|
-
|
175
157
|
// https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
|
176
158
|
// Issue #785
|
177
159
|
function getSupportsPassive() {
|
178
160
|
var supportsPassive = false;
|
179
|
-
|
180
161
|
/* eslint-disable */
|
181
162
|
try {
|
182
163
|
var opts = Object.defineProperty({}, "passive", {
|
183
|
-
get: function() {
|
164
|
+
get: function () {
|
184
165
|
supportsPassive = true;
|
185
|
-
}
|
166
|
+
},
|
186
167
|
});
|
187
|
-
|
168
|
+
// @ts-ignore
|
188
169
|
window.addEventListener("test", null, opts);
|
189
|
-
}
|
170
|
+
}
|
171
|
+
catch (e) { }
|
190
172
|
/* eslint-enable */
|
191
|
-
|
192
173
|
return supportsPassive;
|
193
174
|
}
|
194
|
-
|
195
175
|
function getSupportsTouchActionNone() {
|
196
176
|
return window.CSS && CSS.supports && CSS.supports("touch-action", "none");
|
197
177
|
}
|
198
|
-
|
199
178
|
//endregion
|
200
|
-
|
201
179
|
//region Range Calculation
|
202
|
-
|
203
180
|
// Determine the size of a sub-range in relation to a full range.
|
204
181
|
function subRangeRatio(pa, pb) {
|
205
182
|
return 100 / (pb - pa);
|
206
183
|
}
|
207
|
-
|
208
184
|
// (percentage) How many percent is this value of this range?
|
209
185
|
function fromPercentage(range, value, startRange) {
|
210
186
|
return (value * 100) / (range[startRange + 1] - range[startRange]);
|
211
187
|
}
|
212
|
-
|
213
188
|
// (percentage) Where is this value on this range?
|
214
189
|
function toPercentage(range, value) {
|
215
190
|
return fromPercentage(range, range[0] < 0 ? value + Math.abs(range[0]) : value - range[0], 0);
|
216
191
|
}
|
217
|
-
|
218
192
|
// (value) How much is this percentage on this range?
|
219
193
|
function isPercentage(range, value) {
|
220
194
|
return (value * (range[1] - range[0])) / 100 + range[0];
|
221
195
|
}
|
222
|
-
|
223
196
|
function getJ(value, arr) {
|
224
197
|
var j = 1;
|
225
|
-
|
226
198
|
while (value >= arr[j]) {
|
227
199
|
j += 1;
|
228
200
|
}
|
229
|
-
|
230
201
|
return j;
|
231
202
|
}
|
232
|
-
|
233
203
|
// (percentage) Input a value, find where, on a scale of 0-100, it applies.
|
234
204
|
function toStepping(xVal, xPct, value) {
|
235
205
|
if (value >= xVal.slice(-1)[0]) {
|
236
206
|
return 100;
|
237
207
|
}
|
238
|
-
|
239
208
|
var j = getJ(value, xVal);
|
240
209
|
var va = xVal[j - 1];
|
241
210
|
var vb = xVal[j];
|
242
211
|
var pa = xPct[j - 1];
|
243
212
|
var pb = xPct[j];
|
244
|
-
|
245
213
|
return pa + toPercentage([va, vb], value) / subRangeRatio(pa, pb);
|
246
214
|
}
|
247
|
-
|
248
215
|
// (value) Input a percentage, find where it is on the specified range.
|
249
216
|
function fromStepping(xVal, xPct, value) {
|
250
217
|
// There is no range group that fits 100
|
251
218
|
if (value >= 100) {
|
252
219
|
return xVal.slice(-1)[0];
|
253
220
|
}
|
254
|
-
|
255
221
|
var j = getJ(value, xPct);
|
256
222
|
var va = xVal[j - 1];
|
257
223
|
var vb = xVal[j];
|
258
224
|
var pa = xPct[j - 1];
|
259
225
|
var pb = xPct[j];
|
260
|
-
|
261
226
|
return isPercentage([va, vb], (value - pa) * subRangeRatio(pa, pb));
|
262
227
|
}
|
263
|
-
|
264
228
|
// (percentage) Get the step that applies at a certain value.
|
265
229
|
function getStep(xPct, xSteps, snap, value) {
|
266
230
|
if (value === 100) {
|
267
231
|
return value;
|
268
232
|
}
|
269
|
-
|
270
233
|
var j = getJ(value, xPct);
|
271
234
|
var a = xPct[j - 1];
|
272
235
|
var b = xPct[j];
|
273
|
-
|
274
236
|
// If 'snap' is set, steps are used as fixed points on the slider.
|
275
237
|
if (snap) {
|
276
238
|
// Find the closest position, a or b.
|
277
239
|
if (value - a > (b - a) / 2) {
|
278
240
|
return b;
|
279
241
|
}
|
280
|
-
|
281
242
|
return a;
|
282
243
|
}
|
283
|
-
|
284
244
|
if (!xSteps[j - 1]) {
|
285
245
|
return value;
|
286
246
|
}
|
287
|
-
|
288
247
|
return xPct[j - 1] + closest(value - xPct[j - 1], xSteps[j - 1]);
|
289
248
|
}
|
290
|
-
|
291
|
-
function handleEntryPoint(index, value, that) {
|
292
|
-
var percentage;
|
293
|
-
|
294
|
-
// Wrap numerical input in an array.
|
295
|
-
if (typeof value === "number") {
|
296
|
-
value = [value];
|
297
|
-
}
|
298
|
-
|
299
|
-
// Reject any invalid input, by testing whether value is an array.
|
300
|
-
if (!Array.isArray(value)) {
|
301
|
-
throw new Error("noUiSlider (" + VERSION + "): 'range' contains invalid value.");
|
302
|
-
}
|
303
|
-
|
304
|
-
// Covert min/max syntax to 0 and 100.
|
305
|
-
if (index === "min") {
|
306
|
-
percentage = 0;
|
307
|
-
} else if (index === "max") {
|
308
|
-
percentage = 100;
|
309
|
-
} else {
|
310
|
-
percentage = parseFloat(index);
|
311
|
-
}
|
312
|
-
|
313
|
-
// Check for correct input.
|
314
|
-
if (!isNumeric(percentage) || !isNumeric(value[0])) {
|
315
|
-
throw new Error("noUiSlider (" + VERSION + "): 'range' value isn't numeric.");
|
316
|
-
}
|
317
|
-
|
318
|
-
// Store values.
|
319
|
-
that.xPct.push(percentage);
|
320
|
-
that.xVal.push(value[0]);
|
321
|
-
|
322
|
-
// NaN will evaluate to false too, but to keep
|
323
|
-
// logging clear, set step explicitly. Make sure
|
324
|
-
// not to override the 'step' setting with false.
|
325
|
-
if (!percentage) {
|
326
|
-
if (!isNaN(value[1])) {
|
327
|
-
that.xSteps[0] = value[1];
|
328
|
-
}
|
329
|
-
} else {
|
330
|
-
that.xSteps.push(isNaN(value[1]) ? false : value[1]);
|
331
|
-
}
|
332
|
-
|
333
|
-
that.xHighestCompleteStep.push(0);
|
334
|
-
}
|
335
|
-
|
336
|
-
function handleStepPoint(i, n, that) {
|
337
|
-
// Ignore 'false' stepping.
|
338
|
-
if (!n) {
|
339
|
-
return;
|
340
|
-
}
|
341
|
-
|
342
|
-
// Step over zero-length ranges (#948);
|
343
|
-
if (that.xVal[i] === that.xVal[i + 1]) {
|
344
|
-
that.xSteps[i] = that.xHighestCompleteStep[i] = that.xVal[i];
|
345
|
-
|
346
|
-
return;
|
347
|
-
}
|
348
|
-
|
349
|
-
// Factor to range ratio
|
350
|
-
that.xSteps[i] =
|
351
|
-
fromPercentage([that.xVal[i], that.xVal[i + 1]], n, 0) / subRangeRatio(that.xPct[i], that.xPct[i + 1]);
|
352
|
-
|
353
|
-
var totalSteps = (that.xVal[i + 1] - that.xVal[i]) / that.xNumSteps[i];
|
354
|
-
var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
|
355
|
-
var step = that.xVal[i] + that.xNumSteps[i] * highestStep;
|
356
|
-
|
357
|
-
that.xHighestCompleteStep[i] = step;
|
358
|
-
}
|
359
|
-
|
360
249
|
//endregion
|
361
|
-
|
362
250
|
//region Spectrum
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
if (entry.hasOwnProperty(index)) {
|
379
|
-
ordered.push([entry[index], index]);
|
380
|
-
}
|
381
|
-
}
|
382
|
-
|
383
|
-
// Sort all entries by value (numeric sort).
|
384
|
-
if (ordered.length && typeof ordered[0][0] === "object") {
|
385
|
-
ordered.sort(function(a, b) {
|
386
|
-
return a[0][0] - b[0][0];
|
251
|
+
var Spectrum = /** @class */ (function () {
|
252
|
+
function Spectrum(entry, snap, singleStep) {
|
253
|
+
this.xPct = [];
|
254
|
+
this.xVal = [];
|
255
|
+
this.xSteps = [];
|
256
|
+
this.xNumSteps = [];
|
257
|
+
this.xHighestCompleteStep = [];
|
258
|
+
this.xSteps = [singleStep || false];
|
259
|
+
this.xNumSteps = [false];
|
260
|
+
this.snap = snap;
|
261
|
+
var index;
|
262
|
+
var ordered = [];
|
263
|
+
// Map the object keys to an array.
|
264
|
+
Object.keys(entry).forEach(function (index) {
|
265
|
+
ordered.push([asArray(entry[index]), index]);
|
387
266
|
});
|
388
|
-
|
389
|
-
ordered.sort(function(a, b) {
|
390
|
-
return a[0] - b[0];
|
267
|
+
// Sort all entries by value (numeric sort).
|
268
|
+
ordered.sort(function (a, b) {
|
269
|
+
return a[0][0] - b[0][0];
|
391
270
|
});
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
for (index = 0; index < ordered.length; index++) {
|
396
|
-
handleEntryPoint(ordered[index][1], ordered[index][0], this);
|
397
|
-
}
|
398
|
-
|
399
|
-
// Store the actual step values.
|
400
|
-
// xSteps is sorted in the same order as xPct and xVal.
|
401
|
-
this.xNumSteps = this.xSteps.slice(0);
|
402
|
-
|
403
|
-
// Convert all numeric steps to the percentage of the subrange they represent.
|
404
|
-
for (index = 0; index < this.xNumSteps.length; index++) {
|
405
|
-
handleStepPoint(index, this.xNumSteps[index], this);
|
406
|
-
}
|
407
|
-
}
|
408
|
-
|
409
|
-
Spectrum.prototype.getDistance = function(value) {
|
410
|
-
var index;
|
411
|
-
var distances = [];
|
412
|
-
|
413
|
-
for (index = 0; index < this.xNumSteps.length - 1; index++) {
|
414
|
-
// last "range" can't contain step size as it is purely an endpoint.
|
415
|
-
var step = this.xNumSteps[index];
|
416
|
-
|
417
|
-
if (step && (value / step) % 1 !== 0) {
|
418
|
-
throw new Error(
|
419
|
-
"noUiSlider (" +
|
420
|
-
VERSION +
|
421
|
-
"): 'limit', 'margin' and 'padding' of " +
|
422
|
-
this.xPct[index] +
|
423
|
-
"% range must be divisible by step."
|
424
|
-
);
|
271
|
+
// Convert all entries to subranges.
|
272
|
+
for (index = 0; index < ordered.length; index++) {
|
273
|
+
this.handleEntryPoint(ordered[index][1], ordered[index][0]);
|
425
274
|
}
|
426
|
-
|
427
|
-
//
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
};
|
433
|
-
|
434
|
-
// Calculate the percentual distance over the whole scale of ranges.
|
435
|
-
// direction: 0 = backwards / 1 = forwards
|
436
|
-
Spectrum.prototype.getAbsoluteDistance = function(value, distances, direction) {
|
437
|
-
var xPct_index = 0;
|
438
|
-
|
439
|
-
// Calculate range where to start calculation
|
440
|
-
if (value < this.xPct[this.xPct.length - 1]) {
|
441
|
-
while (value > this.xPct[xPct_index + 1]) {
|
442
|
-
xPct_index++;
|
275
|
+
// Store the actual step values.
|
276
|
+
// xSteps is sorted in the same order as xPct and xVal.
|
277
|
+
this.xNumSteps = this.xSteps.slice(0);
|
278
|
+
// Convert all numeric steps to the percentage of the subrange they represent.
|
279
|
+
for (index = 0; index < this.xNumSteps.length; index++) {
|
280
|
+
this.handleStepPoint(index, this.xNumSteps[index]);
|
443
281
|
}
|
444
|
-
} else if (value === this.xPct[this.xPct.length - 1]) {
|
445
|
-
xPct_index = this.xPct.length - 2;
|
446
|
-
}
|
447
|
-
|
448
|
-
// If looking backwards and the value is exactly at a range separator then look one range further
|
449
|
-
if (!direction && value === this.xPct[xPct_index + 1]) {
|
450
|
-
xPct_index++;
|
451
|
-
}
|
452
|
-
|
453
|
-
var start_factor;
|
454
|
-
var rest_factor = 1;
|
455
|
-
|
456
|
-
var rest_rel_distance = distances[xPct_index];
|
457
|
-
|
458
|
-
var range_pct = 0;
|
459
|
-
|
460
|
-
var rel_range_distance = 0;
|
461
|
-
var abs_distance_counter = 0;
|
462
|
-
var range_counter = 0;
|
463
|
-
|
464
|
-
// Calculate what part of the start range the value is
|
465
|
-
if (direction) {
|
466
|
-
start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
|
467
|
-
} else {
|
468
|
-
start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
|
469
282
|
}
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter];
|
475
|
-
|
476
|
-
// Detect if the margin, padding or limit is larger then the current range and calculate
|
477
|
-
if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) {
|
478
|
-
// If larger then take the percentual distance of the whole range
|
479
|
-
rel_range_distance = range_pct * start_factor;
|
480
|
-
// Rest factor of relative percentual distance still to be calculated
|
481
|
-
rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter];
|
482
|
-
// Set start factor to 1 as for next range it does not apply.
|
483
|
-
start_factor = 1;
|
484
|
-
} else {
|
485
|
-
// If smaller or equal then take the percentual distance of the calculate percentual part of that range
|
486
|
-
rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor;
|
487
|
-
// No rest left as the rest fits in current range
|
488
|
-
rest_factor = 0;
|
283
|
+
Spectrum.prototype.getDistance = function (value) {
|
284
|
+
var distances = [];
|
285
|
+
for (var index = 0; index < this.xNumSteps.length - 1; index++) {
|
286
|
+
distances[index] = fromPercentage(this.xVal, value, index);
|
489
287
|
}
|
490
|
-
|
288
|
+
return distances;
|
289
|
+
};
|
290
|
+
// Calculate the percentual distance over the whole scale of ranges.
|
291
|
+
// direction: 0 = backwards / 1 = forwards
|
292
|
+
Spectrum.prototype.getAbsoluteDistance = function (value, distances, direction) {
|
293
|
+
var xPct_index = 0;
|
294
|
+
// Calculate range where to start calculation
|
295
|
+
if (value < this.xPct[this.xPct.length - 1]) {
|
296
|
+
while (value > this.xPct[xPct_index + 1]) {
|
297
|
+
xPct_index++;
|
298
|
+
}
|
299
|
+
}
|
300
|
+
else if (value === this.xPct[this.xPct.length - 1]) {
|
301
|
+
xPct_index = this.xPct.length - 2;
|
302
|
+
}
|
303
|
+
// If looking backwards and the value is exactly at a range separator then look one range further
|
304
|
+
if (!direction && value === this.xPct[xPct_index + 1]) {
|
305
|
+
xPct_index++;
|
306
|
+
}
|
307
|
+
if (distances === null) {
|
308
|
+
distances = [];
|
309
|
+
}
|
310
|
+
var start_factor;
|
311
|
+
var rest_factor = 1;
|
312
|
+
var rest_rel_distance = distances[xPct_index];
|
313
|
+
var range_pct = 0;
|
314
|
+
var rel_range_distance = 0;
|
315
|
+
var abs_distance_counter = 0;
|
316
|
+
var range_counter = 0;
|
317
|
+
// Calculate what part of the start range the value is
|
491
318
|
if (direction) {
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
319
|
+
start_factor = (value - this.xPct[xPct_index]) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
|
320
|
+
}
|
321
|
+
else {
|
322
|
+
start_factor = (this.xPct[xPct_index + 1] - value) / (this.xPct[xPct_index + 1] - this.xPct[xPct_index]);
|
323
|
+
}
|
324
|
+
// Do until the complete distance across ranges is calculated
|
325
|
+
while (rest_rel_distance > 0) {
|
326
|
+
// Calculate the percentage of total range
|
327
|
+
range_pct = this.xPct[xPct_index + 1 + range_counter] - this.xPct[xPct_index + range_counter];
|
328
|
+
// Detect if the margin, padding or limit is larger then the current range and calculate
|
329
|
+
if (distances[xPct_index + range_counter] * rest_factor + 100 - start_factor * 100 > 100) {
|
330
|
+
// If larger then take the percentual distance of the whole range
|
331
|
+
rel_range_distance = range_pct * start_factor;
|
332
|
+
// Rest factor of relative percentual distance still to be calculated
|
333
|
+
rest_factor = (rest_rel_distance - 100 * start_factor) / distances[xPct_index + range_counter];
|
334
|
+
// Set start factor to 1 as for next range it does not apply.
|
335
|
+
start_factor = 1;
|
496
336
|
}
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
337
|
+
else {
|
338
|
+
// If smaller or equal then take the percentual distance of the calculate percentual part of that range
|
339
|
+
rel_range_distance = ((distances[xPct_index + range_counter] * range_pct) / 100) * rest_factor;
|
340
|
+
// No rest left as the rest fits in current range
|
341
|
+
rest_factor = 0;
|
342
|
+
}
|
343
|
+
if (direction) {
|
344
|
+
abs_distance_counter = abs_distance_counter - rel_range_distance;
|
345
|
+
// Limit range to first range when distance becomes outside of minimum range
|
346
|
+
if (this.xPct.length + range_counter >= 1) {
|
347
|
+
range_counter--;
|
348
|
+
}
|
502
349
|
}
|
350
|
+
else {
|
351
|
+
abs_distance_counter = abs_distance_counter + rel_range_distance;
|
352
|
+
// Limit range to last range when distance becomes outside of maximum range
|
353
|
+
if (this.xPct.length - range_counter >= 1) {
|
354
|
+
range_counter++;
|
355
|
+
}
|
356
|
+
}
|
357
|
+
// Rest of relative percentual distance still to be calculated
|
358
|
+
rest_rel_distance = distances[xPct_index + range_counter] * rest_factor;
|
503
359
|
}
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
Spectrum.prototype.getStep = function(value) {
|
523
|
-
value = getStep(this.xPct, this.xSteps, this.snap, value);
|
524
|
-
|
525
|
-
return value;
|
526
|
-
};
|
527
|
-
|
528
|
-
Spectrum.prototype.getDefaultStep = function(value, isDown, size) {
|
529
|
-
var j = getJ(value, this.xPct);
|
530
|
-
|
531
|
-
// When at the top or stepping down, look at the previous sub-range
|
532
|
-
if (value === 100 || (isDown && value === this.xPct[j - 1])) {
|
533
|
-
j = Math.max(j - 1, 1);
|
534
|
-
}
|
535
|
-
|
536
|
-
return (this.xVal[j] - this.xVal[j - 1]) / size;
|
537
|
-
};
|
538
|
-
|
539
|
-
Spectrum.prototype.getNearbySteps = function(value) {
|
540
|
-
var j = getJ(value, this.xPct);
|
541
|
-
|
542
|
-
return {
|
543
|
-
stepBefore: {
|
544
|
-
startValue: this.xVal[j - 2],
|
545
|
-
step: this.xNumSteps[j - 2],
|
546
|
-
highestStep: this.xHighestCompleteStep[j - 2]
|
547
|
-
},
|
548
|
-
thisStep: {
|
549
|
-
startValue: this.xVal[j - 1],
|
550
|
-
step: this.xNumSteps[j - 1],
|
551
|
-
highestStep: this.xHighestCompleteStep[j - 1]
|
552
|
-
},
|
553
|
-
stepAfter: {
|
554
|
-
startValue: this.xVal[j],
|
555
|
-
step: this.xNumSteps[j],
|
556
|
-
highestStep: this.xHighestCompleteStep[j]
|
360
|
+
return value + abs_distance_counter;
|
361
|
+
};
|
362
|
+
Spectrum.prototype.toStepping = function (value) {
|
363
|
+
value = toStepping(this.xVal, this.xPct, value);
|
364
|
+
return value;
|
365
|
+
};
|
366
|
+
Spectrum.prototype.fromStepping = function (value) {
|
367
|
+
return fromStepping(this.xVal, this.xPct, value);
|
368
|
+
};
|
369
|
+
Spectrum.prototype.getStep = function (value) {
|
370
|
+
value = getStep(this.xPct, this.xSteps, this.snap, value);
|
371
|
+
return value;
|
372
|
+
};
|
373
|
+
Spectrum.prototype.getDefaultStep = function (value, isDown, size) {
|
374
|
+
var j = getJ(value, this.xPct);
|
375
|
+
// When at the top or stepping down, look at the previous sub-range
|
376
|
+
if (value === 100 || (isDown && value === this.xPct[j - 1])) {
|
377
|
+
j = Math.max(j - 1, 1);
|
557
378
|
}
|
379
|
+
return (this.xVal[j] - this.xVal[j - 1]) / size;
|
558
380
|
};
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
381
|
+
Spectrum.prototype.getNearbySteps = function (value) {
|
382
|
+
var j = getJ(value, this.xPct);
|
383
|
+
return {
|
384
|
+
stepBefore: {
|
385
|
+
startValue: this.xVal[j - 2],
|
386
|
+
step: this.xNumSteps[j - 2],
|
387
|
+
highestStep: this.xHighestCompleteStep[j - 2],
|
388
|
+
},
|
389
|
+
thisStep: {
|
390
|
+
startValue: this.xVal[j - 1],
|
391
|
+
step: this.xNumSteps[j - 1],
|
392
|
+
highestStep: this.xHighestCompleteStep[j - 1],
|
393
|
+
},
|
394
|
+
stepAfter: {
|
395
|
+
startValue: this.xVal[j],
|
396
|
+
step: this.xNumSteps[j],
|
397
|
+
highestStep: this.xHighestCompleteStep[j],
|
398
|
+
},
|
399
|
+
};
|
400
|
+
};
|
401
|
+
Spectrum.prototype.countStepDecimals = function () {
|
402
|
+
var stepDecimals = this.xNumSteps.map(countDecimals);
|
403
|
+
return Math.max.apply(null, stepDecimals);
|
404
|
+
};
|
405
|
+
Spectrum.prototype.hasNoSize = function () {
|
406
|
+
return this.xVal[0] === this.xVal[this.xVal.length - 1];
|
407
|
+
};
|
408
|
+
// Outside testing
|
409
|
+
Spectrum.prototype.convert = function (value) {
|
410
|
+
return this.getStep(this.toStepping(value));
|
411
|
+
};
|
412
|
+
Spectrum.prototype.handleEntryPoint = function (index, value) {
|
413
|
+
var percentage;
|
414
|
+
// Covert min/max syntax to 0 and 100.
|
415
|
+
if (index === "min") {
|
416
|
+
percentage = 0;
|
417
|
+
}
|
418
|
+
else if (index === "max") {
|
419
|
+
percentage = 100;
|
420
|
+
}
|
421
|
+
else {
|
422
|
+
percentage = parseFloat(index);
|
423
|
+
}
|
424
|
+
// Check for correct input.
|
425
|
+
if (!isNumeric(percentage) || !isNumeric(value[0])) {
|
426
|
+
throw new Error("noUiSlider: 'range' value isn't numeric.");
|
427
|
+
}
|
428
|
+
// Store values.
|
429
|
+
this.xPct.push(percentage);
|
430
|
+
this.xVal.push(value[0]);
|
431
|
+
var value1 = Number(value[1]);
|
432
|
+
// NaN will evaluate to false too, but to keep
|
433
|
+
// logging clear, set step explicitly. Make sure
|
434
|
+
// not to override the 'step' setting with false.
|
435
|
+
if (!percentage) {
|
436
|
+
if (!isNaN(value1)) {
|
437
|
+
this.xSteps[0] = value1;
|
438
|
+
}
|
439
|
+
}
|
440
|
+
else {
|
441
|
+
this.xSteps.push(isNaN(value1) ? false : value1);
|
442
|
+
}
|
443
|
+
this.xHighestCompleteStep.push(0);
|
444
|
+
};
|
445
|
+
Spectrum.prototype.handleStepPoint = function (i, n) {
|
446
|
+
// Ignore 'false' stepping.
|
447
|
+
if (!n) {
|
448
|
+
return;
|
449
|
+
}
|
450
|
+
// Step over zero-length ranges (#948);
|
451
|
+
if (this.xVal[i] === this.xVal[i + 1]) {
|
452
|
+
this.xSteps[i] = this.xHighestCompleteStep[i] = this.xVal[i];
|
453
|
+
return;
|
454
|
+
}
|
455
|
+
// Factor to range ratio
|
456
|
+
this.xSteps[i] =
|
457
|
+
fromPercentage([this.xVal[i], this.xVal[i + 1]], n, 0) / subRangeRatio(this.xPct[i], this.xPct[i + 1]);
|
458
|
+
var totalSteps = (this.xVal[i + 1] - this.xVal[i]) / this.xNumSteps[i];
|
459
|
+
var highestStep = Math.ceil(Number(totalSteps.toFixed(3)) - 1);
|
460
|
+
var step = this.xVal[i] + this.xNumSteps[i] * highestStep;
|
461
|
+
this.xHighestCompleteStep[i] = step;
|
462
|
+
};
|
463
|
+
return Spectrum;
|
464
|
+
}());
|
571
465
|
//endregion
|
572
|
-
|
573
466
|
//region Options
|
574
|
-
|
575
|
-
/* Every input option is tested and parsed. This'll prevent
|
467
|
+
/* Every input option is tested and parsed. This will prevent
|
576
468
|
endless validation in internal methods. These tests are
|
577
469
|
structured with an item for every option available. An
|
578
470
|
option can be marked as required by setting the 'r' flag.
|
@@ -584,16 +476,13 @@
|
|
584
476
|
The testing function returns false when an error is detected,
|
585
477
|
or true when everything is OK. It can also modify the option
|
586
478
|
object, to make sure all values can be correctly looped elsewhere. */
|
587
|
-
|
588
479
|
//region Defaults
|
589
|
-
|
590
480
|
var defaultFormatter = {
|
591
|
-
to: function(value) {
|
592
|
-
return value
|
481
|
+
to: function (value) {
|
482
|
+
return value === undefined ? "" : value.toFixed(2);
|
593
483
|
},
|
594
|
-
from: Number
|
484
|
+
from: Number,
|
595
485
|
};
|
596
|
-
|
597
486
|
var cssClasses = {
|
598
487
|
target: "target",
|
599
488
|
base: "base",
|
@@ -630,138 +519,110 @@
|
|
630
519
|
valueVertical: "value-vertical",
|
631
520
|
valueNormal: "value-normal",
|
632
521
|
valueLarge: "value-large",
|
633
|
-
valueSub: "value-sub"
|
522
|
+
valueSub: "value-sub",
|
523
|
+
};
|
524
|
+
// Namespaces of internal event listeners
|
525
|
+
var INTERNAL_EVENT_NS = {
|
526
|
+
tooltips: ".__tooltips",
|
527
|
+
aria: ".__aria",
|
634
528
|
};
|
635
|
-
|
636
529
|
//endregion
|
637
|
-
|
638
|
-
function validateFormat(entry) {
|
639
|
-
// Any object with a to and from method is supported.
|
640
|
-
if (isValidFormatter(entry)) {
|
641
|
-
return true;
|
642
|
-
}
|
643
|
-
|
644
|
-
throw new Error("noUiSlider (" + VERSION + "): 'format' requires 'to' and 'from' methods.");
|
645
|
-
}
|
646
|
-
|
647
530
|
function testStep(parsed, entry) {
|
648
531
|
if (!isNumeric(entry)) {
|
649
|
-
throw new Error("noUiSlider
|
532
|
+
throw new Error("noUiSlider: 'step' is not numeric.");
|
650
533
|
}
|
651
|
-
|
652
534
|
// The step option can still be used to set stepping
|
653
535
|
// for linear sliders. Overwritten if set in 'range'.
|
654
536
|
parsed.singleStep = entry;
|
655
537
|
}
|
656
|
-
|
657
538
|
function testKeyboardPageMultiplier(parsed, entry) {
|
658
539
|
if (!isNumeric(entry)) {
|
659
|
-
throw new Error("noUiSlider
|
540
|
+
throw new Error("noUiSlider: 'keyboardPageMultiplier' is not numeric.");
|
660
541
|
}
|
661
|
-
|
662
542
|
parsed.keyboardPageMultiplier = entry;
|
663
543
|
}
|
664
|
-
|
544
|
+
function testKeyboardMultiplier(parsed, entry) {
|
545
|
+
if (!isNumeric(entry)) {
|
546
|
+
throw new Error("noUiSlider: 'keyboardMultiplier' is not numeric.");
|
547
|
+
}
|
548
|
+
parsed.keyboardMultiplier = entry;
|
549
|
+
}
|
665
550
|
function testKeyboardDefaultStep(parsed, entry) {
|
666
551
|
if (!isNumeric(entry)) {
|
667
|
-
throw new Error("noUiSlider
|
552
|
+
throw new Error("noUiSlider: 'keyboardDefaultStep' is not numeric.");
|
668
553
|
}
|
669
|
-
|
670
554
|
parsed.keyboardDefaultStep = entry;
|
671
555
|
}
|
672
|
-
|
673
556
|
function testRange(parsed, entry) {
|
674
557
|
// Filter incorrect input.
|
675
558
|
if (typeof entry !== "object" || Array.isArray(entry)) {
|
676
|
-
throw new Error("noUiSlider
|
559
|
+
throw new Error("noUiSlider: 'range' is not an object.");
|
677
560
|
}
|
678
|
-
|
679
561
|
// Catch missing start or end.
|
680
562
|
if (entry.min === undefined || entry.max === undefined) {
|
681
|
-
throw new Error("noUiSlider
|
563
|
+
throw new Error("noUiSlider: Missing 'min' or 'max' in 'range'.");
|
682
564
|
}
|
683
|
-
|
684
|
-
// Catch equal start or end.
|
685
|
-
if (entry.min === entry.max) {
|
686
|
-
throw new Error("noUiSlider (" + VERSION + "): 'range' 'min' and 'max' cannot be equal.");
|
687
|
-
}
|
688
|
-
|
689
|
-
parsed.spectrum = new Spectrum(entry, parsed.snap, parsed.singleStep);
|
565
|
+
parsed.spectrum = new Spectrum(entry, parsed.snap || false, parsed.singleStep);
|
690
566
|
}
|
691
|
-
|
692
567
|
function testStart(parsed, entry) {
|
693
568
|
entry = asArray(entry);
|
694
|
-
|
695
569
|
// Validate input. Values aren't tested, as the public .val method
|
696
570
|
// will always provide a valid location.
|
697
571
|
if (!Array.isArray(entry) || !entry.length) {
|
698
|
-
throw new Error("noUiSlider
|
572
|
+
throw new Error("noUiSlider: 'start' option is incorrect.");
|
699
573
|
}
|
700
|
-
|
701
574
|
// Store the number of handles.
|
702
575
|
parsed.handles = entry.length;
|
703
|
-
|
704
576
|
// When the slider is initialized, the .val method will
|
705
577
|
// be called with the start options.
|
706
578
|
parsed.start = entry;
|
707
579
|
}
|
708
|
-
|
709
580
|
function testSnap(parsed, entry) {
|
710
|
-
// Enforce 100% stepping within subranges.
|
711
|
-
parsed.snap = entry;
|
712
|
-
|
713
581
|
if (typeof entry !== "boolean") {
|
714
|
-
throw new Error("noUiSlider
|
582
|
+
throw new Error("noUiSlider: 'snap' option must be a boolean.");
|
715
583
|
}
|
584
|
+
// Enforce 100% stepping within subranges.
|
585
|
+
parsed.snap = entry;
|
716
586
|
}
|
717
|
-
|
718
587
|
function testAnimate(parsed, entry) {
|
719
|
-
// Enforce 100% stepping within subranges.
|
720
|
-
parsed.animate = entry;
|
721
|
-
|
722
588
|
if (typeof entry !== "boolean") {
|
723
|
-
throw new Error("noUiSlider
|
589
|
+
throw new Error("noUiSlider: 'animate' option must be a boolean.");
|
724
590
|
}
|
591
|
+
// Enforce 100% stepping within subranges.
|
592
|
+
parsed.animate = entry;
|
725
593
|
}
|
726
|
-
|
727
594
|
function testAnimationDuration(parsed, entry) {
|
728
|
-
parsed.animationDuration = entry;
|
729
|
-
|
730
595
|
if (typeof entry !== "number") {
|
731
|
-
throw new Error("noUiSlider
|
596
|
+
throw new Error("noUiSlider: 'animationDuration' option must be a number.");
|
732
597
|
}
|
598
|
+
parsed.animationDuration = entry;
|
733
599
|
}
|
734
|
-
|
735
600
|
function testConnect(parsed, entry) {
|
736
601
|
var connect = [false];
|
737
602
|
var i;
|
738
|
-
|
739
603
|
// Map legacy options
|
740
604
|
if (entry === "lower") {
|
741
605
|
entry = [true, false];
|
742
|
-
}
|
606
|
+
}
|
607
|
+
else if (entry === "upper") {
|
743
608
|
entry = [false, true];
|
744
609
|
}
|
745
|
-
|
746
610
|
// Handle boolean options
|
747
611
|
if (entry === true || entry === false) {
|
748
612
|
for (i = 1; i < parsed.handles; i++) {
|
749
613
|
connect.push(entry);
|
750
614
|
}
|
751
|
-
|
752
615
|
connect.push(false);
|
753
616
|
}
|
754
|
-
|
755
617
|
// Reject invalid input
|
756
618
|
else if (!Array.isArray(entry) || !entry.length || entry.length !== parsed.handles + 1) {
|
757
|
-
throw new Error("noUiSlider
|
758
|
-
}
|
619
|
+
throw new Error("noUiSlider: 'connect' option doesn't match handle count.");
|
620
|
+
}
|
621
|
+
else {
|
759
622
|
connect = entry;
|
760
623
|
}
|
761
|
-
|
762
624
|
parsed.connect = connect;
|
763
625
|
}
|
764
|
-
|
765
626
|
function testOrientation(parsed, entry) {
|
766
627
|
// Set orientation to an a numerical value for easy
|
767
628
|
// array selection.
|
@@ -773,81 +634,57 @@
|
|
773
634
|
parsed.ort = 1;
|
774
635
|
break;
|
775
636
|
default:
|
776
|
-
throw new Error("noUiSlider
|
637
|
+
throw new Error("noUiSlider: 'orientation' option is invalid.");
|
777
638
|
}
|
778
639
|
}
|
779
|
-
|
780
640
|
function testMargin(parsed, entry) {
|
781
641
|
if (!isNumeric(entry)) {
|
782
|
-
throw new Error("noUiSlider
|
642
|
+
throw new Error("noUiSlider: 'margin' option must be numeric.");
|
783
643
|
}
|
784
|
-
|
785
644
|
// Issue #582
|
786
645
|
if (entry === 0) {
|
787
646
|
return;
|
788
647
|
}
|
789
|
-
|
790
648
|
parsed.margin = parsed.spectrum.getDistance(entry);
|
791
649
|
}
|
792
|
-
|
793
650
|
function testLimit(parsed, entry) {
|
794
651
|
if (!isNumeric(entry)) {
|
795
|
-
throw new Error("noUiSlider
|
652
|
+
throw new Error("noUiSlider: 'limit' option must be numeric.");
|
796
653
|
}
|
797
|
-
|
798
654
|
parsed.limit = parsed.spectrum.getDistance(entry);
|
799
|
-
|
800
655
|
if (!parsed.limit || parsed.handles < 2) {
|
801
|
-
throw new Error(
|
802
|
-
"noUiSlider (" +
|
803
|
-
VERSION +
|
804
|
-
"): 'limit' option is only supported on linear sliders with 2 or more handles."
|
805
|
-
);
|
656
|
+
throw new Error("noUiSlider: 'limit' option is only supported on linear sliders with 2 or more handles.");
|
806
657
|
}
|
807
658
|
}
|
808
|
-
|
809
659
|
function testPadding(parsed, entry) {
|
810
660
|
var index;
|
811
|
-
|
812
661
|
if (!isNumeric(entry) && !Array.isArray(entry)) {
|
813
|
-
throw new Error(
|
814
|
-
"noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
|
815
|
-
);
|
662
|
+
throw new Error("noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers.");
|
816
663
|
}
|
817
|
-
|
818
664
|
if (Array.isArray(entry) && !(entry.length === 2 || isNumeric(entry[0]) || isNumeric(entry[1]))) {
|
819
|
-
throw new Error(
|
820
|
-
"noUiSlider (" + VERSION + "): 'padding' option must be numeric or array of exactly 2 numbers."
|
821
|
-
);
|
665
|
+
throw new Error("noUiSlider: 'padding' option must be numeric or array of exactly 2 numbers.");
|
822
666
|
}
|
823
|
-
|
824
667
|
if (entry === 0) {
|
825
668
|
return;
|
826
669
|
}
|
827
|
-
|
828
670
|
if (!Array.isArray(entry)) {
|
829
671
|
entry = [entry, entry];
|
830
672
|
}
|
831
|
-
|
832
673
|
// 'getDistance' returns false for invalid values.
|
833
674
|
parsed.padding = [parsed.spectrum.getDistance(entry[0]), parsed.spectrum.getDistance(entry[1])];
|
834
|
-
|
835
675
|
for (index = 0; index < parsed.spectrum.xNumSteps.length - 1; index++) {
|
836
676
|
// last "range" can't contain step size as it is purely an endpoint.
|
837
677
|
if (parsed.padding[0][index] < 0 || parsed.padding[1][index] < 0) {
|
838
|
-
throw new Error("noUiSlider
|
678
|
+
throw new Error("noUiSlider: 'padding' option must be a positive number(s).");
|
839
679
|
}
|
840
680
|
}
|
841
|
-
|
842
681
|
var totalPadding = entry[0] + entry[1];
|
843
682
|
var firstValue = parsed.spectrum.xVal[0];
|
844
683
|
var lastValue = parsed.spectrum.xVal[parsed.spectrum.xVal.length - 1];
|
845
|
-
|
846
684
|
if (totalPadding / (lastValue - firstValue) > 1) {
|
847
|
-
throw new Error("noUiSlider
|
685
|
+
throw new Error("noUiSlider: 'padding' option must not exceed 100% of the range.");
|
848
686
|
}
|
849
687
|
}
|
850
|
-
|
851
688
|
function testDirection(parsed, entry) {
|
852
689
|
// Set direction as a numerical value for easy parsing.
|
853
690
|
// Invert connection for RTL sliders, so that the proper
|
@@ -860,16 +697,14 @@
|
|
860
697
|
parsed.dir = 1;
|
861
698
|
break;
|
862
699
|
default:
|
863
|
-
throw new Error("noUiSlider
|
700
|
+
throw new Error("noUiSlider: 'direction' option was not recognized.");
|
864
701
|
}
|
865
702
|
}
|
866
|
-
|
867
703
|
function testBehaviour(parsed, entry) {
|
868
704
|
// Make sure the input is a string.
|
869
705
|
if (typeof entry !== "string") {
|
870
|
-
throw new Error("noUiSlider
|
706
|
+
throw new Error("noUiSlider: 'behaviour' must be a string containing options.");
|
871
707
|
}
|
872
|
-
|
873
708
|
// Check if the string contains any keywords.
|
874
709
|
// None are required.
|
875
710
|
var tap = entry.indexOf("tap") >= 0;
|
@@ -878,132 +713,119 @@
|
|
878
713
|
var snap = entry.indexOf("snap") >= 0;
|
879
714
|
var hover = entry.indexOf("hover") >= 0;
|
880
715
|
var unconstrained = entry.indexOf("unconstrained") >= 0;
|
881
|
-
|
716
|
+
var dragAll = entry.indexOf("drag-all") >= 0;
|
717
|
+
var smoothSteps = entry.indexOf("smooth-steps") >= 0;
|
882
718
|
if (fixed) {
|
883
719
|
if (parsed.handles !== 2) {
|
884
|
-
throw new Error("noUiSlider
|
720
|
+
throw new Error("noUiSlider: 'fixed' behaviour must be used with 2 handles");
|
885
721
|
}
|
886
|
-
|
887
722
|
// Use margin to enforce fixed state
|
888
723
|
testMargin(parsed, parsed.start[1] - parsed.start[0]);
|
889
724
|
}
|
890
|
-
|
891
725
|
if (unconstrained && (parsed.margin || parsed.limit)) {
|
892
|
-
throw new Error(
|
893
|
-
"noUiSlider (" + VERSION + "): 'unconstrained' behaviour cannot be used with margin or limit"
|
894
|
-
);
|
726
|
+
throw new Error("noUiSlider: 'unconstrained' behaviour cannot be used with margin or limit");
|
895
727
|
}
|
896
|
-
|
897
728
|
parsed.events = {
|
898
729
|
tap: tap || snap,
|
899
730
|
drag: drag,
|
731
|
+
dragAll: dragAll,
|
732
|
+
smoothSteps: smoothSteps,
|
900
733
|
fixed: fixed,
|
901
734
|
snap: snap,
|
902
735
|
hover: hover,
|
903
|
-
unconstrained: unconstrained
|
736
|
+
unconstrained: unconstrained,
|
904
737
|
};
|
905
738
|
}
|
906
|
-
|
907
739
|
function testTooltips(parsed, entry) {
|
908
740
|
if (entry === false) {
|
909
741
|
return;
|
910
742
|
}
|
911
|
-
|
912
|
-
if (entry === true) {
|
743
|
+
if (entry === true || isValidPartialFormatter(entry)) {
|
913
744
|
parsed.tooltips = [];
|
914
|
-
|
915
745
|
for (var i = 0; i < parsed.handles; i++) {
|
916
|
-
parsed.tooltips.push(
|
746
|
+
parsed.tooltips.push(entry);
|
917
747
|
}
|
918
|
-
}
|
919
|
-
|
920
|
-
|
921
|
-
if (
|
922
|
-
throw new Error("noUiSlider
|
748
|
+
}
|
749
|
+
else {
|
750
|
+
entry = asArray(entry);
|
751
|
+
if (entry.length !== parsed.handles) {
|
752
|
+
throw new Error("noUiSlider: must pass a formatter for all handles.");
|
923
753
|
}
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
typeof formatter !== "boolean" &&
|
928
|
-
(typeof formatter !== "object" || typeof formatter.to !== "function")
|
929
|
-
) {
|
930
|
-
throw new Error("noUiSlider (" + VERSION + "): 'tooltips' must be passed a formatter or 'false'.");
|
754
|
+
entry.forEach(function (formatter) {
|
755
|
+
if (typeof formatter !== "boolean" && !isValidPartialFormatter(formatter)) {
|
756
|
+
throw new Error("noUiSlider: 'tooltips' must be passed a formatter or 'false'.");
|
931
757
|
}
|
932
758
|
});
|
759
|
+
parsed.tooltips = entry;
|
933
760
|
}
|
934
761
|
}
|
935
|
-
|
762
|
+
function testHandleAttributes(parsed, entry) {
|
763
|
+
if (entry.length !== parsed.handles) {
|
764
|
+
throw new Error("noUiSlider: must pass a attributes for all handles.");
|
765
|
+
}
|
766
|
+
parsed.handleAttributes = entry;
|
767
|
+
}
|
936
768
|
function testAriaFormat(parsed, entry) {
|
769
|
+
if (!isValidPartialFormatter(entry)) {
|
770
|
+
throw new Error("noUiSlider: 'ariaFormat' requires 'to' method.");
|
771
|
+
}
|
937
772
|
parsed.ariaFormat = entry;
|
938
|
-
validateFormat(entry);
|
939
773
|
}
|
940
|
-
|
941
774
|
function testFormat(parsed, entry) {
|
775
|
+
if (!isValidFormatter(entry)) {
|
776
|
+
throw new Error("noUiSlider: 'format' requires 'to' and 'from' methods.");
|
777
|
+
}
|
942
778
|
parsed.format = entry;
|
943
|
-
validateFormat(entry);
|
944
779
|
}
|
945
|
-
|
946
780
|
function testKeyboardSupport(parsed, entry) {
|
947
|
-
parsed.keyboardSupport = entry;
|
948
|
-
|
949
781
|
if (typeof entry !== "boolean") {
|
950
|
-
throw new Error("noUiSlider
|
782
|
+
throw new Error("noUiSlider: 'keyboardSupport' option must be a boolean.");
|
951
783
|
}
|
784
|
+
parsed.keyboardSupport = entry;
|
952
785
|
}
|
953
|
-
|
954
786
|
function testDocumentElement(parsed, entry) {
|
955
787
|
// This is an advanced option. Passed values are used without validation.
|
956
788
|
parsed.documentElement = entry;
|
957
789
|
}
|
958
|
-
|
959
790
|
function testCssPrefix(parsed, entry) {
|
960
791
|
if (typeof entry !== "string" && entry !== false) {
|
961
|
-
throw new Error("noUiSlider
|
792
|
+
throw new Error("noUiSlider: 'cssPrefix' must be a string or `false`.");
|
962
793
|
}
|
963
|
-
|
964
794
|
parsed.cssPrefix = entry;
|
965
795
|
}
|
966
|
-
|
967
796
|
function testCssClasses(parsed, entry) {
|
968
797
|
if (typeof entry !== "object") {
|
969
|
-
throw new Error("noUiSlider
|
798
|
+
throw new Error("noUiSlider: 'cssClasses' must be an object.");
|
970
799
|
}
|
971
|
-
|
972
800
|
if (typeof parsed.cssPrefix === "string") {
|
973
801
|
parsed.cssClasses = {};
|
974
|
-
|
975
|
-
for (var key in entry) {
|
976
|
-
if (!entry.hasOwnProperty(key)) {
|
977
|
-
continue;
|
978
|
-
}
|
979
|
-
|
802
|
+
Object.keys(entry).forEach(function (key) {
|
980
803
|
parsed.cssClasses[key] = parsed.cssPrefix + entry[key];
|
981
|
-
}
|
982
|
-
}
|
804
|
+
});
|
805
|
+
}
|
806
|
+
else {
|
983
807
|
parsed.cssClasses = entry;
|
984
808
|
}
|
985
809
|
}
|
986
|
-
|
987
810
|
// Test all developer settings and parse to assumption-safe values.
|
988
811
|
function testOptions(options) {
|
989
812
|
// To prove a fix for #537, freeze options here.
|
990
813
|
// If the object is modified, an error will be thrown.
|
991
814
|
// Object.freeze(options);
|
992
|
-
|
993
815
|
var parsed = {
|
994
|
-
margin:
|
995
|
-
limit:
|
996
|
-
padding:
|
816
|
+
margin: null,
|
817
|
+
limit: null,
|
818
|
+
padding: null,
|
997
819
|
animate: true,
|
998
820
|
animationDuration: 300,
|
999
821
|
ariaFormat: defaultFormatter,
|
1000
|
-
format: defaultFormatter
|
822
|
+
format: defaultFormatter,
|
1001
823
|
};
|
1002
|
-
|
1003
824
|
// Tests are executed in the order they are presented here.
|
1004
825
|
var tests = {
|
1005
826
|
step: { r: false, t: testStep },
|
1006
827
|
keyboardPageMultiplier: { r: false, t: testKeyboardPageMultiplier },
|
828
|
+
keyboardMultiplier: { r: false, t: testKeyboardMultiplier },
|
1007
829
|
keyboardDefaultStep: { r: false, t: testKeyboardDefaultStep },
|
1008
830
|
start: { r: true, t: testStart },
|
1009
831
|
connect: { r: true, t: testConnect },
|
@@ -1023,9 +845,9 @@
|
|
1023
845
|
keyboardSupport: { r: true, t: testKeyboardSupport },
|
1024
846
|
documentElement: { r: false, t: testDocumentElement },
|
1025
847
|
cssPrefix: { r: true, t: testCssPrefix },
|
1026
|
-
cssClasses: { r: true, t: testCssClasses }
|
848
|
+
cssClasses: { r: true, t: testCssClasses },
|
849
|
+
handleAttributes: { r: false, t: testHandleAttributes },
|
1027
850
|
};
|
1028
|
-
|
1029
851
|
var defaults = {
|
1030
852
|
connect: false,
|
1031
853
|
direction: "ltr",
|
@@ -1035,33 +857,28 @@
|
|
1035
857
|
cssPrefix: "noUi-",
|
1036
858
|
cssClasses: cssClasses,
|
1037
859
|
keyboardPageMultiplier: 5,
|
1038
|
-
|
860
|
+
keyboardMultiplier: 1,
|
861
|
+
keyboardDefaultStep: 10,
|
1039
862
|
};
|
1040
|
-
|
1041
863
|
// AriaFormat defaults to regular format, if any.
|
1042
864
|
if (options.format && !options.ariaFormat) {
|
1043
865
|
options.ariaFormat = options.format;
|
1044
866
|
}
|
1045
|
-
|
1046
867
|
// Run all options through a testing mechanism to ensure correct
|
1047
868
|
// input. It should be noted that options might get modified to
|
1048
869
|
// be handled properly. E.g. wrapping integers in arrays.
|
1049
|
-
Object.keys(tests).forEach(function(name) {
|
870
|
+
Object.keys(tests).forEach(function (name) {
|
1050
871
|
// If the option isn't set, but it is required, throw an error.
|
1051
872
|
if (!isSet(options[name]) && defaults[name] === undefined) {
|
1052
873
|
if (tests[name].r) {
|
1053
|
-
throw new Error("noUiSlider
|
874
|
+
throw new Error("noUiSlider: '" + name + "' is required.");
|
1054
875
|
}
|
1055
|
-
|
1056
|
-
return true;
|
876
|
+
return;
|
1057
877
|
}
|
1058
|
-
|
1059
878
|
tests[name].t(parsed, !isSet(options[name]) ? defaults[name] : options[name]);
|
1060
879
|
});
|
1061
|
-
|
1062
880
|
// Forward pips options
|
1063
881
|
parsed.pips = options.pips;
|
1064
|
-
|
1065
882
|
// All recent browsers accept unprefixed transform.
|
1066
883
|
// We need -ms- for IE9 and -webkit- for older Android;
|
1067
884
|
// Assume use of -webkit- if unprefixed and -ms- are not supported.
|
@@ -1069,26 +886,21 @@
|
|
1069
886
|
var d = document.createElement("div");
|
1070
887
|
var msPrefix = d.style.msTransform !== undefined;
|
1071
888
|
var noPrefix = d.style.transform !== undefined;
|
1072
|
-
|
1073
889
|
parsed.transformRule = noPrefix ? "transform" : msPrefix ? "msTransform" : "webkitTransform";
|
1074
|
-
|
1075
890
|
// Pips don't move, so we can place them using left/top.
|
1076
|
-
var styles = [
|
1077
|
-
|
891
|
+
var styles = [
|
892
|
+
["left", "top"],
|
893
|
+
["right", "bottom"],
|
894
|
+
];
|
1078
895
|
parsed.style = styles[parsed.dir][parsed.ort];
|
1079
|
-
|
1080
896
|
return parsed;
|
1081
897
|
}
|
1082
|
-
|
1083
898
|
//endregion
|
1084
|
-
|
1085
899
|
function scope(target, options, originalOptions) {
|
1086
900
|
var actions = getActions();
|
1087
901
|
var supportsTouchActionNone = getSupportsTouchActionNone();
|
1088
902
|
var supportsPassive = supportsTouchActionNone && getSupportsPassive();
|
1089
|
-
|
1090
903
|
// All variables local to 'scope' are prefixed with 'scope_'
|
1091
|
-
|
1092
904
|
// Slider DOM Nodes
|
1093
905
|
var scope_Target = target;
|
1094
906
|
var scope_Base;
|
@@ -1096,7 +908,6 @@
|
|
1096
908
|
var scope_Connects;
|
1097
909
|
var scope_Pips;
|
1098
910
|
var scope_Tooltips;
|
1099
|
-
|
1100
911
|
// Slider state values
|
1101
912
|
var scope_Spectrum = options.spectrum;
|
1102
913
|
var scope_Values = [];
|
@@ -1104,89 +915,68 @@
|
|
1104
915
|
var scope_HandleNumbers = [];
|
1105
916
|
var scope_ActiveHandlesCount = 0;
|
1106
917
|
var scope_Events = {};
|
1107
|
-
|
1108
|
-
// Exposed API
|
1109
|
-
var scope_Self;
|
1110
|
-
|
1111
918
|
// Document Nodes
|
1112
919
|
var scope_Document = target.ownerDocument;
|
1113
920
|
var scope_DocumentElement = options.documentElement || scope_Document.documentElement;
|
1114
921
|
var scope_Body = scope_Document.body;
|
1115
|
-
|
1116
|
-
// Pips constants
|
1117
|
-
var PIPS_NONE = -1;
|
1118
|
-
var PIPS_NO_VALUE = 0;
|
1119
|
-
var PIPS_LARGE_VALUE = 1;
|
1120
|
-
var PIPS_SMALL_VALUE = 2;
|
1121
|
-
|
1122
922
|
// For horizontal sliders in standard ltr documents,
|
1123
923
|
// make .noUi-origin overflow to the left so the document doesn't scroll.
|
1124
924
|
var scope_DirOffset = scope_Document.dir === "rtl" || options.ort === 1 ? 0 : 100;
|
1125
|
-
|
1126
925
|
// Creates a node, adds it to target, returns the new node.
|
1127
926
|
function addNodeTo(addTarget, className) {
|
1128
927
|
var div = scope_Document.createElement("div");
|
1129
|
-
|
1130
928
|
if (className) {
|
1131
929
|
addClass(div, className);
|
1132
930
|
}
|
1133
|
-
|
1134
931
|
addTarget.appendChild(div);
|
1135
|
-
|
1136
932
|
return div;
|
1137
933
|
}
|
1138
|
-
|
1139
934
|
// Append a origin to the base
|
1140
935
|
function addOrigin(base, handleNumber) {
|
1141
936
|
var origin = addNodeTo(base, options.cssClasses.origin);
|
1142
937
|
var handle = addNodeTo(origin, options.cssClasses.handle);
|
1143
|
-
|
1144
938
|
addNodeTo(handle, options.cssClasses.touchArea);
|
1145
|
-
|
1146
|
-
handle.setAttribute("data-handle", handleNumber);
|
1147
|
-
|
939
|
+
handle.setAttribute("data-handle", String(handleNumber));
|
1148
940
|
if (options.keyboardSupport) {
|
1149
941
|
// https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
|
1150
942
|
// 0 = focusable and reachable
|
1151
943
|
handle.setAttribute("tabindex", "0");
|
1152
|
-
handle.addEventListener("keydown", function(event) {
|
944
|
+
handle.addEventListener("keydown", function (event) {
|
1153
945
|
return eventKeydown(event, handleNumber);
|
1154
946
|
});
|
1155
947
|
}
|
1156
|
-
|
948
|
+
if (options.handleAttributes !== undefined) {
|
949
|
+
var attributes_1 = options.handleAttributes[handleNumber];
|
950
|
+
Object.keys(attributes_1).forEach(function (attribute) {
|
951
|
+
handle.setAttribute(attribute, attributes_1[attribute]);
|
952
|
+
});
|
953
|
+
}
|
1157
954
|
handle.setAttribute("role", "slider");
|
1158
955
|
handle.setAttribute("aria-orientation", options.ort ? "vertical" : "horizontal");
|
1159
|
-
|
1160
956
|
if (handleNumber === 0) {
|
1161
957
|
addClass(handle, options.cssClasses.handleLower);
|
1162
|
-
}
|
958
|
+
}
|
959
|
+
else if (handleNumber === options.handles - 1) {
|
1163
960
|
addClass(handle, options.cssClasses.handleUpper);
|
1164
961
|
}
|
1165
|
-
|
962
|
+
origin.handle = handle;
|
1166
963
|
return origin;
|
1167
964
|
}
|
1168
|
-
|
1169
965
|
// Insert nodes for connect elements
|
1170
966
|
function addConnect(base, add) {
|
1171
967
|
if (!add) {
|
1172
968
|
return false;
|
1173
969
|
}
|
1174
|
-
|
1175
970
|
return addNodeTo(base, options.cssClasses.connect);
|
1176
971
|
}
|
1177
|
-
|
1178
972
|
// Add handles to the slider base.
|
1179
973
|
function addElements(connectOptions, base) {
|
1180
974
|
var connectBase = addNodeTo(base, options.cssClasses.connects);
|
1181
|
-
|
1182
975
|
scope_Handles = [];
|
1183
976
|
scope_Connects = [];
|
1184
|
-
|
1185
977
|
scope_Connects.push(addConnect(connectBase, connectOptions[0]));
|
1186
|
-
|
1187
978
|
// [::::O====O====O====]
|
1188
979
|
// connectOptions = [0, 1, 1, 1]
|
1189
|
-
|
1190
980
|
for (var i = 0; i < options.handles; i++) {
|
1191
981
|
// Keep a list of all added handles.
|
1192
982
|
scope_Handles.push(addOrigin(base, i));
|
@@ -1194,57 +984,74 @@
|
|
1194
984
|
scope_Connects.push(addConnect(connectBase, connectOptions[i + 1]));
|
1195
985
|
}
|
1196
986
|
}
|
1197
|
-
|
1198
987
|
// Initialize a single slider.
|
1199
988
|
function addSlider(addTarget) {
|
1200
989
|
// Apply classes and data to the target.
|
1201
990
|
addClass(addTarget, options.cssClasses.target);
|
1202
|
-
|
1203
991
|
if (options.dir === 0) {
|
1204
992
|
addClass(addTarget, options.cssClasses.ltr);
|
1205
|
-
}
|
993
|
+
}
|
994
|
+
else {
|
1206
995
|
addClass(addTarget, options.cssClasses.rtl);
|
1207
996
|
}
|
1208
|
-
|
1209
997
|
if (options.ort === 0) {
|
1210
998
|
addClass(addTarget, options.cssClasses.horizontal);
|
1211
|
-
}
|
999
|
+
}
|
1000
|
+
else {
|
1212
1001
|
addClass(addTarget, options.cssClasses.vertical);
|
1213
1002
|
}
|
1214
|
-
|
1215
1003
|
var textDirection = getComputedStyle(addTarget).direction;
|
1216
|
-
|
1217
1004
|
if (textDirection === "rtl") {
|
1218
1005
|
addClass(addTarget, options.cssClasses.textDirectionRtl);
|
1219
|
-
}
|
1006
|
+
}
|
1007
|
+
else {
|
1220
1008
|
addClass(addTarget, options.cssClasses.textDirectionLtr);
|
1221
1009
|
}
|
1222
|
-
|
1223
1010
|
return addNodeTo(addTarget, options.cssClasses.base);
|
1224
1011
|
}
|
1225
|
-
|
1226
1012
|
function addTooltip(handle, handleNumber) {
|
1227
|
-
if (!options.tooltips[handleNumber]) {
|
1013
|
+
if (!options.tooltips || !options.tooltips[handleNumber]) {
|
1228
1014
|
return false;
|
1229
1015
|
}
|
1230
|
-
|
1231
1016
|
return addNodeTo(handle.firstChild, options.cssClasses.tooltip);
|
1232
1017
|
}
|
1233
|
-
|
1234
1018
|
function isSliderDisabled() {
|
1235
1019
|
return scope_Target.hasAttribute("disabled");
|
1236
1020
|
}
|
1237
|
-
|
1238
1021
|
// Disable the slider dragging if any handle is disabled
|
1239
1022
|
function isHandleDisabled(handleNumber) {
|
1240
1023
|
var handleOrigin = scope_Handles[handleNumber];
|
1241
1024
|
return handleOrigin.hasAttribute("disabled");
|
1242
1025
|
}
|
1243
|
-
|
1026
|
+
function disable(handleNumber) {
|
1027
|
+
if (handleNumber !== null && handleNumber !== undefined) {
|
1028
|
+
scope_Handles[handleNumber].setAttribute("disabled", "");
|
1029
|
+
scope_Handles[handleNumber].handle.removeAttribute("tabindex");
|
1030
|
+
}
|
1031
|
+
else {
|
1032
|
+
scope_Target.setAttribute("disabled", "");
|
1033
|
+
scope_Handles.forEach(function (handle) {
|
1034
|
+
handle.handle.removeAttribute("tabindex");
|
1035
|
+
});
|
1036
|
+
}
|
1037
|
+
}
|
1038
|
+
function enable(handleNumber) {
|
1039
|
+
if (handleNumber !== null && handleNumber !== undefined) {
|
1040
|
+
scope_Handles[handleNumber].removeAttribute("disabled");
|
1041
|
+
scope_Handles[handleNumber].handle.setAttribute("tabindex", "0");
|
1042
|
+
}
|
1043
|
+
else {
|
1044
|
+
scope_Target.removeAttribute("disabled");
|
1045
|
+
scope_Handles.forEach(function (handle) {
|
1046
|
+
handle.removeAttribute("disabled");
|
1047
|
+
handle.handle.setAttribute("tabindex", "0");
|
1048
|
+
});
|
1049
|
+
}
|
1050
|
+
}
|
1244
1051
|
function removeTooltips() {
|
1245
1052
|
if (scope_Tooltips) {
|
1246
|
-
removeEvent("update.tooltips
|
1247
|
-
scope_Tooltips.forEach(function(tooltip) {
|
1053
|
+
removeEvent("update" + INTERNAL_EVENT_NS.tooltips);
|
1054
|
+
scope_Tooltips.forEach(function (tooltip) {
|
1248
1055
|
if (tooltip) {
|
1249
1056
|
removeElement(tooltip);
|
1250
1057
|
}
|
@@ -1252,48 +1059,40 @@
|
|
1252
1059
|
scope_Tooltips = null;
|
1253
1060
|
}
|
1254
1061
|
}
|
1255
|
-
|
1256
1062
|
// The tooltips option is a shorthand for using the 'update' event.
|
1257
1063
|
function tooltips() {
|
1258
1064
|
removeTooltips();
|
1259
|
-
|
1260
1065
|
// Tooltips are added with options.tooltips in original order.
|
1261
1066
|
scope_Tooltips = scope_Handles.map(addTooltip);
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1067
|
+
bindEvent("update" + INTERNAL_EVENT_NS.tooltips, function (values, handleNumber, unencoded) {
|
1068
|
+
if (!scope_Tooltips || !options.tooltips) {
|
1069
|
+
return;
|
1070
|
+
}
|
1071
|
+
if (scope_Tooltips[handleNumber] === false) {
|
1265
1072
|
return;
|
1266
1073
|
}
|
1267
|
-
|
1268
1074
|
var formattedValue = values[handleNumber];
|
1269
|
-
|
1270
1075
|
if (options.tooltips[handleNumber] !== true) {
|
1271
1076
|
formattedValue = options.tooltips[handleNumber].to(unencoded[handleNumber]);
|
1272
1077
|
}
|
1273
|
-
|
1274
1078
|
scope_Tooltips[handleNumber].innerHTML = formattedValue;
|
1275
1079
|
});
|
1276
1080
|
}
|
1277
|
-
|
1278
1081
|
function aria() {
|
1279
|
-
|
1082
|
+
removeEvent("update" + INTERNAL_EVENT_NS.aria);
|
1083
|
+
bindEvent("update" + INTERNAL_EVENT_NS.aria, function (values, handleNumber, unencoded, tap, positions) {
|
1280
1084
|
// Update Aria Values for all handles, as a change in one changes min and max values for the next.
|
1281
|
-
scope_HandleNumbers.forEach(function(index) {
|
1085
|
+
scope_HandleNumbers.forEach(function (index) {
|
1282
1086
|
var handle = scope_Handles[index];
|
1283
|
-
|
1284
1087
|
var min = checkHandlePosition(scope_Locations, index, 0, true, true, true);
|
1285
1088
|
var max = checkHandlePosition(scope_Locations, index, 100, true, true, true);
|
1286
|
-
|
1287
1089
|
var now = positions[index];
|
1288
|
-
|
1289
1090
|
// Formatted value for display
|
1290
|
-
var text = options.ariaFormat.to(unencoded[index]);
|
1291
|
-
|
1091
|
+
var text = String(options.ariaFormat.to(unencoded[index]));
|
1292
1092
|
// Map to slider range values
|
1293
1093
|
min = scope_Spectrum.fromStepping(min).toFixed(1);
|
1294
1094
|
max = scope_Spectrum.fromStepping(max).toFixed(1);
|
1295
1095
|
now = scope_Spectrum.fromStepping(now).toFixed(1);
|
1296
|
-
|
1297
1096
|
handle.children[0].setAttribute("aria-valuemin", min);
|
1298
1097
|
handle.children[0].setAttribute("aria-valuemax", max);
|
1299
1098
|
handle.children[0].setAttribute("aria-valuenow", now);
|
@@ -1301,88 +1100,75 @@
|
|
1301
1100
|
});
|
1302
1101
|
});
|
1303
1102
|
}
|
1304
|
-
|
1305
|
-
function getGroup(mode, values, stepped) {
|
1103
|
+
function getGroup(pips) {
|
1306
1104
|
// Use the range.
|
1307
|
-
if (mode ===
|
1105
|
+
if (pips.mode === exports.PipsMode.Range || pips.mode === exports.PipsMode.Steps) {
|
1308
1106
|
return scope_Spectrum.xVal;
|
1309
1107
|
}
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
throw new Error("noUiSlider (" + VERSION + "): 'values' (>= 2) required for mode 'count'.");
|
1108
|
+
if (pips.mode === exports.PipsMode.Count) {
|
1109
|
+
if (pips.values < 2) {
|
1110
|
+
throw new Error("noUiSlider: 'values' (>= 2) required for mode 'count'.");
|
1314
1111
|
}
|
1315
|
-
|
1316
1112
|
// Divide 0 - 100 in 'count' parts.
|
1317
|
-
var interval = values - 1;
|
1113
|
+
var interval = pips.values - 1;
|
1318
1114
|
var spread = 100 / interval;
|
1319
|
-
|
1320
|
-
values = [];
|
1321
|
-
|
1115
|
+
var values = [];
|
1322
1116
|
// List these parts and have them handled as 'positions'.
|
1323
1117
|
while (interval--) {
|
1324
1118
|
values[interval] = interval * spread;
|
1325
1119
|
}
|
1326
|
-
|
1327
1120
|
values.push(100);
|
1328
|
-
|
1329
|
-
mode = "positions";
|
1121
|
+
return mapToRange(values, pips.stepped);
|
1330
1122
|
}
|
1331
|
-
|
1332
|
-
if (mode === "positions") {
|
1123
|
+
if (pips.mode === exports.PipsMode.Positions) {
|
1333
1124
|
// Map all percentages to on-range values.
|
1334
|
-
return values.
|
1335
|
-
return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value);
|
1336
|
-
});
|
1125
|
+
return mapToRange(pips.values, pips.stepped);
|
1337
1126
|
}
|
1338
|
-
|
1339
|
-
if (mode === "values") {
|
1127
|
+
if (pips.mode === exports.PipsMode.Values) {
|
1340
1128
|
// If the value must be stepped, it needs to be converted to a percentage first.
|
1341
|
-
if (stepped) {
|
1342
|
-
return values.map(function(value) {
|
1129
|
+
if (pips.stepped) {
|
1130
|
+
return pips.values.map(function (value) {
|
1343
1131
|
// Convert to percentage, apply step, return to value.
|
1344
1132
|
return scope_Spectrum.fromStepping(scope_Spectrum.getStep(scope_Spectrum.toStepping(value)));
|
1345
1133
|
});
|
1346
1134
|
}
|
1347
|
-
|
1348
1135
|
// Otherwise, we can simply use the values.
|
1349
|
-
return values;
|
1136
|
+
return pips.values;
|
1350
1137
|
}
|
1138
|
+
return []; // pips.mode = never
|
1351
1139
|
}
|
1352
|
-
|
1353
|
-
|
1140
|
+
function mapToRange(values, stepped) {
|
1141
|
+
return values.map(function (value) {
|
1142
|
+
return scope_Spectrum.fromStepping(stepped ? scope_Spectrum.getStep(value) : value);
|
1143
|
+
});
|
1144
|
+
}
|
1145
|
+
function generateSpread(pips) {
|
1354
1146
|
function safeIncrement(value, increment) {
|
1355
1147
|
// Avoid floating point variance by dropping the smallest decimal places.
|
1356
|
-
return (value + increment).toFixed(7)
|
1148
|
+
return Number((value + increment).toFixed(7));
|
1357
1149
|
}
|
1358
|
-
|
1150
|
+
var group = getGroup(pips);
|
1359
1151
|
var indexes = {};
|
1360
1152
|
var firstInRange = scope_Spectrum.xVal[0];
|
1361
1153
|
var lastInRange = scope_Spectrum.xVal[scope_Spectrum.xVal.length - 1];
|
1362
1154
|
var ignoreFirst = false;
|
1363
1155
|
var ignoreLast = false;
|
1364
1156
|
var prevPct = 0;
|
1365
|
-
|
1366
1157
|
// Create a copy of the group, sort it and filter away all duplicates.
|
1367
|
-
group = unique(
|
1368
|
-
|
1369
|
-
|
1370
|
-
})
|
1371
|
-
);
|
1372
|
-
|
1158
|
+
group = unique(group.slice().sort(function (a, b) {
|
1159
|
+
return a - b;
|
1160
|
+
}));
|
1373
1161
|
// Make sure the range starts with the first element.
|
1374
1162
|
if (group[0] !== firstInRange) {
|
1375
1163
|
group.unshift(firstInRange);
|
1376
1164
|
ignoreFirst = true;
|
1377
1165
|
}
|
1378
|
-
|
1379
1166
|
// Likewise for the last one.
|
1380
1167
|
if (group[group.length - 1] !== lastInRange) {
|
1381
1168
|
group.push(lastInRange);
|
1382
1169
|
ignoreLast = true;
|
1383
1170
|
}
|
1384
|
-
|
1385
|
-
group.forEach(function(current, index) {
|
1171
|
+
group.forEach(function (current, index) {
|
1386
1172
|
// Get the current step and the lower + upper positions.
|
1387
1173
|
var step;
|
1388
1174
|
var i;
|
@@ -1396,48 +1182,35 @@
|
|
1396
1182
|
var steps;
|
1397
1183
|
var realSteps;
|
1398
1184
|
var stepSize;
|
1399
|
-
var isSteps = mode ===
|
1400
|
-
|
1185
|
+
var isSteps = pips.mode === exports.PipsMode.Steps;
|
1401
1186
|
// When using 'steps' mode, use the provided steps.
|
1402
1187
|
// Otherwise, we'll step on to the next subrange.
|
1403
1188
|
if (isSteps) {
|
1404
1189
|
step = scope_Spectrum.xNumSteps[index];
|
1405
1190
|
}
|
1406
|
-
|
1407
1191
|
// Default to a 'full' step.
|
1408
1192
|
if (!step) {
|
1409
1193
|
step = high - low;
|
1410
1194
|
}
|
1411
|
-
|
1412
|
-
// Low can be 0, so test for false. Index 0 is already handled.
|
1413
|
-
if (low === false) {
|
1414
|
-
return;
|
1415
|
-
}
|
1416
|
-
|
1417
1195
|
// If high is undefined we are at the last subrange. Make sure it iterates once (#1088)
|
1418
1196
|
if (high === undefined) {
|
1419
1197
|
high = low;
|
1420
1198
|
}
|
1421
|
-
|
1422
1199
|
// Make sure step isn't 0, which would cause an infinite loop (#654)
|
1423
1200
|
step = Math.max(step, 0.0000001);
|
1424
|
-
|
1425
1201
|
// Find all steps in the subrange.
|
1426
1202
|
for (i = low; i <= high; i = safeIncrement(i, step)) {
|
1427
1203
|
// Get the percentage value for the current step,
|
1428
1204
|
// calculate the size for the subrange.
|
1429
1205
|
newPct = scope_Spectrum.toStepping(i);
|
1430
1206
|
pctDifference = newPct - prevPct;
|
1431
|
-
|
1432
|
-
steps = pctDifference / density;
|
1207
|
+
steps = pctDifference / (pips.density || 1);
|
1433
1208
|
realSteps = Math.round(steps);
|
1434
|
-
|
1435
1209
|
// This ratio represents the amount of percentage-space a point indicates.
|
1436
1210
|
// For a density 1 the points/percentage = 1. For density 2, that percentage needs to be re-divided.
|
1437
1211
|
// Round the percentage offset to an even number, then divide by two
|
1438
1212
|
// to spread the offset on both sides of the range.
|
1439
1213
|
stepSize = pctDifference / realSteps;
|
1440
|
-
|
1441
1214
|
// Divide all points evenly, adding the correct number to this subrange.
|
1442
1215
|
// Run up to <= so that 100% gets a point, event if ignoreLast is set.
|
1443
1216
|
for (q = 1; q <= realSteps; q += 1) {
|
@@ -1448,155 +1221,125 @@
|
|
1448
1221
|
pctPos = prevPct + q * stepSize;
|
1449
1222
|
indexes[pctPos.toFixed(5)] = [scope_Spectrum.fromStepping(pctPos), 0];
|
1450
1223
|
}
|
1451
|
-
|
1452
1224
|
// Determine the point type.
|
1453
|
-
type = group.indexOf(i) > -1 ?
|
1454
|
-
|
1225
|
+
type = group.indexOf(i) > -1 ? exports.PipsType.LargeValue : isSteps ? exports.PipsType.SmallValue : exports.PipsType.NoValue;
|
1455
1226
|
// Enforce the 'ignoreFirst' option by overwriting the type for 0.
|
1456
1227
|
if (!index && ignoreFirst && i !== high) {
|
1457
1228
|
type = 0;
|
1458
1229
|
}
|
1459
|
-
|
1460
1230
|
if (!(i === high && ignoreLast)) {
|
1461
1231
|
// Mark the 'type' of this point. 0 = plain, 1 = real value, 2 = step value.
|
1462
1232
|
indexes[newPct.toFixed(5)] = [i, type];
|
1463
1233
|
}
|
1464
|
-
|
1465
1234
|
// Update the percentage count.
|
1466
1235
|
prevPct = newPct;
|
1467
1236
|
}
|
1468
1237
|
});
|
1469
|
-
|
1470
1238
|
return indexes;
|
1471
1239
|
}
|
1472
|
-
|
1473
1240
|
function addMarking(spread, filterFunc, formatter) {
|
1241
|
+
var _a, _b;
|
1474
1242
|
var element = scope_Document.createElement("div");
|
1475
|
-
|
1476
|
-
|
1477
|
-
|
1478
|
-
|
1479
|
-
|
1480
|
-
|
1481
|
-
var markerSizeClasses =
|
1482
|
-
|
1483
|
-
|
1484
|
-
|
1485
|
-
|
1243
|
+
var valueSizeClasses = (_a = {},
|
1244
|
+
_a[exports.PipsType.None] = "",
|
1245
|
+
_a[exports.PipsType.NoValue] = options.cssClasses.valueNormal,
|
1246
|
+
_a[exports.PipsType.LargeValue] = options.cssClasses.valueLarge,
|
1247
|
+
_a[exports.PipsType.SmallValue] = options.cssClasses.valueSub,
|
1248
|
+
_a);
|
1249
|
+
var markerSizeClasses = (_b = {},
|
1250
|
+
_b[exports.PipsType.None] = "",
|
1251
|
+
_b[exports.PipsType.NoValue] = options.cssClasses.markerNormal,
|
1252
|
+
_b[exports.PipsType.LargeValue] = options.cssClasses.markerLarge,
|
1253
|
+
_b[exports.PipsType.SmallValue] = options.cssClasses.markerSub,
|
1254
|
+
_b);
|
1486
1255
|
var valueOrientationClasses = [options.cssClasses.valueHorizontal, options.cssClasses.valueVertical];
|
1487
1256
|
var markerOrientationClasses = [options.cssClasses.markerHorizontal, options.cssClasses.markerVertical];
|
1488
|
-
|
1489
1257
|
addClass(element, options.cssClasses.pips);
|
1490
1258
|
addClass(element, options.ort === 0 ? options.cssClasses.pipsHorizontal : options.cssClasses.pipsVertical);
|
1491
|
-
|
1492
1259
|
function getClasses(type, source) {
|
1493
1260
|
var a = source === options.cssClasses.value;
|
1494
1261
|
var orientationClasses = a ? valueOrientationClasses : markerOrientationClasses;
|
1495
1262
|
var sizeClasses = a ? valueSizeClasses : markerSizeClasses;
|
1496
|
-
|
1497
1263
|
return source + " " + orientationClasses[options.ort] + " " + sizeClasses[type];
|
1498
1264
|
}
|
1499
|
-
|
1500
1265
|
function addSpread(offset, value, type) {
|
1501
1266
|
// Apply the filter function, if it is set.
|
1502
1267
|
type = filterFunc ? filterFunc(value, type) : type;
|
1503
|
-
|
1504
|
-
if (type === PIPS_NONE) {
|
1268
|
+
if (type === exports.PipsType.None) {
|
1505
1269
|
return;
|
1506
1270
|
}
|
1507
|
-
|
1508
1271
|
// Add a marker for every point
|
1509
1272
|
var node = addNodeTo(element, false);
|
1510
1273
|
node.className = getClasses(type, options.cssClasses.marker);
|
1511
1274
|
node.style[options.style] = offset + "%";
|
1512
|
-
|
1513
1275
|
// Values are only appended for points marked '1' or '2'.
|
1514
|
-
if (type >
|
1276
|
+
if (type > exports.PipsType.NoValue) {
|
1515
1277
|
node = addNodeTo(element, false);
|
1516
1278
|
node.className = getClasses(type, options.cssClasses.value);
|
1517
|
-
node.setAttribute("data-value", value);
|
1279
|
+
node.setAttribute("data-value", String(value));
|
1518
1280
|
node.style[options.style] = offset + "%";
|
1519
|
-
node.innerHTML = formatter.to(value);
|
1281
|
+
node.innerHTML = String(formatter.to(value));
|
1520
1282
|
}
|
1521
1283
|
}
|
1522
|
-
|
1523
1284
|
// Append all points.
|
1524
|
-
Object.keys(spread).forEach(function(offset) {
|
1285
|
+
Object.keys(spread).forEach(function (offset) {
|
1525
1286
|
addSpread(offset, spread[offset][0], spread[offset][1]);
|
1526
1287
|
});
|
1527
|
-
|
1528
1288
|
return element;
|
1529
1289
|
}
|
1530
|
-
|
1531
1290
|
function removePips() {
|
1532
1291
|
if (scope_Pips) {
|
1533
1292
|
removeElement(scope_Pips);
|
1534
1293
|
scope_Pips = null;
|
1535
1294
|
}
|
1536
1295
|
}
|
1537
|
-
|
1538
|
-
function pips(grid) {
|
1296
|
+
function pips(pips) {
|
1539
1297
|
// Fix #669
|
1540
1298
|
removePips();
|
1541
|
-
|
1542
|
-
var
|
1543
|
-
var
|
1544
|
-
|
1545
|
-
|
1546
|
-
|
1547
|
-
var group = getGroup(mode, values, stepped);
|
1548
|
-
var spread = generateSpread(density, mode, group);
|
1549
|
-
var format = grid.format || {
|
1550
|
-
to: Math.round
|
1299
|
+
var spread = generateSpread(pips);
|
1300
|
+
var filter = pips.filter;
|
1301
|
+
var format = pips.format || {
|
1302
|
+
to: function (value) {
|
1303
|
+
return String(Math.round(value));
|
1304
|
+
},
|
1551
1305
|
};
|
1552
|
-
|
1553
1306
|
scope_Pips = scope_Target.appendChild(addMarking(spread, filter, format));
|
1554
|
-
|
1555
1307
|
return scope_Pips;
|
1556
1308
|
}
|
1557
|
-
|
1558
1309
|
// Shorthand for base dimensions.
|
1559
1310
|
function baseSize() {
|
1560
1311
|
var rect = scope_Base.getBoundingClientRect();
|
1561
|
-
var alt = "offset" + ["Width", "Height"][options.ort];
|
1312
|
+
var alt = ("offset" + ["Width", "Height"][options.ort]);
|
1562
1313
|
return options.ort === 0 ? rect.width || scope_Base[alt] : rect.height || scope_Base[alt];
|
1563
1314
|
}
|
1564
|
-
|
1565
1315
|
// Handler for attaching events trough a proxy.
|
1566
1316
|
function attachEvent(events, element, callback, data) {
|
1567
1317
|
// This function can be used to 'filter' events to the slider.
|
1568
1318
|
// element is a node, not a nodeList
|
1569
|
-
|
1570
|
-
|
1571
|
-
e = fixEvent(e, data.pageOffset, data.target || element);
|
1572
|
-
|
1319
|
+
var method = function (event) {
|
1320
|
+
var e = fixEvent(event, data.pageOffset, data.target || element);
|
1573
1321
|
// fixEvent returns false if this event has a different target
|
1574
1322
|
// when handling (multi-) touch events;
|
1575
1323
|
if (!e) {
|
1576
1324
|
return false;
|
1577
1325
|
}
|
1578
|
-
|
1579
1326
|
// doNotReject is passed by all end events to make sure released touches
|
1580
1327
|
// are not rejected, leaving the slider "stuck" to the cursor;
|
1581
1328
|
if (isSliderDisabled() && !data.doNotReject) {
|
1582
1329
|
return false;
|
1583
1330
|
}
|
1584
|
-
|
1585
1331
|
// Stop if an active 'tap' transition is taking place.
|
1586
1332
|
if (hasClass(scope_Target, options.cssClasses.tap) && !data.doNotReject) {
|
1587
1333
|
return false;
|
1588
1334
|
}
|
1589
|
-
|
1590
1335
|
// Ignore right or middle clicks on start #454
|
1591
1336
|
if (events === actions.start && e.buttons !== undefined && e.buttons > 1) {
|
1592
1337
|
return false;
|
1593
1338
|
}
|
1594
|
-
|
1595
1339
|
// Ignore right or middle clicks on start #454
|
1596
1340
|
if (data.hover && e.buttons) {
|
1597
1341
|
return false;
|
1598
1342
|
}
|
1599
|
-
|
1600
1343
|
// 'supportsPassive' is only true if a browser also supports touch-action: none in CSS.
|
1601
1344
|
// iOS safari does not, so it doesn't get to benefit from passive scrolling. iOS does support
|
1602
1345
|
// touch-action: manipulation, but that allows panning, which breaks
|
@@ -1605,24 +1348,19 @@
|
|
1605
1348
|
if (!supportsPassive) {
|
1606
1349
|
e.preventDefault();
|
1607
1350
|
}
|
1608
|
-
|
1609
1351
|
e.calcPoint = e.points[options.ort];
|
1610
|
-
|
1611
1352
|
// Call the event handler with the event [ and additional data ].
|
1612
1353
|
callback(e, data);
|
1354
|
+
return;
|
1613
1355
|
};
|
1614
|
-
|
1615
1356
|
var methods = [];
|
1616
|
-
|
1617
1357
|
// Bind a closure on the target for every event type.
|
1618
|
-
events.split(" ").forEach(function(eventName) {
|
1358
|
+
events.split(" ").forEach(function (eventName) {
|
1619
1359
|
element.addEventListener(eventName, method, supportsPassive ? { passive: true } : false);
|
1620
1360
|
methods.push([eventName, method]);
|
1621
1361
|
});
|
1622
|
-
|
1623
1362
|
return methods;
|
1624
1363
|
}
|
1625
|
-
|
1626
1364
|
// Provide a clean event with standardized offset values.
|
1627
1365
|
function fixEvent(e, pageOffset, eventTarget) {
|
1628
1366
|
// Filter the event to register the type, which can be
|
@@ -1631,116 +1369,100 @@
|
|
1631
1369
|
var touch = e.type.indexOf("touch") === 0;
|
1632
1370
|
var mouse = e.type.indexOf("mouse") === 0;
|
1633
1371
|
var pointer = e.type.indexOf("pointer") === 0;
|
1634
|
-
|
1635
|
-
var
|
1636
|
-
var y;
|
1637
|
-
|
1372
|
+
var x = 0;
|
1373
|
+
var y = 0;
|
1638
1374
|
// IE10 implemented pointer events with a prefix;
|
1639
1375
|
if (e.type.indexOf("MSPointer") === 0) {
|
1640
1376
|
pointer = true;
|
1641
1377
|
}
|
1642
|
-
|
1378
|
+
// Erroneous events seem to be passed in occasionally on iOS/iPadOS after user finishes interacting with
|
1379
|
+
// the slider. They appear to be of type MouseEvent, yet they don't have usual properties set. Ignore
|
1380
|
+
// events that have no touches or buttons associated with them. (#1057, #1079, #1095)
|
1381
|
+
if (e.type === "mousedown" && !e.buttons && !e.touches) {
|
1382
|
+
return false;
|
1383
|
+
}
|
1643
1384
|
// The only thing one handle should be concerned about is the touches that originated on top of it.
|
1644
1385
|
if (touch) {
|
1645
1386
|
// Returns true if a touch originated on the target.
|
1646
|
-
var isTouchOnTarget = function(checkTouch) {
|
1647
|
-
|
1648
|
-
|
1649
|
-
eventTarget.contains(
|
1650
|
-
(
|
1651
|
-
);
|
1387
|
+
var isTouchOnTarget = function (checkTouch) {
|
1388
|
+
var target = checkTouch.target;
|
1389
|
+
return (target === eventTarget ||
|
1390
|
+
eventTarget.contains(target) ||
|
1391
|
+
(e.composed && e.composedPath().shift() === eventTarget));
|
1652
1392
|
};
|
1653
|
-
|
1654
1393
|
// In the case of touchstart events, we need to make sure there is still no more than one
|
1655
1394
|
// touch on the target so we look amongst all touches.
|
1656
1395
|
if (e.type === "touchstart") {
|
1657
1396
|
var targetTouches = Array.prototype.filter.call(e.touches, isTouchOnTarget);
|
1658
|
-
|
1659
1397
|
// Do not support more than one touch per handle.
|
1660
1398
|
if (targetTouches.length > 1) {
|
1661
1399
|
return false;
|
1662
1400
|
}
|
1663
|
-
|
1664
1401
|
x = targetTouches[0].pageX;
|
1665
1402
|
y = targetTouches[0].pageY;
|
1666
|
-
}
|
1403
|
+
}
|
1404
|
+
else {
|
1667
1405
|
// In the other cases, find on changedTouches is enough.
|
1668
1406
|
var targetTouch = Array.prototype.find.call(e.changedTouches, isTouchOnTarget);
|
1669
|
-
|
1670
1407
|
// Cancel if the target touch has not moved.
|
1671
1408
|
if (!targetTouch) {
|
1672
1409
|
return false;
|
1673
1410
|
}
|
1674
|
-
|
1675
1411
|
x = targetTouch.pageX;
|
1676
1412
|
y = targetTouch.pageY;
|
1677
1413
|
}
|
1678
1414
|
}
|
1679
|
-
|
1680
1415
|
pageOffset = pageOffset || getPageOffset(scope_Document);
|
1681
|
-
|
1682
1416
|
if (mouse || pointer) {
|
1683
1417
|
x = e.clientX + pageOffset.x;
|
1684
1418
|
y = e.clientY + pageOffset.y;
|
1685
1419
|
}
|
1686
|
-
|
1687
1420
|
e.pageOffset = pageOffset;
|
1688
1421
|
e.points = [x, y];
|
1689
1422
|
e.cursor = mouse || pointer; // Fix #435
|
1690
|
-
|
1691
1423
|
return e;
|
1692
1424
|
}
|
1693
|
-
|
1694
1425
|
// Translate a coordinate in the document to a percentage on the slider
|
1695
1426
|
function calcPointToPercentage(calcPoint) {
|
1696
1427
|
var location = calcPoint - offset(scope_Base, options.ort);
|
1697
1428
|
var proposal = (location * 100) / baseSize();
|
1698
|
-
|
1699
1429
|
// Clamp proposal between 0% and 100%
|
1700
1430
|
// Out-of-bound coordinates may occur when .noUi-base pseudo-elements
|
1701
1431
|
// are used (e.g. contained handles feature)
|
1702
1432
|
proposal = limit(proposal);
|
1703
|
-
|
1704
1433
|
return options.dir ? 100 - proposal : proposal;
|
1705
1434
|
}
|
1706
|
-
|
1707
1435
|
// Find handle closest to a certain percentage on the slider
|
1708
1436
|
function getClosestHandle(clickedPosition) {
|
1709
1437
|
var smallestDifference = 100;
|
1710
1438
|
var handleNumber = false;
|
1711
|
-
|
1712
|
-
scope_Handles.forEach(function(handle, index) {
|
1439
|
+
scope_Handles.forEach(function (handle, index) {
|
1713
1440
|
// Disabled handles are ignored
|
1714
1441
|
if (isHandleDisabled(index)) {
|
1715
1442
|
return;
|
1716
1443
|
}
|
1717
|
-
|
1718
1444
|
var handlePosition = scope_Locations[index];
|
1719
1445
|
var differenceWithThisHandle = Math.abs(handlePosition - clickedPosition);
|
1720
|
-
|
1721
1446
|
// Initial state
|
1722
1447
|
var clickAtEdge = differenceWithThisHandle === 100 && smallestDifference === 100;
|
1723
|
-
|
1724
1448
|
// Difference with this handle is smaller than the previously checked handle
|
1725
1449
|
var isCloser = differenceWithThisHandle < smallestDifference;
|
1726
1450
|
var isCloserAfter = differenceWithThisHandle <= smallestDifference && clickedPosition > handlePosition;
|
1727
|
-
|
1728
1451
|
if (isCloser || isCloserAfter || clickAtEdge) {
|
1729
1452
|
handleNumber = index;
|
1730
1453
|
smallestDifference = differenceWithThisHandle;
|
1731
1454
|
}
|
1732
1455
|
});
|
1733
|
-
|
1734
1456
|
return handleNumber;
|
1735
1457
|
}
|
1736
|
-
|
1737
1458
|
// Fire 'end' when a mouse or pen leaves the document.
|
1738
1459
|
function documentLeave(event, data) {
|
1739
|
-
if (event.type === "mouseout" &&
|
1460
|
+
if (event.type === "mouseout" &&
|
1461
|
+
event.target.nodeName === "HTML" &&
|
1462
|
+
event.relatedTarget === null) {
|
1740
1463
|
eventEnd(event, data);
|
1741
1464
|
}
|
1742
1465
|
}
|
1743
|
-
|
1744
1466
|
// Handle movement on document for handle and range drag.
|
1745
1467
|
function eventMove(event, data) {
|
1746
1468
|
// Fix #498
|
@@ -1751,16 +1473,12 @@
|
|
1751
1473
|
if (navigator.appVersion.indexOf("MSIE 9") === -1 && event.buttons === 0 && data.buttonsProperty !== 0) {
|
1752
1474
|
return eventEnd(event, data);
|
1753
1475
|
}
|
1754
|
-
|
1755
1476
|
// Check if we are moving up or down
|
1756
1477
|
var movement = (options.dir ? -1 : 1) * (event.calcPoint - data.startCalcPoint);
|
1757
|
-
|
1758
1478
|
// Convert the movement into a percentage of the slider width/height
|
1759
1479
|
var proposal = (movement * 100) / data.baseSize;
|
1760
|
-
|
1761
|
-
moveHandles(movement > 0, proposal, data.locations, data.handleNumbers);
|
1480
|
+
moveHandles(movement > 0, proposal, data.locations, data.handleNumbers, data.connect);
|
1762
1481
|
}
|
1763
|
-
|
1764
1482
|
// Unbind move events on document, call callbacks.
|
1765
1483
|
function eventEnd(event, data) {
|
1766
1484
|
// The handle is no longer active, so remove the class.
|
@@ -1768,102 +1486,93 @@
|
|
1768
1486
|
removeClass(data.handle, options.cssClasses.active);
|
1769
1487
|
scope_ActiveHandlesCount -= 1;
|
1770
1488
|
}
|
1771
|
-
|
1772
1489
|
// Unbind the move and end events, which are added on 'start'.
|
1773
|
-
data.listeners.forEach(function(c) {
|
1490
|
+
data.listeners.forEach(function (c) {
|
1774
1491
|
scope_DocumentElement.removeEventListener(c[0], c[1]);
|
1775
1492
|
});
|
1776
|
-
|
1777
1493
|
if (scope_ActiveHandlesCount === 0) {
|
1778
1494
|
// Remove dragging class.
|
1779
1495
|
removeClass(scope_Target, options.cssClasses.drag);
|
1780
1496
|
setZindex();
|
1781
|
-
|
1782
1497
|
// Remove cursor styles and text-selection events bound to the body.
|
1783
1498
|
if (event.cursor) {
|
1784
1499
|
scope_Body.style.cursor = "";
|
1785
1500
|
scope_Body.removeEventListener("selectstart", preventDefault);
|
1786
1501
|
}
|
1787
1502
|
}
|
1788
|
-
|
1789
|
-
|
1503
|
+
if (options.events.smoothSteps) {
|
1504
|
+
data.handleNumbers.forEach(function (handleNumber) {
|
1505
|
+
setHandle(handleNumber, scope_Locations[handleNumber], true, true, false, false);
|
1506
|
+
});
|
1507
|
+
data.handleNumbers.forEach(function (handleNumber) {
|
1508
|
+
fireEvent("update", handleNumber);
|
1509
|
+
});
|
1510
|
+
}
|
1511
|
+
data.handleNumbers.forEach(function (handleNumber) {
|
1790
1512
|
fireEvent("change", handleNumber);
|
1791
1513
|
fireEvent("set", handleNumber);
|
1792
1514
|
fireEvent("end", handleNumber);
|
1793
1515
|
});
|
1794
1516
|
}
|
1795
|
-
|
1796
1517
|
// Bind move events on document.
|
1797
1518
|
function eventStart(event, data) {
|
1798
1519
|
// Ignore event if any handle is disabled
|
1799
1520
|
if (data.handleNumbers.some(isHandleDisabled)) {
|
1800
|
-
return
|
1521
|
+
return;
|
1801
1522
|
}
|
1802
|
-
|
1803
1523
|
var handle;
|
1804
|
-
|
1805
1524
|
if (data.handleNumbers.length === 1) {
|
1806
1525
|
var handleOrigin = scope_Handles[data.handleNumbers[0]];
|
1807
|
-
|
1808
1526
|
handle = handleOrigin.children[0];
|
1809
1527
|
scope_ActiveHandlesCount += 1;
|
1810
|
-
|
1811
1528
|
// Mark the handle as 'active' so it can be styled.
|
1812
1529
|
addClass(handle, options.cssClasses.active);
|
1813
1530
|
}
|
1814
|
-
|
1815
1531
|
// A drag should never propagate up to the 'tap' event.
|
1816
1532
|
event.stopPropagation();
|
1817
|
-
|
1818
1533
|
// Record the event listeners.
|
1819
1534
|
var listeners = [];
|
1820
|
-
|
1821
1535
|
// Attach the move and end events.
|
1822
1536
|
var moveEvent = attachEvent(actions.move, scope_DocumentElement, eventMove, {
|
1823
1537
|
// The event target has changed so we need to propagate the original one so that we keep
|
1824
1538
|
// relying on it to extract target touches.
|
1825
1539
|
target: event.target,
|
1826
1540
|
handle: handle,
|
1541
|
+
connect: data.connect,
|
1827
1542
|
listeners: listeners,
|
1828
1543
|
startCalcPoint: event.calcPoint,
|
1829
1544
|
baseSize: baseSize(),
|
1830
1545
|
pageOffset: event.pageOffset,
|
1831
1546
|
handleNumbers: data.handleNumbers,
|
1832
1547
|
buttonsProperty: event.buttons,
|
1833
|
-
locations: scope_Locations.slice()
|
1548
|
+
locations: scope_Locations.slice(),
|
1834
1549
|
});
|
1835
|
-
|
1836
1550
|
var endEvent = attachEvent(actions.end, scope_DocumentElement, eventEnd, {
|
1837
1551
|
target: event.target,
|
1838
1552
|
handle: handle,
|
1839
1553
|
listeners: listeners,
|
1840
1554
|
doNotReject: true,
|
1841
|
-
handleNumbers: data.handleNumbers
|
1555
|
+
handleNumbers: data.handleNumbers,
|
1842
1556
|
});
|
1843
|
-
|
1844
1557
|
var outEvent = attachEvent("mouseout", scope_DocumentElement, documentLeave, {
|
1845
1558
|
target: event.target,
|
1846
1559
|
handle: handle,
|
1847
1560
|
listeners: listeners,
|
1848
1561
|
doNotReject: true,
|
1849
|
-
handleNumbers: data.handleNumbers
|
1562
|
+
handleNumbers: data.handleNumbers,
|
1850
1563
|
});
|
1851
|
-
|
1852
1564
|
// We want to make sure we pushed the listeners in the listener list rather than creating
|
1853
1565
|
// a new one as it has already been passed to the event handlers.
|
1854
1566
|
listeners.push.apply(listeners, moveEvent.concat(endEvent, outEvent));
|
1855
|
-
|
1856
1567
|
// Text selection isn't an issue on touch devices,
|
1857
1568
|
// so adding cursor styles can be skipped.
|
1858
1569
|
if (event.cursor) {
|
1859
1570
|
// Prevent the 'I' cursor and extend the range-drag cursor.
|
1860
1571
|
scope_Body.style.cursor = getComputedStyle(event.target).cursor;
|
1861
|
-
|
1862
1572
|
// Mark the target with a dragging state.
|
1863
1573
|
if (scope_Handles.length > 1) {
|
1864
1574
|
addClass(scope_Target, options.cssClasses.drag);
|
1865
1575
|
}
|
1866
|
-
|
1867
1576
|
// Prevent text selection when dragging the handles.
|
1868
1577
|
// In noUiSlider <= 9.2.0, this was handled by calling preventDefault on mouse/touch start/move,
|
1869
1578
|
// which is scroll blocking. The selectstart event is supported by FireFox starting from version 52,
|
@@ -1872,194 +1581,155 @@
|
|
1872
1581
|
// See: http://caniuse.com/#search=selectstart
|
1873
1582
|
scope_Body.addEventListener("selectstart", preventDefault, false);
|
1874
1583
|
}
|
1875
|
-
|
1876
|
-
data.handleNumbers.forEach(function(handleNumber) {
|
1584
|
+
data.handleNumbers.forEach(function (handleNumber) {
|
1877
1585
|
fireEvent("start", handleNumber);
|
1878
1586
|
});
|
1879
1587
|
}
|
1880
|
-
|
1881
1588
|
// Move closest handle to tapped location.
|
1882
1589
|
function eventTap(event) {
|
1883
|
-
// Erroneous events seem to be passed in occasionally on iOS/iPadOS after user finishes interacting with
|
1884
|
-
// the slider. They appear to be of type MouseEvent, yet they don't have usual properties set. Ignore tap
|
1885
|
-
// events that have no touches or buttons associated with them.
|
1886
|
-
if (!event.buttons && !event.touches) {
|
1887
|
-
return false;
|
1888
|
-
}
|
1889
|
-
|
1890
1590
|
// The tap event shouldn't propagate up
|
1891
1591
|
event.stopPropagation();
|
1892
|
-
|
1893
1592
|
var proposal = calcPointToPercentage(event.calcPoint);
|
1894
1593
|
var handleNumber = getClosestHandle(proposal);
|
1895
|
-
|
1896
1594
|
// Tackle the case that all handles are 'disabled'.
|
1897
1595
|
if (handleNumber === false) {
|
1898
|
-
return
|
1596
|
+
return;
|
1899
1597
|
}
|
1900
|
-
|
1901
1598
|
// Flag the slider as it is now in a transitional state.
|
1902
1599
|
// Transition takes a configurable amount of ms (default 300). Re-enable the slider after that.
|
1903
1600
|
if (!options.events.snap) {
|
1904
1601
|
addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
|
1905
1602
|
}
|
1906
|
-
|
1907
1603
|
setHandle(handleNumber, proposal, true, true);
|
1908
|
-
|
1909
1604
|
setZindex();
|
1910
|
-
|
1911
1605
|
fireEvent("slide", handleNumber, true);
|
1912
1606
|
fireEvent("update", handleNumber, true);
|
1913
|
-
|
1914
|
-
|
1915
|
-
|
1916
|
-
|
1607
|
+
if (!options.events.snap) {
|
1608
|
+
fireEvent("change", handleNumber, true);
|
1609
|
+
fireEvent("set", handleNumber, true);
|
1610
|
+
}
|
1611
|
+
else {
|
1917
1612
|
eventStart(event, { handleNumbers: [handleNumber] });
|
1918
1613
|
}
|
1919
1614
|
}
|
1920
|
-
|
1921
1615
|
// Fires a 'hover' event for a hovered mouse/pen position.
|
1922
1616
|
function eventHover(event) {
|
1923
1617
|
var proposal = calcPointToPercentage(event.calcPoint);
|
1924
|
-
|
1925
1618
|
var to = scope_Spectrum.getStep(proposal);
|
1926
1619
|
var value = scope_Spectrum.fromStepping(to);
|
1927
|
-
|
1928
|
-
Object.keys(scope_Events).forEach(function(targetEvent) {
|
1620
|
+
Object.keys(scope_Events).forEach(function (targetEvent) {
|
1929
1621
|
if ("hover" === targetEvent.split(".")[0]) {
|
1930
|
-
scope_Events[targetEvent].forEach(function(callback) {
|
1622
|
+
scope_Events[targetEvent].forEach(function (callback) {
|
1931
1623
|
callback.call(scope_Self, value);
|
1932
1624
|
});
|
1933
1625
|
}
|
1934
1626
|
});
|
1935
1627
|
}
|
1936
|
-
|
1937
1628
|
// Handles keydown on focused handles
|
1938
1629
|
// Don't move the document when pressing arrow keys on focused handles
|
1939
1630
|
function eventKeydown(event, handleNumber) {
|
1940
1631
|
if (isSliderDisabled() || isHandleDisabled(handleNumber)) {
|
1941
1632
|
return false;
|
1942
1633
|
}
|
1943
|
-
|
1944
1634
|
var horizontalKeys = ["Left", "Right"];
|
1945
1635
|
var verticalKeys = ["Down", "Up"];
|
1946
1636
|
var largeStepKeys = ["PageDown", "PageUp"];
|
1947
1637
|
var edgeKeys = ["Home", "End"];
|
1948
|
-
|
1949
1638
|
if (options.dir && !options.ort) {
|
1950
1639
|
// On an right-to-left slider, the left and right keys act inverted
|
1951
1640
|
horizontalKeys.reverse();
|
1952
|
-
}
|
1641
|
+
}
|
1642
|
+
else if (options.ort && !options.dir) {
|
1953
1643
|
// On a top-to-bottom slider, the up and down keys act inverted
|
1954
1644
|
verticalKeys.reverse();
|
1955
1645
|
largeStepKeys.reverse();
|
1956
1646
|
}
|
1957
|
-
|
1958
1647
|
// Strip "Arrow" for IE compatibility. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
1959
1648
|
var key = event.key.replace("Arrow", "");
|
1960
|
-
|
1961
1649
|
var isLargeDown = key === largeStepKeys[0];
|
1962
1650
|
var isLargeUp = key === largeStepKeys[1];
|
1963
1651
|
var isDown = key === verticalKeys[0] || key === horizontalKeys[0] || isLargeDown;
|
1964
1652
|
var isUp = key === verticalKeys[1] || key === horizontalKeys[1] || isLargeUp;
|
1965
1653
|
var isMin = key === edgeKeys[0];
|
1966
1654
|
var isMax = key === edgeKeys[1];
|
1967
|
-
|
1968
1655
|
if (!isDown && !isUp && !isMin && !isMax) {
|
1969
1656
|
return true;
|
1970
1657
|
}
|
1971
|
-
|
1972
1658
|
event.preventDefault();
|
1973
|
-
|
1974
1659
|
var to;
|
1975
|
-
|
1976
1660
|
if (isUp || isDown) {
|
1977
|
-
var multiplier = options.keyboardPageMultiplier;
|
1978
1661
|
var direction = isDown ? 0 : 1;
|
1979
1662
|
var steps = getNextStepsForHandle(handleNumber);
|
1980
1663
|
var step = steps[direction];
|
1981
|
-
|
1982
1664
|
// At the edge of a slider, do nothing
|
1983
1665
|
if (step === null) {
|
1984
1666
|
return false;
|
1985
1667
|
}
|
1986
|
-
|
1987
1668
|
// No step set, use the default of 10% of the sub-range
|
1988
1669
|
if (step === false) {
|
1989
|
-
step = scope_Spectrum.getDefaultStep(
|
1990
|
-
scope_Locations[handleNumber],
|
1991
|
-
isDown,
|
1992
|
-
options.keyboardDefaultStep
|
1993
|
-
);
|
1670
|
+
step = scope_Spectrum.getDefaultStep(scope_Locations[handleNumber], isDown, options.keyboardDefaultStep);
|
1994
1671
|
}
|
1995
|
-
|
1996
1672
|
if (isLargeUp || isLargeDown) {
|
1997
|
-
step *=
|
1673
|
+
step *= options.keyboardPageMultiplier;
|
1674
|
+
}
|
1675
|
+
else {
|
1676
|
+
step *= options.keyboardMultiplier;
|
1998
1677
|
}
|
1999
|
-
|
2000
1678
|
// Step over zero-length ranges (#948);
|
2001
1679
|
step = Math.max(step, 0.0000001);
|
2002
|
-
|
2003
1680
|
// Decrement for down steps
|
2004
1681
|
step = (isDown ? -1 : 1) * step;
|
2005
|
-
|
2006
1682
|
to = scope_Values[handleNumber] + step;
|
2007
|
-
}
|
1683
|
+
}
|
1684
|
+
else if (isMax) {
|
2008
1685
|
// End key
|
2009
1686
|
to = options.spectrum.xVal[options.spectrum.xVal.length - 1];
|
2010
|
-
}
|
1687
|
+
}
|
1688
|
+
else {
|
2011
1689
|
// Home key
|
2012
1690
|
to = options.spectrum.xVal[0];
|
2013
1691
|
}
|
2014
|
-
|
2015
1692
|
setHandle(handleNumber, scope_Spectrum.toStepping(to), true, true);
|
2016
|
-
|
2017
1693
|
fireEvent("slide", handleNumber);
|
2018
1694
|
fireEvent("update", handleNumber);
|
2019
1695
|
fireEvent("change", handleNumber);
|
2020
1696
|
fireEvent("set", handleNumber);
|
2021
|
-
|
2022
1697
|
return false;
|
2023
1698
|
}
|
2024
|
-
|
2025
1699
|
// Attach events to several slider parts.
|
2026
1700
|
function bindSliderEvents(behaviour) {
|
2027
1701
|
// Attach the standard drag event to the handles.
|
2028
1702
|
if (!behaviour.fixed) {
|
2029
|
-
scope_Handles.forEach(function(handle, index) {
|
1703
|
+
scope_Handles.forEach(function (handle, index) {
|
2030
1704
|
// These events are only bound to the visual handle
|
2031
1705
|
// element, not the 'real' origin element.
|
2032
1706
|
attachEvent(actions.start, handle.children[0], eventStart, {
|
2033
|
-
handleNumbers: [index]
|
1707
|
+
handleNumbers: [index],
|
2034
1708
|
});
|
2035
1709
|
});
|
2036
1710
|
}
|
2037
|
-
|
2038
1711
|
// Attach the tap event to the slider base.
|
2039
1712
|
if (behaviour.tap) {
|
2040
1713
|
attachEvent(actions.start, scope_Base, eventTap, {});
|
2041
1714
|
}
|
2042
|
-
|
2043
1715
|
// Fire hover events
|
2044
1716
|
if (behaviour.hover) {
|
2045
1717
|
attachEvent(actions.move, scope_Base, eventHover, {
|
2046
|
-
hover: true
|
1718
|
+
hover: true,
|
2047
1719
|
});
|
2048
1720
|
}
|
2049
|
-
|
2050
1721
|
// Make the range draggable.
|
2051
1722
|
if (behaviour.drag) {
|
2052
|
-
scope_Connects.forEach(function(connect, index) {
|
1723
|
+
scope_Connects.forEach(function (connect, index) {
|
2053
1724
|
if (connect === false || index === 0 || index === scope_Connects.length - 1) {
|
2054
1725
|
return;
|
2055
1726
|
}
|
2056
|
-
|
2057
1727
|
var handleBefore = scope_Handles[index - 1];
|
2058
1728
|
var handleAfter = scope_Handles[index];
|
2059
1729
|
var eventHolders = [connect];
|
2060
|
-
|
1730
|
+
var handlesToDrag = [handleBefore, handleAfter];
|
1731
|
+
var handleNumbersToDrag = [index - 1, index];
|
2061
1732
|
addClass(connect, options.cssClasses.draggable);
|
2062
|
-
|
2063
1733
|
// When the range is fixed, the entire range can
|
2064
1734
|
// be dragged by the handles. The handle in the first
|
2065
1735
|
// origin will propagate the start event upward,
|
@@ -2068,199 +1738,182 @@
|
|
2068
1738
|
eventHolders.push(handleBefore.children[0]);
|
2069
1739
|
eventHolders.push(handleAfter.children[0]);
|
2070
1740
|
}
|
2071
|
-
|
2072
|
-
|
1741
|
+
if (behaviour.dragAll) {
|
1742
|
+
handlesToDrag = scope_Handles;
|
1743
|
+
handleNumbersToDrag = scope_HandleNumbers;
|
1744
|
+
}
|
1745
|
+
eventHolders.forEach(function (eventHolder) {
|
2073
1746
|
attachEvent(actions.start, eventHolder, eventStart, {
|
2074
|
-
handles:
|
2075
|
-
handleNumbers:
|
1747
|
+
handles: handlesToDrag,
|
1748
|
+
handleNumbers: handleNumbersToDrag,
|
1749
|
+
connect: connect,
|
2076
1750
|
});
|
2077
1751
|
});
|
2078
1752
|
});
|
2079
1753
|
}
|
2080
1754
|
}
|
2081
|
-
|
2082
1755
|
// Attach an event to this slider, possibly including a namespace
|
2083
1756
|
function bindEvent(namespacedEvent, callback) {
|
2084
1757
|
scope_Events[namespacedEvent] = scope_Events[namespacedEvent] || [];
|
2085
1758
|
scope_Events[namespacedEvent].push(callback);
|
2086
|
-
|
2087
1759
|
// If the event bound is 'update,' fire it immediately for all handles.
|
2088
1760
|
if (namespacedEvent.split(".")[0] === "update") {
|
2089
|
-
scope_Handles.forEach(function(a, index) {
|
1761
|
+
scope_Handles.forEach(function (a, index) {
|
2090
1762
|
fireEvent("update", index);
|
2091
1763
|
});
|
2092
1764
|
}
|
2093
1765
|
}
|
2094
|
-
|
1766
|
+
function isInternalNamespace(namespace) {
|
1767
|
+
return namespace === INTERNAL_EVENT_NS.aria || namespace === INTERNAL_EVENT_NS.tooltips;
|
1768
|
+
}
|
2095
1769
|
// Undo attachment of event
|
2096
1770
|
function removeEvent(namespacedEvent) {
|
2097
1771
|
var event = namespacedEvent && namespacedEvent.split(".")[0];
|
2098
|
-
var namespace = event
|
2099
|
-
|
2100
|
-
Object.keys(scope_Events).forEach(function(bind) {
|
1772
|
+
var namespace = event ? namespacedEvent.substring(event.length) : namespacedEvent;
|
1773
|
+
Object.keys(scope_Events).forEach(function (bind) {
|
2101
1774
|
var tEvent = bind.split(".")[0];
|
2102
1775
|
var tNamespace = bind.substring(tEvent.length);
|
2103
|
-
|
2104
1776
|
if ((!event || event === tEvent) && (!namespace || namespace === tNamespace)) {
|
2105
|
-
delete
|
1777
|
+
// only delete protected internal event if intentional
|
1778
|
+
if (!isInternalNamespace(tNamespace) || namespace === tNamespace) {
|
1779
|
+
delete scope_Events[bind];
|
1780
|
+
}
|
2106
1781
|
}
|
2107
1782
|
});
|
2108
1783
|
}
|
2109
|
-
|
2110
1784
|
// External event handling
|
2111
1785
|
function fireEvent(eventName, handleNumber, tap) {
|
2112
|
-
Object.keys(scope_Events).forEach(function(targetEvent) {
|
1786
|
+
Object.keys(scope_Events).forEach(function (targetEvent) {
|
2113
1787
|
var eventType = targetEvent.split(".")[0];
|
2114
|
-
|
2115
1788
|
if (eventName === eventType) {
|
2116
|
-
scope_Events[targetEvent].forEach(function(callback) {
|
1789
|
+
scope_Events[targetEvent].forEach(function (callback) {
|
2117
1790
|
callback.call(
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
|
2132
|
-
);
|
1791
|
+
// Use the slider public API as the scope ('this')
|
1792
|
+
scope_Self,
|
1793
|
+
// Return values as array, so arg_1[arg_2] is always valid.
|
1794
|
+
scope_Values.map(options.format.to),
|
1795
|
+
// Handle index, 0 or 1
|
1796
|
+
handleNumber,
|
1797
|
+
// Un-formatted slider values
|
1798
|
+
scope_Values.slice(),
|
1799
|
+
// Event is fired by tap, true or false
|
1800
|
+
tap || false,
|
1801
|
+
// Left offset of the handle, in relation to the slider
|
1802
|
+
scope_Locations.slice(),
|
1803
|
+
// add the slider public API to an accessible parameter when this is unavailable
|
1804
|
+
scope_Self);
|
2133
1805
|
});
|
2134
1806
|
}
|
2135
1807
|
});
|
2136
1808
|
}
|
2137
|
-
|
2138
1809
|
// Split out the handle positioning logic so the Move event can use it, too
|
2139
|
-
function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue) {
|
1810
|
+
function checkHandlePosition(reference, handleNumber, to, lookBackward, lookForward, getValue, smoothSteps) {
|
2140
1811
|
var distance;
|
2141
|
-
|
2142
1812
|
// For sliders with multiple handles, limit movement to the other handle.
|
2143
1813
|
// Apply the margin option by adding it to the handle positions.
|
2144
1814
|
if (scope_Handles.length > 1 && !options.events.unconstrained) {
|
2145
1815
|
if (lookBackward && handleNumber > 0) {
|
2146
|
-
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin,
|
1816
|
+
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.margin, false);
|
2147
1817
|
to = Math.max(to, distance);
|
2148
1818
|
}
|
2149
|
-
|
2150
1819
|
if (lookForward && handleNumber < scope_Handles.length - 1) {
|
2151
|
-
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin,
|
1820
|
+
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.margin, true);
|
2152
1821
|
to = Math.min(to, distance);
|
2153
1822
|
}
|
2154
1823
|
}
|
2155
|
-
|
2156
1824
|
// The limit option has the opposite effect, limiting handles to a
|
2157
1825
|
// maximum distance from another. Limit must be > 0, as otherwise
|
2158
1826
|
// handles would be unmovable.
|
2159
1827
|
if (scope_Handles.length > 1 && options.limit) {
|
2160
1828
|
if (lookBackward && handleNumber > 0) {
|
2161
|
-
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit,
|
1829
|
+
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber - 1], options.limit, false);
|
2162
1830
|
to = Math.min(to, distance);
|
2163
1831
|
}
|
2164
|
-
|
2165
1832
|
if (lookForward && handleNumber < scope_Handles.length - 1) {
|
2166
|
-
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit,
|
1833
|
+
distance = scope_Spectrum.getAbsoluteDistance(reference[handleNumber + 1], options.limit, true);
|
2167
1834
|
to = Math.max(to, distance);
|
2168
1835
|
}
|
2169
1836
|
}
|
2170
|
-
|
2171
1837
|
// The padding option keeps the handles a certain distance from the
|
2172
1838
|
// edges of the slider. Padding must be > 0.
|
2173
1839
|
if (options.padding) {
|
2174
1840
|
if (handleNumber === 0) {
|
2175
|
-
distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0],
|
1841
|
+
distance = scope_Spectrum.getAbsoluteDistance(0, options.padding[0], false);
|
2176
1842
|
to = Math.max(to, distance);
|
2177
1843
|
}
|
2178
|
-
|
2179
1844
|
if (handleNumber === scope_Handles.length - 1) {
|
2180
|
-
distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1],
|
1845
|
+
distance = scope_Spectrum.getAbsoluteDistance(100, options.padding[1], true);
|
2181
1846
|
to = Math.min(to, distance);
|
2182
1847
|
}
|
2183
1848
|
}
|
2184
|
-
|
2185
|
-
|
2186
|
-
|
1849
|
+
if (!smoothSteps) {
|
1850
|
+
to = scope_Spectrum.getStep(to);
|
1851
|
+
}
|
2187
1852
|
// Limit percentage to the 0 - 100 range
|
2188
1853
|
to = limit(to);
|
2189
|
-
|
2190
1854
|
// Return false if handle can't move
|
2191
1855
|
if (to === reference[handleNumber] && !getValue) {
|
2192
1856
|
return false;
|
2193
1857
|
}
|
2194
|
-
|
2195
1858
|
return to;
|
2196
1859
|
}
|
2197
|
-
|
2198
1860
|
// Uses slider orientation to create CSS rules. a = base value;
|
2199
1861
|
function inRuleOrder(v, a) {
|
2200
1862
|
var o = options.ort;
|
2201
1863
|
return (o ? a : v) + ", " + (o ? v : a);
|
2202
1864
|
}
|
2203
|
-
|
2204
1865
|
// Moves handle(s) by a percentage
|
2205
1866
|
// (bool, % to move, [% where handle started, ...], [index in scope_Handles, ...])
|
2206
|
-
function moveHandles(upward, proposal, locations, handleNumbers) {
|
1867
|
+
function moveHandles(upward, proposal, locations, handleNumbers, connect) {
|
2207
1868
|
var proposals = locations.slice();
|
2208
|
-
|
1869
|
+
// Store first handle now, so we still have it in case handleNumbers is reversed
|
1870
|
+
var firstHandle = handleNumbers[0];
|
1871
|
+
var smoothSteps = options.events.smoothSteps;
|
2209
1872
|
var b = [!upward, upward];
|
2210
1873
|
var f = [upward, !upward];
|
2211
|
-
|
2212
1874
|
// Copy handleNumbers so we don't change the dataset
|
2213
1875
|
handleNumbers = handleNumbers.slice();
|
2214
|
-
|
2215
1876
|
// Check to see which handle is 'leading'.
|
2216
1877
|
// If that one can't move the second can't either.
|
2217
1878
|
if (upward) {
|
2218
1879
|
handleNumbers.reverse();
|
2219
1880
|
}
|
2220
|
-
|
2221
1881
|
// Step 1: get the maximum percentage that any of the handles can move
|
2222
1882
|
if (handleNumbers.length > 1) {
|
2223
|
-
handleNumbers.forEach(function(handleNumber, o) {
|
2224
|
-
var to = checkHandlePosition(
|
2225
|
-
proposals,
|
2226
|
-
handleNumber,
|
2227
|
-
proposals[handleNumber] + proposal,
|
2228
|
-
b[o],
|
2229
|
-
f[o],
|
2230
|
-
false
|
2231
|
-
);
|
2232
|
-
|
1883
|
+
handleNumbers.forEach(function (handleNumber, o) {
|
1884
|
+
var to = checkHandlePosition(proposals, handleNumber, proposals[handleNumber] + proposal, b[o], f[o], false, smoothSteps);
|
2233
1885
|
// Stop if one of the handles can't move.
|
2234
1886
|
if (to === false) {
|
2235
1887
|
proposal = 0;
|
2236
|
-
}
|
1888
|
+
}
|
1889
|
+
else {
|
2237
1890
|
proposal = to - proposals[handleNumber];
|
2238
1891
|
proposals[handleNumber] = to;
|
2239
1892
|
}
|
2240
1893
|
});
|
2241
1894
|
}
|
2242
|
-
|
2243
1895
|
// If using one handle, check backward AND forward
|
2244
1896
|
else {
|
2245
1897
|
b = f = [true];
|
2246
1898
|
}
|
2247
|
-
|
2248
1899
|
var state = false;
|
2249
|
-
|
2250
1900
|
// Step 2: Try to set the handles with the found percentage
|
2251
|
-
handleNumbers.forEach(function(handleNumber, o) {
|
2252
|
-
state =
|
1901
|
+
handleNumbers.forEach(function (handleNumber, o) {
|
1902
|
+
state =
|
1903
|
+
setHandle(handleNumber, locations[handleNumber] + proposal, b[o], f[o], false, smoothSteps) || state;
|
2253
1904
|
});
|
2254
|
-
|
2255
1905
|
// Step 3: If a handle moved, fire events
|
2256
1906
|
if (state) {
|
2257
|
-
handleNumbers.forEach(function(handleNumber) {
|
1907
|
+
handleNumbers.forEach(function (handleNumber) {
|
2258
1908
|
fireEvent("update", handleNumber);
|
2259
1909
|
fireEvent("slide", handleNumber);
|
2260
1910
|
});
|
1911
|
+
// If target is a connect, then fire drag event
|
1912
|
+
if (connect != undefined) {
|
1913
|
+
fireEvent("drag", firstHandle);
|
1914
|
+
}
|
2261
1915
|
}
|
2262
1916
|
}
|
2263
|
-
|
2264
1917
|
// Takes a base value and an offset. This offset is used for the connect bar size.
|
2265
1918
|
// In the initial design for this feature, the origin element was 1% wide.
|
2266
1919
|
// Unfortunately, a rounding bug in Chrome makes it impossible to implement this feature
|
@@ -2268,66 +1921,54 @@
|
|
2268
1921
|
function transformDirection(a, b) {
|
2269
1922
|
return options.dir ? 100 - a - b : a;
|
2270
1923
|
}
|
2271
|
-
|
2272
1924
|
// Updates scope_Locations and scope_Values, updates visual state
|
2273
1925
|
function updateHandlePosition(handleNumber, to) {
|
2274
1926
|
// Update locations.
|
2275
1927
|
scope_Locations[handleNumber] = to;
|
2276
|
-
|
2277
1928
|
// Convert the value to the slider stepping/range.
|
2278
1929
|
scope_Values[handleNumber] = scope_Spectrum.fromStepping(to);
|
2279
|
-
|
2280
|
-
var translation = 10 * (transformDirection(to, 0) - scope_DirOffset);
|
1930
|
+
var translation = transformDirection(to, 0) - scope_DirOffset;
|
2281
1931
|
var translateRule = "translate(" + inRuleOrder(translation + "%", "0") + ")";
|
2282
|
-
|
2283
1932
|
scope_Handles[handleNumber].style[options.transformRule] = translateRule;
|
2284
|
-
|
2285
1933
|
updateConnect(handleNumber);
|
2286
1934
|
updateConnect(handleNumber + 1);
|
2287
1935
|
}
|
2288
|
-
|
2289
1936
|
// Handles before the slider middle are stacked later = higher,
|
2290
1937
|
// Handles after the middle later is lower
|
2291
1938
|
// [[7] [8] .......... | .......... [5] [4]
|
2292
1939
|
function setZindex() {
|
2293
|
-
scope_HandleNumbers.forEach(function(handleNumber) {
|
1940
|
+
scope_HandleNumbers.forEach(function (handleNumber) {
|
2294
1941
|
var dir = scope_Locations[handleNumber] > 50 ? -1 : 1;
|
2295
1942
|
var zIndex = 3 + (scope_Handles.length + dir * handleNumber);
|
2296
|
-
scope_Handles[handleNumber].style.zIndex = zIndex;
|
1943
|
+
scope_Handles[handleNumber].style.zIndex = String(zIndex);
|
2297
1944
|
});
|
2298
1945
|
}
|
2299
|
-
|
2300
1946
|
// Test suggested values and apply margin, step.
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
1947
|
+
// if exactInput is true, don't run checkHandlePosition, then the handle can be placed in between steps (#436)
|
1948
|
+
function setHandle(handleNumber, to, lookBackward, lookForward, exactInput, smoothSteps) {
|
1949
|
+
if (!exactInput) {
|
1950
|
+
to = checkHandlePosition(scope_Locations, handleNumber, to, lookBackward, lookForward, false, smoothSteps);
|
1951
|
+
}
|
2304
1952
|
if (to === false) {
|
2305
1953
|
return false;
|
2306
1954
|
}
|
2307
|
-
|
2308
1955
|
updateHandlePosition(handleNumber, to);
|
2309
|
-
|
2310
1956
|
return true;
|
2311
1957
|
}
|
2312
|
-
|
2313
1958
|
// Updates style attribute for connect nodes
|
2314
1959
|
function updateConnect(index) {
|
2315
1960
|
// Skip connects set to false
|
2316
1961
|
if (!scope_Connects[index]) {
|
2317
1962
|
return;
|
2318
1963
|
}
|
2319
|
-
|
2320
1964
|
var l = 0;
|
2321
1965
|
var h = 100;
|
2322
|
-
|
2323
1966
|
if (index !== 0) {
|
2324
1967
|
l = scope_Locations[index - 1];
|
2325
1968
|
}
|
2326
|
-
|
2327
1969
|
if (index !== scope_Connects.length - 1) {
|
2328
1970
|
h = scope_Locations[index];
|
2329
1971
|
}
|
2330
|
-
|
2331
1972
|
// We use two rules:
|
2332
1973
|
// 'translate' to change the left/top offset;
|
2333
1974
|
// 'scale' to change the width of the element;
|
@@ -2335,10 +1976,9 @@
|
|
2335
1976
|
var connectWidth = h - l;
|
2336
1977
|
var translateRule = "translate(" + inRuleOrder(transformDirection(l, connectWidth) + "%", "0") + ")";
|
2337
1978
|
var scaleRule = "scale(" + inRuleOrder(connectWidth / 100, "1") + ")";
|
2338
|
-
|
2339
|
-
|
1979
|
+
scope_Connects[index].style[options.transformRule] =
|
1980
|
+
translateRule + " " + scaleRule;
|
2340
1981
|
}
|
2341
|
-
|
2342
1982
|
// Parses value passed to .set method. Returns current value if not parse-able.
|
2343
1983
|
function resolveToValue(to, handleNumber) {
|
2344
1984
|
// Setting with null indicates an 'ignore'.
|
@@ -2346,131 +1986,122 @@
|
|
2346
1986
|
if (to === null || to === false || to === undefined) {
|
2347
1987
|
return scope_Locations[handleNumber];
|
2348
1988
|
}
|
2349
|
-
|
2350
1989
|
// If a formatted number was passed, attempt to decode it.
|
2351
1990
|
if (typeof to === "number") {
|
2352
1991
|
to = String(to);
|
2353
1992
|
}
|
2354
|
-
|
2355
1993
|
to = options.format.from(to);
|
2356
|
-
to
|
2357
|
-
|
1994
|
+
if (to !== false) {
|
1995
|
+
to = scope_Spectrum.toStepping(to);
|
1996
|
+
}
|
2358
1997
|
// If parsing the number failed, use the current value.
|
2359
1998
|
if (to === false || isNaN(to)) {
|
2360
1999
|
return scope_Locations[handleNumber];
|
2361
2000
|
}
|
2362
|
-
|
2363
2001
|
return to;
|
2364
2002
|
}
|
2365
|
-
|
2366
2003
|
// Set the slider value.
|
2367
|
-
function valueSet(input, fireSetEvent) {
|
2004
|
+
function valueSet(input, fireSetEvent, exactInput) {
|
2368
2005
|
var values = asArray(input);
|
2369
2006
|
var isInit = scope_Locations[0] === undefined;
|
2370
|
-
|
2371
2007
|
// Event fires by default
|
2372
|
-
fireSetEvent = fireSetEvent === undefined ? true :
|
2373
|
-
|
2008
|
+
fireSetEvent = fireSetEvent === undefined ? true : fireSetEvent;
|
2374
2009
|
// Animation is optional.
|
2375
2010
|
// Make sure the initial values were set before using animated placement.
|
2376
2011
|
if (options.animate && !isInit) {
|
2377
2012
|
addClassFor(scope_Target, options.cssClasses.tap, options.animationDuration);
|
2378
2013
|
}
|
2379
|
-
|
2380
2014
|
// First pass, without lookAhead but with lookBackward. Values are set from left to right.
|
2381
|
-
scope_HandleNumbers.forEach(function(handleNumber) {
|
2382
|
-
setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false);
|
2015
|
+
scope_HandleNumbers.forEach(function (handleNumber) {
|
2016
|
+
setHandle(handleNumber, resolveToValue(values[handleNumber], handleNumber), true, false, exactInput);
|
2383
2017
|
});
|
2384
|
-
|
2385
2018
|
var i = scope_HandleNumbers.length === 1 ? 0 : 1;
|
2386
|
-
|
2019
|
+
// Spread handles evenly across the slider if the range has no size (min=max)
|
2020
|
+
if (isInit && scope_Spectrum.hasNoSize()) {
|
2021
|
+
exactInput = true;
|
2022
|
+
scope_Locations[0] = 0;
|
2023
|
+
if (scope_HandleNumbers.length > 1) {
|
2024
|
+
var space_1 = 100 / (scope_HandleNumbers.length - 1);
|
2025
|
+
scope_HandleNumbers.forEach(function (handleNumber) {
|
2026
|
+
scope_Locations[handleNumber] = handleNumber * space_1;
|
2027
|
+
});
|
2028
|
+
}
|
2029
|
+
}
|
2387
2030
|
// Secondary passes. Now that all base values are set, apply constraints.
|
2388
2031
|
// Iterate all handles to ensure constraints are applied for the entire slider (Issue #1009)
|
2389
2032
|
for (; i < scope_HandleNumbers.length; ++i) {
|
2390
|
-
scope_HandleNumbers.forEach(function(handleNumber) {
|
2391
|
-
setHandle(handleNumber, scope_Locations[handleNumber], true, true);
|
2033
|
+
scope_HandleNumbers.forEach(function (handleNumber) {
|
2034
|
+
setHandle(handleNumber, scope_Locations[handleNumber], true, true, exactInput);
|
2392
2035
|
});
|
2393
2036
|
}
|
2394
|
-
|
2395
2037
|
setZindex();
|
2396
|
-
|
2397
|
-
scope_HandleNumbers.forEach(function(handleNumber) {
|
2038
|
+
scope_HandleNumbers.forEach(function (handleNumber) {
|
2398
2039
|
fireEvent("update", handleNumber);
|
2399
|
-
|
2400
2040
|
// Fire the event only for handles that received a new value, as per #579
|
2401
2041
|
if (values[handleNumber] !== null && fireSetEvent) {
|
2402
2042
|
fireEvent("set", handleNumber);
|
2403
2043
|
}
|
2404
2044
|
});
|
2405
2045
|
}
|
2406
|
-
|
2407
2046
|
// Reset slider to initial values
|
2408
2047
|
function valueReset(fireSetEvent) {
|
2409
2048
|
valueSet(options.start, fireSetEvent);
|
2410
2049
|
}
|
2411
|
-
|
2412
2050
|
// Set value for a single handle
|
2413
|
-
function valueSetHandle(handleNumber, value, fireSetEvent) {
|
2051
|
+
function valueSetHandle(handleNumber, value, fireSetEvent, exactInput) {
|
2414
2052
|
// Ensure numeric input
|
2415
2053
|
handleNumber = Number(handleNumber);
|
2416
|
-
|
2417
2054
|
if (!(handleNumber >= 0 && handleNumber < scope_HandleNumbers.length)) {
|
2418
|
-
throw new Error("noUiSlider
|
2055
|
+
throw new Error("noUiSlider: invalid handle number, got: " + handleNumber);
|
2419
2056
|
}
|
2420
|
-
|
2421
2057
|
// Look both backward and forward, since we don't want this handle to "push" other handles (#960);
|
2422
|
-
|
2423
|
-
|
2058
|
+
// The exactInput argument can be used to ignore slider stepping (#436)
|
2059
|
+
setHandle(handleNumber, resolveToValue(value, handleNumber), true, true, exactInput);
|
2424
2060
|
fireEvent("update", handleNumber);
|
2425
|
-
|
2426
2061
|
if (fireSetEvent) {
|
2427
2062
|
fireEvent("set", handleNumber);
|
2428
2063
|
}
|
2429
2064
|
}
|
2430
|
-
|
2431
2065
|
// Get the slider value.
|
2432
|
-
function valueGet() {
|
2066
|
+
function valueGet(unencoded) {
|
2067
|
+
if (unencoded === void 0) { unencoded = false; }
|
2068
|
+
if (unencoded) {
|
2069
|
+
// return a copy of the raw values
|
2070
|
+
return scope_Values.length === 1 ? scope_Values[0] : scope_Values.slice(0);
|
2071
|
+
}
|
2433
2072
|
var values = scope_Values.map(options.format.to);
|
2434
|
-
|
2435
2073
|
// If only one handle is used, return a single value.
|
2436
2074
|
if (values.length === 1) {
|
2437
2075
|
return values[0];
|
2438
2076
|
}
|
2439
|
-
|
2440
2077
|
return values;
|
2441
2078
|
}
|
2442
|
-
|
2443
2079
|
// Removes classes from the root and empties it.
|
2444
2080
|
function destroy() {
|
2445
|
-
|
2446
|
-
|
2447
|
-
|
2448
|
-
|
2081
|
+
// remove protected internal listeners
|
2082
|
+
removeEvent(INTERNAL_EVENT_NS.aria);
|
2083
|
+
removeEvent(INTERNAL_EVENT_NS.tooltips);
|
2084
|
+
Object.keys(options.cssClasses).forEach(function (key) {
|
2449
2085
|
removeClass(scope_Target, options.cssClasses[key]);
|
2450
|
-
}
|
2451
|
-
|
2086
|
+
});
|
2452
2087
|
while (scope_Target.firstChild) {
|
2453
2088
|
scope_Target.removeChild(scope_Target.firstChild);
|
2454
2089
|
}
|
2455
|
-
|
2456
2090
|
delete scope_Target.noUiSlider;
|
2457
2091
|
}
|
2458
|
-
|
2459
2092
|
function getNextStepsForHandle(handleNumber) {
|
2460
2093
|
var location = scope_Locations[handleNumber];
|
2461
2094
|
var nearbySteps = scope_Spectrum.getNearbySteps(location);
|
2462
2095
|
var value = scope_Values[handleNumber];
|
2463
2096
|
var increment = nearbySteps.thisStep.step;
|
2464
2097
|
var decrement = null;
|
2465
|
-
|
2466
2098
|
// If snapped, directly use defined step value
|
2467
2099
|
if (options.snap) {
|
2468
2100
|
return [
|
2469
2101
|
value - nearbySteps.stepBefore.startValue || null,
|
2470
|
-
nearbySteps.stepAfter.startValue - value || null
|
2102
|
+
nearbySteps.stepAfter.startValue - value || null,
|
2471
2103
|
];
|
2472
2104
|
}
|
2473
|
-
|
2474
2105
|
// If the next value in this step moves into the next step,
|
2475
2106
|
// the increment is the start of the next step - the current value
|
2476
2107
|
if (increment !== false) {
|
@@ -2478,53 +2109,45 @@
|
|
2478
2109
|
increment = nearbySteps.stepAfter.startValue - value;
|
2479
2110
|
}
|
2480
2111
|
}
|
2481
|
-
|
2482
2112
|
// If the value is beyond the starting point
|
2483
2113
|
if (value > nearbySteps.thisStep.startValue) {
|
2484
2114
|
decrement = nearbySteps.thisStep.step;
|
2485
|
-
}
|
2115
|
+
}
|
2116
|
+
else if (nearbySteps.stepBefore.step === false) {
|
2486
2117
|
decrement = false;
|
2487
2118
|
}
|
2488
|
-
|
2489
2119
|
// If a handle is at the start of a step, it always steps back into the previous step first
|
2490
2120
|
else {
|
2491
2121
|
decrement = value - nearbySteps.stepBefore.highestStep;
|
2492
2122
|
}
|
2493
|
-
|
2494
2123
|
// Now, if at the slider edges, there is no in/decrement
|
2495
2124
|
if (location === 100) {
|
2496
2125
|
increment = null;
|
2497
|
-
}
|
2126
|
+
}
|
2127
|
+
else if (location === 0) {
|
2498
2128
|
decrement = null;
|
2499
2129
|
}
|
2500
|
-
|
2501
2130
|
// As per #391, the comparison for the decrement step can have some rounding issues.
|
2502
2131
|
var stepDecimals = scope_Spectrum.countStepDecimals();
|
2503
|
-
|
2504
2132
|
// Round per #391
|
2505
2133
|
if (increment !== null && increment !== false) {
|
2506
2134
|
increment = Number(increment.toFixed(stepDecimals));
|
2507
2135
|
}
|
2508
|
-
|
2509
2136
|
if (decrement !== null && decrement !== false) {
|
2510
2137
|
decrement = Number(decrement.toFixed(stepDecimals));
|
2511
2138
|
}
|
2512
|
-
|
2513
2139
|
return [decrement, increment];
|
2514
2140
|
}
|
2515
|
-
|
2516
2141
|
// Get the current step size for the slider.
|
2517
2142
|
function getNextSteps() {
|
2518
2143
|
return scope_HandleNumbers.map(getNextStepsForHandle);
|
2519
2144
|
}
|
2520
|
-
|
2521
|
-
// Updateable: margin, limit, padding, step, range, animate, snap
|
2145
|
+
// Updatable: margin, limit, padding, step, range, animate, snap
|
2522
2146
|
function updateOptions(optionsToUpdate, fireSetEvent) {
|
2523
2147
|
// Spectrum is created using the range, snap, direction and step options.
|
2524
2148
|
// 'snap' and 'step' can be updated.
|
2525
2149
|
// If 'snap' and 'step' are not passed, they should remain unchanged.
|
2526
2150
|
var v = valueGet();
|
2527
|
-
|
2528
2151
|
var updateAble = [
|
2529
2152
|
"margin",
|
2530
2153
|
"limit",
|
@@ -2535,81 +2158,65 @@
|
|
2535
2158
|
"step",
|
2536
2159
|
"format",
|
2537
2160
|
"pips",
|
2538
|
-
"tooltips"
|
2161
|
+
"tooltips",
|
2539
2162
|
];
|
2540
|
-
|
2541
2163
|
// Only change options that we're actually passed to update.
|
2542
|
-
updateAble.forEach(function(name) {
|
2164
|
+
updateAble.forEach(function (name) {
|
2543
2165
|
// Check for undefined. null removes the value.
|
2544
2166
|
if (optionsToUpdate[name] !== undefined) {
|
2545
2167
|
originalOptions[name] = optionsToUpdate[name];
|
2546
2168
|
}
|
2547
2169
|
});
|
2548
|
-
|
2549
2170
|
var newOptions = testOptions(originalOptions);
|
2550
|
-
|
2551
2171
|
// Load new options into the slider state
|
2552
|
-
updateAble.forEach(function(name) {
|
2172
|
+
updateAble.forEach(function (name) {
|
2553
2173
|
if (optionsToUpdate[name] !== undefined) {
|
2554
2174
|
options[name] = newOptions[name];
|
2555
2175
|
}
|
2556
2176
|
});
|
2557
|
-
|
2558
2177
|
scope_Spectrum = newOptions.spectrum;
|
2559
|
-
|
2560
2178
|
// Limit, margin and padding depend on the spectrum but are stored outside of it. (#677)
|
2561
2179
|
options.margin = newOptions.margin;
|
2562
2180
|
options.limit = newOptions.limit;
|
2563
2181
|
options.padding = newOptions.padding;
|
2564
|
-
|
2565
2182
|
// Update pips, removes existing.
|
2566
2183
|
if (options.pips) {
|
2567
2184
|
pips(options.pips);
|
2568
|
-
}
|
2185
|
+
}
|
2186
|
+
else {
|
2569
2187
|
removePips();
|
2570
2188
|
}
|
2571
|
-
|
2572
2189
|
// Update tooltips, removes existing.
|
2573
2190
|
if (options.tooltips) {
|
2574
2191
|
tooltips();
|
2575
|
-
}
|
2192
|
+
}
|
2193
|
+
else {
|
2576
2194
|
removeTooltips();
|
2577
2195
|
}
|
2578
|
-
|
2579
2196
|
// Invalidate the current positioning so valueSet forces an update.
|
2580
2197
|
scope_Locations = [];
|
2581
|
-
valueSet(optionsToUpdate.start
|
2198
|
+
valueSet(isSet(optionsToUpdate.start) ? optionsToUpdate.start : v, fireSetEvent);
|
2582
2199
|
}
|
2583
|
-
|
2584
2200
|
// Initialization steps
|
2585
2201
|
function setupSlider() {
|
2586
2202
|
// Create the base element, initialize HTML and set classes.
|
2587
2203
|
// Add handles and connect elements.
|
2588
2204
|
scope_Base = addSlider(scope_Target);
|
2589
|
-
|
2590
2205
|
addElements(options.connect, scope_Base);
|
2591
|
-
|
2592
2206
|
// Attach user events.
|
2593
2207
|
bindSliderEvents(options.events);
|
2594
|
-
|
2595
2208
|
// Use the public value method to set the start values.
|
2596
2209
|
valueSet(options.start);
|
2597
|
-
|
2598
2210
|
if (options.pips) {
|
2599
2211
|
pips(options.pips);
|
2600
2212
|
}
|
2601
|
-
|
2602
2213
|
if (options.tooltips) {
|
2603
2214
|
tooltips();
|
2604
2215
|
}
|
2605
|
-
|
2606
2216
|
aria();
|
2607
2217
|
}
|
2608
|
-
|
2609
2218
|
setupSlider();
|
2610
|
-
|
2611
|
-
// noinspection JSUnusedGlobalSymbols
|
2612
|
-
scope_Self = {
|
2219
|
+
var scope_Self = {
|
2613
2220
|
destroy: destroy,
|
2614
2221
|
steps: getNextSteps,
|
2615
2222
|
on: bindEvent,
|
@@ -2618,55 +2225,58 @@
|
|
2618
2225
|
set: valueSet,
|
2619
2226
|
setHandle: valueSetHandle,
|
2620
2227
|
reset: valueReset,
|
2228
|
+
disable: disable,
|
2229
|
+
enable: enable,
|
2621
2230
|
// Exposed for unit testing, don't use this in your application.
|
2622
|
-
__moveHandles: function(
|
2623
|
-
moveHandles(
|
2231
|
+
__moveHandles: function (upward, proposal, handleNumbers) {
|
2232
|
+
moveHandles(upward, proposal, scope_Locations, handleNumbers);
|
2624
2233
|
},
|
2625
|
-
options: originalOptions,
|
2234
|
+
options: originalOptions,
|
2626
2235
|
updateOptions: updateOptions,
|
2627
|
-
target: scope_Target,
|
2236
|
+
target: scope_Target,
|
2628
2237
|
removePips: removePips,
|
2629
2238
|
removeTooltips: removeTooltips,
|
2630
|
-
|
2239
|
+
getPositions: function () {
|
2240
|
+
return scope_Locations.slice();
|
2241
|
+
},
|
2242
|
+
getTooltips: function () {
|
2631
2243
|
return scope_Tooltips;
|
2632
2244
|
},
|
2633
|
-
getOrigins: function() {
|
2245
|
+
getOrigins: function () {
|
2634
2246
|
return scope_Handles;
|
2635
2247
|
},
|
2636
|
-
pips: pips // Issue #594
|
2248
|
+
pips: pips, // Issue #594
|
2637
2249
|
};
|
2638
|
-
|
2639
2250
|
return scope_Self;
|
2640
2251
|
}
|
2641
|
-
|
2642
2252
|
// Run the standard initializer
|
2643
2253
|
function initialize(target, originalOptions) {
|
2644
2254
|
if (!target || !target.nodeName) {
|
2645
|
-
throw new Error("noUiSlider
|
2255
|
+
throw new Error("noUiSlider: create requires a single element, got: " + target);
|
2646
2256
|
}
|
2647
|
-
|
2648
2257
|
// Throw an error if the slider was already initialized.
|
2649
2258
|
if (target.noUiSlider) {
|
2650
|
-
throw new Error("noUiSlider
|
2259
|
+
throw new Error("noUiSlider: Slider was already initialized.");
|
2651
2260
|
}
|
2652
|
-
|
2653
2261
|
// Test the options and create the slider environment;
|
2654
|
-
var options = testOptions(originalOptions
|
2262
|
+
var options = testOptions(originalOptions);
|
2655
2263
|
var api = scope(target, options, originalOptions);
|
2656
|
-
|
2657
2264
|
target.noUiSlider = api;
|
2658
|
-
|
2659
2265
|
return api;
|
2660
2266
|
}
|
2661
|
-
|
2662
|
-
// Use an object instead of a function for future expandability;
|
2663
|
-
return {
|
2267
|
+
var nouislider = {
|
2664
2268
|
// Exposed for unit testing, don't use this in your application.
|
2665
2269
|
__spectrum: Spectrum,
|
2666
|
-
version: VERSION,
|
2667
2270
|
// A reference to the default classes, allows global changes.
|
2668
2271
|
// Use the cssClasses option for changes to one slider.
|
2669
2272
|
cssClasses: cssClasses,
|
2670
|
-
create: initialize
|
2273
|
+
create: initialize,
|
2671
2274
|
};
|
2672
|
-
|
2275
|
+
|
2276
|
+
exports.create = initialize;
|
2277
|
+
exports.cssClasses = cssClasses;
|
2278
|
+
exports["default"] = nouislider;
|
2279
|
+
|
2280
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
2281
|
+
|
2282
|
+
}));
|