rating.component.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { Component, EventEmitter, HostListener, Input, Output, forwardRef, TemplateRef, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
  6. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  7. /** @type {?} */
  8. export var RATING_CONTROL_VALUE_ACCESSOR = {
  9. provide: NG_VALUE_ACCESSOR,
  10. /* tslint:disable-next-line: no-use-before-declare */
  11. useExisting: forwardRef((/**
  12. * @return {?}
  13. */
  14. function () { return RatingComponent; })),
  15. multi: true
  16. };
  17. var RatingComponent = /** @class */ (function () {
  18. function RatingComponent(changeDetection) {
  19. this.changeDetection = changeDetection;
  20. /**
  21. * number of icons
  22. */
  23. this.max = 5;
  24. /**
  25. * fired when icon selected, $event:number equals to selected rating
  26. */
  27. this.onHover = new EventEmitter();
  28. /**
  29. * fired when icon selected, $event:number equals to previous rating value
  30. */
  31. this.onLeave = new EventEmitter();
  32. // tslint:disable-next-line:no-any
  33. this.onChange = Function.prototype;
  34. // tslint:disable-next-line:no-any
  35. this.onTouched = Function.prototype;
  36. }
  37. /**
  38. * @param {?} event
  39. * @return {?}
  40. */
  41. RatingComponent.prototype.onKeydown = /**
  42. * @param {?} event
  43. * @return {?}
  44. */
  45. function (event) {
  46. /* tslint:disable-next-line: deprecation */
  47. if ([37, 38, 39, 40].indexOf(event.which) === -1) {
  48. return;
  49. }
  50. event.preventDefault();
  51. event.stopPropagation();
  52. /* tslint:disable-next-line: deprecation */
  53. /** @type {?} */
  54. var sign = event.which === 38 || event.which === 39 ? 1 : -1;
  55. this.rate(this.value + sign);
  56. };
  57. /**
  58. * @return {?}
  59. */
  60. RatingComponent.prototype.ngOnInit = /**
  61. * @return {?}
  62. */
  63. function () {
  64. this.max = typeof this.max !== 'undefined' ? this.max : 5;
  65. this.titles =
  66. typeof this.titles !== 'undefined' && this.titles.length > 0
  67. ? this.titles
  68. : [];
  69. this.range = this.buildTemplateObjects(this.max);
  70. };
  71. // model -> view
  72. // model -> view
  73. /**
  74. * @param {?} value
  75. * @return {?}
  76. */
  77. RatingComponent.prototype.writeValue =
  78. // model -> view
  79. /**
  80. * @param {?} value
  81. * @return {?}
  82. */
  83. function (value) {
  84. if (value % 1 !== value) {
  85. this.value = Math.round(value);
  86. this.preValue = value;
  87. this.changeDetection.markForCheck();
  88. return;
  89. }
  90. this.preValue = value;
  91. this.value = value;
  92. this.changeDetection.markForCheck();
  93. };
  94. /**
  95. * @param {?} value
  96. * @return {?}
  97. */
  98. RatingComponent.prototype.enter = /**
  99. * @param {?} value
  100. * @return {?}
  101. */
  102. function (value) {
  103. if (!this.readonly) {
  104. this.value = value;
  105. this.changeDetection.markForCheck();
  106. this.onHover.emit(value);
  107. }
  108. };
  109. /**
  110. * @return {?}
  111. */
  112. RatingComponent.prototype.reset = /**
  113. * @return {?}
  114. */
  115. function () {
  116. this.value = this.preValue;
  117. this.changeDetection.markForCheck();
  118. this.onLeave.emit(this.value);
  119. };
  120. /**
  121. * @param {?} fn
  122. * @return {?}
  123. */
  124. RatingComponent.prototype.registerOnChange = /**
  125. * @param {?} fn
  126. * @return {?}
  127. */
  128. function (fn) {
  129. this.onChange = fn;
  130. };
  131. /**
  132. * @param {?} fn
  133. * @return {?}
  134. */
  135. RatingComponent.prototype.registerOnTouched = /**
  136. * @param {?} fn
  137. * @return {?}
  138. */
  139. function (fn) {
  140. this.onTouched = fn;
  141. };
  142. /**
  143. * @param {?} value
  144. * @return {?}
  145. */
  146. RatingComponent.prototype.rate = /**
  147. * @param {?} value
  148. * @return {?}
  149. */
  150. function (value) {
  151. if (!this.readonly && value >= 0 && value <= this.range.length) {
  152. this.writeValue(value);
  153. this.onChange(value);
  154. }
  155. };
  156. /**
  157. * @protected
  158. * @param {?} max
  159. * @return {?}
  160. */
  161. RatingComponent.prototype.buildTemplateObjects = /**
  162. * @protected
  163. * @param {?} max
  164. * @return {?}
  165. */
  166. function (max) {
  167. /** @type {?} */
  168. var result = [];
  169. for (var i = 0; i < max; i++) {
  170. result.push({
  171. index: i,
  172. title: this.titles[i] || i + 1
  173. });
  174. }
  175. return result;
  176. };
  177. RatingComponent.decorators = [
  178. { type: Component, args: [{
  179. selector: 'rating',
  180. template: "<span (mouseleave)=\"reset()\" (keydown)=\"onKeydown($event)\" tabindex=\"0\"\n role=\"slider\" aria-valuemin=\"0\" [attr.aria-valuemax]=\"range.length\"\n [attr.aria-valuenow]=\"value\">\n <ng-template #star let-value=\"value\" let-index=\"index\">{{ index < value ? '&#9733;' : '&#9734;' }}</ng-template>\n <ng-template ngFor let-r [ngForOf]=\"range\" let-index=\"index\">\n <span class=\"sr-only\">({{ index < value ? '*' : ' ' }})</span>\n <span class=\"bs-rating-star\"\n (mouseenter)=\"enter(index + 1)\"\n (click)=\"rate(index + 1)\"\n [title]=\"r.title\"\n [style.cursor]=\"readonly ? 'default' : 'pointer'\"\n [class.active]=\"index < value\">\n <ng-template [ngTemplateOutlet]=\"customTemplate || star\"\n [ngTemplateOutletContext]=\"{index: index, value: value}\">\n </ng-template>\n </span>\n </ng-template>\n</span>\n",
  181. providers: [RATING_CONTROL_VALUE_ACCESSOR],
  182. changeDetection: ChangeDetectionStrategy.OnPush
  183. }] }
  184. ];
  185. /** @nocollapse */
  186. RatingComponent.ctorParameters = function () { return [
  187. { type: ChangeDetectorRef }
  188. ]; };
  189. RatingComponent.propDecorators = {
  190. max: [{ type: Input }],
  191. readonly: [{ type: Input }],
  192. titles: [{ type: Input }],
  193. customTemplate: [{ type: Input }],
  194. onHover: [{ type: Output }],
  195. onLeave: [{ type: Output }],
  196. onKeydown: [{ type: HostListener, args: ['keydown', ['$event'],] }]
  197. };
  198. return RatingComponent;
  199. }());
  200. export { RatingComponent };
  201. if (false) {
  202. /**
  203. * number of icons
  204. * @type {?}
  205. */
  206. RatingComponent.prototype.max;
  207. /**
  208. * if true will not react on any user events
  209. * @type {?}
  210. */
  211. RatingComponent.prototype.readonly;
  212. /**
  213. * array of icons titles, default: (["one", "two", "three", "four", "five"])
  214. * @type {?}
  215. */
  216. RatingComponent.prototype.titles;
  217. /**
  218. * custom template for icons
  219. * @type {?}
  220. */
  221. RatingComponent.prototype.customTemplate;
  222. /**
  223. * fired when icon selected, $event:number equals to selected rating
  224. * @type {?}
  225. */
  226. RatingComponent.prototype.onHover;
  227. /**
  228. * fired when icon selected, $event:number equals to previous rating value
  229. * @type {?}
  230. */
  231. RatingComponent.prototype.onLeave;
  232. /** @type {?} */
  233. RatingComponent.prototype.onChange;
  234. /** @type {?} */
  235. RatingComponent.prototype.onTouched;
  236. /** @type {?} */
  237. RatingComponent.prototype.range;
  238. /** @type {?} */
  239. RatingComponent.prototype.value;
  240. /**
  241. * @type {?}
  242. * @protected
  243. */
  244. RatingComponent.prototype.preValue;
  245. /**
  246. * @type {?}
  247. * @private
  248. */
  249. RatingComponent.prototype.changeDetection;
  250. }
  251. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmF0aW5nLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1ib290c3RyYXAvcmF0aW5nLyIsInNvdXJjZXMiOlsicmF0aW5nLmNvbXBvbmVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7O0FBQUEsT0FBTyxFQUNMLFNBQVMsRUFDVCxZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBQ04sVUFBVSxFQUFFLFdBQVcsRUFBRSx1QkFBdUIsRUFBRSxpQkFBaUIsRUFDcEUsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUF3QixpQkFBaUIsRUFBRSxNQUFNLGdCQUFnQixDQUFDOztBQUd6RSxNQUFNLEtBQU8sNkJBQTZCLEdBQW9CO0lBQzVELE9BQU8sRUFBRSxpQkFBaUI7O0lBRTFCLFdBQVcsRUFBRSxVQUFVOzs7SUFBQyxjQUFNLE9BQUEsZUFBZSxFQUFmLENBQWUsRUFBQztJQUM5QyxLQUFLLEVBQUUsSUFBSTtDQUNaO0FBRUQ7SUE4QkUseUJBQW9CLGVBQWtDO1FBQWxDLG9CQUFlLEdBQWYsZUFBZSxDQUFtQjs7OztRQXRCN0MsUUFBRyxHQUFHLENBQUMsQ0FBQzs7OztRQVNQLFlBQU8sR0FBeUIsSUFBSSxZQUFZLEVBQUUsQ0FBQzs7OztRQUVuRCxZQUFPLEdBQXlCLElBQUksWUFBWSxFQUFFLENBQUM7O1FBRzdELGFBQVEsR0FBUSxRQUFRLENBQUMsU0FBUyxDQUFDOztRQUVuQyxjQUFTLEdBQVEsUUFBUSxDQUFDLFNBQVMsQ0FBQztJQU1xQixDQUFDOzs7OztJQUcxRCxtQ0FBUzs7OztJQURULFVBQ1UsS0FBb0I7UUFDNUIsMkNBQTJDO1FBQzNDLElBQUksQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFO1lBQ2hELE9BQU87U0FDUjtRQUVELEtBQUssQ0FBQyxjQUFjLEVBQUUs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b0IsRUFBRTtRQUNsQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQzVCLE1BQU0sQ0FBQyxJQUFJLENBQUM7Z0JBQ1IsS0FBSyxFQUFFLENBQUM7Z0JBQ1IsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7YUFDL0IsQ0FBQyxDQUFDO1NBQ047UUFFRCxPQUFPLE1BQU0sQ0FBQztJQUNoQixDQUFDOztnQkE3R0YsU0FBUyxTQUFDO29CQUNULFFBQVEsRUFBRSxRQUFRO29CQUNsQix5NkJBQXNDO29CQUN0QyxTQUFTLEVBQUUsQ0FBQyw2QkFBNkIsQ0FBQztvQkFDMUMsZUFBZSxFQUFFLHVCQUF1QixDQUFDLE1BQU07aUJBQ2hEOzs7O2dCQWpCbUQsaUJBQWlCOzs7c0JBb0JsRSxLQUFLOzJCQUVMLEtBQUs7eUJBRUwsS0FBSztpQ0FHTCxLQUFLOzBCQUVMLE1BQU07MEJBRU4sTUFBTTs0QkFhTixZQUFZLFNBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxDQUFDOztJQThFckMsc0JBQUM7Q0FBQSxBQTlHRCxJQThHQztTQXhHWSxlQUFlOzs7Ozs7SUFFMUIsOEJBQWlCOzs7OztJQUVqQixtQ0FBMkI7Ozs7O0lBRTNCLGlDQUEwQjs7Ozs7SUFHMUIseUNBQTBDOzs7OztJQUUxQyxrQ0FBNkQ7Ozs7O0lBRTdELGtDQUE2RDs7SUFHN0QsbUNBQW1DOztJQUVuQyxvQ0FBb0M7O0lBRXBDLGdDQUF1Qjs7SUFDdkIsZ0NBQWM7Ozs7O0lBQ2QsbUNBQTJCOzs7OztJQUVmLDBDQUEwQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgZm9yd2FyZFJlZiwgVGVtcGxhdGVSZWYsIENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZlxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbnRyb2xWYWx1ZUFjY2Vzc29yLCBOR19WQUxVRV9BQ0NFU1NPUiB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFjY2Vzc29yQ29udGVudCwgUmF0aW5nUmVzdWx0cyB9IGZyb20gJy4vbW9kZWxzJztcblxuZXhwb3J0IGNvbnN0IFJBVElOR19DT05UUk9MX1ZBTFVFX0FDQ0VTU09SOiBBY2Nlc3NvckNvbnRlbnQgPSB7XG4gIHByb3ZpZGU6IE5HX1ZBTFVFX0FDQ0VTU09SLFxuICAvKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IG5vLXVzZS1iZWZvcmUtZGVjbGFyZSAqL1xuICB1c2VFeGlzdGluZzogZm9yd2FyZFJlZigoKSA9PiBSYXRpbmdDb21wb25lbnQpLFxuICBtdWx0aTogdHJ1ZVxufTtcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAncmF0aW5nJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3JhdGluZy5jb21wb25lbnQuaHRtbCcsXG4gIHByb3ZpZGVyczogW1JBVElOR19DT05UUk9MX1ZBTFVFX0FDQ0VTU09SXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2hcbn0pXG5leHBvcnQgY2xhc3MgUmF0aW5nQ29tcG9uZW50IGltcGxlbWVudHMgQ29udHJvbFZhbHVlQWNjZXNzb3IsIE9uSW5pdCB7XG4gIC8qKiBudW1iZXIgb2YgaWNvbnMgKi9cbiAgQElucHV0KCkgbWF4ID0gNTtcbiAgLyoqIGlmIHRydWUgd2lsbCBub3QgcmVhY3Qgb24gYW55IHVzZXIgZXZlbnRzICovXG4gIEBJbnB1dCgpIHJlYWRvbmx5OiBib29sZWFuO1xuICAvKiogYXJyYXkgb2YgaWNvbnMgdGl0bGVzLCBkZWZhdWx0OiAoW1wib25lXCIsIFwidHdvXCIsIFwidGhyZWVcIiwgXCJmb3VyXCIsIFwiZml2ZVwiXSkgKi9cbiAgQElucHV0KCkgdGl0bGVzOiBzdHJpbmdbXTtcbiAgLyoqIGN1c3RvbSB0ZW1wbGF0ZSBmb3IgaWNvbnMgKi9cbiAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOm5vLWFueVxuICBASW5wdXQoKSBjdXN0b21UZW1wbGF0ZTogVGVtcGxhdGVSZWY8YW55PjtcbiAgLyoqIGZpcmVkIHdoZW4gaWNvbiBzZWxlY3RlZCwgJGV2ZW50Om51bWJlciBlcXVhbHMgdG8gc2VsZWN0ZWQgcmF0aW5nICovXG4gIEBPdXRwdXQoKSBvbkhvdmVyOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgLyoqIGZpcmVkIHdoZW4gaWNvbiBzZWxlY3RlZCwgJGV2ZW50Om51bWJlciBlcXVhbHMgdG8gcHJldmlvdXMgcmF0aW5nIHZhbHVlICovXG4gIEBPdXRwdXQoKSBvbkxlYXZlOiBFdmVudEVtaXR0ZXI8bnVtYmVyPiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gIG9uQ2hhbmdlOiBhbnkgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG4gIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpuby1hbnlcbiAgb25Ub3VjaGVkOiBhbnkgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG5cbiAgcmFuZ2U6IFJhdGluZ1Jlc3VsdHNbXTtcbiAgdmFsdWU6IG51bWJlcjtcbiAgcHJvdGVjdGVkIHByZVZhbHVlOiBudW1iZXI7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdG9yUmVmKSB7fVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2tleWRvd24nLCBbJyRldmVudCddKVxuICBvbktleWRvd24oZXZlbnQ6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IGRlcHJlY2F0aW9uICovXG4gICAgaWYgKFszNywgMzgsIDM5LCA0MF0uaW5kZXhPZihldmVudC53aGljaCkgPT09IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAvKiB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6IGRlcHJlY2F0aW9uICovXG4gICAgY29uc3Qgc2lnbiA9IGV2ZW50LndoaWNoID09PSAzOCB8fCBldmVudC53aGljaCA9PT0gMzkgPyAxIDogLTE7XG4gICAgdGhpcy5yYXRlKHRoaXMudmFsdWUgKyBzaWduKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMubWF4ID0gdHlwZW9mIHRoaXMubWF4ICE9PSAndW5kZWZpbmVkJyA/IHRoaXMubWF4IDogNTtcbiAgICB0aGlzLnRpdGxlcyA9XG4gICAgICB0eXBlb2YgdGhpcy50aXRsZXMgIT09ICd1bmRlZmluZWQnICYmIHRoaXMudGl0bGVzLmxlbmd0aCA+IDBcbiAgICAgICAgPyB0aGlzLnRpdGxlc1xuICAgICAgICA6IFtdO1xuICAgIHRoaXMucmFuZ2UgPSB0aGlzLmJ1aWxkVGVtcGxhdGVPYmplY3RzKHRoaXMubWF4KTtcbiAgfVxuXG4gIC8vIG1vZGVsIC0+IHZpZXdcbiAgd3JpdGVWYWx1ZSh2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHZhbHVlICUgMSAhPT0gdmFsdWUpIHtcbiAgICAgIHRoaXMudmFsdWUgPSBNYXRoLnJvdW5kKHZhbHVlKTtcbiAgICAgIHRoaXMucHJlVmFsdWUgPSB2YWx1ZTtcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5wcmVWYWx1ZSA9IHZhbHVlO1xuICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICB0aGlzLmNoYW5nZURldGVjdGlvbi5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGVudGVyKHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucmVhZG9ubHkpIHtcbiAgICAgIHRoaXMudmFsdWUgPSB2YWx1ZTtcbiAgICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLm1hcmtGb3JDaGVjaygpO1xuICAgICAgdGhpcy5vbkhvdmVyLmVtaXQodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHJlc2V0KCk6IHZvaWQge1xuICAgIHRoaXMudmFsdWUgPSB0aGlzLnByZVZhbHVlO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLm1hcmtGb3JDaGVjaygpO1xuICAgIHRoaXMub25MZWF2ZS5lbWl0KHRoaXMudmFsdWUpO1xuICB9XG5cbiAgcmVnaXN0ZXJPbkNoYW5nZShmbjogKF86IG51bWJlcikgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLm9uQ2hhbmdlID0gZm47XG4gIH1cblxuICByZWdpc3Rlck9uVG91Y2hlZChmbjogKCkgPT4ge30pOiB2b2lkIHtcbiAgICB0aGlzLm9uVG91Y2hlZCA9IGZuO1xuICB9XG5cbiAgcmF0ZSh2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnJlYWRvbmx5ICYmIHZhbHVlID49IDAgJiYgdmFsdWUgPD0gdGhpcy5yYW5nZS5sZW5ndGgpIHtcbiAgICAgIHRoaXMud3JpdGVWYWx1ZSh2YWx1ZSk7XG4gICAgICB0aGlzLm9uQ2hhbmdlKHZhbHVlKTtcbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgYnVpbGRUZW1wbGF0ZU9iamVjdHMobWF4OiBudW1iZXIpOiBSYXRpbmdSZXN1bHRzW10ge1xuICAgIGNvbnN0IHJlc3VsdDogUmF0aW5nUmVzdWx0c1tdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtYXg7IGkrKykge1xuICAgICAgcmVzdWx0LnB1c2goe1xuICAgICAgICAgIGluZGV4OiBpLFxuICAgICAgICAgIHRpdGxlOiB0aGlzLnRpdGxlc1tpXSB8fCBpICsgMVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG59XG4iXX0=