| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035 |
- /**
- * @license
- * Copyright 2020 Google Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
- import { __assign, __extends } from "tslib";
- import { AnimationFrame } from '@material/animation/animationframe';
- import { getCorrectPropertyName } from '@material/animation/util';
- import { MDCFoundation } from '@material/base/foundation';
- import { attributes, cssClasses, numbers, strings } from './constants';
- import { Thumb, TickMark } from './types';
- var AnimationKeys;
- (function (AnimationKeys) {
- AnimationKeys["SLIDER_UPDATE"] = "slider_update";
- })(AnimationKeys || (AnimationKeys = {}));
- // Accessing `window` without a `typeof` check will throw on Node environments.
- var HAS_WINDOW = typeof window !== 'undefined';
- /**
- * Foundation class for slider. Responsibilities include:
- * - Updating slider values (internal state and DOM updates) based on client
- * 'x' position.
- * - Updating DOM after slider property updates (e.g. min, max).
- */
- var MDCSliderFoundation = /** @class */ (function (_super) {
- __extends(MDCSliderFoundation, _super);
- function MDCSliderFoundation(adapter) {
- var _this = _super.call(this, __assign(__assign({}, MDCSliderFoundation.defaultAdapter), adapter)) || this;
- // Whether the initial styles (to position the thumb, before component
- // initialization) have been removed.
- _this.initialStylesRemoved = false;
- _this.isDisabled = false;
- _this.isDiscrete = false;
- _this.step = numbers.STEP_SIZE;
- _this.minRange = numbers.MIN_RANGE;
- _this.hasTickMarks = false;
- // The following properties are only set for range sliders.
- _this.isRange = false;
- // Tracks the thumb being moved across a slider pointer interaction (down,
- // move event).
- _this.thumb = null;
- // `clientX` from the most recent down event. Used in subsequent move
- // events to determine which thumb to move (in the case of
- // overlapping thumbs).
- _this.downEventClientX = null;
- // Width of the start thumb knob.
- _this.startThumbKnobWidth = 0;
- // Width of the end thumb knob.
- _this.endThumbKnobWidth = 0;
- _this.animFrame = new AnimationFrame();
- return _this;
- }
- Object.defineProperty(MDCSliderFoundation, "defaultAdapter", {
- get: function () {
- // tslint:disable:object-literal-sort-keys Methods should be in the same
- // order as the adapter interface.
- return {
- hasClass: function () { return false; },
- addClass: function () { return undefined; },
- removeClass: function () { return undefined; },
- addThumbClass: function () { return undefined; },
- removeThumbClass: function () { return undefined; },
- getAttribute: function () { return null; },
- getInputValue: function () { return ''; },
- setInputValue: function () { return undefined; },
- getInputAttribute: function () { return null; },
- setInputAttribute: function () { return null; },
- removeInputAttribute: function () { return null; },
- focusInput: function () { return undefined; },
- isInputFocused: function () { return false; },
- shouldHideFocusStylesForPointerEvents: function () { return false; },
- getThumbKnobWidth: function () { return 0; },
- getValueIndicatorContainerWidth: function () { return 0; },
- getThumbBoundingClientRect: function () {
- return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 });
- },
- getBoundingClientRect: function () {
- return ({ top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 });
- },
- isRTL: function () { return false; },
- setThumbStyleProperty: function () { return undefined; },
- removeThumbStyleProperty: function () { return undefined; },
- setTrackActiveStyleProperty: function () { return undefined; },
- removeTrackActiveStyleProperty: function () { return undefined; },
- setValueIndicatorText: function () { return undefined; },
- getValueToAriaValueTextFn: function () { return null; },
- updateTickMarks: function () { return undefined; },
- setPointerCapture: function () { return undefined; },
- emitChangeEvent: function () { return undefined; },
- emitInputEvent: function () { return undefined; },
- emitDragStartEvent: function () { return undefined; },
- emitDragEndEvent: function () { return undefined; },
- registerEventHandler: function () { return undefined; },
- deregisterEventHandler: function () { return undefined; },
- registerThumbEventHandler: function () { return undefined; },
- deregisterThumbEventHandler: function () { return undefined; },
- registerInputEventHandler: function () { return undefined; },
- deregisterInputEventHandler: function () { return undefined; },
- registerBodyEventHandler: function () { return undefined; },
- deregisterBodyEventHandler: function () { return undefined; },
- registerWindowEventHandler: function () { return undefined; },
- deregisterWindowEventHandler: function () { return undefined; },
- };
- // tslint:enable:object-literal-sort-keys
- },
- enumerable: false,
- configurable: true
- });
- MDCSliderFoundation.prototype.init = function () {
- var _this = this;
- this.isDisabled = this.adapter.hasClass(cssClasses.DISABLED);
- this.isDiscrete = this.adapter.hasClass(cssClasses.DISCRETE);
- this.hasTickMarks = this.adapter.hasClass(cssClasses.TICK_MARKS);
- this.isRange = this.adapter.hasClass(cssClasses.RANGE);
- var min = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_MIN, this.isRange ? Thumb.START : Thumb.END), attributes.INPUT_MIN);
- var max = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_MAX, Thumb.END), attributes.INPUT_MAX);
- var value = this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_VALUE, Thumb.END), attributes.INPUT_VALUE);
- var valueStart = this.isRange ?
- this.convertAttributeValueToNumber(this.adapter.getInputAttribute(attributes.INPUT_VALUE, Thumb.START), attributes.INPUT_VALUE) :
- min;
- var stepAttr = this.adapter.getInputAttribute(attributes.INPUT_STEP, Thumb.END);
- var step = stepAttr ?
- this.convertAttributeValueToNumber(stepAttr, attributes.INPUT_STEP) :
- this.step;
- var minRangeAttr = this.adapter.getAttribute(attributes.DATA_MIN_RANGE);
- var minRange = minRangeAttr ?
- this.convertAttributeValueToNumber(minRangeAttr, attributes.DATA_MIN_RANGE) :
- this.minRange;
- this.validateProperties({ min: min, max: max, value: value, valueStart: valueStart, step: step, minRange: minRange });
- this.min = min;
- this.max = max;
- this.value = value;
- this.valueStart = valueStart;
- this.step = step;
- this.minRange = minRange;
- this.numDecimalPlaces = getNumDecimalPlaces(this.step);
- this.valueBeforeDownEvent = value;
- this.valueStartBeforeDownEvent = valueStart;
- this.mousedownOrTouchstartListener =
- this.handleMousedownOrTouchstart.bind(this);
- this.moveListener = this.handleMove.bind(this);
- this.pointerdownListener = this.handlePointerdown.bind(this);
- this.pointerupListener = this.handlePointerup.bind(this);
- this.thumbMouseenterListener = this.handleThumbMouseenter.bind(this);
- this.thumbMouseleaveListener = this.handleThumbMouseleave.bind(this);
- this.inputStartChangeListener = function () {
- _this.handleInputChange(Thumb.START);
- };
- this.inputEndChangeListener = function () {
- _this.handleInputChange(Thumb.END);
- };
- this.inputStartFocusListener = function () {
- _this.handleInputFocus(Thumb.START);
- };
- this.inputEndFocusListener = function () {
- _this.handleInputFocus(Thumb.END);
- };
- this.inputStartBlurListener = function () {
- _this.handleInputBlur(Thumb.START);
- };
- this.inputEndBlurListener = function () {
- _this.handleInputBlur(Thumb.END);
- };
- this.resizeListener = this.handleResize.bind(this);
- this.registerEventHandlers();
- };
- MDCSliderFoundation.prototype.destroy = function () {
- this.deregisterEventHandlers();
- };
- MDCSliderFoundation.prototype.setMin = function (value) {
- this.min = value;
- if (!this.isRange) {
- this.valueStart = value;
- }
- this.updateUI();
- };
- MDCSliderFoundation.prototype.setMax = function (value) {
- this.max = value;
- this.updateUI();
- };
- MDCSliderFoundation.prototype.getMin = function () {
- return this.min;
- };
- MDCSliderFoundation.prototype.getMax = function () {
- return this.max;
- };
- /**
- * - For single point sliders, returns the thumb value.
- * - For range (two-thumb) sliders, returns the end thumb's value.
- */
- MDCSliderFoundation.prototype.getValue = function () {
- return this.value;
- };
- /**
- * - For single point sliders, sets the thumb value.
- * - For range (two-thumb) sliders, sets the end thumb's value.
- */
- MDCSliderFoundation.prototype.setValue = function (value) {
- if (this.isRange && value < this.valueStart + this.minRange) {
- throw new Error("end thumb value (" + value + ") must be >= start thumb " +
- ("value (" + this.valueStart + ") + min range (" + this.minRange + ")"));
- }
- this.updateValue(value, Thumb.END);
- };
- /**
- * Only applicable for range sliders.
- * @return The start thumb's value.
- */
- MDCSliderFoundation.prototype.getValueStart = function () {
- if (!this.isRange) {
- throw new Error('`valueStart` is only applicable for range sliders.');
- }
- return this.valueStart;
- };
- /**
- * Only applicable for range sliders. Sets the start thumb's value.
- */
- MDCSliderFoundation.prototype.setValueStart = function (valueStart) {
- if (!this.isRange) {
- throw new Error('`valueStart` is only applicable for range sliders.');
- }
- if (this.isRange && valueStart > this.value - this.minRange) {
- throw new Error("start thumb value (" + valueStart + ") must be <= end thumb " +
- ("value (" + this.value + ") - min range (" + this.minRange + ")"));
- }
- this.updateValue(valueStart, Thumb.START);
- };
- MDCSliderFoundation.prototype.setStep = function (value) {
- this.step = value;
- this.numDecimalPlaces = getNumDecimalPlaces(value);
- this.updateUI();
- };
- /**
- * Only applicable for range sliders. Sets the minimum difference between the
- * start and end values.
- */
- MDCSliderFoundation.prototype.setMinRange = function (value) {
- if (!this.isRange) {
- throw new Error('`minRange` is only applicable for range sliders.');
- }
- if (value < 0) {
- throw new Error('`minRange` must be non-negative. ' +
- ("Current value: " + value));
- }
- if (this.value - this.valueStart < value) {
- throw new Error("start thumb value (" + this.valueStart + ") and end thumb value " +
- ("(" + this.value + ") must differ by at least " + value + "."));
- }
- this.minRange = value;
- };
- MDCSliderFoundation.prototype.setIsDiscrete = function (value) {
- this.isDiscrete = value;
- this.updateValueIndicatorUI();
- this.updateTickMarksUI();
- };
- MDCSliderFoundation.prototype.getStep = function () {
- return this.step;
- };
- MDCSliderFoundation.prototype.getMinRange = function () {
- if (!this.isRange) {
- throw new Error('`minRange` is only applicable for range sliders.');
- }
- return this.minRange;
- };
- MDCSliderFoundation.prototype.setHasTickMarks = function (value) {
- this.hasTickMarks = value;
- this.updateTickMarksUI();
- };
- MDCSliderFoundation.prototype.getDisabled = function () {
- return this.isDisabled;
- };
- /**
- * Sets disabled state, including updating styles and thumb tabindex.
- */
- MDCSliderFoundation.prototype.setDisabled = function (disabled) {
- this.isDisabled = disabled;
- if (disabled) {
- this.adapter.addClass(cssClasses.DISABLED);
- if (this.isRange) {
- this.adapter.setInputAttribute(attributes.INPUT_DISABLED, '', Thumb.START);
- }
- this.adapter.setInputAttribute(attributes.INPUT_DISABLED, '', Thumb.END);
- }
- else {
- this.adapter.removeClass(cssClasses.DISABLED);
- if (this.isRange) {
- this.adapter.removeInputAttribute(attributes.INPUT_DISABLED, Thumb.START);
- }
- this.adapter.removeInputAttribute(attributes.INPUT_DISABLED, Thumb.END);
- }
- };
- /** @return Whether the slider is a range slider. */
- MDCSliderFoundation.prototype.getIsRange = function () {
- return this.isRange;
- };
- /**
- * - Syncs slider boundingClientRect with the current DOM.
- * - Updates UI based on internal state.
- */
- MDCSliderFoundation.prototype.layout = function (_a) {
- var _b = _a === void 0 ? {} : _a, skipUpdateUI = _b.skipUpdateUI;
- this.rect = this.adapter.getBoundingClientRect();
- if (this.isRange) {
- this.startThumbKnobWidth = this.adapter.getThumbKnobWidth(Thumb.START);
- this.endThumbKnobWidth = this.adapter.getThumbKnobWidth(Thumb.END);
- }
- if (!skipUpdateUI) {
- this.updateUI();
- }
- };
- /** Handles resize events on the window. */
- MDCSliderFoundation.prototype.handleResize = function () {
- this.layout();
- };
- /**
- * Handles pointer down events on the slider root element.
- */
- MDCSliderFoundation.prototype.handleDown = function (event) {
- if (this.isDisabled)
- return;
- this.valueStartBeforeDownEvent = this.valueStart;
- this.valueBeforeDownEvent = this.value;
- var clientX = event.clientX != null ?
- event.clientX :
- event.targetTouches[0].clientX;
- this.downEventClientX = clientX;
- var value = this.mapClientXOnSliderScale(clientX);
- this.thumb = this.getThumbFromDownEvent(clientX, value);
- if (this.thumb === null)
- return;
- this.handleDragStart(event, value, this.thumb);
- this.updateValue(value, this.thumb, { emitInputEvent: true });
- };
- /**
- * Handles pointer move events on the slider root element.
- */
- MDCSliderFoundation.prototype.handleMove = function (event) {
- if (this.isDisabled)
- return;
- // Prevent scrolling.
- event.preventDefault();
- var clientX = event.clientX != null ?
- event.clientX :
- event.targetTouches[0].clientX;
- var dragAlreadyStarted = this.thumb != null;
- this.thumb = this.getThumbFromMoveEvent(clientX);
- if (this.thumb === null)
- return;
- var value = this.mapClientXOnSliderScale(clientX);
- if (!dragAlreadyStarted) {
- this.handleDragStart(event, value, this.thumb);
- this.adapter.emitDragStartEvent(value, this.thumb);
- }
- this.updateValue(value, this.thumb, { emitInputEvent: true });
- };
- /**
- * Handles pointer up events on the slider root element.
- */
- MDCSliderFoundation.prototype.handleUp = function () {
- var _a, _b;
- if (this.isDisabled || this.thumb === null)
- return;
- // Remove the focused state and hide the value indicator(s) (if present)
- // if focus state is meant to be hidden.
- if ((_b = (_a = this.adapter).shouldHideFocusStylesForPointerEvents) === null || _b === void 0 ? void 0 : _b.call(_a)) {
- this.handleInputBlur(this.thumb);
- }
- var oldValue = this.thumb === Thumb.START ?
- this.valueStartBeforeDownEvent :
- this.valueBeforeDownEvent;
- var newValue = this.thumb === Thumb.START ? this.valueStart : this.value;
- if (oldValue !== newValue) {
- this.adapter.emitChangeEvent(newValue, this.thumb);
- }
- this.adapter.emitDragEndEvent(newValue, this.thumb);
- this.thumb = null;
- };
- /**
- * For range, discrete slider, shows the value indicator on both thumbs.
- */
- MDCSliderFoundation.prototype.handleThumbMouseenter = function () {
- if (!this.isDiscrete || !this.isRange)
- return;
- this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.START);
- this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.END);
- };
- /**
- * For range, discrete slider, hides the value indicator on both thumbs.
- */
- MDCSliderFoundation.prototype.handleThumbMouseleave = function () {
- var _a, _b;
- if (!this.isDiscrete || !this.isRange)
- return;
- if ((!((_b = (_a = this.adapter).shouldHideFocusStylesForPointerEvents) === null || _b === void 0 ? void 0 : _b.call(_a)) &&
- (this.adapter.isInputFocused(Thumb.START) ||
- this.adapter.isInputFocused(Thumb.END))) ||
- this.thumb) {
- // Leave value indicator shown if either input is focused or the thumb is
- // being dragged.
- return;
- }
- this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.START);
- this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, Thumb.END);
- };
- MDCSliderFoundation.prototype.handleMousedownOrTouchstart = function (event) {
- var _this = this;
- var moveEventType = event.type === 'mousedown' ? 'mousemove' : 'touchmove';
- // After a down event on the slider root, listen for move events on
- // body (so the slider value is updated for events outside of the
- // slider root).
- this.adapter.registerBodyEventHandler(moveEventType, this.moveListener);
- var upHandler = function () {
- _this.handleUp();
- // Once the drag is finished (up event on body), remove the move
- // handler.
- _this.adapter.deregisterBodyEventHandler(moveEventType, _this.moveListener);
- // Also stop listening for subsequent up events.
- _this.adapter.deregisterEventHandler('mouseup', upHandler);
- _this.adapter.deregisterEventHandler('touchend', upHandler);
- };
- this.adapter.registerBodyEventHandler('mouseup', upHandler);
- this.adapter.registerBodyEventHandler('touchend', upHandler);
- this.handleDown(event);
- };
- MDCSliderFoundation.prototype.handlePointerdown = function (event) {
- var isPrimaryButton = event.button === 0;
- if (!isPrimaryButton)
- return;
- if (event.pointerId != null) {
- this.adapter.setPointerCapture(event.pointerId);
- }
- this.adapter.registerEventHandler('pointermove', this.moveListener);
- this.handleDown(event);
- };
- /**
- * Handles input `change` event by setting internal slider value to match
- * input's new value.
- */
- MDCSliderFoundation.prototype.handleInputChange = function (thumb) {
- var value = Number(this.adapter.getInputValue(thumb));
- if (thumb === Thumb.START) {
- this.setValueStart(value);
- }
- else {
- this.setValue(value);
- }
- this.adapter.emitChangeEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
- this.adapter.emitInputEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
- };
- /** Shows activated state and value indicator on thumb(s). */
- MDCSliderFoundation.prototype.handleInputFocus = function (thumb) {
- this.adapter.addThumbClass(cssClasses.THUMB_FOCUSED, thumb);
- if (!this.isDiscrete)
- return;
- this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, thumb);
- if (this.isRange) {
- var otherThumb = thumb === Thumb.START ? Thumb.END : Thumb.START;
- this.adapter.addThumbClass(cssClasses.THUMB_WITH_INDICATOR, otherThumb);
- }
- };
- /** Removes activated state and value indicator from thumb(s). */
- MDCSliderFoundation.prototype.handleInputBlur = function (thumb) {
- this.adapter.removeThumbClass(cssClasses.THUMB_FOCUSED, thumb);
- if (!this.isDiscrete)
- return;
- this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, thumb);
- if (this.isRange) {
- var otherThumb = thumb === Thumb.START ? Thumb.END : Thumb.START;
- this.adapter.removeThumbClass(cssClasses.THUMB_WITH_INDICATOR, otherThumb);
- }
- };
- /**
- * Emits custom dragStart event, along with focusing the underlying input.
- */
- MDCSliderFoundation.prototype.handleDragStart = function (event, value, thumb) {
- var _a, _b;
- this.adapter.emitDragStartEvent(value, thumb);
- this.adapter.focusInput(thumb);
- // Restore focused state and show the value indicator(s) (if present)
- // in case they were previously hidden on dragEnd.
- // This is needed if the input is already focused, in which case
- // #focusInput above wouldn't actually trigger #handleInputFocus,
- // which is why we need to invoke it manually here.
- if ((_b = (_a = this.adapter).shouldHideFocusStylesForPointerEvents) === null || _b === void 0 ? void 0 : _b.call(_a)) {
- this.handleInputFocus(thumb);
- }
- // Prevent the input (that we just focused) from losing focus.
- event.preventDefault();
- };
- /**
- * @return The thumb to be moved based on initial down event.
- */
- MDCSliderFoundation.prototype.getThumbFromDownEvent = function (clientX, value) {
- // For single point slider, thumb to be moved is always the END (only)
- // thumb.
- if (!this.isRange)
- return Thumb.END;
- // Check if event press point is in the bounds of any thumb.
- var thumbStartRect = this.adapter.getThumbBoundingClientRect(Thumb.START);
- var thumbEndRect = this.adapter.getThumbBoundingClientRect(Thumb.END);
- var inThumbStartBounds = clientX >= thumbStartRect.left && clientX <= thumbStartRect.right;
- var inThumbEndBounds = clientX >= thumbEndRect.left && clientX <= thumbEndRect.right;
- if (inThumbStartBounds && inThumbEndBounds) {
- // Thumbs overlapping. Thumb to be moved cannot be determined yet.
- return null;
- }
- // If press is in bounds for either thumb on down event, that's the thumb
- // to be moved.
- if (inThumbStartBounds) {
- return Thumb.START;
- }
- if (inThumbEndBounds) {
- return Thumb.END;
- }
- // For presses outside the range, return whichever thumb is closer.
- if (value < this.valueStart) {
- return Thumb.START;
- }
- if (value > this.value) {
- return Thumb.END;
- }
- // For presses inside the range, return whichever thumb is closer.
- return (value - this.valueStart <= this.value - value) ? Thumb.START :
- Thumb.END;
- };
- /**
- * @return The thumb to be moved based on move event (based on drag
- * direction from original down event). Only applicable if thumbs
- * were overlapping in the down event.
- */
- MDCSliderFoundation.prototype.getThumbFromMoveEvent = function (clientX) {
- // Thumb has already been chosen.
- if (this.thumb !== null)
- return this.thumb;
- if (this.downEventClientX === null) {
- throw new Error('`downEventClientX` is null after move event.');
- }
- var moveDistanceUnderThreshold = Math.abs(this.downEventClientX - clientX) < numbers.THUMB_UPDATE_MIN_PX;
- if (moveDistanceUnderThreshold)
- return this.thumb;
- var draggedThumbToLeft = clientX < this.downEventClientX;
- if (draggedThumbToLeft) {
- return this.adapter.isRTL() ? Thumb.END : Thumb.START;
- }
- else {
- return this.adapter.isRTL() ? Thumb.START : Thumb.END;
- }
- };
- /**
- * Updates UI based on internal state.
- * @param thumb Thumb whose value is being updated. If undefined, UI is
- * updated for both thumbs based on current internal state.
- */
- MDCSliderFoundation.prototype.updateUI = function (thumb) {
- if (thumb) {
- this.updateThumbAndInputAttributes(thumb);
- }
- else {
- this.updateThumbAndInputAttributes(Thumb.START);
- this.updateThumbAndInputAttributes(Thumb.END);
- }
- this.updateThumbAndTrackUI(thumb);
- this.updateValueIndicatorUI(thumb);
- this.updateTickMarksUI();
- };
- /**
- * Updates thumb and input attributes based on current value.
- * @param thumb Thumb whose aria attributes to update.
- */
- MDCSliderFoundation.prototype.updateThumbAndInputAttributes = function (thumb) {
- if (!thumb)
- return;
- var value = this.isRange && thumb === Thumb.START ? this.valueStart : this.value;
- var valueStr = String(value);
- this.adapter.setInputAttribute(attributes.INPUT_VALUE, valueStr, thumb);
- if (this.isRange && thumb === Thumb.START) {
- this.adapter.setInputAttribute(attributes.INPUT_MIN, String(value + this.minRange), Thumb.END);
- }
- else if (this.isRange && thumb === Thumb.END) {
- this.adapter.setInputAttribute(attributes.INPUT_MAX, String(value - this.minRange), Thumb.START);
- }
- // Sync attribute with property.
- if (this.adapter.getInputValue(thumb) !== valueStr) {
- this.adapter.setInputValue(valueStr, thumb);
- }
- var valueToAriaValueTextFn = this.adapter.getValueToAriaValueTextFn();
- if (valueToAriaValueTextFn) {
- this.adapter.setInputAttribute(attributes.ARIA_VALUETEXT, valueToAriaValueTextFn(value, thumb), thumb);
- }
- };
- /**
- * Updates value indicator UI based on current value.
- * @param thumb Thumb whose value indicator to update. If undefined, all
- * thumbs' value indicators are updated.
- */
- MDCSliderFoundation.prototype.updateValueIndicatorUI = function (thumb) {
- if (!this.isDiscrete)
- return;
- var value = this.isRange && thumb === Thumb.START ? this.valueStart : this.value;
- this.adapter.setValueIndicatorText(value, thumb === Thumb.START ? Thumb.START : Thumb.END);
- if (!thumb && this.isRange) {
- this.adapter.setValueIndicatorText(this.valueStart, Thumb.START);
- }
- };
- /**
- * Updates tick marks UI within slider, based on current min, max, and step.
- */
- MDCSliderFoundation.prototype.updateTickMarksUI = function () {
- if (!this.isDiscrete || !this.hasTickMarks)
- return;
- var numTickMarksInactiveStart = (this.valueStart - this.min) / this.step;
- var numTickMarksActive = (this.value - this.valueStart) / this.step + 1;
- var numTickMarksInactiveEnd = (this.max - this.value) / this.step;
- var tickMarksInactiveStart = Array.from({ length: numTickMarksInactiveStart })
- .fill(TickMark.INACTIVE);
- var tickMarksActive = Array.from({ length: numTickMarksActive })
- .fill(TickMark.ACTIVE);
- var tickMarksInactiveEnd = Array.from({ length: numTickMarksInactiveEnd })
- .fill(TickMark.INACTIVE);
- this.adapter.updateTickMarks(tickMarksInactiveStart.concat(tickMarksActive)
- .concat(tickMarksInactiveEnd));
- };
- /** Maps clientX to a value on the slider scale. */
- MDCSliderFoundation.prototype.mapClientXOnSliderScale = function (clientX) {
- var xPos = clientX - this.rect.left;
- var pctComplete = xPos / this.rect.width;
- if (this.adapter.isRTL()) {
- pctComplete = 1 - pctComplete;
- }
- // Fit the percentage complete between the range [min,max]
- // by remapping from [0, 1] to [min, min+(max-min)].
- var value = this.min + pctComplete * (this.max - this.min);
- if (value === this.max || value === this.min) {
- return value;
- }
- return Number(this.quantize(value).toFixed(this.numDecimalPlaces));
- };
- /** Calculates the quantized value based on step value. */
- MDCSliderFoundation.prototype.quantize = function (value) {
- var numSteps = Math.round((value - this.min) / this.step);
- return this.min + numSteps * this.step;
- };
- /**
- * Updates slider value (internal state and UI) based on the given value.
- */
- MDCSliderFoundation.prototype.updateValue = function (value, thumb, _a) {
- var _b = _a === void 0 ? {} : _a, emitInputEvent = _b.emitInputEvent;
- value = this.clampValue(value, thumb);
- if (this.isRange && thumb === Thumb.START) {
- // Exit early if current value is the same as the new value.
- if (this.valueStart === value)
- return;
- this.valueStart = value;
- }
- else {
- // Exit early if current value is the same as the new value.
- if (this.value === value)
- return;
- this.value = value;
- }
- this.updateUI(thumb);
- if (emitInputEvent) {
- this.adapter.emitInputEvent(thumb === Thumb.START ? this.valueStart : this.value, thumb);
- }
- };
- /**
- * Clamps the given value for the given thumb based on slider properties:
- * - Restricts value within [min, max].
- * - If range slider, clamp start value <= end value - min range, and
- * end value >= start value + min range.
- */
- MDCSliderFoundation.prototype.clampValue = function (value, thumb) {
- // Clamp value to [min, max] range.
- value = Math.min(Math.max(value, this.min), this.max);
- var thumbStartMovedPastThumbEnd = this.isRange && thumb === Thumb.START &&
- value > this.value - this.minRange;
- if (thumbStartMovedPastThumbEnd) {
- return this.value - this.minRange;
- }
- var thumbEndMovedPastThumbStart = this.isRange && thumb === Thumb.END &&
- value < this.valueStart + this.minRange;
- if (thumbEndMovedPastThumbStart) {
- return this.valueStart + this.minRange;
- }
- return value;
- };
- /**
- * Updates the active track and thumb style properties to reflect current
- * value.
- */
- MDCSliderFoundation.prototype.updateThumbAndTrackUI = function (thumb) {
- var _this = this;
- var _a = this, max = _a.max, min = _a.min;
- var pctComplete = (this.value - this.valueStart) / (max - min);
- var rangePx = pctComplete * this.rect.width;
- var isRtl = this.adapter.isRTL();
- var transformProp = HAS_WINDOW ? getCorrectPropertyName(window, 'transform') : 'transform';
- if (this.isRange) {
- var thumbLeftPos_1 = this.adapter.isRTL() ?
- (max - this.value) / (max - min) * this.rect.width :
- (this.valueStart - min) / (max - min) * this.rect.width;
- var thumbRightPos_1 = thumbLeftPos_1 + rangePx;
- this.animFrame.request(AnimationKeys.SLIDER_UPDATE, function () {
- // Set active track styles, accounting for animation direction by
- // setting `transform-origin`.
- var trackAnimatesFromRight = (!isRtl && thumb === Thumb.START) ||
- (isRtl && thumb !== Thumb.START);
- if (trackAnimatesFromRight) {
- _this.adapter.setTrackActiveStyleProperty('transform-origin', 'right');
- _this.adapter.setTrackActiveStyleProperty('left', 'auto');
- _this.adapter.setTrackActiveStyleProperty('right', _this.rect.width - thumbRightPos_1 + "px");
- }
- else {
- _this.adapter.setTrackActiveStyleProperty('transform-origin', 'left');
- _this.adapter.setTrackActiveStyleProperty('right', 'auto');
- _this.adapter.setTrackActiveStyleProperty('left', thumbLeftPos_1 + "px");
- }
- _this.adapter.setTrackActiveStyleProperty(transformProp, "scaleX(" + pctComplete + ")");
- // Set thumb styles.
- var thumbStartPos = isRtl ? thumbRightPos_1 : thumbLeftPos_1;
- var thumbEndPos = _this.adapter.isRTL() ? thumbLeftPos_1 : thumbRightPos_1;
- if (thumb === Thumb.START || !thumb || !_this.initialStylesRemoved) {
- _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbStartPos + "px)", Thumb.START);
- _this.alignValueIndicator(Thumb.START, thumbStartPos);
- }
- if (thumb === Thumb.END || !thumb || !_this.initialStylesRemoved) {
- _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbEndPos + "px)", Thumb.END);
- _this.alignValueIndicator(Thumb.END, thumbEndPos);
- }
- _this.removeInitialStyles(isRtl);
- _this.updateOverlappingThumbsUI(thumbStartPos, thumbEndPos, thumb);
- });
- }
- else {
- this.animFrame.request(AnimationKeys.SLIDER_UPDATE, function () {
- var thumbStartPos = isRtl ? _this.rect.width - rangePx : rangePx;
- _this.adapter.setThumbStyleProperty(transformProp, "translateX(" + thumbStartPos + "px)", Thumb.END);
- _this.alignValueIndicator(Thumb.END, thumbStartPos);
- _this.adapter.setTrackActiveStyleProperty(transformProp, "scaleX(" + pctComplete + ")");
- _this.removeInitialStyles(isRtl);
- });
- }
- };
- /**
- * Shifts the value indicator to either side if it would otherwise stick
- * beyond the slider's length while keeping the caret above the knob.
- */
- MDCSliderFoundation.prototype.alignValueIndicator = function (thumb, thumbPos) {
- if (!this.isDiscrete)
- return;
- var thumbHalfWidth = this.adapter.getThumbBoundingClientRect(thumb).width / 2;
- var containerWidth = this.adapter.getValueIndicatorContainerWidth(thumb);
- var sliderWidth = this.adapter.getBoundingClientRect().width;
- if (containerWidth / 2 > thumbPos + thumbHalfWidth) {
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_LEFT, thumbHalfWidth + "px", thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_RIGHT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_TRANSFORM, 'translateX(-50%)', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_LEFT, '0', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_RIGHT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_TRANSFORM, 'none', thumb);
- }
- else if (containerWidth / 2 > sliderWidth - thumbPos + thumbHalfWidth) {
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_LEFT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_RIGHT, thumbHalfWidth + "px", thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_TRANSFORM, 'translateX(50%)', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_LEFT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_RIGHT, '0', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_TRANSFORM, 'none', thumb);
- }
- else {
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_LEFT, '50%', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_RIGHT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CARET_TRANSFORM, 'translateX(-50%)', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_LEFT, '50%', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_RIGHT, 'auto', thumb);
- this.adapter.setThumbStyleProperty(strings.VAR_VALUE_INDICATOR_CONTAINER_TRANSFORM, 'translateX(-50%)', thumb);
- }
- };
- /**
- * Removes initial inline styles if not already removed. `left:<...>%`
- * inline styles can be added to position the thumb correctly before JS
- * initialization. However, they need to be removed before the JS starts
- * positioning the thumb. This is because the JS uses
- * `transform:translateX(<...>)px` (for performance reasons) to position
- * the thumb (which is not possible for initial styles since we need the
- * bounding rect measurements).
- */
- MDCSliderFoundation.prototype.removeInitialStyles = function (isRtl) {
- if (this.initialStylesRemoved)
- return;
- // Remove thumb position properties that were added for initial render.
- var position = isRtl ? 'right' : 'left';
- this.adapter.removeThumbStyleProperty(position, Thumb.END);
- if (this.isRange) {
- this.adapter.removeThumbStyleProperty(position, Thumb.START);
- }
- this.initialStylesRemoved = true;
- this.resetTrackAndThumbAnimation();
- };
- /**
- * Resets track/thumb animation to prevent animation when adding
- * `transform` styles to thumb initially.
- */
- MDCSliderFoundation.prototype.resetTrackAndThumbAnimation = function () {
- var _this = this;
- if (!this.isDiscrete)
- return;
- // Set transition properties to default (no animation), so that the
- // newly added `transform` styles do not animate thumb/track from
- // their default positions.
- var transitionProp = HAS_WINDOW ?
- getCorrectPropertyName(window, 'transition') :
- 'transition';
- var transitionDefault = 'none 0s ease 0s';
- this.adapter.setThumbStyleProperty(transitionProp, transitionDefault, Thumb.END);
- if (this.isRange) {
- this.adapter.setThumbStyleProperty(transitionProp, transitionDefault, Thumb.START);
- }
- this.adapter.setTrackActiveStyleProperty(transitionProp, transitionDefault);
- // In the next frame, remove the transition inline styles we just
- // added, such that any animations added in the CSS can now take effect.
- requestAnimationFrame(function () {
- _this.adapter.removeThumbStyleProperty(transitionProp, Thumb.END);
- _this.adapter.removeTrackActiveStyleProperty(transitionProp);
- if (_this.isRange) {
- _this.adapter.removeThumbStyleProperty(transitionProp, Thumb.START);
- }
- });
- };
- /**
- * Adds THUMB_TOP class to active thumb if thumb knobs overlap; otherwise
- * removes THUMB_TOP class from both thumbs.
- * @param thumb Thumb that is active (being moved).
- */
- MDCSliderFoundation.prototype.updateOverlappingThumbsUI = function (thumbStartPos, thumbEndPos, thumb) {
- var thumbsOverlap = false;
- if (this.adapter.isRTL()) {
- var startThumbLeftEdge = thumbStartPos - this.startThumbKnobWidth / 2;
- var endThumbRightEdge = thumbEndPos + this.endThumbKnobWidth / 2;
- thumbsOverlap = endThumbRightEdge >= startThumbLeftEdge;
- }
- else {
- var startThumbRightEdge = thumbStartPos + this.startThumbKnobWidth / 2;
- var endThumbLeftEdge = thumbEndPos - this.endThumbKnobWidth / 2;
- thumbsOverlap = startThumbRightEdge >= endThumbLeftEdge;
- }
- if (thumbsOverlap) {
- this.adapter.addThumbClass(cssClasses.THUMB_TOP,
- // If no thumb was dragged (in the case of initial layout), end
- // thumb is on top by default.
- thumb || Thumb.END);
- this.adapter.removeThumbClass(cssClasses.THUMB_TOP, thumb === Thumb.START ? Thumb.END : Thumb.START);
- }
- else {
- this.adapter.removeThumbClass(cssClasses.THUMB_TOP, Thumb.START);
- this.adapter.removeThumbClass(cssClasses.THUMB_TOP, Thumb.END);
- }
- };
- /**
- * Converts attribute value to a number, e.g. '100' => 100. Throws errors
- * for invalid values.
- * @param attributeValue Attribute value, e.g. 100.
- * @param attributeName Attribute name, e.g. `aria-valuemax`.
- */
- MDCSliderFoundation.prototype.convertAttributeValueToNumber = function (attributeValue, attributeName) {
- if (attributeValue === null) {
- throw new Error('MDCSliderFoundation: `' + attributeName + '` must be non-null.');
- }
- var value = Number(attributeValue);
- if (isNaN(value)) {
- throw new Error('MDCSliderFoundation: `' + attributeName + '` value is `' +
- attributeValue + '`, but must be a number.');
- }
- return value;
- };
- /** Checks that the given properties are valid slider values. */
- MDCSliderFoundation.prototype.validateProperties = function (_a) {
- var min = _a.min, max = _a.max, value = _a.value, valueStart = _a.valueStart, step = _a.step, minRange = _a.minRange;
- if (min >= max) {
- throw new Error("MDCSliderFoundation: min must be strictly less than max. " +
- ("Current: [min: " + min + ", max: " + max + "]"));
- }
- if (step <= 0) {
- throw new Error("MDCSliderFoundation: step must be a positive number. " +
- ("Current step: " + step));
- }
- if (this.isRange) {
- if (value < min || value > max || valueStart < min || valueStart > max) {
- throw new Error("MDCSliderFoundation: values must be in [min, max] range. " +
- ("Current values: [start value: " + valueStart + ", end value: ") +
- (value + ", min: " + min + ", max: " + max + "]"));
- }
- if (valueStart > value) {
- throw new Error("MDCSliderFoundation: start value must be <= end value. " +
- ("Current values: [start value: " + valueStart + ", end value: " + value + "]"));
- }
- if (minRange < 0) {
- throw new Error("MDCSliderFoundation: minimum range must be non-negative. " +
- ("Current min range: " + minRange));
- }
- if (value - valueStart < minRange) {
- throw new Error("MDCSliderFoundation: start value and end value must differ by at least " +
- (minRange + ". Current values: [start value: " + valueStart + ", ") +
- ("end value: " + value + "]"));
- }
- var numStepsValueStartFromMin = (valueStart - min) / step;
- var numStepsValueFromMin = (value - min) / step;
- if (!Number.isInteger(parseFloat(numStepsValueStartFromMin.toFixed(6))) ||
- !Number.isInteger(parseFloat(numStepsValueFromMin.toFixed(6)))) {
- throw new Error("MDCSliderFoundation: Slider values must be valid based on the " +
- ("step value (" + step + "). Current values: [start value: ") +
- (valueStart + ", end value: " + value + ", min: " + min + "]"));
- }
- }
- else { // Single point slider.
- if (value < min || value > max) {
- throw new Error("MDCSliderFoundation: value must be in [min, max] range. " +
- ("Current values: [value: " + value + ", min: " + min + ", max: " + max + "]"));
- }
- var numStepsValueFromMin = (value - min) / step;
- if (!Number.isInteger(parseFloat(numStepsValueFromMin.toFixed(6)))) {
- throw new Error("MDCSliderFoundation: Slider value must be valid based on the " +
- ("step value (" + step + "). Current value: " + value));
- }
- }
- };
- MDCSliderFoundation.prototype.registerEventHandlers = function () {
- this.adapter.registerWindowEventHandler('resize', this.resizeListener);
- if (MDCSliderFoundation.SUPPORTS_POINTER_EVENTS) {
- // If supported, use pointer events API with #setPointerCapture.
- this.adapter.registerEventHandler('pointerdown', this.pointerdownListener);
- this.adapter.registerEventHandler('pointerup', this.pointerupListener);
- }
- else {
- // Otherwise, fall back to mousedown/touchstart events.
- this.adapter.registerEventHandler('mousedown', this.mousedownOrTouchstartListener);
- this.adapter.registerEventHandler('touchstart', this.mousedownOrTouchstartListener);
- }
- if (this.isRange) {
- this.adapter.registerThumbEventHandler(Thumb.START, 'mouseenter', this.thumbMouseenterListener);
- this.adapter.registerThumbEventHandler(Thumb.START, 'mouseleave', this.thumbMouseleaveListener);
- this.adapter.registerInputEventHandler(Thumb.START, 'change', this.inputStartChangeListener);
- this.adapter.registerInputEventHandler(Thumb.START, 'focus', this.inputStartFocusListener);
- this.adapter.registerInputEventHandler(Thumb.START, 'blur', this.inputStartBlurListener);
- }
- this.adapter.registerThumbEventHandler(Thumb.END, 'mouseenter', this.thumbMouseenterListener);
- this.adapter.registerThumbEventHandler(Thumb.END, 'mouseleave', this.thumbMouseleaveListener);
- this.adapter.registerInputEventHandler(Thumb.END, 'change', this.inputEndChangeListener);
- this.adapter.registerInputEventHandler(Thumb.END, 'focus', this.inputEndFocusListener);
- this.adapter.registerInputEventHandler(Thumb.END, 'blur', this.inputEndBlurListener);
- };
- MDCSliderFoundation.prototype.deregisterEventHandlers = function () {
- this.adapter.deregisterWindowEventHandler('resize', this.resizeListener);
- if (MDCSliderFoundation.SUPPORTS_POINTER_EVENTS) {
- this.adapter.deregisterEventHandler('pointerdown', this.pointerdownListener);
- this.adapter.deregisterEventHandler('pointerup', this.pointerupListener);
- }
- else {
- this.adapter.deregisterEventHandler('mousedown', this.mousedownOrTouchstartListener);
- this.adapter.deregisterEventHandler('touchstart', this.mousedownOrTouchstartListener);
- }
- if (this.isRange) {
- this.adapter.deregisterThumbEventHandler(Thumb.START, 'mouseenter', this.thumbMouseenterListener);
- this.adapter.deregisterThumbEventHandler(Thumb.START, 'mouseleave', this.thumbMouseleaveListener);
- this.adapter.deregisterInputEventHandler(Thumb.START, 'change', this.inputStartChangeListener);
- this.adapter.deregisterInputEventHandler(Thumb.START, 'focus', this.inputStartFocusListener);
- this.adapter.deregisterInputEventHandler(Thumb.START, 'blur', this.inputStartBlurListener);
- }
- this.adapter.deregisterThumbEventHandler(Thumb.END, 'mouseenter', this.thumbMouseenterListener);
- this.adapter.deregisterThumbEventHandler(Thumb.END, 'mouseleave', this.thumbMouseleaveListener);
- this.adapter.deregisterInputEventHandler(Thumb.END, 'change', this.inputEndChangeListener);
- this.adapter.deregisterInputEventHandler(Thumb.END, 'focus', this.inputEndFocusListener);
- this.adapter.deregisterInputEventHandler(Thumb.END, 'blur', this.inputEndBlurListener);
- };
- MDCSliderFoundation.prototype.handlePointerup = function () {
- this.handleUp();
- this.adapter.deregisterEventHandler('pointermove', this.moveListener);
- };
- MDCSliderFoundation.SUPPORTS_POINTER_EVENTS = HAS_WINDOW && Boolean(window.PointerEvent) &&
- // #setPointerCapture is buggy on iOS, so we can't use pointer events
- // until the following bug is fixed:
- // https://bugs.webkit.org/show_bug.cgi?id=220196
- !isIOS();
- return MDCSliderFoundation;
- }(MDCFoundation));
- export { MDCSliderFoundation };
- function isIOS() {
- // Source:
- // https://stackoverflow.com/questions/9038625/detect-if-device-is-ios
- return [
- 'iPad Simulator', 'iPhone Simulator', 'iPod Simulator', 'iPad', 'iPhone',
- 'iPod'
- ].includes(navigator.platform)
- // iPad on iOS 13 detection
- || (navigator.userAgent.includes('Mac') && 'ontouchend' in document);
- }
- /**
- * Given a number, returns the number of digits that appear after the
- * decimal point.
- * See
- * https://stackoverflow.com/questions/9539513/is-there-a-reliable-way-in-javascript-to-obtain-the-number-of-decimal-places-of
- */
- function getNumDecimalPlaces(n) {
- // Pull out the fraction and the exponent.
- var match = /(?:\.(\d+))?(?:[eE]([+\-]?\d+))?$/.exec(String(n));
- // NaN or Infinity or integer.
- // We arbitrarily decide that Infinity is integral.
- if (!match)
- return 0;
- var fraction = match[1] || ''; // E.g. 1.234e-2 => 234
- var exponent = match[2] || 0; // E.g. 1.234e-2 => -2
- // Count the number of digits in the fraction and subtract the
- // exponent to simulate moving the decimal point left by exponent places.
- // 1.234e+2 has 1 fraction digit and '234'.length - 2 == 1
- // 1.234e-2 has 5 fraction digit and '234'.length - -2 == 5
- return Math.max(0, // lower limit
- (fraction === '0' ? 0 : fraction.length) - Number(exponent));
- }
- //# sourceMappingURL=foundation.js.map
|