1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 | import { __assign, __extends } from "tslib";
|
24 | import { AnimationFrame } from '@material/animation/animationframe';
|
25 | import { getCorrectPropertyName } from '@material/animation/util';
|
26 | import { MDCFoundation } from '@material/base/foundation';
|
27 | import { attributes, cssClasses, numbers } from './constants';
|
28 | import { Thumb, TickMark } from './types';
|
29 | var AnimationKeys;
|
30 | (function (AnimationKeys) {
|
31 | AnimationKeys["SLIDER_UPDATE"] = "slider_update";
|
32 | })(AnimationKeys || (AnimationKeys = {}));
|
33 |
|
34 | var HAS_WINDOW = typeof window !== 'undefined';
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 | var MDCSliderFoundation = (function (_super) {
|
42 | __extends(MDCSliderFoundation, _super);
|
43 | function MDCSliderFoundation(adapter) {
|
44 | var _this = _super.call(this, __assign(__assign({}, MDCSliderFoundation.defaultAdapter), adapter)) || this;
|
45 |
|
46 |
|
47 | _this.initialStylesRemoved = false;
|
48 | _this.isDisabled = false;
|
49 | _this.isDiscrete = false;
|
50 | _this.step = numbers.STEP_SIZE;
|
51 | _this.hasTickMarks = false;
|
52 |
|
53 | _this.isRange = false;
|
54 |
|
55 |
|
56 | _this.thumb = null;
|
57 |
|
58 |
|
59 |
|
60 | _this.downEventClientX = null;
|
61 |
|
62 | _this.startThumbKnobWidth = 0;
|
63 |
|
64 | _this.endThumbKnobWidth = 0;
|
65 | _this.animFrame = new AnimationFrame();
|
66 | return _this;
|
67 | }
|
68 | Object.defineProperty(MDCSliderFoundation, "defaultAdapter", {
|
69 | get: function () {
|
70 |
|
71 |
|
72 | return {
|
73 | hasClass: function () { return false; },
|
74 | addClass: function () { return undefined; },
|
75 | removeClass: function () { return undefined; },
|
76 | addThumbClass: function () { return undefined; },
|
77 | removeThumbClass: function () { return undefined; },
|
78 | getAttribute: function () { return null; },
|
79 | getInputValue: function () { return ''; },
|
80 | setInputValue: function () { return undefined; },
|
81 | getInputAttribute: function () { return null; },
|
82 | setInputAttribute: function () { return null; },
|
83 | removeInputAttribute: function () { return null; },
|
84 | focusInput: function () { return undefined; },
|
85 | isInputFocused: function () { return false; },
|
86 | getThumbKnobWidth: function () { return 0; },
|
87 | getThumbBoundingClientRect: function () {
|
88 | return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 });
|
89 | },
|
90 | getBoundingClientRect: function () {
|
91 | return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 });
|
92 | },
|
93 | isRTL: function () { return false; },
|
94 | setThumbStyleProperty: function () { return undefined; },
|
95 | removeThumbStyleProperty: function () { return undefined; },
|
96 | setTrackActiveStyleProperty: function () { return undefined; },
|
97 | removeTrackActiveStyleProperty: function () { return undefined; },
|
98 | setValueIndicatorText: function () { return undefined; },
|
99 | getValueToAriaValueTextFn: function () { return null; },
|
100 | updateTickMarks: function () { return undefined; },
|
101 | setPointerCapture: function () { return undefined; },
|
102 | emitChangeEvent: function () { return undefined; },
|
103 | emitInputEvent: function () { return undefined; },
|
104 | emitDragStartEvent: function () { return undefined; },
|
105 | emitDragEndEvent: function () { return undefined; },
|
106 | registerEventHandler: function () { return undefined; },
|
107 | deregisterEventHandler: function () { return undefined; },
|
108 | registerThumbEventHandler: function () { return undefined; },
|
109 | deregisterThumbEventHandler: function () { return undefined; },
|
110 | registerInputEventHandler: function () { return undefined; },
|
111 | deregisterInputEventHandler: function () { return undefined; },
|
112 | registerBodyEventHandler: function () { return undefined; },
|
113 | deregisterBodyEventHandler: function () { return undefined; },
|
114 | registerWindowEventHandler: function () { return undefined; },
|
115 | deregisterWindowEventHandler: function () { return undefined; },
|
116 | };
|
117 |
|
118 | },
|
119 | enumerable: false,
|
120 | configurable: true
|
121 | });
|
122 | MDCSliderFoundation.prototype.init = function () {
|
123 | var _this = this;
|
124 | this.isDisabled = this.adapter.hasClass(cssClasses.DISABLED);
|
125 | this.isDiscrete = this.adapter.hasClass(cssClasses.DISCRETE);
|
126 | this.hasTickMarks = this.adapter.hasClass(cssClasses.TICK_MARKS);
|
127 | this.isRange = this.adapter.hasClass(cssClasses.RANGE);
|
128 | var min = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_MIN, this.isRange ? Thumb.START : Thumb.END), attributes.INPUT_MIN);
|
129 | var max = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_MAX, Thumb.END), attributes.INPUT_MAX);
|
130 | var value = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_VALUE, Thumb.END), attributes.INPUT_VALUE);
|
131 | var valueStart = this.isRange ?
|
132 | this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_VALUE, Thumb.START), attributes.INPUT_VALUE) :
|
133 | min;
|
134 | var stepAttr = this.adapter.getInputAttribute(attributes.INPUT_STEP, Thumb.END);
|
135 | var step = stepAttr ?
|
136 | this.convertAttributeValueToNumber(stepAttr, attributes.INPUT_STEP) :
|
137 | this.step;
|
138 | this.validateProperties({ min: min, max: max, value: value, valueStart: valueStart, step: step });
|
139 | this.min = min;
|
140 | this.max = max;
|
141 | this.value = value;
|
142 | this.valueStart = valueStart;
|
143 | this.step = step;
|
144 | this.numDecimalPlaces = getNumDecimalPlaces(this.step);
|
145 | this.valueBeforeDownEvent = value;
|
146 | this.valueStartBeforeDownEvent = valueStart;
|
147 | this.mousedownOrTouchstartListener =
|
148 | this.handleMousedownOrTouchstart.bind(this);
|
149 | this.moveListener = this.handleMove.bind(this);
|
150 | this.pointerdownListener = this.handlePointerdown.bind(this);
|
151 | this.pointerupListener = this.handlePointerup.bind(this);
|
152 | this.thumbMouseenterListener = this.handleThumbMouseenter.bind(this);
|
153 | this.thumbMouseleaveListener = this.handleThumbMouseleave.bind(this);
|
154 | this.inputStartChangeListener = function () {
|
155 | _this.handleInputChange(Thumb.START);
|
156 | };
|
157 | this.inputEndChangeListener = function () {
|
158 | _this.handleInputChange(Thumb.END);
|
159 | };
|
160 | this.inputStartFocusListener = function () {
|
161 | _this.handleInputFocus(Thumb.START);
|
162 | };
|
163 | this.inputEndFocusListener = function () {
|
164 | _this.handleInputFocus(Thumb.END);
|
165 | };
|
166 | this.inputStartBlurListener = function () {
|
167 | _this.handleInputBlur(Thumb.START);
|
168 | };
|
169 | this.inputEndBlurListener = function () {
|
170 | _this.handleInputBlur(Thumb.END);
|
171 | };
|
172 | this.resizeListener = this.handleResize.bind(this);
|
173 | this.registerEventHandlers();
|
174 | };
|
175 | MDCSliderFoundation.prototype.destroy = function () {
|
176 | this.deregisterEventHandlers();
|
177 | };
|
178 | MDCSliderFoundation.prototype.setMin = function (value) {
|
179 | this.min = value;
|
180 | if (!this.isRange) {
|
181 | this.valueStart = value;
|
182 | }
|
183 | this.updateUI();
|
184 | };
|
185 | MDCSliderFoundation.prototype.setMax = function (value) {
|
186 | this.max = value;
|
187 | this.updateUI();
|
188 | };
|
189 | MDCSliderFoundation.prototype.getMin = function () {
|
190 | return this.min;
|
191 | };
|
192 | MDCSliderFoundation.prototype.getMax = function () {
|
193 | return this.max;
|
194 | };
|
195 | |
196 |
|
197 |
|
198 |
|
199 | MDCSliderFoundation.prototype.getValue = function () {
|
200 | return this.value;
|
201 | };
|
202 | |
203 |
|
204 |
|
205 |
|
206 | MDCSliderFoundation.prototype.setValue = function (value) {
|
207 | if (this.isRange && value < this.valueStart) {
|
208 | throw new Error("end thumb value (" + value + ") must be >= start thumb " +
|
209 | ("value (" + this.valueStart + ")"));
|
210 | }
|
211 | this.updateValue(value, Thumb.END);
|
212 | };
|
213 | |
214 |
|
215 |
|
216 |
|
217 | MDCSliderFoundation.prototype.getValueStart = function () {
|
218 | if (!this.isRange) {
|
219 | throw new Error('`valueStart` is only applicable for range sliders.');
|
220 | }
|
221 | return this.valueStart;
|
222 | };
|
223 | |
224 |
|
225 |
|
226 | MDCSliderFoundation.prototype.setValueStart = function (valueStart) {
|
227 | if (!this.isRange) {
|
228 | throw new Error('`valueStart` is only applicable for range sliders.');
|
229 | }
|
230 | if (this.isRange && valueStart > this.value) {
|
231 | throw new Error("start thumb value (" + valueStart + ") must be <= end thumb " +
|
232 | ("value (" + this.value + ")"));
|
233 | }
|
234 | this.updateValue(valueStart, Thumb.START);
|
235 | };
|
236 | MDCSliderFoundation.prototype.setStep = function (value) {
|
237 | this.step = value;
|
238 | this.numDecimalPlaces = getNumDecimalPlaces(value);
|
239 | this.updateUI();
|
240 | };
|
241 | MDCSliderFoundation.prototype.setIsDiscrete = function (value) {
|
242 | this.isDiscrete = value;
|
243 | this.updateValueIndicatorUI();
|
244 | this.updateTickMarksUI();
|
245 | };
|
246 | MDCSliderFoundation.prototype.getStep = function () {
|
247 | return this.step;
|
248 | };
|
249 | MDCSliderFoundation.prototype.setHasTickMarks = function (value) {
|
250 | this.hasTickMarks = value;
|
251 | this.updateTickMarksUI();
|
252 | };
|
253 | MDCSliderFoundation.prototype.getDisabled = function () {
|
254 | return this.isDisabled;
|
255 | };
|
256 | |
257 |
|
258 |
|
259 | MDCSliderFoundation.prototype.setDisabled = function (disabled) {
|
260 | this.isDisabled = disabled;
|
261 | if (disabled) {
|
262 | this.adapter.addClass(cssClasses.DISABLED);
|
263 | if (this.isRange) {
|
264 | this.adapter.setInputAttribute(attributes.INPUT_DISABLED, '', Thumb.START);
|
265 | }
|
266 | this.adapter.setInputAttribute(attributes.INPUT_DISABLED, '', Thumb.END);
|
267 | }
|
268 | else {
|
269 | this.adapter.removeClass(cssClasses.DISABLED);
|
270 | if (this.isRange) {
|
271 | this.adapter.removeInputAttribute(attributes.INPUT_DISABLED, Thumb.START);
|
272 | }
|
273 | this.adapter.removeInputAttribute(attributes.INPUT_DISABLED, Thumb.END);
|
274 | }
|
275 | };
|
276 |
|
277 | MDCSliderFoundation.prototype.getIsRange = function () {
|
278 | return this.isRange;
|
279 | };
|
280 | |
281 |
|
282 |
|
283 |
|
284 | MDCSliderFoundation.prototype.layout = function (_a) {
|
285 | var _b = _a === void 0 ? {} : _a, skipUpdateUI = _b.skipUpdateUI;
|
286 | this.rect = this.adapter.getBoundingClientRect();
|
287 | if (this.isRange) {
|
288 | this.startThumbKnobWidth = this.adapter.getThumbKnobWidth(Thumb.START);
|
289 | this.endThumbKnobWidth = this.adapter.getThumbKnobWidth(Thumb.END);
|
290 | }
|
291 | if (!skipUpdateUI) {
|
292 | this.updateUI();
|
293 | }
|
294 | };
|
295 |
|
296 | MDCSliderFoundation.prototype.handleResize = function () {
|
297 | this.layout();
|
298 | };
|
299 | |
300 |
|
301 |
|
302 | MDCSliderFoundation.prototype.handleDown = function (event) {
|
303 | if (this.isDisabled)
|
304 | return;
|
305 | this.valueStartBeforeDownEvent = this.valueStart;
|
306 | this.valueBeforeDownEvent = this.value;
|
307 | var clientX = event.clientX != null ?
|
308 | event.clientX :
|
309 | event.targetTouches[0].clientX;
|
310 | this.downEventClientX = clientX;
|
311 | var value = this.mapClientXOnSliderScale(clientX);
|
312 | this.thumb = this.getThumbFromDownEvent(clientX, value);
|
313 | if (this.thumb === null)
|
314 | return;
|
315 | this.handleDragStart(event, value, this.thumb);
|
316 | this.updateValue(value, this.thumb, { emitInputEvent: true });
|
317 | };
|
318 | |
319 |
|
320 |
|
321 | MDCSliderFoundation.prototype.handleMove = function (event) {
|
322 | if (this.isDisabled)
|
323 | return;
|
324 |
|
325 | event.preventDefault();
|
326 | var clientX = event.clientX != null ?
|
327 | event.clientX :
|
328 | event.targetTouches[0].clientX;
|
329 | var dragAlreadyStarted = this.thumb != null;
|
330 | this.thumb = this.getThumbFromMoveEvent(clientX);
|
331 | if (this.thumb === null)
|
332 | return;
|
333 | var value = this.mapClientXOnSliderScale(clientX);
|
334 | if (!dragAlreadyStarted) {
|
335 | this.handleDragStart(event, value, this.thumb);
|
336 | this.adapter.emitDragStartEvent(value, this.thumb);
|
337 | }
|
338 | this.updateValue(value, this.thumb, { emitInputEvent: true });
|
339 | };
|
340 | |
341 |
|
342 |
|
343 | MDCSliderFoundation.prototype.handleUp = function () {
|
344 | if (this.isDisabled || this.thumb === null)
|
345 | return;
|
346 | var oldValue = this.thumb === Thumb.START ?
|
347 | this.valueStartBeforeDownEvent :
|
348 | this.valueBeforeDownEvent;
|
349 | var newValue = this.thumb === Thumb.START ? this.valueStart : this.value;
|
350 | if (oldValue !== newValue) {
|
351 | this.adapter.emitChangeEvent(newValue, this.thumb);
|
352 | }
|
353 | this.adapter.emitDragEndEvent(newValue, this.thumb);
|
354 | this.thumb = null;
|
355 | };
|
356 | |
357 |
|
358 |
|
359 | MDCSliderFoundation.prototype.handleThumbMouseenter = function () {
|
360 | if (!this.isDiscrete || !this.isRange)
|
361 | return;
|
362 | this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.START);
|
363 | this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.END);
|
364 | };
|
365 | |
366 |
|
367 |
|
368 | MDCSliderFoundation.prototype.handleThumbMouseleave = function () {
|
369 | if (!this.isDiscrete || !this.isRange)
|
370 | return;
|
371 | if (this.adapter.isInputFocused(Thumb.START) ||
|
372 | this.adapter.isInputFocused(Thumb.END)) {
|
373 |
|
374 | return;
|
375 | }
|
376 | this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.START);
|
377 | this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.END);
|
378 | };
|
379 | MDCSliderFoundation.prototype.handleMousedownOrTouchstart = function (event) {
|
380 | var _this = this;
|
381 | var moveEventType = event.type === 'mousedown' ? 'mousemove' : 'touchmove';
|
382 |
|
383 |
|
384 |
|
385 | this.adapter.registerBodyEventHandler(moveEventType, this.moveListener);
|
386 | var upHandler = function () {
|
387 | _this.handleUp();
|
388 |
|
389 |
|
390 | _this.adapter.deregisterBodyEventHandler(moveEventType, _this.moveListener);
|
391 |
|
392 | _this.adapter.deregisterEventHandler('mouseup', upHandler);
|
393 | _this.adapter.deregisterEventHandler('touchend', upHandler);
|
394 | };
|
395 | this.adapter.registerBodyEventHandler('mouseup', upHandler);
|
396 | this.adapter.registerBodyEventHandler('touchend', upHandler);
|
397 | this.handleDown(event);
|
398 | };
|
399 | MDCSliderFoundation.prototype.handlePointerdown = function (event) {
|
400 | this.adapter.setPointerCapture(event.pointerId);
|
401 | this.adapter.registerEventHandler('pointermove', this.moveListener);
|
402 | this.handleDown(event);
|
403 | };
|
404 | |
405 |
|
406 |
|
407 |
|
408 | MDCSliderFoundation.prototype.handleInputChange = function (thumb) {
|
409 | var value = Number(this.adapter.getInputValue(thumb));
|
410 | if (thumb === Thumb.START) {
|
411 | this.setValueStart(value);
|
412 | }
|
413 | else {
|
414 | this.setValue(value);
|
415 | }
|
416 | this.adapter.emitChangeEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
|
417 | this.adapter.emitInputEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
|
418 | };
|
419 |
|
420 | MDCSliderFoundation.prototype.handleInputFocus = function (thumb) {
|
421 | this.adapter.addThumbClass(cssClasses.THUMB_FOCUSED, thumb);
|
422 | if (!this.isDiscrete)
|
423 | return;
|
424 | this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, thumb);
|
425 | if (this.isRange) {
|
426 | var otherThumb = thumb === Thumb.START ? Thumb.END : Thumb.START;
|
427 | this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, otherThumb);
|
428 | }
|
429 | };
|
430 |
|
431 | MDCSliderFoundation.prototype.handleInputBlur = function (thumb) {
|
432 | this.adapter.removeThumbClass(cssClasses.THUMB_FOCUSED, thumb);
|
433 | if (!this.isDiscrete)
|
434 | return;
|
435 | this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, thumb);
|
436 | if (this.isRange) {
|
437 | var otherThumb = thumb === Thumb.START ? Thumb.END : Thumb.START;
|
438 | this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, otherThumb);
|
439 | }
|
440 | };
|
441 | |
442 |
|
443 |
|
444 | MDCSliderFoundation.prototype.handleDragStart = function (event, value, thumb) {
|
445 | this.adapter.emitDragStartEvent(value, thumb);
|
446 | this.adapter.focusInput(thumb);
|
447 |
|
448 | event.preventDefault();
|
449 | };
|
450 | |
451 |
|
452 |
|
453 | MDCSliderFoundation.prototype.getThumbFromDownEvent = function (clientX, value) {
|
454 |
|
455 |
|
456 | if (!this.isRange)
|
457 | return Thumb.END;
|
458 |
|
459 | var thumbStartRect = this.adapter.getThumbBoundingClientRect(Thumb.START);
|
460 | var thumbEndRect = this.adapter.getThumbBoundingClientRect(Thumb.END);
|
461 | var inThumbStartBounds = clientX >= thumbStartRect.left && clientX <= thumbStartRect.right;
|
462 | var inThumbEndBounds = clientX >= thumbEndRect.left && clientX <= thumbEndRect.right;
|
463 | if (inThumbStartBounds && inThumbEndBounds) {
|
464 |
|
465 | return null;
|
466 | }
|
467 |
|
468 |
|
469 | if (inThumbStartBounds) {
|
470 | return Thumb.START;
|
471 | }
|
472 | if (inThumbEndBounds) {
|
473 | return Thumb.END;
|
474 | }
|
475 |
|
476 | if (value < this.valueStart) {
|
477 | return Thumb.START;
|
478 | }
|
479 | if (value > this.value) {
|
480 | return Thumb.END;
|
481 | }
|
482 |
|
483 | return (value - this.valueStart <= this.value - value) ? Thumb.START :
|
484 | Thumb.END;
|
485 | };
|
486 | |
487 |
|
488 |
|
489 |
|
490 |
|
491 | MDCSliderFoundation.prototype.getThumbFromMoveEvent = function (clientX) {
|
492 |
|
493 | if (this.thumb !== null)
|
494 | return this.thumb;
|
495 | if (this.downEventClientX === null) {
|
496 | throw new Error('`downEventClientX` is null after move event.');
|
497 | }
|
498 | var moveDistanceUnderThreshold = Math.abs(this.downEventClientX - clientX) < numbers.THUMB_UPDATE_MIN_PX;
|
499 | if (moveDistanceUnderThreshold)
|
500 | return this.thumb;
|
501 | var draggedThumbToLeft = clientX < this.downEventClientX;
|
502 | if (draggedThumbToLeft) {
|
503 | return this.adapter.isRTL() ? Thumb.END : Thumb.START;
|
504 | }
|
505 | else {
|
506 | return this.adapter.isRTL() ? Thumb.START : Thumb.END;
|
507 | }
|
508 | };
|
509 | |
510 |
|
511 |
|
512 |
|
513 |
|
514 | MDCSliderFoundation.prototype.updateUI = function (thumb) {
|
515 | this.updateThumbAndInputAttributes(thumb);
|
516 | this.updateThumbAndTrackUI(thumb);
|
517 | this.updateValueIndicatorUI(thumb);
|
518 | this.updateTickMarksUI();
|
519 | };
|
520 | |
521 |
|
522 |
|
523 |
|
524 | MDCSliderFoundation.prototype.updateThumbAndInputAttributes = function (thumb) {
|
525 | if (!thumb)
|
526 | return;
|
527 | var value = this.isRange && thumb === Thumb.START ? this.valueStart : this.value;
|
528 | var valueStr = String(value);
|
529 | this.adapter.setInputAttribute(attributes.INPUT_VALUE, valueStr, thumb);
|
530 | if (this.isRange && thumb === Thumb.START) {
|
531 | this.adapter.setInputAttribute(attributes.INPUT_MIN, valueStr, Thumb.END);
|
532 | }
|
533 | else if (this.isRange && thumb === Thumb.END) {
|
534 | this.adapter.setInputAttribute(attributes.INPUT_MAX, valueStr, Thumb.START);
|
535 | }
|
536 |
|
537 | if (this.adapter.getInputValue(thumb) !== valueStr) {
|
538 | this.adapter.setInputValue(valueStr, thumb);
|
539 | }
|
540 | var valueToAriaValueTextFn = this.adapter.getValueToAriaValueTextFn();
|
541 | if (valueToAriaValueTextFn) {
|
542 | this.adapter.setInputAttribute(attributes.ARIA_VALUETEXT, valueToAriaValueTextFn(value), thumb);
|
543 | }
|
544 | };
|
545 | |
546 |
|
547 |
|
548 |
|
549 |
|
550 | MDCSliderFoundation.prototype.updateValueIndicatorUI = function (thumb) {
|
551 | if (!this.isDiscrete)
|
552 | return;
|
553 | var value = this.isRange && thumb === Thumb.START ? this.valueStart : this.value;
|
554 | this.adapter.setValueIndicatorText(value, thumb === Thumb.START ? Thumb.START : Thumb.END);
|
555 | if (!thumb && this.isRange) {
|
556 | this.adapter.setValueIndicatorText(this.valueStart, Thumb.START);
|
557 | }
|
558 | };
|
559 | |
560 |
|
561 |
|
562 | MDCSliderFoundation.prototype.updateTickMarksUI = function () {
|
563 | if (!this.isDiscrete || !this.hasTickMarks)
|
564 | return;
|
565 | var numTickMarksInactiveStart = (this.valueStart - this.min) / this.step;
|
566 | var numTickMarksActive = (this.value - this.valueStart) / this.step + 1;
|
567 | var numTickMarksInactiveEnd = (this.max - this.value) / this.step;
|
568 | var tickMarksInactiveStart = Array.from({ length: numTickMarksInactiveStart })
|
569 | .fill(TickMark.INACTIVE);
|
570 | var tickMarksActive = Array.from({ length: numTickMarksActive })
|
571 | .fill(TickMark.ACTIVE);
|
572 | var tickMarksInactiveEnd = Array.from({ length: numTickMarksInactiveEnd })
|
573 | .fill(TickMark.INACTIVE);
|
574 | this.adapter.updateTickMarks(tickMarksInactiveStart.concat(tickMarksActive)
|
575 | .concat(tickMarksInactiveEnd));
|
576 | };
|
577 |
|
578 | MDCSliderFoundation.prototype.mapClientXOnSliderScale = function (clientX) {
|
579 | var xPos = clientX - this.rect.left;
|
580 | var pctComplete = xPos / this.rect.width;
|
581 | if (this.adapter.isRTL()) {
|
582 | pctComplete = 1 - pctComplete;
|
583 | }
|
584 |
|
585 |
|
586 | var value = this.min + pctComplete * (this.max - this.min);
|
587 | if (value === this.max || value === this.min) {
|
588 | return value;
|
589 | }
|
590 | return Number(this.quantize(value).toFixed(this.numDecimalPlaces));
|
591 | };
|
592 |
|
593 | MDCSliderFoundation.prototype.quantize = function (value) {
|
594 | var numSteps = Math.round((value - this.min) / this.step);
|
595 | return this.min + numSteps * this.step;
|
596 | };
|
597 | |
598 |
|
599 |
|
600 | MDCSliderFoundation.prototype.updateValue = function (value, thumb, _a) {
|
601 | var _b = _a === void 0 ? {} : _a, emitInputEvent = _b.emitInputEvent;
|
602 | value = this.clampValue(value, thumb);
|
603 | if (this.isRange && thumb === Thumb.START) {
|
604 |
|
605 | if (this.valueStart === value)
|
606 | return;
|
607 | this.valueStart = value;
|
608 | }
|
609 | else {
|
610 |
|
611 | if (this.value === value)
|
612 | return;
|
613 | this.value = value;
|
614 | }
|
615 | this.updateUI(thumb);
|
616 | if (emitInputEvent) {
|
617 | this.adapter.emitInputEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
|
618 | }
|
619 | };
|
620 | |
621 |
|
622 |
|
623 |
|
624 |
|
625 |
|
626 | MDCSliderFoundation.prototype.clampValue = function (value, thumb) {
|
627 |
|
628 | value = Math.min(Math.max(value, this.min), this.max);
|
629 | var thumbStartMovedPastThumbEnd = this.isRange && thumb === Thumb.START && value > this.value;
|
630 | if (thumbStartMovedPastThumbEnd) {
|
631 | return this.value;
|
632 | }
|
633 | var thumbEndMovedPastThumbStart = this.isRange && thumb === Thumb.END && value < this.valueStart;
|
634 | if (thumbEndMovedPastThumbStart) {
|
635 | return this.valueStart;
|
636 | }
|
637 | return value;
|
638 | };
|
639 | |
640 |
|
641 |
|
642 |
|
643 | MDCSliderFoundation.prototype.updateThumbAndTrackUI = function (thumb) {
|
644 | var _this = this;
|
645 | var _a = this, max = _a.max, min = _a.min;
|
646 | var pctComplete = (this.value - this.valueStart) / (max - min);
|
647 | var rangePx = pctComplete * this.rect.width;
|
648 | var isRtl = this.adapter.isRTL();
|
649 | var transformProp = HAS_WINDOW ? getCorrectPropertyName(window, 'transform') : 'transform';
|
650 | if (this.isRange) {
|
651 | var thumbLeftPos_1 = this.adapter.isRTL() ?
|
652 | (max - this.value) / (max - min) * this.rect.width :
|
653 | (this.valueStart - min) / (max - min) * this.rect.width;
|
654 | var thumbRightPos_1 = thumbLeftPos_1 + rangePx;
|
655 | this.animFrame.request(AnimationKeys.SLIDER_UPDATE, function () {
|
656 |
|
657 |
|
658 | var trackAnimatesFromRight = (!isRtl && thumb === Thumb.START) ||
|
659 | (isRtl && thumb !== Thumb.START);
|
660 | if (trackAnimatesFromRight) {
|
661 | _this.adapter.setTrackActiveStyleProperty('transform-origin', 'right');
|
662 | _this.adapter.setTrackActiveStyleProperty('left', 'unset');
|
663 | _this.adapter.setTrackActiveStyleProperty('right', _this.rect.width - thumbRightPos_1 + "px");
|
664 | }
|
665 | else {
|
666 | _this.adapter.setTrackActiveStyleProperty('transform-origin', 'left');
|
667 | _this.adapter.setTrackActiveStyleProperty('right', 'unset');
|
668 | _this.adapter.setTrackActiveStyleProperty('left', thumbLeftPos_1 + "px");
|
669 | }
|
670 | _this.adapter.setTrackActiveStyleProperty(transformProp, "scaleX(" + pctComplete + ")");
|
671 |
|
672 | var thumbStartPos = isRtl ? thumbRightPos_1 : thumbLeftPos_1;
|
673 | var thumbEndPos = _this.adapter.isRTL() ? thumbLeftPos_1 : thumbRightPos_1;
|
674 | if (thumb === Thumb.START || !thumb || !_this.initialStylesRemoved) {
|
675 | _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbStartPos + "px)", Thumb.START);
|
676 | }
|
677 | if (thumb === Thumb.END || !thumb || !_this.initialStylesRemoved) {
|
678 | _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbEndPos + "px)", Thumb.END);
|
679 | }
|
680 | _this.removeInitialStyles(isRtl);
|
681 | _this.updateOverlappingThumbsUI(thumbStartPos, thumbEndPos, thumb);
|
682 | });
|
683 | }
|
684 | else {
|
685 | this.animFrame.request(AnimationKeys.SLIDER_UPDATE, function () {
|
686 | var thumbStartPos = isRtl ? _this.rect.width - rangePx : rangePx;
|
687 | _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbStartPos + "px)", Thumb.END);
|
688 | _this.adapter.setTrackActiveStyleProperty(transformProp, "scaleX(" + pctComplete + ")");
|
689 | _this.removeInitialStyles(isRtl);
|
690 | });
|
691 | }
|
692 | };
|
693 | |
694 |
|
695 |
|
696 |
|
697 |
|
698 |
|
699 |
|
700 |
|
701 |
|
702 | MDCSliderFoundation.prototype.removeInitialStyles = function (isRtl) {
|
703 | if (this.initialStylesRemoved)
|
704 | return;
|
705 |
|
706 | var position = isRtl ? 'right' : 'left';
|
707 | this.adapter.removeThumbStyleProperty(position, Thumb.END);
|
708 | if (this.isRange) {
|
709 | this.adapter.removeThumbStyleProperty(position, Thumb.START);
|
710 | }
|
711 | this.initialStylesRemoved = true;
|
712 | this.resetTrackAndThumbAnimation();
|
713 | };
|
714 | |
715 |
|
716 |
|
717 |
|
718 | MDCSliderFoundation.prototype.resetTrackAndThumbAnimation = function () {
|
719 | var _this = this;
|
720 | if (!this.isDiscrete)
|
721 | return;
|
722 |
|
723 |
|
724 |
|
725 | var transitionProp = HAS_WINDOW ?
|
726 | getCorrectPropertyName(window, 'transition') :
|
727 | 'transition';
|
728 | var transitionDefault = 'all 0s ease 0s';
|
729 | this.adapter.setThumbStyleProperty(transitionProp, transitionDefault, Thumb.END);
|
730 | if (this.isRange) {
|
731 | this.adapter.setThumbStyleProperty(transitionProp, transitionDefault, Thumb.START);
|
732 | }
|
733 | this.adapter.setTrackActiveStyleProperty(transitionProp, transitionDefault);
|
734 |
|
735 |
|
736 | requestAnimationFrame(function () {
|
737 | _this.adapter.removeThumbStyleProperty(transitionProp, Thumb.END);
|
738 | _this.adapter.removeTrackActiveStyleProperty(transitionProp);
|
739 | if (_this.isRange) {
|
740 | _this.adapter.removeThumbStyleProperty(transitionProp, Thumb.START);
|
741 | }
|
742 | });
|
743 | };
|
744 | |
745 |
|
746 |
|
747 |
|
748 |
|
749 | MDCSliderFoundation.prototype.updateOverlappingThumbsUI = function (thumbStartPos, thumbEndPos, thumb) {
|
750 | var thumbsOverlap = false;
|
751 | if (this.adapter.isRTL()) {
|
752 | var startThumbLeftEdge = thumbStartPos - this.startThumbKnobWidth / 2;
|
753 | var endThumbRightEdge = thumbEndPos + this.endThumbKnobWidth / 2;
|
754 | thumbsOverlap = endThumbRightEdge >= startThumbLeftEdge;
|
755 | }
|
756 | else {
|
757 | var startThumbRightEdge = thumbStartPos + this.startThumbKnobWidth / 2;
|
758 | var endThumbLeftEdge = thumbEndPos - this.endThumbKnobWidth / 2;
|
759 | thumbsOverlap = startThumbRightEdge >= endThumbLeftEdge;
|
760 | }
|
761 | if (thumbsOverlap) {
|
762 | this.adapter.addThumbClass(cssClasses.THUMB_TOP,
|
763 |
|
764 |
|
765 | thumb || Thumb.END);
|
766 | this.adapter.removeThumbClass(cssClasses.THUMB_TOP, thumb === Thumb.START ? Thumb.END : Thumb.START);
|
767 | }
|
768 | else {
|
769 | this.adapter.removeThumbClass(cssClasses.THUMB_TOP, Thumb.START);
|
770 | this.adapter.removeThumbClass(cssClasses.THUMB_TOP, Thumb.END);
|
771 | }
|
772 | };
|
773 | |
774 |
|
775 |
|
776 |
|
777 |
|
778 |
|
779 | MDCSliderFoundation.prototype.convertAttributeValueToNumber = function (attributeValue, attributeName) {
|
780 | if (attributeValue === null) {
|
781 | throw new Error("MDCSliderFoundation: `" + attributeName + "` must be non-null.");
|
782 | }
|
783 | var value = Number(attributeValue);
|
784 | if (isNaN(value)) {
|
785 | throw new Error("MDCSliderFoundation: `" + attributeName + "` value is " +
|
786 | ("`" + attributeValue + "`, but must be a number."));
|
787 | }
|
788 | return value;
|
789 | };
|
790 |
|
791 | MDCSliderFoundation.prototype.validateProperties = function (_a) {
|
792 | var min = _a.min, max = _a.max, value = _a.value, valueStart = _a.valueStart, step = _a.step;
|
793 | if (min >= max) {
|
794 | throw new Error("MDCSliderFoundation: min must be strictly less than max. " +
|
795 | ("Current: [min: " + min + ", max: " + max + "]"));
|
796 | }
|
797 | if (step <= 0) {
|
798 | throw new Error("MDCSliderFoundation: step must be a positive number. " +
|
799 | ("Current step: " + this.step));
|
800 | }
|
801 | if (this.isRange) {
|
802 | if (value < min || value > max || valueStart < min || valueStart > max) {
|
803 | throw new Error("MDCSliderFoundation: values must be in [min, max] range. " +
|
804 | ("Current values: [start value: " + valueStart + ", end value: " + value + "]"));
|
805 | }
|
806 | if (valueStart > value) {
|
807 | throw new Error("MDCSliderFoundation: start value must be <= end value. " +
|
808 | ("Current values: [start value: " + valueStart + ", end value: " + value + "]"));
|
809 | }
|
810 | var numStepsValueStartFromMin = (valueStart - min) / step;
|
811 | var numStepsValueFromMin = (value - min) / step;
|
812 | if ((numStepsValueStartFromMin % 1) !== 0 ||
|
813 | (numStepsValueFromMin % 1) !== 0) {
|
814 | throw new Error("MDCSliderFoundation: Slider values must be valid based on the " +
|
815 | ("step value. Current values: [start value: " + valueStart + ", ") +
|
816 | ("end value: " + value + "]"));
|
817 | }
|
818 | }
|
819 | else {
|
820 | if (value < min || value > max) {
|
821 | throw new Error("MDCSliderFoundation: value must be in [min, max] range. " +
|
822 | ("Current value: " + value));
|
823 | }
|
824 | var numStepsValueFromMin = (value - min) / step;
|
825 | if ((numStepsValueFromMin % 1) !== 0) {
|
826 | throw new Error("MDCSliderFoundation: Slider value must be valid based on the " +
|
827 | ("step value. Current value: " + value));
|
828 | }
|
829 | }
|
830 | };
|
831 | MDCSliderFoundation.prototype.registerEventHandlers = function () {
|
832 | this.adapter.registerWindowEventHandler('resize', this.resizeListener);
|
833 | if (MDCSliderFoundation.SUPPORTS_POINTER_EVENTS) {
|
834 |
|
835 | this.adapter.registerEventHandler('pointerdown', this.pointerdownListener);
|
836 | this.adapter.registerEventHandler('pointerup', this.pointerupListener);
|
837 | }
|
838 | else {
|
839 |
|
840 | this.adapter.registerEventHandler('mousedown', this.mousedownOrTouchstartListener);
|
841 | this.adapter.registerEventHandler('touchstart', this.mousedownOrTouchstartListener);
|
842 | }
|
843 | if (this.isRange) {
|
844 | this.adapter.registerThumbEventHandler(Thumb.START, 'mouseenter', this.thumbMouseenterListener);
|
845 | this.adapter.registerThumbEventHandler(Thumb.START, 'mouseleave', this.thumbMouseleaveListener);
|
846 | this.adapter.registerInputEventHandler(Thumb.START, 'change', this.inputStartChangeListener);
|
847 | this.adapter.registerInputEventHandler(Thumb.START, 'focus', this.inputStartFocusListener);
|
848 | this.adapter.registerInputEventHandler(Thumb.START, 'blur', this.inputStartBlurListener);
|
849 | }
|
850 | this.adapter.registerThumbEventHandler(Thumb.END, 'mouseenter', this.thumbMouseenterListener);
|
851 | this.adapter.registerThumbEventHandler(Thumb.END, 'mouseleave', this.thumbMouseleaveListener);
|
852 | this.adapter.registerInputEventHandler(Thumb.END, 'change', this.inputEndChangeListener);
|
853 | this.adapter.registerInputEventHandler(Thumb.END, 'focus', this.inputEndFocusListener);
|
854 | this.adapter.registerInputEventHandler(Thumb.END, 'blur', this.inputEndBlurListener);
|
855 | };
|
856 | MDCSliderFoundation.prototype.deregisterEventHandlers = function () {
|
857 | this.adapter.deregisterWindowEventHandler('resize', this.resizeListener);
|
858 | if (MDCSliderFoundation.SUPPORTS_POINTER_EVENTS) {
|
859 | this.adapter.deregisterEventHandler('pointerdown', this.pointerdownListener);
|
860 | this.adapter.deregisterEventHandler('pointerup', this.pointerupListener);
|
861 | }
|
862 | else {
|
863 | this.adapter.deregisterEventHandler('mousedown', this.mousedownOrTouchstartListener);
|
864 | this.adapter.deregisterEventHandler('touchstart', this.mousedownOrTouchstartListener);
|
865 | }
|
866 | if (this.isRange) {
|
867 | this.adapter.deregisterThumbEventHandler(Thumb.START, 'mouseenter', this.thumbMouseenterListener);
|
868 | this.adapter.deregisterThumbEventHandler(Thumb.START, 'mouseleave', this.thumbMouseleaveListener);
|
869 | this.adapter.deregisterInputEventHandler(Thumb.START, 'change', this.inputStartChangeListener);
|
870 | this.adapter.deregisterInputEventHandler(Thumb.START, 'focus', this.inputStartFocusListener);
|
871 | this.adapter.deregisterInputEventHandler(Thumb.START, 'blur', this.inputStartBlurListener);
|
872 | }
|
873 | this.adapter.deregisterThumbEventHandler(Thumb.END, 'mouseenter', this.thumbMouseenterListener);
|
874 | this.adapter.deregisterThumbEventHandler(Thumb.END, 'mouseleave', this.thumbMouseleaveListener);
|
875 | this.adapter.deregisterInputEventHandler(Thumb.END, 'change', this.inputEndChangeListener);
|
876 | this.adapter.deregisterInputEventHandler(Thumb.END, 'focus', this.inputEndFocusListener);
|
877 | this.adapter.deregisterInputEventHandler(Thumb.END, 'blur', this.inputEndBlurListener);
|
878 | };
|
879 | MDCSliderFoundation.prototype.handlePointerup = function () {
|
880 | this.handleUp();
|
881 | this.adapter.deregisterEventHandler('pointermove', this.moveListener);
|
882 | };
|
883 | MDCSliderFoundation.SUPPORTS_POINTER_EVENTS = HAS_WINDOW && Boolean(window.PointerEvent) &&
|
884 |
|
885 |
|
886 |
|
887 | !isIOS();
|
888 | return MDCSliderFoundation;
|
889 | }(MDCFoundation));
|
890 | export { MDCSliderFoundation };
|
891 | function isIOS() {
|
892 |
|
893 |
|
894 | return [
|
895 | 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone',
|
896 | 'iPod'
|
897 | ].includes(navigator.platform)
|
898 |
|
899 | || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
|
900 | }
|
901 |
|
902 |
|
903 |
|
904 |
|
905 |
|
906 |
|
907 | function getNumDecimalPlaces(n) {
|
908 |
|
909 | var match = /(?:\.(\d+))?(?:[eE]([+\-]?\d+))?$/.exec(String(n));
|
910 |
|
911 |
|
912 | if (!match)
|
913 | return 0;
|
914 | var fraction = match[1] || '';
|
915 | var exponent = match[2] || 0;
|
916 |
|
917 |
|
918 |
|
919 |
|
920 | return Math.max(0,
|
921 | (fraction === '0' ? 0 : fraction.length) - Number(exponent));
|
922 | }
|
923 |
|
\ | No newline at end of file |