UNPKG

@blox/material

Version:

Material Components for Angular

453 lines 65.7 kB
import { Directive, ElementRef, EventEmitter, forwardRef, HostBinding, HostListener, Inject, Input, Output, Renderer2, Self, SimpleChange } from '@angular/core'; import { DOCUMENT } from '@angular/common'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; import { MDCSliderFoundation } from '@material/slider'; import { events } from '@material/dom'; import { asBoolean } from '../../utils/value.utils'; import { MdcEventRegistry } from '../../utils/mdc.event.registry'; /** * Directive for creating a Material Design slider input. * (Modelled after the <code>&lt;input type="range"/&gt;</code> element). * The slider is fully accessible. The current implementation * will add and manage all DOM child elements that are required for the wrapped * <code>mdc-slider</code> component. * Future implementations will also support supplying (customized) * DOM children. */ export class MdcSliderDirective { constructor(_rndr, _root, _registry, doc) { this._rndr = _rndr; this._root = _root; this._registry = _registry; /** @internal */ this._cls = true; /** @internal */ this._role = 'slider'; /** * Event emitted when the value changes. The value may change because of user input, * or as a side affect of setting new min, max, or step values. */ this.valueChange = new EventEmitter(); /** * Event emitted when the min range value changes. This may happen as a side effect * of setting a new max value (when the new max is smaller than the old min). */ this.minValueChange = new EventEmitter(); /** * Event emitted when the max range value changes. This may happen as a side effect * of setting a new min value (when the new min is larger than the old max). */ this.maxValueChange = new EventEmitter(); /** * Event emitted when the step value changes. This may happen as a side effect * of making the slider discrete. */ this.stepValueChange = new EventEmitter(); this.trackCntr = null; this._elmThumbCntr = null; this._elmSliderPin = null; this._elmValueMarker = null; this._elmTrack = null; this._elmTrackMarkerCntr = null; this._reinitTabIndex = null; this._onChange = (value) => { }; this._onTouched = () => { }; this._discrete = false; this._markers = false; this._disabled = false; this._value = 0; this._min = 0; this._max = 100; this._step = 0; this._lastWidth = null; this.mdcAdapter = { hasClass: (className) => { if (className === 'mdc-slider--discrete') return this._discrete; if (className === 'mdc-slider--display-markers') return this._markers; return this._root.nativeElement.classList.contains(className); }, addClass: (className) => { this._rndr.addClass(this._root.nativeElement, className); }, removeClass: (className) => { this._rndr.removeClass(this._root.nativeElement, className); }, getAttribute: (name) => this._root.nativeElement.getAttribute(name), setAttribute: (name, value) => { // skip attributes that we control with angular if (!/^aria-(value.*|disabled)$/.test(name)) this._rndr.setAttribute(this._root.nativeElement, name, value); }, removeAttribute: (name) => { this._rndr.removeAttribute(this._root.nativeElement, name); }, computeBoundingRect: () => this._root.nativeElement.getBoundingClientRect(), getTabIndex: () => this._root.nativeElement.tabIndex, registerInteractionHandler: (evtType, handler) => this._registry.listen(this._rndr, evtType, handler, this._root, events.applyPassive()), deregisterInteractionHandler: (evtType, handler) => this._registry.unlisten(evtType, handler), registerThumbContainerInteractionHandler: (evtType, handler) => this._registry.listenElm(this._rndr, evtType, handler, this._elmThumbCntr, events.applyPassive()), deregisterThumbContainerInteractionHandler: (evtType, handler) => this._registry.unlisten(evtType, handler), registerBodyInteractionHandler: (evtType, handler) => this._registry.listenElm(this._rndr, evtType, handler, this.document.body), deregisterBodyInteractionHandler: (evtType, handler) => this._registry.unlisten(evtType, handler), registerResizeHandler: (handler) => this._registry.listenElm(this._rndr, 'resize', handler, this.document.defaultView), deregisterResizeHandler: (handler) => this._registry.unlisten('resize', handler), notifyInput: () => { let newValue = this.asNumber(this.foundation.getValue()); if (newValue !== this._value) { this._value = newValue; this.notifyValueChanged(); } }, notifyChange: () => { // currently not handling this event, if there is a usecase for this, please // create a feature request. }, setThumbContainerStyleProperty: (propertyName, value) => { this._rndr.setStyle(this._elmThumbCntr, propertyName, value); }, setTrackStyleProperty: (propertyName, value) => { this._rndr.setStyle(this._elmTrack, propertyName, value); }, setMarkerValue: (value) => { if (this._elmValueMarker) this._elmValueMarker.innerText = value != null ? value.toLocaleString() : ''; }, setTrackMarkers: (step, max, min) => { if (this._elmTrackMarkerCntr) { // from https://github.com/material-components/material-components-web/blob/v5.1.0/packages/mdc-slider/component.ts#L141 const stepStr = step.toLocaleString(); const maxStr = max.toLocaleString(); const minStr = min.toLocaleString(); const markerAmount = `((${maxStr} - ${minStr}) / ${stepStr})`; const markerWidth = `2px`; const markerBkgdImage = `linear-gradient(to right, currentColor ${markerWidth}, transparent 0)`; const markerBkgdLayout = `0 center / calc((100% - ${markerWidth}) / ${markerAmount}) 100% repeat-x`; const markerBkgdShorthand = `${markerBkgdImage} ${markerBkgdLayout}`; this._rndr.setStyle(this._elmTrackMarkerCntr, 'background', markerBkgdShorthand); } }, isRTL: () => getComputedStyle(this._root.nativeElement).direction === 'rtl' }; this.foundation = null; this.document = doc; // work around ngc issue https://github.com/angular/angular/issues/20351 } ngAfterContentInit() { this.initElements(); this.initDefaultAttributes(); this.foundation = new MDCSliderFoundation(this.mdcAdapter); this.foundation.init(); this._lastWidth = this.mdcAdapter.computeBoundingRect().width; this.updateValues({}); } ngAfterViewInit() { this.updateLayout(); } ngOnDestroy() { var _a; (_a = this.foundation) === null || _a === void 0 ? void 0 : _a.destroy(); } ngOnChanges(changes) { this._onChanges(changes); } /** @internal */ _onChanges(changes) { if (this.foundation) { if (this.isChanged('discrete', changes) || this.isChanged('markers', changes)) { this.foundation.destroy(); this.initElements(); this.initDefaultAttributes(); this.foundation = new MDCSliderFoundation(this.mdcAdapter); this.foundation.init(); } this.updateValues(changes); this.updateLayout(); } } isChanged(name, changes) { return changes[name] && changes[name].currentValue !== changes[name].previousValue; } initElements() { // initElements is also called when changes dictate a new Foundation initialization, // in which case we create new child elements: if (this.trackCntr) { this._rndr.removeChild(this._root.nativeElement, this.trackCntr); this._rndr.removeChild(this._root.nativeElement, this._elmThumbCntr); } this.trackCntr = this.addElement(this._root.nativeElement, 'div', ['mdc-slider__track-container']); this._elmTrack = this.addElement(this.trackCntr, 'div', ['mdc-slider__track']); if (this._discrete && this._markers) this._elmTrackMarkerCntr = this.addElement(this.trackCntr, 'div', ['mdc-slider__track-marker-container']); else this._elmTrackMarkerCntr = null; this._elmThumbCntr = this.addElement(this._root.nativeElement, 'div', ['mdc-slider__thumb-container']); if (this._discrete) { this._elmSliderPin = this.addElement(this._elmThumbCntr, 'div', ['mdc-slider__pin']); this._elmValueMarker = this.addElement(this._elmSliderPin, 'div', ['mdc-slider__pin-value-marker']); } else { this._elmSliderPin = null; this._elmValueMarker = null; } const svg = this._rndr.createElement('svg', 'svg'); this._rndr.addClass(svg, 'mdc-slider__thumb'); this._rndr.setAttribute(svg, 'width', '21'); this._rndr.setAttribute(svg, 'height', '21'); this._rndr.appendChild(this._elmThumbCntr, svg); const circle = this._rndr.createElement('circle', 'svg'); this._rndr.setAttribute(circle, 'cx', '10.5'); this._rndr.setAttribute(circle, 'cy', '10.5'); this._rndr.setAttribute(circle, 'r', '7.875'); this._rndr.appendChild(svg, circle); this.addElement(this._elmThumbCntr, 'div', ['mdc-slider__focus-ring']); } addElement(parent, element, classNames) { let child = this._rndr.createElement(element); classNames.forEach(name => { this._rndr.addClass(child, name); }); this._rndr.appendChild(parent, child); return child; } initDefaultAttributes() { if (this._reinitTabIndex) // value was set the first time we initialized the foundation, // so it should also be set when we reinitialize evrything: this._root.nativeElement.tabIndex = this._reinitTabIndex; else if (!this._root.nativeElement.hasAttribute('tabindex')) { // unless overridden by another tabIndex, we want sliders to // participate in tabbing (the foundation will remove the tabIndex // when the slider is disabled, reset to the initial value when enabled again): this._root.nativeElement.tabIndex = 0; this._reinitTabIndex = 0; } else { this._reinitTabIndex = this._root.nativeElement.tabIndex; } } updateValues(changes) { if (this._discrete && this._step < 1) { // See https://github.com/material-components/material-components-web/issues/1426 // mdc-slider doesn't allow a discrete step value < 1 currently: this._step = 1; Promise.resolve().then(() => { this.stepValueChange.emit(this._step); }); } else if (this._step < 0) { this._step = 0; Promise.resolve().then(() => { this.stepValueChange.emit(this._step); }); } if (this._min > this._max) { if (this.isChanged('maxValue', changes)) { this._min = this._max; Promise.resolve().then(() => { this.minValueChange.emit(this._min); }); } else { this._max = this._min; Promise.resolve().then(() => { this.maxValueChange.emit(this._max); }); } } let currValue = this.asNumber(changes['value'] ? changes['value'].currentValue : this._value); if (this._value < this._min) this._value = this._min; if (this._value > this._max) this._value = this._max; // find an order in which the changed values will be accepted by the foundation // (since the foundation will throw errors for min > max and other conditions): if (this._min < this.foundation.getMax()) { this.foundation.setMin(this._min); this.foundation.setMax(this._max); } else { this.foundation.setMax(this._max); this.foundation.setMin(this._min); } this.foundation.setStep(this._step); if (this.foundation.isDisabled() !== this._disabled) { // without this check, MDCFoundation may remove the tabIndex incorrectly, // preventing the slider from getting focus on keyboard commands: this.foundation.setDisabled(this._disabled); } this.foundation.setValue(this._value); // value may have changed during setValue(), due to step settings: this._value = this.asNumber(this.foundation.getValue()); // compare with '!=' as null and undefined are considered the same (for initialisation sake): if (currValue !== this._value) Promise.resolve().then(() => { this.notifyValueChanged(); }); } updateLayout() { let newWidth = this.mdcAdapter.computeBoundingRect().width; if (newWidth !== this._lastWidth) { this._lastWidth = newWidth; this.foundation.layout(); } } notifyValueChanged() { this.valueChange.emit(this._value); this._onChange(this._value); } /** @internal */ registerOnChange(onChange) { this._onChange = onChange; } /** @internal */ registerOnTouched(onTouched) { this._onTouched = onTouched; } /** * Make the slider discrete. Note from the wrapped <code>mdc-slider</code> * component: * <blockquote>If a slider contains a step value it does not mean that the slider is a "discrete" slider. * "Discrete slider" is a UX treatment, while having a step value is behavioral.</blockquote> */ get discrete() { return this._discrete; } set discrete(value) { this._discrete = asBoolean(value); } /** * Property to enable/disable the display of track markers. Display markers * are only supported for discrete sliders. Thus they are only shown when the values * of both markers and discrete equal true. */ get markers() { return this._markers; } set markers(value) { this._markers = asBoolean(value); } /** * The current value of the slider. */ get value() { return this._value; } set value(value) { this._value = this.asNumber(value); } /** * The minumum allowed value of the slider. */ get minValue() { return this._min; } set minValue(value) { this._min = this.asNumber(value); } /** * The maximum allowed value of the slider. */ get maxValue() { return this._max; } set maxValue(value) { this._max = this.asNumber(value); } /** * Set the step value (or set to 0 for no step value). * The step value can be a floating point value &gt;= 0. * The slider will quantize all values to match the step value, except for the minimum and * maximum, which can always be set. * Discrete sliders are required to have a step value other than 0. * Note from the wrapped <code>mdc-slider</code> component: * <blockquote>If a slider contains a step value it does not mean that the slider is a "discrete" slider. * "Discrete slider" is a UX treatment, while having a step value is behavioral.</blockquote> */ get stepValue() { return this._step; } set stepValue(value) { this._step = this.asNumber(value); } /** * A property to disable the slider. */ get disabled() { return this._disabled; } set disabled(value) { this._disabled = asBoolean(value); } /** @internal */ _onBlur() { this._onTouched(); } /** @internal */ asNumber(value) { if (value == null) return 0; let result = +value; if (isNaN(result)) return 0; return result; } } MdcSliderDirective.decorators = [ { type: Directive, args: [{ selector: '[mdcSlider]' },] } ]; MdcSliderDirective.ctorParameters = () => [ { type: Renderer2 }, { type: ElementRef }, { type: MdcEventRegistry }, { type: undefined, decorators: [{ type: Inject, args: [DOCUMENT,] }] } ]; MdcSliderDirective.propDecorators = { _cls: [{ type: HostBinding, args: ['class.mdc-slider',] }], _role: [{ type: HostBinding, args: ['attr.role',] }], valueChange: [{ type: Output }], minValueChange: [{ type: Output }], maxValueChange: [{ type: Output }], stepValueChange: [{ type: Output }], discrete: [{ type: Input }, { type: HostBinding, args: ['class.mdc-slider--discrete',] }], markers: [{ type: Input }, { type: HostBinding, args: ['class.mdc-slider--display-markers',] }], value: [{ type: Input }, { type: HostBinding, args: ['attr.aria-valuenow',] }], minValue: [{ type: Input }, { type: HostBinding, args: ['attr.aria-valuemin',] }], maxValue: [{ type: Input }, { type: HostBinding, args: ['attr.aria-valuemax',] }], stepValue: [{ type: Input }], disabled: [{ type: Input }, { type: HostBinding, args: ['attr.aria-disabled',] }], _onBlur: [{ type: HostListener, args: ['blur',] }] }; /** * Directive for adding Angular Forms (<code>ControlValueAccessor</code>) behavior to an * <code>MdcSliderDirective</code>. Allows the use of the Angular Forms API with * icon toggles, e.g. binding to <code>[(ngModel)]</code>, form validation, etc. */ export class MdcFormsSliderDirective { constructor(mdcSlider) { this.mdcSlider = mdcSlider; } /** @docs-private */ writeValue(obj) { let change = new SimpleChange(this.mdcSlider.value, this.mdcSlider.asNumber(obj), false); this.mdcSlider.value = obj; this.mdcSlider._onChanges({ value: change }); } /** @docs-private */ registerOnChange(onChange) { this.mdcSlider.registerOnChange(onChange); } /** @docs-private */ registerOnTouched(onTouched) { this.mdcSlider.registerOnTouched(onTouched); } /** @docs-private */ setDisabledState(disabled) { this.mdcSlider.disabled = disabled; } } MdcFormsSliderDirective.decorators = [ { type: Directive, args: [{ selector: '[mdcSlider][formControlName],[mdcSlider][formControl],[mdcSlider][ngModel]', providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => MdcFormsSliderDirective), multi: true } ] },] } ]; MdcFormsSliderDirective.ctorParameters = () => [ { type: MdcSliderDirective, decorators: [{ type: Self }] } ]; export const SLIDER_DIRECTIVES = [ MdcSliderDirective, MdcFormsSliderDirective ]; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWRjLnNsaWRlci5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvY29tcG9uZW50cy9zbGlkZXIvbWRjLnNsaWRlci5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFtQyxTQUFTLEVBQUUsVUFBVSxFQUFFLFlBQVksRUFBRSxVQUFVLEVBQ3JGLFdBQVcsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBd0IsTUFBTSxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsWUFBWSxFQUN0RixNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsUUFBUSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDM0MsT0FBTyxFQUFFLGlCQUFpQixFQUF3QixNQUFNLGdCQUFnQixDQUFDO0FBQ3pFLE9BQU8sRUFBRSxtQkFBbUIsRUFBb0IsTUFBTSxrQkFBa0IsQ0FBQztBQUN6RSxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUNwRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVsRTs7Ozs7Ozs7R0FRRztBQUlILE1BQU0sT0FBTyxrQkFBa0I7SUFtSDNCLFlBQW9CLEtBQWdCLEVBQVUsS0FBaUIsRUFBVSxTQUEyQixFQUM5RSxHQUFRO1FBRFYsVUFBSyxHQUFMLEtBQUssQ0FBVztRQUFVLFVBQUssR0FBTCxLQUFLLENBQVk7UUFBVSxjQUFTLEdBQVQsU0FBUyxDQUFrQjtRQWxIcEcsZ0JBQWdCO1FBQzBCLFNBQUksR0FBRyxJQUFJLENBQUM7UUFDdEQsZ0JBQWdCO1FBQ1UsVUFBSyxHQUFXLFFBQVEsQ0FBQztRQUNuRDs7O1dBR0c7UUFDZ0IsZ0JBQVcsR0FBeUIsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUMxRTs7O1dBR0c7UUFDZ0IsbUJBQWMsR0FB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LGlCQUFpQixHQUFHO0lBQzdCLGtCQUFrQixFQUFFLHVCQUF1QjtDQUM5QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJWaWV3SW5pdCwgRGlyZWN0aXZlLCBFbGVtZW50UmVmLCBFdmVudEVtaXR0ZXIsIGZvcndhcmRSZWYsXG4gICAgSG9zdEJpbmRpbmcsIEhvc3RMaXN0ZW5lciwgSW5qZWN0LCBJbnB1dCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3ksIE91dHB1dCwgUmVuZGVyZXIyLCBTZWxmLCBTaW1wbGVDaGFuZ2UsXG4gICAgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgRE9DVU1FTlQgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xuaW1wb3J0IHsgTkdfVkFMVUVfQUNDRVNTT1IsIENvbnRyb2xWYWx1ZUFjY2Vzc29yIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgTURDU2xpZGVyRm91bmRhdGlvbiwgTURDU2xpZGVyQWRhcHRlciB9IGZyb20gJ0BtYXRlcmlhbC9zbGlkZXInO1xuaW1wb3J0IHsgZXZlbnRzIH0gZnJvbSAnQG1hdGVyaWFsL2RvbSc7XG5pbXBvcnQgeyBhc0Jvb2xlYW4gfSBmcm9tICcuLi8uLi91dGlscy92YWx1ZS51dGlscyc7XG5pbXBvcnQgeyBNZGNFdmVudFJlZ2lzdHJ5IH0gZnJvbSAnLi4vLi4vdXRpbHMvbWRjLmV2ZW50LnJlZ2lzdHJ5JztcblxuLyoqXG4gKiBEaXJlY3RpdmUgZm9yIGNyZWF0aW5nIGEgTWF0ZXJpYWwgRGVzaWduIHNsaWRlciBpbnB1dC5cbiAqIChNb2RlbGxlZCBhZnRlciB0aGUgPGNvZGU+Jmx0O2lucHV0IHR5cGU9XCJyYW5nZVwiLyZndDs8L2NvZGU+IGVsZW1lbnQpLlxuICogVGhlIHNsaWRlciBpcyBmdWxseSBhY2Nlc3NpYmxlLiBUaGUgY3VycmVudCBpbXBsZW1lbnRhdGlvblxuICogd2lsbCBhZGQgYW5kIG1hbmFnZSBhbGwgRE9NIGNoaWxkIGVsZW1lbnRzIHRoYXQgYXJlIHJlcXVpcmVkIGZvciB0aGUgd3JhcHBlZFxuICogPGNvZGU+bWRjLXNsaWRlcjwvY29kZT4gY29tcG9uZW50LlxuICogRnV0dXJlIGltcGxlbWVudGF0aW9ucyB3aWxsIGFsc28gc3VwcG9ydCBzdXBwbHlpbmcgKGN1c3RvbWl6ZWQpXG4gKiBET00gY2hpbGRyZW4uXG4gKi9cbkBEaXJlY3RpdmUoe1xuICAgIHNlbGVjdG9yOiAnW21kY1NsaWRlcl0nXG59KVxuZXhwb3J0IGNsYXNzIE1kY1NsaWRlckRpcmVjdGl2ZSBpbXBsZW1lbnRzIEFmdGVyQ29udGVudEluaXQsIEFmdGVyVmlld0luaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgQEhvc3RCaW5kaW5nKCdjbGFzcy5tZGMtc2xpZGVyJykgcmVhZG9ubHkgX2NscyA9IHRydWU7XG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIEBIb3N0QmluZGluZygnYXR0ci5yb2xlJykgX3JvbGU6IHN0cmluZyA9ICdzbGlkZXInO1xuICAgIC8qKlxuICAgICAqIEV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgdmFsdWUgY2hhbmdlcy4gVGhlIHZhbHVlIG1heSBjaGFuZ2UgYmVjYXVzZSBvZiB1c2VyIGlucHV0LFxuICAgICAqIG9yIGFzIGEgc2lkZSBhZmZlY3Qgb2Ygc2V0dGluZyBuZXcgbWluLCBtYXgsIG9yIHN0ZXAgdmFsdWVzLlxuICAgICAqL1xuICAgIEBPdXRwdXQoKSByZWFkb25seSB2YWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBtaW4gcmFuZ2UgdmFsdWUgY2hhbmdlcy4gVGhpcyBtYXkgaGFwcGVuIGFzIGEgc2lkZSBlZmZlY3RcbiAgICAgKiBvZiBzZXR0aW5nIGEgbmV3IG1heCB2YWx1ZSAod2hlbiB0aGUgbmV3IG1heCBpcyBzbWFsbGVyIHRoYW4gdGhlIG9sZCBtaW4pLlxuICAgICAqL1xuICAgIEBPdXRwdXQoKSByZWFkb25seSBtaW5WYWx1ZUNoYW5nZTogRXZlbnRFbWl0dGVyPG51bWJlcj4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gICAgLyoqXG4gICAgICogRXZlbnQgZW1pdHRlZCB3aGVuIHRoZSBtYXggcmFuZ2UgdmFsdWUgY2hhbmdlcy4gVGhpcyBtYXkgaGFwcGVuIGFzIGEgc2lkZSBlZmZlY3RcbiAgICAgKiBvZiBzZXR0aW5nIGEgbmV3IG1pbiB2YWx1ZSAod2hlbiB0aGUgbmV3IG1pbiBpcyBsYXJnZXIgdGhhbiB0aGUgb2xkIG1heCkuXG4gICAgICovXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IG1heFZhbHVlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICAvKipcbiAgICAgKiBFdmVudCBlbWl0dGVkIHdoZW4gdGhlIHN0ZXAgdmFsdWUgY2hhbmdlcy4gVGhpcyBtYXkgaGFwcGVuIGFzIGEgc2lkZSBlZmZlY3RcbiAgICAgKiBvZiBtYWtpbmcgdGhlIHNsaWRlciBkaXNjcmV0ZS5cbiAgICAgKi9cbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgc3RlcFZhbHVlQ2hhbmdlOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgICBwcml2YXRlIHRyYWNrQ250cjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIF9lbG1UaHVtYkNudHI6IEhUTUxFbGVtZW50IHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfZWxtU2xpZGVyUGluOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2VsbVZhbHVlTWFya2VyOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2VsbVRyYWNrOiBIVE1MRWxlbWVudCB8IG51bGwgPSBudWxsO1xuICAgIHByaXZhdGUgX2VsbVRyYWNrTWFya2VyQ250cjogSFRNTEVsZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgICBwcml2YXRlIF9yZWluaXRUYWJJbmRleDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBfb25DaGFuZ2U6ICh2YWx1ZTogYW55KSA9PiB2b2lkID0gKHZhbHVlKSA9PiB7fTtcbiAgICBwcml2YXRlIF9vblRvdWNoZWQ6ICgpID0+IGFueSA9ICgpID0+IHt9O1xuICAgIHByaXZhdGUgX2Rpc2NyZXRlID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfbWFya2VycyA9IGZhbHNlO1xuICAgIHByaXZhdGUgX2Rpc2FibGVkID0gZmFsc2U7XG4gICAgcHJpdmF0ZSBfdmFsdWU6IG51bWJlciA9IDA7XG4gICAgcHJpdmF0ZSBfbWluID0gMDtcbiAgICBwcml2YXRlIF9tYXggPSAxMDA7XG4gICAgcHJpdmF0ZSBfc3RlcCA9IDA7XG4gICAgcHJpdmF0ZSBfbGFzdFdpZHRoOiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICAgIHByaXZhdGUgbWRjQWRhcHRlcjogTURDU2xpZGVyQWRhcHRlciA9IHtcbiAgICAgICAgaGFzQ2xhc3M6IChjbGFzc05hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICAgICAgaWYgKGNsYXNzTmFtZSA9PT0gJ21kYy1zbGlkZXItLWRpc2NyZXRlJylcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fZGlzY3JldGU7XG4gICAgICAgICAgICBpZiAoY2xhc3NOYW1lID09PSAnbWRjLXNsaWRlci0tZGlzcGxheS1tYXJrZXJzJylcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5fbWFya2VycztcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9yb290Lm5hdGl2ZUVsZW1lbnQuY2xhc3NMaXN0LmNvbnRhaW5zKGNsYXNzTmFtZSk7XG4gICAgICAgIH0sXG4gICAgICAgIGFkZENsYXNzOiAoY2xhc3NOYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIuYWRkQ2xhc3ModGhpcy5fcm9vdC5uYXRpdmVFbGVtZW50LCBjbGFzc05hbWUpO1xuICAgICAgICB9LFxuICAgICAgICByZW1vdmVDbGFzczogKGNsYXNzTmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICB0aGlzLl9ybmRyLnJlbW92ZUNsYXNzKHRoaXMuX3Jvb3QubmF0aXZlRWxlbWVudCwgY2xhc3NOYW1lKTtcbiAgICAgICAgfSxcbiAgICAgICAgZ2V0QXR0cmlidXRlOiAobmFtZTogc3RyaW5nKSA9PiB0aGlzLl9yb290Lm5hdGl2ZUVsZW1lbnQuZ2V0QXR0cmlidXRlKG5hbWUpLFxuICAgICAgICBzZXRBdHRyaWJ1dGU6IChuYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIC8vIHNraXAgYXR0cmlidXRlcyB0aGF0IHdlIGNvbnRyb2wgd2l0aCBhbmd1bGFyXG4gICAgICAgICAgICBpZiAoIS9eYXJpYS0odmFsdWUuKnxkaXNhYmxlZCkkLy50ZXN0KG5hbWUpKVxuICAgICAgICAgICAgICAgIHRoaXMuX3JuZHIuc2V0QXR0cmlidXRlKHRoaXMuX3Jvb3QubmF0aXZlRWxlbWVudCwgbmFtZSwgdmFsdWUpO1xuICAgICAgICB9LFxuICAgICAgICByZW1vdmVBdHRyaWJ1dGU6IChuYW1lOiBzdHJpbmcpID0+IHt0aGlzLl9ybmRyLnJlbW92ZUF0dHJpYnV0ZSh0aGlzLl9yb290Lm5hdGl2ZUVsZW1lbnQsIG5hbWUpOyB9LFxuICAgICAgICBjb21wdXRlQm91bmRpbmdSZWN0OiAoKSA9PiB0aGlzLl9yb290Lm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCksXG4gICAgICAgIGdldFRhYkluZGV4OiAoKSA9PiB0aGlzLl9yb290Lm5hdGl2ZUVsZW1lbnQudGFiSW5kZXgsXG4gICAgICAgIHJlZ2lzdGVySW50ZXJhY3Rpb25IYW5kbGVyOiAoZXZ0VHlwZSwgaGFuZGxlcikgPT4gdGhpcy5fcmVnaXN0cnkubGlzdGVuKHRoaXMuX3JuZHIsIGV2dFR5cGUsIGhhbmRsZXIsIHRoaXMuX3Jvb3QsIGV2ZW50cy5hcHBseVBhc3NpdmUoKSksXG4gICAgICAgIGRlcmVnaXN0ZXJJbnRlcmFjdGlvbkhhbmRsZXI6IChldnRUeXBlLCBoYW5kbGVyKSA9PiB0aGlzLl9yZWdpc3RyeS51bmxpc3RlbihldnRUeXBlLCBoYW5kbGVyKSxcbiAgICAgICAgcmVnaXN0ZXJUaHVtYkNvbnRhaW5lckludGVyYWN0aW9uSGFuZGxlcjogKGV2dFR5cGUsIGhhbmRsZXIpID0+IHRoaXMuX3JlZ2lzdHJ5Lmxpc3RlbkVsbSh0aGlzLl9ybmRyLCBldnRUeXBlLCBoYW5kbGVyLCB0aGlzLl9lbG1UaHVtYkNudHIhLCBldmVudHMuYXBwbHlQYXNzaXZlKCkpLFxuICAgICAgICBkZXJlZ2lzdGVyVGh1bWJDb250YWluZXJJbnRlcmFjdGlvbkhhbmRsZXI6IChldnRUeXBlLCBoYW5kbGVyKSA9PiB0aGlzLl9yZWdpc3RyeS51bmxpc3RlbihldnRUeXBlLCBoYW5kbGVyKSxcbiAgICAgICAgcmVnaXN0ZXJCb2R5SW50ZXJhY3Rpb25IYW5kbGVyOiAoZXZ0VHlwZSwgaGFuZGxlcikgPT4gdGhpcy5fcmVnaXN0cnkubGlzdGVuRWxtKHRoaXMuX3JuZHIsIGV2dFR5cGUsIGhhbmRsZXIsIHRoaXMuZG9jdW1lbnQuYm9keSksXG4gICAgICAgIGRlcmVnaXN0ZXJCb2R5SW50ZXJhY3Rpb25IYW5kbGVyOiAoZXZ0VHlwZSwgaGFuZGxlcikgPT4gdGhpcy5fcmVnaXN0cnkudW5saXN0ZW4oZXZ0VHlwZSwgaGFuZGxlciksXG4gICAgICAgIHJlZ2lzdGVyUmVzaXplSGFuZGxlcjogKGhhbmRsZXIpID0+IHRoaXMuX3JlZ2lzdHJ5Lmxpc3RlbkVsbSh0aGlzLl9ybmRyLCAncmVzaXplJywgaGFuZGxlciwgdGhpcy5kb2N1bWVudC5kZWZhdWx0VmlldyEpLFxuICAgICAgICBkZXJlZ2lzdGVyUmVzaXplSGFuZGxlcjogKGhhbmRsZXIpID0+IHRoaXMuX3JlZ2lzdHJ5LnVubGlzdGVuKCdyZXNpemUnLCBoYW5kbGVyKSxcbiAgICAgICAgbm90aWZ5SW5wdXQ6ICgpID0+IHtcbiAgICAgICAgICAgIGxldCBuZXdWYWx1ZSA9IHRoaXMuYXNOdW1iZXIodGhpcy5mb3VuZGF0aW9uIS5nZXRWYWx1ZSgpKTtcbiAgICAgICAgICAgIGlmIChuZXdWYWx1ZSAhPT0gdGhpcy5fdmFsdWUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl92YWx1ZSA9IG5ld1ZhbHVlITtcbiAgICAgICAgICAgICAgICB0aGlzLm5vdGlmeVZhbHVlQ2hhbmdlZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBub3RpZnlDaGFuZ2U6ICgpID0+IHtcbiAgICAgICAgICAgIC8vIGN1cnJlbnRseSBub3QgaGFuZGxpbmcgdGhpcyBldmVudCwgaWYgdGhlcmUgaXMgYSB1c2VjYXNlIGZvciB0aGlzLCBwbGVhc2VcbiAgICAgICAgICAgIC8vIGNyZWF0ZSBhIGZlYXR1cmUgcmVxdWVzdC5cbiAgICAgICAgfSxcbiAgICAgICAgc2V0VGh1bWJDb250YWluZXJTdHlsZVByb3BlcnR5OiAocHJvcGVydHlOYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIuc2V0U3R5bGUodGhpcy5fZWxtVGh1bWJDbnRyLCBwcm9wZXJ0eU5hbWUsIHZhbHVlKTtcbiAgICAgICAgfSxcbiAgICAgICAgc2V0VHJhY2tTdHlsZVByb3BlcnR5OiAocHJvcGVydHlOYW1lOiBzdHJpbmcsIHZhbHVlOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX3JuZHIuc2V0U3R5bGUodGhpcy5fZWxtVHJhY2ssIHByb3BlcnR5TmFtZSwgdmFsdWUpO1xuICAgICAgICB9LFxuICAgICAgICBzZXRNYXJrZXJWYWx1ZTogKHZhbHVlOiBudW1iZXIpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9lbG1WYWx1ZU1hcmtlcilcbiAgICAgICAgICAgICAgICB0aGlzLl9lbG1WYWx1ZU1hcmtlci5pbm5lclRleHQgPSB2YWx1ZSAhPSBudWxsID8gdmFsdWUudG9Mb2NhbGVTdHJpbmcoKSA6ICcnO1xuICAgICAgICB9LFxuICAgICAgICBzZXRUcmFja01hcmtlcnM6IChzdGVwLCBtYXgsIG1pbikgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2VsbVRyYWNrTWFya2VyQ250cikge1xuICAgICAgICAgICAgICAgIC8vIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL21hdGVyaWFsLWNvbXBvbmVudHMvbWF0ZXJpYWwtY29tcG9uZW50cy13ZWIvYmxvYi92NS4xLjAvcGFja2FnZXMvbWRjLXNsaWRlci9jb21wb25lbnQudHMjTDE0MVxuICAgICAgICAgICAgICAgIGNvbnN0IHN0ZXBTdHIgPSBzdGVwLnRvTG9jYWxlU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbWF4U3RyID0gbWF4LnRvTG9jYWxlU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbWluU3RyID0gbWluLnRvTG9jYWxlU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgY29uc3QgbWFya2VyQW1vdW50ID0gYCgoJHttYXhTdHJ9IC0gJHttaW5TdHJ9KSAvICR7c3RlcFN0cn0pYDtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXJrZXJXaWR0aCA9IGAycHhgO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hcmtlckJrZ2RJbWFnZSA9IGBsaW5lYXItZ3JhZGllbnQodG8gcmlnaHQsIGN1cnJlbnRDb2xvciAke21hcmtlcldpZHRofSwgdHJhbnNwYXJlbnQgMClgO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1hcmtlckJrZ2RMYXlvdXQgPSBgMCBjZW50ZXIgLyBjYWxjKCgxMDAlIC0gJHttYXJrZXJXaWR0aH0pIC8gJHttYXJrZXJBbW91bnR9KSAxMDAlIHJlcGVhdC14YDtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXJrZXJCa2dkU2hvcnRoYW5kID0gYCR7bWFya2VyQmtnZEltYWdlfSAke21hcmtlckJrZ2RMYXlvdXR9YDtcbiAgICAgICAgICAgICAgICB0aGlzLl9ybmRyLnNldFN0eWxlKHRoaXMuX2VsbVRyYWNrTWFya2VyQ250ciwgJ2JhY2tncm91bmQnLCBtYXJrZXJCa2dkU2hvcnRoYW5kKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgaXNSVEw6ICgpID0+IGdldENvbXB1dGVkU3R5bGUodGhpcy5fcm9vdC5uYXRpdmVFbGVtZW50KS5kaXJlY3Rpb24gPT09ICdydGwnXG4gICAgIFxuICAgIH07XG4gICAgcHJpdmF0ZSBmb3VuZGF0aW9uOiBNRENTbGlkZXJGb3VuZGF0aW9uIHwgbnVsbCA9IG51bGw7XG4gICAgcHJpdmF0ZSBkb2N1bWVudDogRG9jdW1lbnQ7XG5cbiAgICBjb25zdHJ1Y3Rvcihwcml2YXRlIF9ybmRyOiBSZW5kZXJlcjIsIHByaXZhdGUgX3Jvb3Q6IEVsZW1lbnRSZWYsIHByaXZhdGUgX3JlZ2lzdHJ5OiBNZGNFdmVudFJlZ2lzdHJ5LFxuICAgICAgICBASW5qZWN0KERPQ1VNRU5UKSBkb2M6IGFueSkge1xuICAgICAgICAgICAgdGhpcy5kb2N1bWVudCA9IGRvYyBhcyBEb2N1bWVudDsgLy8gd29yayBhcm91bmQgbmdjIGlzc3VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hbmd1bGFyL2FuZ3VsYXIvaXNzdWVzLzIwMzUxXG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCkge1xuICAgICAgICB0aGlzLmluaXRFbGVtZW50cygpO1xuICAgICAgICB0aGlzLmluaXREZWZhdWx0QXR0cmlidXRlcygpO1xuICAgICAgICB0aGlzLmZvdW5kYXRpb24gPSBuZXcgTURDU2xpZGVyRm91bmRhdGlvbih0aGlzLm1kY0FkYXB0ZXIpXG4gICAgICAgIHRoaXMuZm91bmRhdGlvbi5pbml0KCk7XG4gICAgICAgIHRoaXMuX2xhc3RXaWR0aCA9IHRoaXMubWRjQWRhcHRlci5jb21wdXRlQm91bmRpbmdSZWN0KCkud2lkdGg7XG4gICAgICAgIHRoaXMudXBkYXRlVmFsdWVzKHt9KTtcbiAgICB9XG5cbiAgICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgICAgIHRoaXMudXBkYXRlTGF5b3V0KCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZm91bmRhdGlvbj8uZGVzdHJveSgpO1xuICAgIH1cblxuICAgIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpIHtcbiAgICAgICAgdGhpcy5fb25DaGFuZ2VzKGNoYW5nZXMpO1xuICAgIH1cblxuICAgIC8qKiBAaW50ZXJuYWwg