UNPKG

@logo-software/timepicker

Version:

Timepicker helps users select and set a specific time in your timesheet in 24-hour format.

293 lines 34.7 kB
/** * @license * Copyright LOGO YAZILIM SANAYİ VE TİCARET A.Ş. All Rights Reserved. * * Save to the extent permitted by law, you may not use, copy, modify, * distribute or create derivative works of this material or any part * of it without the prior written consent of LOGO YAZILIM SANAYİ VE TİCARET A.Ş. Limited. * Any reproduction of this material must contain this notice. */ import { Directive, ElementRef, EventEmitter, HostListener, Input, Output } from '@angular/core'; import { NgModel } from '@angular/forms'; import * as momentNs from 'moment'; import { Util } from '../util/util'; const moment = momentNs; let selectionStart; /** * An input mask is a string of characters that indicates the format of valid input values. You can help * people enter data correctly into input by providing input masks for fields that contain data that is * always formatted a certain way. For example, you can use an input mask to make * sure that people enter correctly formatted phone numbers into a phone number field. * * __Usage Example:__ * * <input [(ngModel)]="tourDate" masker /> * * For __Time__ correction example, this will be check for HH:mm format: * ```html * <input * logoMask * [regexp]="'^[0-2]{1}$|^[0-2]{1}[0-9]{1}$|^[0-2]{1}[0-9]{1}[0-5]{1}$|^[0-2]{1}[0-9]{1}[0-5]{1}[0-9]{1}$'" * [placeholder]="HH:mm" * /> * ``` * @stacked-example(MaskDirective, logo/core-sample/mask-directive-showcase/mask-directive-showcase.component) * For __Date__ correction example, this will be check for YYYY-MM-DD format: * ```html * <input * logoMask * [placeholder]="'YYYY-MM-DD'" * [regexp]="'^\\d+$'" * /> * ``` * * Full usage example with contains conditions: * * ```html * <input * logoMask * [(ngModel)]="value" * (change)="onDateChangeHandler($event)" * (click)="onInputClick($event)" * [placeholder]="'XX-00000'" * [conditions]="[{cases: [{position: 2, regexp:'^[0-9]$'}], placeholder: 'X-0000000000'}]" * [case]="'lower'" * [regexp]="'^X{1,2}$|^X{1,2}[0-9]*$'" * [maskType]="'date'" * #dateRef * /> * ``` * * __Another Example:__ * ```html * <input * logoMask * [placeholder]="'XX-0000000000'" * [conditions]="[{cases: [{position: 2, regexp: '^[0-9]$'}], placeholder: 'X-0000000000'}]" * [regexp]="'^[A-ZĞÜŞİÖÇ]{1,2}$|^[A-ZĞÜŞİÖÇ]{1,2}[0-9]*$'" * [case]="'upper'" * /> * ``` */ export class MaskDirective { constructor(elementRef) { this.elementRef = elementRef; /** * Case use for upper or lower case selection * For example [case]="'lower'" it makes all char to lowercase */ this.case = null; // "upper|lower" /** * Conditions uses for set special status different than defined placeholder. * If placeholder set to 'XX-00000' and 'X-00000' also acceptable you need this property * For example [conditions]="[{cases: [{position: 2, regexp:'^[0-9]$'}], placeholder: 'X-0000000000'}]" * With this at 2 position if inserted char is a digit (regexp) then placeholder will be redefine to 'X-0000000000' */ this.conditions = []; this.ngModelChange = new EventEmitter(); this.oldValue = ''; this.defaultChars = '^\\wğüşıöçĞÜŞİÖÇ'; } /** * This propert removes inserted char if format not same with defined pattern. * For example [regexp]="'^9{1,3}$|^9{3}[0-9]*$'" * Above example just accepts beginning 999 then accept digits like 999123456 */ get regexp() { return this._regexp; } set regexp(value) { this._regexp = value; } /** * Used for format check. What format will be used for display text. * if need some special chars like "- / or space" this will be looks their position * and will be added automatically * For example : [placeholder] = {TK-1234} This format will be add "-" char automatically to third cursor position. * And also will restrict insert more than char length to textbox. */ get placeholder() { return this._placeholder; } set placeholder(value) { this._placeholder = value; if (typeof value !== 'undefined' && this.input) { this.setPlaceholder(value); } if (!this.maxLength) { this.maxLength = this.placeholder.length; } } /** * This property used for definition of acceptable max char length of the input field * For example, [maxLength]='13' it sets the input file's acceptable chars length to max 13 */ get maxLength() { return this._maxLength; } set maxLength(value) { const length = this.elementRef.nativeElement.maxLength; const maxLength = length ? length : this._placeholder.length; this._maxLength = (typeof value !== 'undefined' && value !== null) ? value : maxLength; if (value && this.input) { this.setInputAttributes(); } } get extendedChars() { return this._extendedChars; } set extendedChars(value) { this._extendedChars = value; if (typeof value !== 'undefined' && this.input) { this.setPlaceholder(this.placeholder); } } ngOnInit() { this.input = this.elementRef.nativeElement; if (this._placeholder) { this.setPlaceholder(this._placeholder); } } setPlaceholder(placeholder) { let specialChars; this.acceptedChars = `[${this.defaultChars}${this._extendedChars}]`; specialChars = placeholder.match(new RegExp(this.acceptedChars, 'g')); this.list = specialChars && Util.union(specialChars).map((value) => { 'use strict'; return { what: value, position: Util.findAllIndex(placeholder.split(''), value) }; }); this.setInputAttributes(); } setInputAttributes() { this.input.setAttribute('maxLength', this._maxLength); this.input.setAttribute('placeholder', this._placeholder); } clear(value) { return value.replace(new RegExp(this.acceptedChars, 'g'), ''); // Removes every non-digit character; } isValid(value) { const convertDate = new Date(value); return Object.prototype.toString.call(convertDate) === '[object Date]' && !isNaN(convertDate.getTime()); } onFocus($event) { this.oldValue = this.input.value; } onBlur($event) { if (this.maskType === 'date' && !this.isValid(this.input.value)) { this.emit(this.oldValue); } } onKeyDown($event) { selectionStart = this.input.selectionStart; if ($event.keyCode === 13) { if (this.maskType === 'date' && !this.isValid(this.input.value)) { this.emit(this.oldValue); } } } emit(value) { this.input.value = value; this.oldValue = value; this.ngModelChange.emit(value); } conditionCheck() { const clear = this.clear(this.input.value); if (this.conditions.length > 0) { this.conditions.forEach(condition => { const status = condition.cases.every(item => { if (clear[item.position - 1]) { const isTrue = new RegExp(item.regexp, 'gi').test(clear[item.position - 1]); selectionStart = isTrue ? selectionStart + 1 : selectionStart; return isTrue; } return false; }); const placehoder = status ? condition.placeholder : this._placeholder; this.setPlaceholder(placehoder); }); } } mask(value) { const clear = this.clear(value); return clear.replace(/./g, (val, index) => { let specialChar = 0; if (this.list) { this.list.forEach(item => { 'use strict'; item.position.forEach((position) => { val = (index === (position - 1 - specialChar)) ? val + item.what : val; specialChar++; }); }); } return val; }); } onInput($event) { let value, newValue; switch (this.case) { case 'lower': value = Util.turkishToLower(this.input.value); break; case 'upper': value = Util.turkishToUpper(this.input.value); break; default: value = this.input.value; break; } const isTrue = new RegExp(this._regexp).test(this.clear(value)); const insertedCharLength = this.input.selectionEnd - selectionStart; if (!isTrue) { $event.preventDefault(); this.emit(Util.removeCharsBetween(value, selectionStart, insertedCharLength)); this.input.setSelectionRange(selectionStart, selectionStart); return; } if ($event.data || $event.inputType === 'insertFromPaste') { this.conditionCheck(); newValue = this.mask(value); if (this.maskType === 'date' && !moment(newValue).isValid() && this._maxLength === this.input.value) { this.emit(this.oldValue); } else { this.emit(newValue); } if (this.input.value.length !== this._maxLength) { if (this.list) { this.list.map(item => item.position).join().split(',').map(item => { if (Number(item) >= selectionStart + 1 && selectionStart + insertedCharLength >= Number(item)) { selectionStart = selectionStart + 1; } }); } this.input.setSelectionRange(selectionStart + insertedCharLength, selectionStart + insertedCharLength); } } } } MaskDirective.decorators = [ { type: Directive, args: [{ selector: '[logoMask]', providers: [NgModel], },] } ]; MaskDirective.ctorParameters = () => [ { type: ElementRef } ]; MaskDirective.propDecorators = { ngModel: [{ type: Input }], maskType: [{ type: Input }], case: [{ type: Input }], conditions: [{ type: Input }], ngModelChange: [{ type: Output }], regexp: [{ type: Input }], placeholder: [{ type: Input }], maxLength: [{ type: Input }], extendedChars: [{ type: Input }], onFocus: [{ type: HostListener, args: ['focus', ['$event'],] }], onBlur: [{ type: HostListener, args: ['blur', ['$event'],] }], onKeyDown: [{ type: HostListener, args: ['keydown', ['$event'],] }], onInput: [{ type: HostListener, args: ['input', ['$event'],] }] }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWFzay5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9sb2dvLXNvZnR3YXJlL3RpbWVwaWNrZXIvc3JjL2xpYi9kaXJlY3RpdmUvbWFzay5kaXJlY3RpdmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7O0dBUUc7QUFFSCxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDekcsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRXpDLE9BQU8sS0FBSyxRQUFRLE1BQU0sUUFBUSxDQUFDO0FBQ25DLE9BQU8sRUFBRSxJQUFJLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFFcEMsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDO0FBQ3hCLElBQUksY0FBbUIsQ0FBQztBQU94Qjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXVERztBQUtILE1BQU0sT0FBTyxhQUFhO0lBeUJ4QixZQUFvQixVQUFzQjtRQUF0QixlQUFVLEdBQVYsVUFBVSxDQUFZO1FBbkIxQzs7O1dBR0c7UUFDYyxTQUFJLEdBQTZCLElBQUksQ0FBQyxDQUFDLGdCQUFnQjtRQUN4RTs7Ozs7V0FLRztRQUNjLGVBQVUsR0FBcUIsRUFBRSxDQUFDO1FBQ2pDLGtCQUFhLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUU3QyxhQUFRLEdBQUcsRUFBRSxDQUFDO1FBRWQsaUJBQVksR0FBRyxrQkFBa0IsQ0FBQztJQUkxQyxDQUFDO0lBSUQ7Ozs7T0FJRztJQUNILElBQWEsTUFBTTtRQUNqQixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLEtBQWE7UUFDdEIsSUFBSSxDQUFDLE9B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UUFBUSxDQUFDO3NCQW1EbEMsWUFBWSxTQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBMT0dPIFlBWklMSU0gU0FOQVnEsCBWRSBUxLBDQVJFVCBBLsWeLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFNhdmUgdG8gdGhlIGV4dGVudCBwZXJtaXR0ZWQgYnkgbGF3LCB5b3UgbWF5IG5vdCB1c2UsIGNvcHksIG1vZGlmeSxcbiAqIGRpc3RyaWJ1dGUgb3IgY3JlYXRlIGRlcml2YXRpdmUgd29ya3Mgb2YgdGhpcyBtYXRlcmlhbCBvciBhbnkgcGFydFxuICogb2YgaXQgd2l0aG91dCB0aGUgcHJpb3Igd3JpdHRlbiBjb25zZW50IG9mIExPR08gWUFaSUxJTSBTQU5BWcSwIFZFIFTEsENBUkVUIEEuxZ4uIExpbWl0ZWQuXG4gKiBBbnkgcmVwcm9kdWN0aW9uIG9mIHRoaXMgbWF0ZXJpYWwgbXVzdCBjb250YWluIHRoaXMgbm90aWNlLlxuICovXG5cbmltcG9ydCB7IERpcmVjdGl2ZSwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkluaXQsIE91dHB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTmdNb2RlbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcblxuaW1wb3J0ICogYXMgbW9tZW50TnMgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IFV0aWwgfSBmcm9tICcuLi91dGlsL3V0aWwnO1xuXG5jb25zdCBtb21lbnQgPSBtb21lbnROcztcbmxldCBzZWxlY3Rpb25TdGFydDogYW55O1xuXG5leHBvcnQgaW50ZXJmYWNlIE1hc2tDb25kaXRpb25zIHtcbiAgY2FzZXM6IHsgcG9zaXRpb246IG51bWJlciwgcmVnZXhwOiBzdHJpbmcgfVtdLFxuICBwbGFjZWhvbGRlcjogc3RyaW5nXG59XG5cbi8qKlxuICogQW4gaW5wdXQgbWFzayBpcyBhIHN0cmluZyBvZiBjaGFyYWN0ZXJzIHRoYXQgaW5kaWNhdGVzIHRoZSBmb3JtYXQgb2YgdmFsaWQgaW5wdXQgdmFsdWVzLiBZb3UgY2FuIGhlbHBcbiAqIHBlb3BsZSBlbnRlciBkYXRhIGNvcnJlY3RseSBpbnRvIGlucHV0IGJ5IHByb3ZpZGluZyBpbnB1dCBtYXNrcyBmb3IgZmllbGRzIHRoYXQgY29udGFpbiBkYXRhIHRoYXQgaXNcbiAqIGFsd2F5cyBmb3JtYXR0ZWQgYSBjZXJ0YWluIHdheS4gRm9yIGV4YW1wbGUsIHlvdSBjYW4gdXNlIGFuIGlucHV0IG1hc2sgdG8gbWFrZVxuICogc3VyZSB0aGF0IHBlb3BsZSBlbnRlciBjb3JyZWN0bHkgZm9ybWF0dGVkIHBob25lIG51bWJlcnMgaW50byBhIHBob25lIG51bWJlciBmaWVsZC5cbiAqXG4gKiBfX1VzYWdlIEV4YW1wbGU6X19cbiAqXG4gKiA8aW5wdXQgWyhuZ01vZGVsKV09XCJ0b3VyRGF0ZVwiIG1hc2tlciAvPlxuICpcbiAqIEZvciBfX1RpbWVfXyBjb3JyZWN0aW9uIGV4YW1wbGUsIHRoaXMgd2lsbCBiZSBjaGVjayBmb3IgSEg6bW0gZm9ybWF0OlxuICogIGBgYGh0bWxcbiAqIDxpbnB1dFxuICogICBsb2dvTWFza1xuICogICBbcmVnZXhwXT1cIideWzAtMl17MX0kfF5bMC0yXXsxfVswLTldezF9JHxeWzAtMl17MX1bMC05XXsxfVswLTVdezF9JHxeWzAtMl17MX1bMC05XXsxfVswLTVdezF9WzAtOV17MX0kJ1wiXG4gKiAgIFtwbGFjZWhvbGRlcl09XCJISDptbVwiXG4gKiAgLz5cbiAqICBgYGBcbiAqIEBzdGFja2VkLWV4YW1wbGUoTWFza0RpcmVjdGl2ZSwgbG9nby9jb3JlLXNhbXBsZS9tYXNrLWRpcmVjdGl2ZS1zaG93Y2FzZS9tYXNrLWRpcmVjdGl2ZS1zaG93Y2FzZS5jb21wb25lbnQpXG4gKiBGb3IgX19EYXRlX18gY29ycmVjdGlvbiBleGFtcGxlLCB0aGlzIHdpbGwgYmUgY2hlY2sgZm9yIFlZWVktTU0tREQgZm9ybWF0OlxuICogYGBgaHRtbFxuICogPGlucHV0XG4gKiAgIGxvZ29NYXNrXG4gKiAgIFtwbGFjZWhvbGRlcl09XCInWVlZWS1NTS1ERCdcIlxuICogICBbcmVnZXhwXT1cIideXFxcXGQrJCdcIlxuICogLz5cbiAqIGBgYFxuICpcbiAqIEZ1bGwgdXNhZ2UgZXhhbXBsZSB3aXRoIGNvbnRhaW5zIGNvbmRpdGlvbnM6XG4gKlxuICogYGBgaHRtbFxuICogPGlucHV0XG4gKiAgIGxvZ29NYXNrXG4gKiAgIFsobmdNb2RlbCldPVwidmFsdWVcIlxuICogICAoY2hhbmdlKT1cIm9uRGF0ZUNoYW5nZUhhbmRsZXIoJGV2ZW50KVwiXG4gKiAgIChjbGljayk9XCJvbklucHV0Q2xpY2soJGV2ZW50KVwiXG4gKiAgIFtwbGFjZWhvbGRlcl09XCInWFgtMDAwMDAnXCJcbiAqICAgW2NvbmRpdGlvbnNdPVwiW3tjYXNlczogW3twb3NpdGlvbjogMiwgcmVnZXhwOideWzAtOV0kJ31dLCBwbGFjZWhvbGRlcjogJ1gtMDAwMDAwMDAwMCd9XVwiXG4gKiAgIFtjYXNlXT1cIidsb3dlcidcIlxuICogICBbcmVnZXhwXT1cIideWHsxLDJ9JHxeWHsxLDJ9WzAtOV0qJCdcIlxuICogICBbbWFza1R5cGVdPVwiJ2RhdGUnXCJcbiAqICAgI2RhdGVSZWZcbiAqIC8+XG4gKiBgYGBcbiAqXG4gKiBfX0Fub3RoZXIgRXhhbXBsZTpfX1xuICogYGBgaHRtbFxuICogPGlucHV0XG4gKiAgIGxvZ29NYXNrXG4gKiAgIFtwbGFjZWhvbGRlcl09XCInWFgtMDAwMDAwMDAwMCdcIlxuICogICBbY29uZGl0aW9uc109XCJbe2Nhc2VzOiBbe3Bvc2l0aW9uOiAyLCByZWdleHA6ICdeWzAtOV0kJ31dLCBwbGFjZWhvbGRlcjogJ1gtMDAwMDAwMDAwMCd9XVwiXG4gKiAgIFtyZWdleHBdPVwiJ15bQS1axJ7DnMWexLDDlsOHXXsxLDJ9JHxeW0EtWsSew5zFnsSww5bDh117MSwyfVswLTldKiQnXCJcbiAqICAgW2Nhc2VdPVwiJ3VwcGVyJ1wiXG4gKiAvPlxuICogYGBgXG4gKi9cbkBEaXJlY3RpdmUoe1xuICBzZWxlY3RvcjogJ1tsb2dvTWFza10nLFxuICBwcm92aWRlcnM6IFtOZ01vZGVsXSxcbn0pXG5leHBvcnQgY2xhc3MgTWFza0RpcmVjdGl2ZSBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIG5nTW9kZWw6IHN0cmluZztcbiAgLyoqXG4gICAqICBUaGlzIGlucHV0IHNldCB0byBkYXRlIGlmIHdpbGwgYmUgdXNlIGZvciBkYXRlIGZvcm1hdHRlZFxuICAgKi9cbiAgQElucHV0KCkgcHJpdmF0ZSBtYXNrVHlwZTogc3RyaW5nO1xuICAvKipcbiAgICogQ2FzZSB1c2UgZm9yIHVwcGVyIG9yIGxvd2VyIGNhc2Ugc2VsZWN0aW9uXG4gICAqIEZvciBleGFtcGxlIFtjYXNlXT1cIidsb3dlcidcIiBpdCBtYWtlcyBhbGwgY2hhciB0byBsb3dlcmNhc2VcbiAgICovXG4gIEBJbnB1dCgpIHByaXZhdGUgY2FzZTogJ2xvd2VyJyB8ICd1cHBlcicgfCBudWxsID0gbnVsbDsgLy8gXCJ1cHBlcnxsb3dlclwiXG4gIC8qKlxuICAgKiBDb25kaXRpb25zIHVzZXMgZm9yIHNldCBzcGVjaWFsIHN0YXR1cyBkaWZmZXJlbnQgdGhhbiBkZWZpbmVkIHBsYWNlaG9sZGVyLlxuICAgKiBJZiBwbGFjZWhvbGRlciBzZXQgdG8gJ1hYLTAwMDAwJyBhbmQgJ1gtMDAwMDAnIGFsc28gYWNjZXB0YWJsZSB5b3UgbmVlZCB0aGlzIHByb3BlcnR5XG4gICAqIEZvciBleGFtcGxlIFtjb25kaXRpb25zXT1cIlt7Y2FzZXM6IFt7cG9zaXRpb246IDIsIHJlZ2V4cDonXlswLTldJCd9XSwgcGxhY2Vob2xkZXI6ICdYLTAwMDAwMDAwMDAnfV1cIlxuICAgKiBXaXRoIHRoaXMgYXQgMiBwb3NpdGlvbiBpZiBpbnNlcnRlZCBjaGFyIGlzIGEgZGlnaXQgKHJlZ2V4cCkgdGhlbiBwbGFjZWhvbGRlciB3aWxsIGJlIHJlZGVmaW5lIHRvICdYLTAwMDAwMDAwMDAnXG4gICAqL1xuICBASW5wdXQoKSBwcml2YXRlIGNvbmRpdGlvbnM6IE1hc2tDb25kaXRpb25zW10gPSBbXTtcbiAgQE91dHB1dCgpIHByaXZhdGUgbmdNb2RlbENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcHJpdmF0ZSBsaXN0OiBhbnlbXTtcbiAgcHJpdmF0ZSBvbGRWYWx1ZSA9ICcnO1xuICBwcml2YXRlIGlucHV0OiBhbnk7XG4gIHByaXZhdGUgZGVmYXVsdENoYXJzID0gJ15cXFxcd8Sfw7zFn8Sxw7bDp8Sew5zFnsSww5bDhyc7XG4gIHByaXZhdGUgYWNjZXB0ZWRDaGFyczogc3RyaW5nO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZikge1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVnZXhwOiBzdHJpbmc7XG5cbiAgLyoqXG4gICAqIFRoaXMgcHJvcGVydCByZW1vdmVzIGluc2VydGVkIGNoYXIgaWYgZm9ybWF0IG5vdCBzYW1lIHdpdGggZGVmaW5lZCBwYXR0ZXJuLlxuICAgKiBGb3IgZXhhbXBsZSBbcmVnZXhwXT1cIideOXsxLDN9JHxeOXszfVswLTldKiQnXCJcbiAgICogQWJvdmUgZXhhbXBsZSBqdXN0IGFjY2VwdHMgYmVnaW5uaW5nIDk5OSB0aGVuIGFjY2VwdCBkaWdpdHMgbGlrZSA5OTkxMjM0NTZcbiAgICovXG4gIEBJbnB1dCgpIGdldCByZWdleHAoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fcmVnZXhwO1xuICB9XG5cbiAgc2V0IHJlZ2V4cCh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fcmVnZXhwID0gdmFsdWU7XG4gIH1cblxuICBwcml2YXRlIF9wbGFjZWhvbGRlcjogc3RyaW5nO1xuXG4gIC8qKlxuICAgKiBVc2VkIGZvciBmb3JtYXQgY2hlY2suIFdoYXQgZm9ybWF0IHdpbGwgYmUgdXNlZCBmb3IgZGlzcGxheSB0ZXh0LlxuICAgKiBpZiBuZWVkIHNvbWUgc3BlY2lhbCBjaGFycyBsaWtlIFwiLSAvIG9yIHNwYWNlXCIgdGhpcyB3aWxsIGJlIGxvb2tzIHRoZWlyIHBvc2l0aW9uXG4gICAqIGFuZCB3aWxsIGJlIGFkZGVkIGF1dG9tYXRpY2FsbHlcbiAgICogRm9yIGV4YW1wbGUgOiAgW3BsYWNlaG9sZGVyXSA9IHtUSy0xMjM0fSBUaGlzIGZvcm1hdCB3aWxsIGJlIGFkZCBcIi1cIiBjaGFyIGF1dG9tYXRpY2FsbHkgdG8gdGhpcmQgY3Vyc29yIHBvc2l0aW9uLlxuICAgKiBBbmQgYWxzbyB3aWxsIHJlc3RyaWN0IGluc2VydCBtb3JlIHRoYW4gY2hhciBsZW5ndGggdG8gdGV4dGJveC5cbiAgICovXG4gIEBJbnB1dCgpIGdldCBwbGFjZWhvbGRlcigpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLl9wbGFjZWhvbGRlcjtcbiAgfVxuXG4gIHNldCBwbGFjZWhvbGRlcih2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fcGxhY2Vob2xkZXIgPSB2YWx1ZTtcbiAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAndW5kZWZpbmVkJyAmJiB0aGlzLmlucHV0KSB7XG4gICAgICB0aGlzLnNldFBsYWNlaG9sZGVyKHZhbHVlKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLm1heExlbmd0aCkge1xuICAgICAgdGhpcy5tYXhMZW5ndGggPSB0aGlzLnBsYWNlaG9sZGVyLmxlbmd0aDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9tYXhMZW5ndGg6IG51bWJlcjtcblxuICAvKipcbiAgICogVGhpcyBwcm9wZXJ0eSB1c2VkIGZvciBkZWZpbml0aW9uIG9mIGFjY2VwdGFibGUgbWF4IGNoYXIgbGVuZ3RoIG9mIHRoZSBpbnB1dCBmaWVsZFxuICAgKiBGb3IgZXhhbXBsZSwgW21heExlbmd0aF09JzEzJyBpdCBzZXRzIHRoZSBpbnB1dCBmaWxlJ3MgYWNjZXB0YWJsZSBjaGFycyBsZW5ndGggdG8gbWF4IDEzXG4gICAqL1xuICBASW5wdXQoKSBnZXQgbWF4TGVuZ3RoKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX21heExlbmd0aDtcbiAgfVxuXG4gIHNldCBtYXhMZW5ndGgodmFsdWU6IG51bWJlcikge1xuICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50Lm1heExlbmd0aDtcbiAgICBjb25zdCBtYXhMZW5ndGggPSBsZW5ndGggPyBsZW5ndGggOiB0aGlzLl9wbGFjZWhvbGRlci5sZW5ndGg7XG4gICAgdGhpcy5fbWF4TGVuZ3RoID0gKHR5cGVvZiB2YWx1ZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdmFsdWUgIT09IG51bGwpID8gdmFsdWUgOiBtYXhMZW5ndGg7XG4gICAgaWYgKHZhbHVlICYmIHRoaXMuaW5wdXQpIHtcbiAgICAgIHRoaXMuc2V0SW5wdXRBdHRyaWJ1dGVzKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZXh0ZW5kZWRDaGFyczogc3RyaW5nO1xuXG4gIEBJbnB1dCgpIGdldCBleHRlbmRlZENoYXJzKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuX2V4dGVuZGVkQ2hhcnM7XG4gIH1cblxuICBzZXQgZXh0ZW5kZWRDaGFycyh2YWx1ZTogc3RyaW5nKSB7XG4gICAgdGhpcy5fZXh0ZW5kZWRDaGFycyA9IHZhbHVlO1xuICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICd1bmRlZmluZWQnICYmIHRoaXMuaW5wdXQpIHtcbiAgICAgIHRoaXMuc2V0UGxhY2Vob2xkZXIodGhpcy5wbGFjZWhvbGRlcik7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy5pbnB1dCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuICAgIGlmICh0aGlzLl9wbGFjZWhvbGRlcikge1xuICAgICAgdGhpcy5zZXRQbGFjZWhvbGRlcih0aGlzLl9wbGFjZWhvbGRlcik7XG4gICAgfVxuICB9XG5cbiAgc2V0UGxhY2Vob2xkZXIocGxhY2Vob2xkZXI6IHN0cmluZykge1xuICAgIGxldCBzcGVjaWFsQ2hhcnM6IFJlZ0V4cE1hdGNoQXJyYXkgfCBudWxsO1xuICAgIHRoaXMuYWNjZXB0ZWRDaGFycyA9IGBbJHt0aGlzLmRlZmF1bHRDaGFyc30ke3RoaXMuX2V4dGVuZGVkQ2hhcnN9XWA7XG4gICAgc3BlY2lhbENoYXJzID0gcGxhY2Vob2xkZXIubWF0Y2gobmV3IFJlZ0V4cCh0aGlzLmFjY2VwdGVkQ2hhcnMsICdnJykpO1xuICAgIHRoaXMubGlzdCA9IHNwZWNpYWxDaGFycyAmJiBVdGlsLnVuaW9uKHNwZWNpYWxDaGFycykubWFwKCh2YWx1ZTogYW55KSA9PiB7XG4gICAgICAndXNlIHN0cmljdCc7XG4gICAgICByZXR1cm4ge3doYXQ6IHZhbHVlLCBwb3NpdGlvbjogVXRpbC5maW5kQWxsSW5kZXgocGxhY2Vob2xkZXIuc3BsaXQoJycpLCB2YWx1ZSl9O1xuICAgIH0pO1xuICAgIHRoaXMuc2V0SW5wdXRBdHRyaWJ1dGVzKCk7XG4gIH1cblxuICBzZXRJbnB1dEF0dHJpYnV0ZXMoKSB7XG4gICAgdGhpcy5pbnB1dC5zZXRBdHRyaWJ1dGUoJ21heExlbmd0aCcsIHRoaXMuX21heExlbmd0aCk7XG4gICAgdGhpcy5pbnB1dC5zZXRBdHRyaWJ1dGUoJ3BsYWNlaG9sZGVyJywgdGhpcy5fcGxhY2Vob2xkZXIpO1xuICB9XG5cbiAgY2xlYXIodmFsdWU6IGFueSkge1xuICAgIHJldHVybiB2YWx1ZS5yZXBsYWNlKG5ldyBSZWdFeHAodGhpcy5hY2NlcHRlZENoYXJzLCAnZycpLCAnJyk7IC8vIFJlbW92ZXMgZXZlcnkgbm9uLWRpZ2l0IGNoYXJhY3RlcjtcbiAgfVxuXG4gIGlzVmFsaWQodmFsdWU6IGFueSkge1xuICAgIGNvbnN0IGNvbnZlcnREYXRlID0gbmV3IERhdGUodmFsdWUpO1xuICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoY29udmVydERhdGUpID09PSAnW29iamVjdCBEYXRlXScgJiYgIWlzTmFOKGNvbnZlcnREYXRlLmdldFRpbWUoKSk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdmb2N1cycsIFsnJGV2ZW50J10pXG4gIG9uRm9jdXMoJGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgdGhpcy5vbGRWYWx1ZSA9IHRoaXMuaW5wdXQudmFsdWU7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdibHVyJywgWyckZXZlbnQnXSlcbiAgb25CbHVyKCRldmVudDogS2V5Ym9hcmRFdmVudCkge1xuICAgIGlmICh0aGlzLm1hc2tUeXBlID09PSAnZGF0ZScgJiYgIXRoaXMuaXNWYWxpZCh0aGlzLmlucHV0LnZhbHVlKSkge1xuICAgICAgdGhpcy5lbWl0KHRoaXMub2xkVmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICBvbktleURvd24oJGV2ZW50OiBLZXlib2FyZEV2ZW50KSB7XG4gICAgc2VsZWN0aW9uU3RhcnQgPSB0aGlzLmlucHV0LnNlbGVjdGlvblN0YXJ0O1xuICAgIGlmICgkZXZlbnQua2V5Q29kZSA9PT0gMTMpIHtcbiAgICAgIGlmICh0aGlzLm1hc2tUeXBlID09PSAnZGF0ZScgJiYgIXRoaXMuaXNWYWxpZCh0aGlzLmlucHV0LnZhbHVlKSkge1xuICAgICAgICB0aGlzLmVtaXQodGhpcy5vbGRWYWx1ZSk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZW1pdCh2YWx1ZTogYW55KSB7XG4gICAgdGhpcy5pbnB1dC52YWx1ZSA9IHZhbHVlO1xuICAgIHRoaXMub2xkVmFsdWUgPSB2YWx1ZTtcbiAgICB0aGlzLm5nTW9kZWxDaGFuZ2UuZW1pdCh2YWx1ZSk7XG4gIH1cblxuICBjb25kaXRpb25DaGVjaygpIHtcbiAgICBjb25zdCBjbGVhciA9IHRoaXMuY2xlYXIodGhpcy5pbnB1dC52YWx1ZSk7XG4gICAgaWYgKHRoaXMuY29uZGl0aW9ucy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLmNvbmRpdGlvbnMuZm9yRWFjaChjb25kaXRpb24gPT4ge1xuICAgICAgICBjb25zdCBzdGF0dXMgPSBjb25kaXRpb24uY2FzZXMuZXZlcnkoaXRlbSA9PiB7XG4gICAgICAgICAgaWYgKGNsZWFyW2l0ZW0ucG9zaXRpb24gLSAxXSkge1xuICAgICAgICAgICAgY29uc3QgaXNUcnVlID0gbmV3IFJlZ0V4cChpdGVtLnJlZ2V4cCwgJ2dpJykudGVzdChjbGVhcltpdGVtLnBvc2l0aW9uIC0gMV0pO1xuICAgICAgICAgICAgc2VsZWN0aW9uU3RhcnQgPSBpc1RydWUgPyBzZWxlY3Rpb25TdGFydCArIDEgOiBzZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgIHJldHVybiBpc1RydWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgICAgIGNvbnN0IHBsYWNlaG9kZXIgPSBzdGF0dXMgPyBjb25kaXRpb24ucGxhY2Vob2xkZXIgOiB0aGlzLl9wbGFjZWhvbGRlcjtcbiAgICAgICAgdGhpcy5zZXRQbGFjZWhvbGRlcihwbGFjZWhvZGVyKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG1hc2sodmFsdWU6IGFueSkge1xuICAgIGNvbnN0IGNsZWFyID0gdGhpcy5jbGVhcih2YWx1ZSk7XG4gICAgcmV0dXJuIGNsZWFyLnJlcGxhY2UoLy4vZywgKHZhbDogYW55LCBpbmRleDogYW55KSA9PiB7XG4gICAgICBsZXQgc3BlY2lhbENoYXIgPSAwO1xuICAgICAgaWYgKHRoaXMubGlzdCkge1xuICAgICAgICB0aGlzLmxpc3QuZm9yRWFjaChpdGVtID0+IHtcbiAgICAgICAgICAndXNlIHN0cmljdCc7XG4gICAgICAgICAgaXRlbS5wb3NpdGlvbi5mb3JFYWNoKChwb3NpdGlvbjogYW55KSA9PiB7XG4gICAgICAgICAgICB2YWwgPSAoaW5kZXggPT09IChwb3NpdGlvbiAtIDEgLSBzcGVjaWFsQ2hhcikpID8gdmFsICsgaXRlbS53aGF0IDogdmFsO1xuICAgICAgICAgICAgc3BlY2lhbENoYXIrKztcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gdmFsO1xuICAgIH0pO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignaW5wdXQnLCBbJyRldmVudCddKVxuICBvbklucHV0KCRldmVudDogYW55KSB7XG4gICAgbGV0IHZhbHVlLCBuZXdWYWx1ZTtcbiAgICBzd2l0Y2ggKHRoaXMuY2FzZSkge1xuICAgICAgY2FzZSAnbG93ZXInOlxuICAgICAgICB2YWx1ZSA9IFV0aWwudHVya2lzaFRvTG93ZXIodGhpcy5pbnB1dC52YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndXBwZXInOlxuICAgICAgICB2YWx1ZSA9IFV0aWwudHVya2lzaFRvVXBwZXIodGhpcy5pbnB1dC52YWx1ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdmFsdWUgPSB0aGlzLmlucHV0LnZhbHVlO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gICAgY29uc3QgaXNUcnVlID0gbmV3IFJlZ0V4cCh0aGlzLl9yZWdleHApLnRlc3QodGhpcy5jbGVhcih2YWx1ZSkpO1xuICAgIGNvbnN0IGluc2VydGVkQ2hhckxlbmd0aCA9IHRoaXMuaW5wdXQuc2VsZWN0aW9uRW5kIC0gc2VsZWN0aW9uU3RhcnQ7XG4gICAgaWYgKCFpc1RydWUpIHtcbiAgICAgICRldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgdGhpcy5lbWl0KFV0aWwucmVtb3ZlQ2hhcnNCZXR3ZWVuKHZhbHVlLCBzZWxlY3Rpb25TdGFydCwgaW5zZXJ0ZWRDaGFyTGVuZ3RoKSk7XG4gICAgICB0aGlzLmlucHV0LnNldFNlbGVjdGlvblJhbmdlKHNlbGVjdGlvblN0YXJ0LCBzZWxlY3Rpb25TdGFydCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICgkZXZlbnQuZGF0YSB8fCAkZXZlbnQuaW5wdXRUeXBlID09PSAnaW5zZXJ0RnJvbVBhc3RlJykge1xuICAgICAgdGhpcy5jb25kaXRpb25DaGVjaygpO1xuICAgICAgbmV3VmFsdWUgPSB0aGlzLm1hc2sodmFsdWUpO1xuICAgICAgaWYgKHRoaXMubWFza1R5cGUgPT09ICdkYXRlJyAmJiAhbW9tZW50KG5ld1ZhbHVlKS5pc1ZhbGlkKCkgJiYgdGhpcy5fbWF4TGVuZ3RoID09PSB0aGlzLmlucHV0LnZhbHVlKSB7XG4gICAgICAgIHRoaXMuZW1pdCh0aGlzLm9sZFZhbHVlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuZW1pdChuZXdWYWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5pbnB1dC52YWx1ZS5sZW5ndGggIT09IHRoaXMuX21heExlbmd0aCkge1xuICAgICAgICBpZiAodGhpcy5saXN0KSB7XG4gICAgICAgICAgdGhpcy5saXN0Lm1hcChpdGVtID0+IGl0ZW0ucG9zaXRpb24pLmpvaW4oKS5zcGxpdCgnLCcpLm1hcChpdGVtID0+IHtcbiAgICAgICAgICAgIGlmIChOdW1iZXIoaXRlbSkgPj0gc2VsZWN0aW9uU3RhcnQgKyAxICYmIHNlbGVjdGlvblN0YXJ0ICsgaW5zZXJ0ZWRDaGFyTGVuZ3RoID49IE51bWJlcihpdGVtKSkge1xuICAgICAgICAgICAgICBzZWxlY3Rpb25TdGFydCA9IHNlbGVjdGlvblN0YXJ0ICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmlucHV0LnNldFNlbGVjdGlvblJhbmdlKHNlbGVjdGlvblN0YXJ0ICsgaW5zZXJ0ZWRDaGFyTGVuZ3RoLCBzZWxlY3Rpb25TdGFydCArIGluc2VydGVkQ2hhckxlbmd0aCk7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG4iXX0=