@blox/material
Version:
Material Components for Angular
453 lines • 65.7 kB
JavaScript
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><input type="range"/></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 >= 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