rating.js 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, EventEmitter, forwardRef, Input, Output, TemplateRef, ViewEncapsulation } from '@angular/core';
  6. import { NgbRatingConfig } from './rating-config';
  7. import { getValueInRange } from '../util/util';
  8. import { Key } from '../util/key';
  9. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  10. /**
  11. * The context for the custom star display template defined in the `starTemplate`.
  12. * @record
  13. */
  14. export function StarTemplateContext() { }
  15. if (false) {
  16. /**
  17. * The star fill percentage, an integer in the `[0, 100]` range.
  18. * @type {?}
  19. */
  20. StarTemplateContext.prototype.fill;
  21. /**
  22. * Index of the star, starts with `0`.
  23. * @type {?}
  24. */
  25. StarTemplateContext.prototype.index;
  26. }
  27. /** @type {?} */
  28. const NGB_RATING_VALUE_ACCESSOR = {
  29. provide: NG_VALUE_ACCESSOR,
  30. useExisting: forwardRef((/**
  31. * @return {?}
  32. */
  33. () => NgbRating)),
  34. multi: true
  35. };
  36. /**
  37. * A directive that helps visualising and interacting with a star rating bar.
  38. */
  39. export class NgbRating {
  40. /**
  41. * @param {?} config
  42. * @param {?} _changeDetectorRef
  43. */
  44. constructor(config, _changeDetectorRef) {
  45. this._changeDetectorRef = _changeDetectorRef;
  46. this.contexts = [];
  47. this.disabled = false;
  48. /**
  49. * An event emitted when the user is hovering over a given rating.
  50. *
  51. * Event payload equals to the rating being hovered over.
  52. */
  53. this.hover = new EventEmitter();
  54. /**
  55. * An event emitted when the user stops hovering over a given rating.
  56. *
  57. * Event payload equals to the rating of the last item being hovered over.
  58. */
  59. this.leave = new EventEmitter();
  60. /**
  61. * An event emitted when the user selects a new rating.
  62. *
  63. * Event payload equals to the newly selected rating.
  64. */
  65. this.rateChange = new EventEmitter(true);
  66. this.onChange = (/**
  67. * @param {?} _
  68. * @return {?}
  69. */
  70. (_) => { });
  71. this.onTouched = (/**
  72. * @return {?}
  73. */
  74. () => { });
  75. this.max = config.max;
  76. this.readonly = config.readonly;
  77. }
  78. /**
  79. * @return {?}
  80. */
  81. ariaValueText() { return `${this.nextRate} out of ${this.max}`; }
  82. /**
  83. * @param {?} value
  84. * @return {?}
  85. */
  86. enter(value) {
  87. if (!this.readonly && !this.disabled) {
  88. this._updateState(value);
  89. }
  90. this.hover.emit(value);
  91. }
  92. /**
  93. * @return {?}
  94. */
  95. handleBlur() { this.onTouched(); }
  96. /**
  97. * @param {?} value
  98. * @return {?}
  99. */
  100. handleClick(value) { this.update(this.resettable && this.rate === value ? 0 : value); }
  101. /**
  102. * @param {?} event
  103. * @return {?}
  104. */
  105. handleKeyDown(event) {
  106. // tslint:disable-next-line:deprecation
  107. switch (event.which) {
  108. case Key.ArrowDown:
  109. case Key.ArrowLeft:
  110. this.update(this.rate - 1);
  111. break;
  112. case Key.ArrowUp:
  113. case Key.ArrowRight:
  114. this.update(this.rate + 1);
  115. break;
  116. case Key.Home:
  117. this.update(0);
  118. break;
  119. case Key.End:
  120. this.update(this.max);
  121. break;
  122. default:
  123. return;
  124. }
  125. // note 'return' in default case
  126. event.preventDefault();
  127. }
  128. /**
  129. * @param {?} changes
  130. * @return {?}
  131. */
  132. ngOnChanges(changes) {
  133. if (changes['rate']) {
  134. this.update(this.rate);
  135. }
  136. }
  137. /**
  138. * @return {?}
  139. */
  140. ngOnInit() {
  141. this.contexts = Array.from({ length: this.max }, (/**
  142. * @param {?} v
  143. * @param {?} k
  144. * @return {?}
  145. */
  146. (v, k) => ({ fill: 0, index: k })));
  147. this._updateState(this.rate);
  148. }
  149. /**
  150. * @param {?} fn
  151. * @return {?}
  152. */
  153. registerOnChange(fn) { this.onChange = fn; }
  154. /**
  155. * @param {?} fn
  156. * @return {?}
  157. */
  158. registerOnTouched(fn) { this.onTouched = fn; }
  159. /**
  160. * @return {?}
  161. */
  162. reset() {
  163. this.leave.emit(this.nextRate);
  164. this._updateState(this.rate);
  165. }
  166. /**
  167. * @param {?} isDisabled
  168. * @return {?}
  169. */
  170. setDisabledState(isDisabled) { this.disabled = isDisabled; }
  171. /**
  172. * @param {?} value
  173. * @param {?=} internalChange
  174. * @return {?}
  175. */
  176. update(value, internalChange = true) {
  177. /** @type {?} */
  178. const newRate = getValueInRange(value, this.max, 0);
  179. if (!this.readonly && !this.disabled && this.rate !== newRate) {
  180. this.rate = newRate;
  181. this.rateChange.emit(this.rate);
  182. }
  183. if (internalChange) {
  184. this.onChange(this.rate);
  185. this.onTouched();
  186. }
  187. this._updateState(this.rate);
  188. }
  189. /**
  190. * @param {?} value
  191. * @return {?}
  192. */
  193. writeValue(value) {
  194. this.update(value, false);
  195. this._changeDetectorRef.markForCheck();
  196. }
  197. /**
  198. * @private
  199. * @param {?} index
  200. * @return {?}
  201. */
  202. _getFillValue(index) {
  203. /** @type {?} */
  204. const diff = this.nextRate - index;
  205. if (diff >= 1) {
  206. return 100;
  207. }
  208. if (diff < 1 && diff > 0) {
  209. return parseInt((diff * 100).toFixed(2), 10);
  210. }
  211. return 0;
  212. }
  213. /**
  214. * @private
  215. * @param {?} nextValue
  216. * @return {?}
  217. */
  218. _updateState(nextValue) {
  219. this.nextRate = nextValue;
  220. this.contexts.forEach((/**
  221. * @param {?} context
  222. * @param {?} index
  223. * @return {?}
  224. */
  225. (context, index) => context.fill = this._getFillValue(index)));
  226. }
  227. }
  228. NgbRating.decorators = [
  229. { type: Component, args: [{
  230. selector: 'ngb-rating',
  231. changeDetection: ChangeDetectionStrategy.OnPush,
  232. encapsulation: ViewEncapsulation.None,
  233. host: {
  234. 'class': 'd-inline-flex',
  235. 'tabindex': '0',
  236. 'role': 'slider',
  237. 'aria-valuemin': '0',
  238. '[attr.aria-valuemax]': 'max',
  239. '[attr.aria-valuenow]': 'nextRate',
  240. '[attr.aria-valuetext]': 'ariaValueText()',
  241. '[attr.aria-disabled]': 'readonly ? true : null',
  242. '(blur)': 'handleBlur()',
  243. '(keydown)': 'handleKeyDown($event)',
  244. '(mouseleave)': 'reset()'
  245. },
  246. template: `
  247. <ng-template #t let-fill="fill">{{ fill === 100 ? '&#9733;' : '&#9734;' }}</ng-template>
  248. <ng-template ngFor [ngForOf]="contexts" let-index="index">
  249. <span class="sr-only">({{ index < nextRate ? '*' : ' ' }})</span>
  250. <span (mouseenter)="enter(index + 1)" (click)="handleClick(index + 1)" [style.cursor]="readonly || disabled ? 'default' : 'pointer'">
  251. <ng-template [ngTemplateOutlet]="starTemplate || starTemplateFromContent || t" [ngTemplateOutletContext]="contexts[index]">
  252. </ng-template>
  253. </span>
  254. </ng-template>
  255. `,
  256. providers: [NGB_RATING_VALUE_ACCESSOR]
  257. }] }
  258. ];
  259. /** @nocollapse */
  260. NgbRating.ctorParameters = () => [
  261. { type: NgbRatingConfig },
  262. { type: ChangeDetectorRef }
  263. ];
  264. NgbRating.propDecorators = {
  265. max: [{ type: Input }],
  266. rate: [{ type: Input }],
  267. readonly: [{ type: Input }],
  268. resettable: [{ type: Input }],
  269. starTemplate: [{ type: Input }],
  270. starTemplateFromContent: [{ type: ContentChild, args: [TemplateRef, { static: false },] }],
  271. hover: [{ type: Output }],
  272. leave: [{ type: Output }],
  273. rateChange: [{ type: Output }]
  274. };
  275. if (false) {
  276. /** @type {?} */
  277. NgbRating.prototype.contexts;
  278. /** @type {?} */
  279. NgbRating.prototype.disabled;
  280. /** @type {?} */
  281. NgbRating.prototype.nextRate;
  282. /**
  283. * The maximal rating that can be given.
  284. * @type {?}
  285. */
  286. NgbRating.prototype.max;
  287. /**
  288. * The current rating. Could be a decimal value like `3.75`.
  289. * @type {?}
  290. */
  291. NgbRating.prototype.rate;
  292. /**
  293. * If `true`, the rating can't be changed.
  294. * @type {?}
  295. */
  296. NgbRating.prototype.readonly;
  297. /**
  298. * If `true`, the rating can be reset to `0` by mouse clicking currently set rating.
  299. * @type {?}
  300. */
  301. NgbRating.prototype.resettable;
  302. /**
  303. * The template to override the way each star is displayed.
  304. *
  305. * Alternatively put an `<ng-template>` as the only child of your `<ngb-rating>` element
  306. * @type {?}
  307. */
  308. NgbRating.prototype.starTemplate;
  309. /** @type {?} */
  310. NgbRating.prototype.starTemplateFromContent;
  311. /**
  312. * An event emitted when the user is hovering over a given rating.
  313. *
  314. * Event payload equals to the rating being hovered over.
  315. * @type {?}
  316. */
  317. NgbRating.prototype.hover;
  318. /**
  319. * An event emitted when the user stops hovering over a given rating.
  320. *
  321. * Event payload equals to the rating of the last item being hovered over.
  322. * @type {?}
  323. */
  324. NgbRating.prototype.leave;
  325. /**
  326. * An event emitted when the user selects a new rating.
  327. *
  328. * Event payload equals to the newly selected rating.
  329. * @type {?}
  330. */
  331. NgbRating.prototype.rateChange;
  332. /** @type {?} */
  333. NgbRating.prototype.onChange;
  334. /** @type {?} */
  335. NgbRating.prototype.onTouched;
  336. /**
  337. * @type {?}
  338. * @private
  339. */
  340. NgbRating.prototype._changeDetectorRef;
  341. }
  342. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmF0aW5nLmpzIiwic291cmNlUm9vdCI6Im5nOi8vQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAvIiwic291cmNlcyI6WyJyYXRpbmcvcmF0aW5nLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsdUJBQXVCLEVBQ3ZCLGlCQUFpQixFQUNqQixTQUFTLEVBQ1QsWUFBWSxFQUNaLFlBQVksRUFDWixVQUFVLEVBQ1YsS0FBSyxFQUdMLE1BQU0sRUFFTixXQUFXLEVBQ1gsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBQyxlQUFlLEVBQUMsTUFBTSxpQkFBaUIsQ0FBQztBQUNoRCxPQUFPLEVBQUMsZUFBZSxFQUFDLE1BQU0sY0FBYyxDQUFDO0FBQzdDLE9BQU8sRUFBQyxHQUFHLEVBQUMsTUFBTSxhQUFhLENBQUM7QUFDaEMsT0FBTyxFQUF1QixpQkFBaUIsRUFBQyxNQUFNLGdCQUFnQixDQUFDOzs7OztBQUt2RSx5Q0FVQzs7Ozs7O0lBTkMsbUNBQWE7Ozs7O0lBS2Isb0NBQWM7OztNQUdWLHlCQUF5QixHQUFHO0lBQ2hDLE9BQU8sRUFBRSxpQkFBaUI7SUFDMUIsV0FBVyxFQUFFLFVBQVU7OztJQUFDLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBQztJQUN4QyxLQUFLLEVBQUUsSUFBSTtDQUNaOzs7O0FBa0NELE1BQU0sT0FBTyxTQUFTOzs7OztJQTJEcEIsWUFBWSxNQUF1QixFQUFVLGtCQUFxQztRQUFyQyx1QkFBa0IsR0FBbEIsa0JBQWtCLENBQW1CO1FBekRsRixhQUFRLEdBQTBCLEVBQUUsQ0FBQztRQUNyQyxhQUFRLEdBQUcsS0FBSyxDQUFDOzs7Ozs7UUFxQ1AsVUFBSyxHQUFHLElBQUksWUFBWSxFQUFVLENBQUM7Ozs7OztRQU9uQyxVQUFLLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQzs7Ozs7O1FBT25DLGVBQVUsR0FBRyxJQUFJLFlBQVksQ0FBUyxJQUFJLENBQUMsQ0FBQztRQUV0RCxh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bUJBS0wsS0FBSzt1QkFLTCxLQUFLO3lCQUtMLEtBQUs7MkJBT0wsS0FBSztzQ0FDTCxZQUFZLFNBQUMsV0FBVyxFQUFFLEVBQUMsTUFBTSxFQUFFLEtBQUssRUFBQztvQkFPekMsTUFBTTtvQkFPTixNQUFNO3lCQU9OLE1BQU07Ozs7SUFwRFAsNkJBQXFDOztJQUNyQyw2QkFBaUI7O0lBQ2pCLDZCQUFpQjs7Ozs7SUFNakIsd0JBQXFCOzs7OztJQUtyQix5QkFBc0I7Ozs7O0lBS3RCLDZCQUEyQjs7Ozs7SUFLM0IsK0JBQTZCOzs7Ozs7O0lBTzdCLGlDQUF3RDs7SUFDeEQsNENBQXNHOzs7Ozs7O0lBT3RHLDBCQUE2Qzs7Ozs7OztJQU83QywwQkFBNkM7Ozs7Ozs7SUFPN0MsK0JBQXNEOztJQUV0RCw2QkFBMEI7O0lBQzFCLDhCQUFxQjs7Ozs7SUFFZ0IsdUNBQTZDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb21wb25lbnQsXG4gIENvbnRlbnRDaGlsZCxcbiAgRXZlbnRFbWl0dGVyLFxuICBmb3J3YXJkUmVmLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVGVtcGxhdGVSZWYsXG4gIFZpZXdFbmNhcHN1bGF0aW9uXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtOZ2JSYXRpbmdDb25maWd9IGZyb20gJy4vcmF0aW5nLWNvbmZpZyc7XG5pbXBvcnQge2dldFZhbHVlSW5SYW5nZX0gZnJvbSAnLi4vdXRpbC91dGlsJztcbmltcG9ydCB7S2V5fSBmcm9tICcuLi91dGlsL2tleSc7XG5pbXBvcnQge0NvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUn0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuXG4vKipcbiAqIFRoZSBjb250ZXh0IGZvciB0aGUgY3VzdG9tIHN0YXIgZGlzcGxheSB0ZW1wbGF0ZSBkZWZpbmVkIGluIHRoZSBgc3RhclRlbXBsYXRlYC5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBTdGFyVGVtcGxhdGVDb250ZXh0IHtcbiAgLyoqXG4gICAqIFRoZSBzdGFyIGZpbGwgcGVyY2VudGFnZSwgYW4gaW50ZWdlciBpbiB0aGUgYFswLCAxMDBdYCByYW5nZS5cbiAgICovXG4gIGZpbGw6IG51bWJlcjtcblxuICAvKipcbiAgICogSW5kZXggb2YgdGhlIHN0YXIsIHN0YXJ0cyB3aXRoIGAwYC5cbiAgICovXG4gIGluZGV4OiBudW1iZXI7XG59XG5cbmNvbnN0IE5HQl9SQVRJTkdfVkFMVUVfQUNDRVNTT1IgPSB7XG4gIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBOZ2JSYXRpbmcpLFxuICBtdWx0aTogdHJ1ZVxufTtcblxuLyoqXG4gKiBBIGRpcmVjdGl2ZSB0aGF0IGhlbHBzIHZpc3VhbGlzaW5nIGFuZCBpbnRlcmFjdGluZyB3aXRoIGEgc3RhciByYXRpbmcgYmFyLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICduZ2ItcmF0aW5nJyxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gIGhvc3Q6IHtcbiAgICAnY2xhc3MnOiAnZC1pbmxpbmUtZmxleCcsXG4gICAgJ3RhYmluZGV4JzogJzAnLFxuICAgICdyb2xlJzogJ3NsaWRlcicsXG4gICAgJ2FyaWEtdmFsdWVtaW4nOiAnMCcsXG4gICAgJ1thdHRyLmFyaWEtdmFsdWVtYXhdJzogJ21heCcsXG4gICAgJ1thdHRyLmFyaWEtdmFsdWVub3ddJzogJ25leHRSYXRlJyxcbiAgICAnW2F0dHIuYXJpYS12YWx1ZXRleHRdJzogJ2FyaWFWYWx1ZVRleHQoKScsXG4gICAgJ1thdHRyLmFyaWEtZGlzYWJsZWRdJzogJ3JlYWRvbmx5ID8gdHJ1ZSA6IG51bGwnLFxuICAgICcoYmx1ciknOiAnaGFuZGxlQmx1cigpJyxcbiAgICAnKGtleWRvd24pJzogJ2hhbmRsZUtleURvd24oJGV2ZW50KScsXG4gICAgJyhtb3VzZWxlYXZlKSc6ICdyZXNldCgpJ1xuICB9LFxuICB0ZW1wbGF0ZTogYFxuICAgIDxuZy10ZW1wbGF0ZSAjdCBsZXQtZmlsbD1cImZpbGxcIj57eyBmaWxsID09PSAxMDAgPyAnJiM5NzMzOycgOiAnJiM5NzM0OycgfX08L25nLXRlbXBsYXRlPlxuICAgIDxuZy10ZW1wbGF0ZSBuZ0ZvciBbbmdGb3JPZl09XCJjb250ZXh0c1wiIGxldC1pbmRleD1cImluZGV4XCI+XG4gICAgICA8c3BhbiBjbGFzcz1cInNyLW9ubHlcIj4oe3sgaW5kZXggPCBuZXh0UmF0ZSA/ICcqJyA6ICcgJyB9fSk8L3NwYW4+XG4gICAgICA8c3BhbiAobW91c2VlbnRlcik9XCJlbnRlcihpbmRleCArIDEpXCIgKGNsaWNrKT1cImhhbmRsZUNsaWNrKGluZGV4ICsgMSlcIiBbc3R5bGUuY3Vyc29yXT1cInJlYWRvbmx5IHx8IGRpc2FibGVkID8gJ2RlZmF1bHQnIDogJ3BvaW50ZXInXCI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBbbmdUZW1wbGF0ZU91dGxldF09XCJzdGFyVGVtcGxhdGUgfHwgc3RhclRlbXBsYXRlRnJvbUNvbnRlbnQgfHwgdFwiIFtuZ1RlbXBsYXRlT3V0bGV0Q29udGV4dF09XCJjb250ZXh0c1tpbmRleF1cIj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvc3Bhbj5cbiAgICA8L25nLXRlbXBsYXRlPlxuICBgLFxuICBwcm92aWRlcnM6IFtOR0JfUkFUSU5HX1ZBTFVFX0FDQ0VTU09SXVxufSlcbmV4cG9ydCBjbGFzcyBOZ2JSYXRpbmcgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvcixcbiAgICBPbkluaXQsIE9uQ2hhbmdlcyB7XG4gIGNvbnRleHRzOiBTdGFyVGVtcGxhdGVDb250ZXh0W10gPSBbXTtcbiAgZGlzYWJsZWQgPSBmYWxzZTtcbiAgbmV4dFJhdGU6IG51bWJlcjtcblxuXG4gIC8qKlxuICAgKiBUaGUgbWF4aW1hbCByYXRpbmcgdGhhdCBjYW4gYmUgZ2l2ZW4uXG4gICAqL1xuICBASW5wdXQoKSBtYXg6IG51bWJlcjtcblxuICAvKipcbiAgICogVGhlIGN1cnJlbnQgcmF0aW5nLiBDb3VsZCBiZSBhIGRlY2ltYWwgdmFsdWUgbGlrZSBgMy43NWAuXG4gICAqL1xuICBASW5wdXQoKSByYXRlOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgdGhlIHJhdGluZyBjYW4ndCBiZSBjaGFuZ2VkLlxuICAgKi9cbiAgQElucHV0KCkgcmVhZG9ubHk6IGJvb2xlYW47XG5cbiAgLyoqXG4gICAqIElmIGB0cnVlYCwgdGhlIHJhdGluZyBjYW4gYmUgcmVzZXQgdG8gYDBgIGJ5IG1vdXNlIGNsaWNraW5nIGN1cnJlbnRseSBzZXQgcmF0aW5nLlxuICAgKi9cbiAgQElucHV0KCkgcmVzZXR0YWJsZTogYm9vbGVhbjtcblxuICAvKipcbiAgICogVGhlIHRlbXBsYXRlIHRvIG92ZXJyaWRlIHRoZSB3YXkgZWFjaCBzdGFyIGlzIGRpc3BsYXllZC5cbiAgICpcbiAgICogQWx0ZXJuYXRpdmVseSBwdXQgYW4gYDxuZy10ZW1wbGF0ZT5gIGFzIHRoZSBvbmx5IGNoaWxkIG9mIHlvdXIgYDxuZ2ItcmF0aW5nPmAgZWxlbWVudFxuICAgKi9cbiAgQElucHV0KCkgc3RhclRlbXBsYXRlOiBUZW1wbGF0ZVJlZjxTdGFyVGVtcGxhdGVDb250ZXh0PjtcbiAgQENvbnRlbnRDaGlsZChUZW1wbGF0ZVJlZiwge3N0YXRpYzogZmFsc2V9KSBzdGFyVGVtcGxhdGVGcm9tQ29udGVudDogVGVtcGxhdGVSZWY8U3RhclRlbXBsYXRlQ29udGV4dD47XG5cbiAgLyoqXG4gICAqIEFuIGV2ZW50IGVtaXR0ZWQgd2hlbiB0aGUgdXNlciBpcyBob3ZlcmluZyBvdmVyIGEgZ2l2ZW4gcmF0aW5nLlxuICAgKlxuICAgKiBFdmVudCBwYXlsb2FkIGVxdWFscyB0byB0aGUgcmF0aW5nIGJlaW5nIGhvdmVyZWQgb3Zlci5cbiAgICovXG4gIEBPdXRwdXQoKSBob3ZlciA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gIC8qKlxuICAgKiBBbiBldmVudCBlbWl0dGVkIHdoZW4gdGhlIHVzZXIgc3RvcHMgaG92ZXJpbmcgb3ZlciBhIGdpdmVuIHJhdGluZy5cbiAgICpcbiAgICogRXZlbnQgcGF5bG9hZCBlcXVhbHMgdG8gdGhlIHJhdGluZyBvZiB0aGUgbGFzdCBpdGVtIGJlaW5nIGhvdmVyZWQgb3Zlci5cbiAgICovXG4gIEBPdXRwdXQoKSBsZWF2ZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPigpO1xuXG4gIC8qKlxuICAgKiBBbiBldmVudCBlbWl0dGVkIHdoZW4gdGhlIHVzZXIgc2VsZWN0cyBhIG5ldyByYXRpbmcuXG4gICAqXG4gICAqIEV2ZW50IHBheWxvYWQgZXF1YWxzIHRvIHRoZSBuZXdseSBzZWxlY3RlZCByYXRpbmcuXG4gICAqL1xuICBAT3V0cHV0KCkgcmF0ZUNoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8bnVtYmVyPih0cnVlKTtcblxuICBvbkNoYW5nZSA9IChfOiBhbnkpID0+IHt9O1xuICBvblRvdWNoZWQgPSAoKSA9PiB7fTtcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IE5nYlJhdGluZ0NvbmZpZywgcHJpdmF0ZSBfY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgdGhpcy5tYXggPSBjb25maWcubWF4O1xuICAgIHRoaXMucmVhZG9ubHkgPSBjb25maWcucmVhZG9ubHk7XG4gIH1cblxuICBhcmlhVmFsdWVUZXh0KCkgeyByZXR1cm4gYCR7dGhpcy5uZXh0UmF0ZX0gb3V0IG9mICR7dGhpcy5tYXh9YDsgfVxuXG4gIGVudGVyKHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucmVhZG9ubHkgJiYgIXRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZVN0YXRlKHZhbHVlKTtcbiAgICB9XG4gICAgdGhpcy5ob3Zlci5lbWl0KHZhbHVlKTtcbiAgfVxuXG4gIGhhbmRsZUJsdXIoKSB7IHRoaXMub25Ub3VjaGVkKCk7IH1cblxuICBoYW5kbGVDbGljayh2YWx1ZTogbnVtYmVyKSB7IHRoaXMudXBkYXRlKHRoaXMucmVzZXR0YWJsZSAmJiB0aGlzLnJhdGUgPT09IHZhbHVlID8gMCA6IHZhbHVlKTsgfVxuXG4gIGhhbmRsZUtleURvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6ZGVwcmVjYXRpb25cbiAgICBzd2l0Y2ggKGV2ZW50LndoaWNoKSB7XG4gICAgICBjYXNlIEtleS5BcnJvd0Rvd246XG4gICAgICBjYXNlIEtleS5BcnJvd0xlZnQ6XG4gICAgICAgIHRoaXMudXBkYXRlKHRoaXMucmF0ZSAtIDEpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgS2V5LkFycm93VXA6XG4gICAgICBjYXNlIEtleS5BcnJvd1JpZ2h0OlxuICAgICAgICB0aGlzLnVwZGF0ZSh0aGlzLnJhdGUgKyAxKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEtleS5Ib21lOlxuICAgICAgICB0aGlzLnVwZGF0ZSgwKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIEtleS5FbmQ6XG4gICAgICAgIHRoaXMudXBkYXRlKHRoaXMubWF4KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gbm90ZSAncmV0dXJuJyBpbiBkZWZhdWx0IGNhc2VcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIGlmIChjaGFuZ2VzWydyYXRlJ10pIHtcbiAgICAgIHRoaXMudXBkYXRlKHRoaXMucmF0ZSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5jb250ZXh0cyA9IEFycmF5LmZyb20oe2xlbmd0aDogdGhpcy5tYXh9LCAodiwgaykgPT4gKHtmaWxsOiAwLCBpbmRleDoga30pKTtcbiAgICB0aGlzLl91cGRhdGVTdGF0ZSh0aGlzLnJhdGUpO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKHZhbHVlOiBhbnkpID0+IGFueSk6IHZvaWQgeyB0aGlzLm9uQ2hhbmdlID0gZm47IH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4gYW55KTogdm9pZCB7IHRoaXMub25Ub3VjaGVkID0gZm47IH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLmxlYXZlLmVtaXQodGhpcy5uZXh0UmF0ZSk7XG4gICAgdGhpcy5fdXBkYXRlU3RhdGUodGhpcy5yYXRlKTtcbiAgfVxuXG4gIHNldERpc2FibGVkU3RhdGUoaXNEaXNhYmxlZDogYm9vbGVhbikgeyB0aGlzLmRpc2FibGVkID0gaXNEaXNhYmxlZDsgfVxuXG4gIHVwZGF0ZSh2YWx1ZTogbnVtYmVyLCBpbnRlcm5hbENoYW5nZSA9IHRydWUpOiB2b2lkIHtcbiAgICBjb25zdCBuZXdSYXRlID0gZ2V0VmFsdWVJblJhbmdlKHZhbHVlLCB0aGlzLm1heCwgMCk7XG4gICAgaWYgKCF0aGlzLnJlYWRvbmx5ICYmICF0aGlzLmRpc2FibGVkICYmIHRoaXMucmF0ZSAhPT0gbmV3UmF0ZSkge1xuICAgICAgdGhpcy5yYXRlID0gbmV3UmF0ZTtcbiAgICAgIHRoaXMucmF0ZUNoYW5nZS5lbWl0KHRoaXMucmF0ZSk7XG4gICAgfVxuICAgIGlmIChpbnRlcm5hbENoYW5nZSkge1xuICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLnJhdGUpO1xuICAgICAgdGhpcy5vblRvdWNoZWQoKTtcbiAgICB9XG4gICAgdGhpcy5fdXBkYXRlU3RhdGUodGhpcy5yYXRlKTtcbiAgfVxuXG4gIHdyaXRlVmFsdWUodmFsdWUpIHtcbiAgICB0aGlzLnVwZGF0ZSh2YWx1ZSwgZmFsc2UpO1xuICAgIHRoaXMuX2NoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0RmlsbFZhbHVlKGluZGV4OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IGRpZmYgPSB0aGlzLm5leHRSYXRlIC0gaW5kZXg7XG5cbiAgICBpZiAoZGlmZiA+PSAxKSB7XG4gICAgICByZXR1cm4gMTAwO1xuICAgIH1cbiAgICBpZiAoZGlmZiA8IDEgJiYgZGlmZiA+IDApIHtcbiAgICAgIHJldHVybiBwYXJzZUludCgoZGlmZiAqIDEwMCkudG9GaXhlZCgyKSwgMTApO1xuICAgIH1cblxuICAgIHJldHVybiAwO1xuICB9XG5cbiAgcHJpdmF0ZSBfdXBkYXRlU3RhdGUobmV4dFZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLm5leHRSYXRlID0gbmV4dFZhbHVlO1xuICAgIHRoaXMuY29udGV4dHMuZm9yRWFjaCgoY29udGV4dCwgaW5kZXgpID0+IGNvbnRleHQuZmlsbCA9IHRoaXMuX2dldEZpbGxWYWx1ZShpbmRleCkpO1xuICB9XG59XG4iXX0=