pager.component.js 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { ChangeDetectorRef, Component, ElementRef, EventEmitter, forwardRef, Input, Output } from '@angular/core';
  6. import { NG_VALUE_ACCESSOR } from '@angular/forms';
  7. import { PaginationConfig } from './pagination.config';
  8. /** @type {?} */
  9. export const PAGER_CONTROL_VALUE_ACCESSOR = {
  10. provide: NG_VALUE_ACCESSOR,
  11. /* tslint:disable-next-line: no-use-before-declare */
  12. useExisting: forwardRef((/**
  13. * @return {?}
  14. */
  15. () => PagerComponent)),
  16. multi: true
  17. };
  18. export class PagerComponent {
  19. /**
  20. * @param {?} elementRef
  21. * @param {?} paginationConfig
  22. * @param {?} changeDetection
  23. */
  24. constructor(elementRef, paginationConfig, changeDetection) {
  25. this.elementRef = elementRef;
  26. this.changeDetection = changeDetection;
  27. /**
  28. * fired when total pages count changes, $event:number equals to total pages count
  29. */
  30. this.numPages = new EventEmitter();
  31. /**
  32. * fired when page was changed, $event:{page, itemsPerPage} equals to
  33. * object with current page index and number of items per page
  34. */
  35. this.pageChanged = new EventEmitter();
  36. this.onChange = Function.prototype;
  37. this.onTouched = Function.prototype;
  38. this.inited = false;
  39. this._page = 1;
  40. this.elementRef = elementRef;
  41. if (!this.config) {
  42. this.configureOptions(Object.assign({}, paginationConfig.main, paginationConfig.pager));
  43. }
  44. }
  45. /**
  46. * maximum number of items per page. If value less than 1 will display all items on one page
  47. * @return {?}
  48. */
  49. get itemsPerPage() {
  50. return this._itemsPerPage;
  51. }
  52. /**
  53. * @param {?} v
  54. * @return {?}
  55. */
  56. set itemsPerPage(v) {
  57. this._itemsPerPage = v;
  58. this.totalPages = this.calculateTotalPages();
  59. }
  60. /**
  61. * total number of items in all pages
  62. * @return {?}
  63. */
  64. get totalItems() {
  65. return this._totalItems;
  66. }
  67. /**
  68. * @param {?} v
  69. * @return {?}
  70. */
  71. set totalItems(v) {
  72. this._totalItems = v;
  73. this.totalPages = this.calculateTotalPages();
  74. }
  75. /**
  76. * @return {?}
  77. */
  78. get totalPages() {
  79. return this._totalPages;
  80. }
  81. /**
  82. * @param {?} v
  83. * @return {?}
  84. */
  85. set totalPages(v) {
  86. this._totalPages = v;
  87. this.numPages.emit(v);
  88. if (this.inited) {
  89. this.selectPage(this.page);
  90. }
  91. }
  92. /**
  93. * @param {?} value
  94. * @return {?}
  95. */
  96. set page(value) {
  97. /** @type {?} */
  98. const _previous = this._page;
  99. this._page = value > this.totalPages ? this.totalPages : value || 1;
  100. this.changeDetection.markForCheck();
  101. if (_previous === this._page || typeof _previous === 'undefined') {
  102. return;
  103. }
  104. this.pageChanged.emit({
  105. page: this._page,
  106. itemsPerPage: this.itemsPerPage
  107. });
  108. }
  109. /**
  110. * @return {?}
  111. */
  112. get page() {
  113. return this._page;
  114. }
  115. /**
  116. * @param {?} config
  117. * @return {?}
  118. */
  119. configureOptions(config) {
  120. this.config = Object.assign({}, config);
  121. }
  122. /**
  123. * @return {?}
  124. */
  125. ngOnInit() {
  126. if (typeof window !== 'undefined') {
  127. this.classMap = this.elementRef.nativeElement.getAttribute('class') || '';
  128. }
  129. // watch for maxSize
  130. this.maxSize =
  131. typeof this.maxSize !== 'undefined' ? this.maxSize : this.config.maxSize;
  132. this.rotate =
  133. typeof this.rotate !== 'undefined' ? this.rotate : this.config.rotate;
  134. this.boundaryLinks =
  135. typeof this.boundaryLinks !== 'undefined'
  136. ? this.boundaryLinks
  137. : this.config.boundaryLinks;
  138. this.directionLinks =
  139. typeof this.directionLinks !== 'undefined'
  140. ? this.directionLinks
  141. : this.config.directionLinks;
  142. this.pageBtnClass =
  143. typeof this.pageBtnClass !== 'undefined'
  144. ? this.pageBtnClass
  145. : this.config.pageBtnClass;
  146. // base class
  147. this.itemsPerPage =
  148. typeof this.itemsPerPage !== 'undefined'
  149. ? this.itemsPerPage
  150. : this.config.itemsPerPage;
  151. this.totalPages = this.calculateTotalPages();
  152. // this class
  153. this.pages = this.getPages(this.page, this.totalPages);
  154. this.inited = true;
  155. }
  156. /**
  157. * @param {?} value
  158. * @return {?}
  159. */
  160. writeValue(value) {
  161. this.page = value;
  162. this.pages = this.getPages(this.page, this.totalPages);
  163. }
  164. /**
  165. * @param {?} key
  166. * @return {?}
  167. */
  168. getText(key) {
  169. // tslint:disable-next-line:no-any
  170. return ((/** @type {?} */ (this)))[`${key}Text`] || ((/** @type {?} */ (this))).config[`${key}Text`];
  171. }
  172. /**
  173. * @return {?}
  174. */
  175. noPrevious() {
  176. return this.page === 1;
  177. }
  178. /**
  179. * @return {?}
  180. */
  181. noNext() {
  182. return this.page === this.totalPages;
  183. }
  184. /**
  185. * @param {?} fn
  186. * @return {?}
  187. */
  188. registerOnChange(fn) {
  189. this.onChange = fn;
  190. }
  191. /**
  192. * @param {?} fn
  193. * @return {?}
  194. */
  195. registerOnTouched(fn) {
  196. this.onTouched = fn;
  197. }
  198. /**
  199. * @param {?} page
  200. * @param {?=} event
  201. * @return {?}
  202. */
  203. selectPage(page, event) {
  204. if (event) {
  205. event.preventDefault();
  206. }
  207. if (!this.disabled) {
  208. if (event && event.target) {
  209. // tslint:disable-next-line:no-any
  210. /** @type {?} */
  211. const target = event.target;
  212. target.blur();
  213. }
  214. this.writeValue(page);
  215. this.onChange(this.page);
  216. }
  217. }
  218. // Create page object used in template
  219. /**
  220. * @protected
  221. * @param {?} num
  222. * @param {?} text
  223. * @param {?} active
  224. * @return {?}
  225. */
  226. makePage(num, text, active) {
  227. return { text, number: num, active };
  228. }
  229. /**
  230. * @protected
  231. * @param {?} currentPage
  232. * @param {?} totalPages
  233. * @return {?}
  234. */
  235. getPages(currentPage, totalPages) {
  236. /** @type {?} */
  237. const pages = [];
  238. // Default page limits
  239. /** @type {?} */
  240. let startPage = 1;
  241. /** @type {?} */
  242. let endPage = totalPages;
  243. /** @type {?} */
  244. const isMaxSized = typeof this.maxSize !== 'undefined' && this.maxSize < totalPages;
  245. // recompute if maxSize
  246. if (isMaxSized) {
  247. if (this.rotate) {
  248. // Current page is displayed in the middle of the visible ones
  249. startPage = Math.max(currentPage - Math.floor(this.maxSize / 2), 1);
  250. endPage = startPage + this.maxSize - 1;
  251. // Adjust if limit is exceeded
  252. if (endPage > totalPages) {
  253. endPage = totalPages;
  254. startPage = endPage - this.maxSize + 1;
  255. }
  256. }
  257. else {
  258. // Visible pages are paginated with maxSize
  259. startPage =
  260. (Math.ceil(currentPage / this.maxSize) - 1) * this.maxSize + 1;
  261. // Adjust last page if limit is exceeded
  262. endPage = Math.min(startPage + this.maxSize - 1, totalPages);
  263. }
  264. }
  265. // Add page number links
  266. for (let num = startPage; num <= endPage; num++) {
  267. /** @type {?} */
  268. const page = this.makePage(num, num.toString(), num === currentPage);
  269. pages.push(page);
  270. }
  271. // Add links to move between page sets
  272. if (isMaxSized && !this.rotate) {
  273. if (startPage > 1) {
  274. /** @type {?} */
  275. const previousPageSet = this.makePage(startPage - 1, '...', false);
  276. pages.unshift(previousPageSet);
  277. }
  278. if (endPage < totalPages) {
  279. /** @type {?} */
  280. const nextPageSet = this.makePage(endPage + 1, '...', false);
  281. pages.push(nextPageSet);
  282. }
  283. }
  284. return pages;
  285. }
  286. // base class
  287. /**
  288. * @protected
  289. * @return {?}
  290. */
  291. calculateTotalPages() {
  292. /** @type {?} */
  293. const totalPages = this.itemsPerPage < 1
  294. ? 1
  295. : Math.ceil(this.totalItems / this.itemsPerPage);
  296. return Math.max(totalPages || 0, 1);
  297. }
  298. }
  299. PagerComponent.decorators = [
  300. { type: Component, args: [{
  301. selector: 'pager',
  302. template: "<ul class=\"pager\">\n <li [class.disabled]=\"noPrevious()\" [class.previous]=\"align\"\n [ngClass]=\"{'pull-right': align, 'float-right': align}\"\n class=\"{{ pageBtnClass }}\">\n <a href (click)=\"selectPage(page - 1, $event)\">{{ getText('previous') }}</a>\n </li>\n <li [class.disabled]=\"noNext()\" [class.next]=\"align\"\n [ngClass]=\"{'pull-right': align, 'float-right': align}\"\n class=\"{{ pageBtnClass }}\">\n <a href (click)=\"selectPage(page + 1, $event)\">{{ getText('next') }}</a>\n </li>\n</ul>\n",
  303. providers: [PAGER_CONTROL_VALUE_ACCESSOR]
  304. }] }
  305. ];
  306. /** @nocollapse */
  307. PagerComponent.ctorParameters = () => [
  308. { type: ElementRef },
  309. { type: PaginationConfig },
  310. { type: ChangeDetectorRef }
  311. ];
  312. PagerComponent.propDecorators = {
  313. align: [{ type: Input }],
  314. maxSize: [{ type: Input }],
  315. boundaryLinks: [{ type: Input }],
  316. directionLinks: [{ type: Input }],
  317. firstText: [{ type: Input }],
  318. previousText: [{ type: Input }],
  319. nextText: [{ type: Input }],
  320. lastText: [{ type: Input }],
  321. rotate: [{ type: Input }],
  322. pageBtnClass: [{ type: Input }],
  323. disabled: [{ type: Input }],
  324. numPages: [{ type: Output }],
  325. pageChanged: [{ type: Output }],
  326. itemsPerPage: [{ type: Input }],
  327. totalItems: [{ type: Input }]
  328. };
  329. if (false) {
  330. /** @type {?} */
  331. PagerComponent.prototype.config;
  332. /**
  333. * if `true` aligns each link to the sides of pager
  334. * @type {?}
  335. */
  336. PagerComponent.prototype.align;
  337. /**
  338. * limit number for page links in pager
  339. * @type {?}
  340. */
  341. PagerComponent.prototype.maxSize;
  342. /**
  343. * if false first and last buttons will be hidden
  344. * @type {?}
  345. */
  346. PagerComponent.prototype.boundaryLinks;
  347. /**
  348. * if false previous and next buttons will be hidden
  349. * @type {?}
  350. */
  351. PagerComponent.prototype.directionLinks;
  352. /**
  353. * first button text
  354. * @type {?}
  355. */
  356. PagerComponent.prototype.firstText;
  357. /**
  358. * previous button text
  359. * @type {?}
  360. */
  361. PagerComponent.prototype.previousText;
  362. /**
  363. * next button text
  364. * @type {?}
  365. */
  366. PagerComponent.prototype.nextText;
  367. /**
  368. * last button text
  369. * @type {?}
  370. */
  371. PagerComponent.prototype.lastText;
  372. /**
  373. * if true current page will in the middle of pages list
  374. * @type {?}
  375. */
  376. PagerComponent.prototype.rotate;
  377. /**
  378. * add class to <code><li\></code>
  379. * @type {?}
  380. */
  381. PagerComponent.prototype.pageBtnClass;
  382. /**
  383. * if true pagination component will be disabled
  384. * @type {?}
  385. */
  386. PagerComponent.prototype.disabled;
  387. /**
  388. * fired when total pages count changes, $event:number equals to total pages count
  389. * @type {?}
  390. */
  391. PagerComponent.prototype.numPages;
  392. /**
  393. * fired when page was changed, $event:{page, itemsPerPage} equals to
  394. * object with current page index and number of items per page
  395. * @type {?}
  396. */
  397. PagerComponent.prototype.pageChanged;
  398. /** @type {?} */
  399. PagerComponent.prototype.onChange;
  400. /** @type {?} */
  401. PagerComponent.prototype.onTouched;
  402. /** @type {?} */
  403. PagerComponent.prototype.classMap;
  404. /** @type {?} */
  405. PagerComponent.prototype.pages;
  406. /**
  407. * @type {?}
  408. * @protected
  409. */
  410. PagerComponent.prototype._itemsPerPage;
  411. /**
  412. * @type {?}
  413. * @protected
  414. */
  415. PagerComponent.prototype._totalItems;
  416. /**
  417. * @type {?}
  418. * @protected
  419. */
  420. PagerComponent.prototype._totalPages;
  421. /**
  422. * @type {?}
  423. * @protected
  424. */
  425. PagerComponent.prototype.inited;
  426. /**
  427. * @type {?}
  428. * @protected
  429. */
  430. PagerComponent.prototype._page;
  431. /**
  432. * @type {?}
  433. * @private
  434. */
  435. PagerComponent.prototype.elementRef;
  436. /**
  437. * @type {?}
  438. * @private
  439. */
  440. PagerComponent.prototype.changeDetection;
  441. }
  442. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFnZXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6Im5nOi8vbmd4LWJvb3RzdHJhcC9wYWdpbmF0aW9uLyIsInNvdXJjZXMiOlsicGFnZXIuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQ0wsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsWUFBWSxFQUNaLFVBQVUsRUFDVixLQUFLLEVBRUwsTUFBTSxFQUVQLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBd0IsaUJBQWlCLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUd6RSxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQzs7QUFJdkQsTUFBTSxPQUFPLDRCQUE0QixHQUFhO0lBQ3BELE9BQU8sRUFBRSxpQkFBaUI7O0lBRTFCLFdBQVcsRUFBRSxVQUFVOzs7SUFBQyxHQUFHLEVBQUUsQ0FBQyxjQUFjLEVBQUM7SUFDN0MsS0FBSyxFQUFFLElBQUk7Q0FDWjtBQU9ELE1BQU0sT0FBTyxjQUFjOzs7Ozs7SUFxR3pCLFlBQW9CLFVBQXNCLEVBQzlCLGdCQUFrQyxFQUMxQixlQUFrQztRQUZsQyxlQUFVLEdBQVYsVUFBVSxDQUFZO1FBRXRCLG9CQUFlLEdBQWYsZUFBZSxDQUFtQjs7OztRQTFFNUMsYUFBUSxHQUF5QixJQUFJLFlBQVksRUFBVSxDQUFDOzs7OztRQUt0RSxnQkFBVyxHQUFtQyxJQUFJLFlBQVksRUFBb0IsQ0FBQztRQXVEbkYsYUFBUSxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFDOUIsY0FBUyxHQUFHLFFBQVEsQ0FBQyxTQUFTLENBQUM7UUFRckIsV0FBTSxHQUFHLEtBQUssQ0FBQztRQUNmLFVBQUssR0FBRyxDQUFDLENBQUM7UUFLbEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUM7UUFDN0IsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsSUFBSSxDQUFDLGdCQUFnQixD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Ozs7WUExQkMsVUFBVTtZQVdILGdCQUFnQjtZQWJ2QixpQkFBaUI7OztvQkFnQ2hCLEtBQUs7c0JBRUwsS0FBSzs0QkFFTCxLQUFLOzZCQUVMLEtBQUs7d0JBR0wsS0FBSzsyQkFFTCxLQUFLO3VCQUVMLEtBQUs7dUJBRUwsS0FBSztxQkFFTCxLQUFLOzJCQUdMLEtBQUs7dUJBR0wsS0FBSzt1QkFHTCxNQUFNOzBCQUlOLE1BQU07MkJBSU4sS0FBSzt5QkFXTCxLQUFLOzs7O0lBL0NOLGdDQUFvQjs7Ozs7SUFFcEIsK0JBQXdCOzs7OztJQUV4QixpQ0FBeUI7Ozs7O0lBRXpCLHVDQUFnQzs7Ozs7SUFFaEMsd0NBQWlDOzs7OztJQUdqQyxtQ0FBMkI7Ozs7O0lBRTNCLHNDQUE4Qjs7Ozs7SUFFOUIsa0NBQTBCOzs7OztJQUUxQixrQ0FBMEI7Ozs7O0lBRTFCLGdDQUF5Qjs7Ozs7SUFHekIsc0NBQThCOzs7OztJQUc5QixrQ0FBMkI7Ozs7O0lBRzNCLGtDQUFzRTs7Ozs7O0lBSXRFLHFDQUNtRjs7SUF1RG5GLGtDQUE4Qjs7SUFDOUIsbUNBQStCOztJQUUvQixrQ0FBaUI7O0lBQ2pCLCtCQUFvQjs7Ozs7SUFFcEIsdUNBQWdDOzs7OztJQUNoQyxxQ0FBOEI7Ozs7O0lBQzlCLHFDQUE4Qjs7Ozs7SUFDOUIsZ0NBQXlCOzs7OztJQUN6QiwrQkFBb0I7Ozs7O0lBRVIsb0NBQThCOzs7OztJQUU5Qix5Q0FBMEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIGZvcndhcmRSZWYsXG4gIElucHV0LFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgUHJvdmlkZXJcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBDb250cm9sVmFsdWVBY2Nlc3NvciwgTkdfVkFMVUVfQUNDRVNTT1IgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IFBhZ2VDaGFuZ2VkRXZlbnQgfSBmcm9tICcuL3BhZ2luYXRpb24uY29tcG9uZW50JztcbmltcG9ydCB7IFBhZ2luYXRpb25Db25maWcgfSBmcm9tICcuL3BhZ2luYXRpb24uY29uZmlnJztcblxuaW1wb3J0IHsgQ29uZmlnTW9kZWwsIFBhZ2VzTW9kZWwgfSBmcm9tICcuL21vZGVscyc7XG5cbmV4cG9ydCBjb25zdCBQQUdFUl9DT05UUk9MX1ZBTFVFX0FDQ0VTU09SOiBQcm92aWRlciA9IHtcbiAgcHJvdmlkZTogTkdfVkFMVUVfQUNDRVNTT1IsXG4gIC8qIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTogbm8tdXNlLWJlZm9yZS1kZWNsYXJlICovXG4gIHVzZUV4aXN0aW5nOiBmb3J3YXJkUmVmKCgpID0+IFBhZ2VyQ29tcG9uZW50KSxcbiAgbXVsdGk6IHRydWVcbn07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3BhZ2VyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3BhZ2VyLmNvbXBvbmVudC5odG1sJyxcbiAgcHJvdmlkZXJzOiBbUEFHRVJfQ09OVFJPTF9WQUxVRV9BQ0NFU1NPUl1cbn0pXG5leHBvcnQgY2xhc3MgUGFnZXJDb21wb25lbnQgaW1wbGVtZW50cyBDb250cm9sVmFsdWVBY2Nlc3NvciwgT25Jbml0IHtcbiAgY29uZmlnOiBDb25maWdNb2RlbDtcbiAgLyoqIGlmIGB0cnVlYCBhbGlnbnMgZWFjaCBsaW5rIHRvIHRoZSBzaWRlcyBvZiBwYWdlciAqL1xuICBASW5wdXQoKSBhbGlnbjogYm9vbGVhbjtcbiAgLyoqIGxpbWl0IG51bWJlciBmb3IgcGFnZSBsaW5rcyBpbiBwYWdlciAqL1xuICBASW5wdXQoKSBtYXhTaXplOiBudW1iZXI7XG4gIC8qKiBpZiBmYWxzZSBmaXJzdCBhbmQgbGFzdCBidXR0b25zIHdpbGwgYmUgaGlkZGVuICovXG4gIEBJbnB1dCgpIGJvdW5kYXJ5TGlua3M6IGJvb2xlYW47XG4gIC8qKiBpZiBmYWxzZSBwcmV2aW91cyBhbmQgbmV4dCBidXR0b25zIHdpbGwgYmUgaGlkZGVuICovXG4gIEBJbnB1dCgpIGRpcmVjdGlvbkxpbmtzOiBib29sZWFuO1xuICAvLyBsYWJlbHNcbiAgLyoqIGZpcnN0IGJ1dHRvbiB0ZXh0ICovXG4gIEBJbnB1dCgpIGZpcnN0VGV4dDogc3RyaW5nO1xuICAvKiogcHJldmlvdXMgYnV0dG9uIHRleHQgKi9cbiAgQElucHV0KCkgcHJldmlvdXNUZXh0OiBzdHJpbmc7XG4gIC8qKiBuZXh0IGJ1dHRvbiB0ZXh0ICovXG4gIEBJbnB1dCgpIG5leHRUZXh0OiBzdHJpbmc7XG4gIC8qKiBsYXN0IGJ1dHRvbiB0ZXh0ICovXG4gIEBJbnB1dCgpIGxhc3RUZXh0OiBzdHJpbmc7XG4gIC8qKiBpZiB0cnVlIGN1cnJlbnQgcGFnZSB3aWxsIGluIHRoZSBtaWRkbGUgb2YgcGFnZXMgbGlzdCAqL1xuICBASW5wdXQoKSByb3RhdGU6IGJvb2xlYW47XG4gIC8vIGNzc1xuICAvKiogYWRkIGNsYXNzIHRvIDxjb2RlPjxsaVxcPjwvY29kZT4gKi9cbiAgQElucHV0KCkgcGFnZUJ0bkNsYXNzOiBzdHJpbmc7XG5cbiAgLyoqIGlmIHRydWUgcGFnaW5hdGlvbiBjb21wb25lbnQgd2lsbCBiZSBkaXNhYmxlZCAqL1xuICBASW5wdXQoKSBkaXNhYmxlZDogYm9vbGVhbjtcblxuICAvKiogZmlyZWQgd2hlbiB0b3RhbCBwYWdlcyBjb3VudCBjaGFuZ2VzLCAkZXZlbnQ6bnVtYmVyIGVxdWFscyB0byB0b3RhbCBwYWdlcyBjb3VudCAqL1xuICBAT3V0cHV0KCkgbnVtUGFnZXM6IEV2ZW50RW1pdHRlcjxudW1iZXI+ID0gbmV3IEV2ZW50RW1pdHRlcjxudW1iZXI+KCk7XG4gIC8qKiBmaXJlZCB3aGVuIHBhZ2Ugd2FzIGNoYW5nZWQsICRldmVudDp7cGFnZSwgaXRlbXNQZXJQYWdlfSBlcXVhbHMgdG9cbiAgICogb2JqZWN0IHdpdGggY3VycmVudCBwYWdlIGluZGV4IGFuZCBudW1iZXIgb2YgaXRlbXMgcGVyIHBhZ2VcbiAgICovXG4gIEBPdXRwdXQoKVxuICBwYWdlQ2hhbmdlZDogRXZlbnRFbWl0dGVyPFBhZ2VDaGFuZ2VkRXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcjxQYWdlQ2hhbmdlZEV2ZW50PigpO1xuXG4gIC8qKiBtYXhpbXVtIG51bWJlciBvZiBpdGVtcyBwZXIgcGFnZS4gSWYgdmFsdWUgbGVzcyB0aGFuIDEgd2lsbCBkaXNwbGF5IGFsbCBpdGVtcyBvbiBvbmUgcGFnZSAqL1xuICBASW5wdXQoKVxuICBnZXQgaXRlbXNQZXJQYWdlKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2l0ZW1zUGVyUGFnZTtcbiAgfVxuXG4gIHNldCBpdGVtc1BlclBhZ2UodjogbnVtYmVyKSB7XG4gICAgdGhpcy5faXRlbXNQZXJQYWdlID0gdjtcbiAgICB0aGlzLnRvdGFsUGFnZXMgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsUGFnZXMoKTtcbiAgfVxuXG4gIC8qKiB0b3RhbCBudW1iZXIgb2YgaXRlbXMgaW4gYWxsIHBhZ2VzICovXG4gIEBJbnB1dCgpXG4gIGdldCB0b3RhbEl0ZW1zKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdGFsSXRlbXM7XG4gIH1cblxuICBzZXQgdG90YWxJdGVtcyh2OiBudW1iZXIpIHtcbiAgICB0aGlzLl90b3RhbEl0ZW1zID0gdjtcbiAgICB0aGlzLnRvdGFsUGFnZXMgPSB0aGlzLmNhbGN1bGF0ZVRvdGFsUGFnZXMoKTtcbiAgfVxuXG4gIGdldCB0b3RhbFBhZ2VzKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX3RvdGFsUGFnZXM7XG4gIH1cblxuICBzZXQgdG90YWxQYWdlcyh2OiBudW1iZXIpIHtcbiAgICB0aGlzLl90b3RhbFBhZ2VzID0gdjtcbiAgICB0aGlzLm51bVBhZ2VzLmVtaXQodik7XG4gICAgaWYgKHRoaXMuaW5pdGVkKSB7XG4gICAgICB0aGlzLnNlbGVjdFBhZ2UodGhpcy5wYWdlKTtcbiAgICB9XG4gIH1cblxuICBzZXQgcGFnZSh2YWx1ZTogbnVtYmVyKSB7XG4gICAgY29uc3QgX3ByZXZpb3VzID0gdGhpcy5fcGFnZTtcbiAgICB0aGlzLl9wYWdlID0gdmFsdWUgPiB0aGlzLnRvdGFsUGFnZXMgPyB0aGlzLnRvdGFsUGFnZXMgOiB2YWx1ZSB8fCAxO1xuICAgIHRoaXMuY2hhbmdlRGV0ZWN0aW9uLm1hcmtGb3JDaGVjaygpO1xuXG4gICAgaWYgKF9wcmV2aW91cyA9PT0gdGhpcy5fcGFnZSB8fCB0eXBlb2YgX3ByZXZpb3VzID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMucGFnZUNoYW5nZWQuZW1pdCh7XG4gICAgICBwYWdlOiB0aGlzLl9wYWdlLFxuICAgICAgaXRlbXNQZXJQYWdlOiB0aGlzLml0ZW1zUGVyUGFnZVxuICAgIH0pO1xuICB9XG5cbiAgZ2V0IHBhZ2UoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fcGFnZTtcbiAgfVxuXG4gIG9uQ2hhbmdlID0gRnVuY3Rpb24ucHJvdG90eXBlO1xuICBvblRvdWNoZWQgPSBGdW5jdGlvbi5wcm90b3R5cGU7XG5cbiAgY2xhc3NNYXA6IHN0cmluZztcbiAgcGFnZXM6IFBhZ2VzTW9kZWxbXTtcblxuICBwcm90ZWN0ZWQgX2l0ZW1zUGVyUGFnZTogbnVtYmVyO1xuICBwcm90ZWN0ZWQgX3RvdGFsSXRlbXM6IG51bWJlcjtcbiAgcHJvdGVjdGVkIF90b3RhbFBhZ2VzOiBudW1iZXI7XG4gIHByb3RlY3RlZCBpbml0ZWQgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIF9wYWdlID0gMTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWYsXG4gICAgICAgICAgICAgIHBhZ2luYXRpb25Db25maWc6IFBhZ2luYXRpb25Db25maWcsXG4gICAgICAgICAgICAgIHByaXZhdGUgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3RvclJlZikge1xuICAgIHRoaXMuZWxlbWVudFJlZiA9IGVsZW1lbnRSZWY7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgdGhpcy5jb25maWd1cmVPcHRpb25zKFxuICAgICAgICBPYmplY3QuYXNzaWduKHt9LCBwYWdpbmF0aW9uQ29uZmlnLm1haW4sIHBhZ2luYXRpb25Db25maWcucGFnZXIpXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGNvbmZpZ3VyZU9wdGlvbnMoY29uZmlnOiBDb25maWdNb2RlbCk6IHZvaWQge1xuICAgIHRoaXMuY29uZmlnID0gT2JqZWN0LmFzc2lnbih7fSwgY29uZmlnKTtcbiAgfVxuXG4gIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykge1xuICAgICAgdGhpcy5jbGFzc01hcCA9IHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmdldEF0dHJpYnV0ZSgnY2xhc3MnKSB8fCAnJztcbiAgICB9XG4gICAgLy8gd2F0Y2ggZm9yIG1heFNpemVcbiAgICB0aGlzLm1heFNpemUgPVxuICAgICAgdHlwZW9mIHRoaXMubWF4U2l6ZSAhPT0gJ3VuZGVmaW5lZCcgPyB0aGlzLm1heFNpemUgOiB0aGlzLmNvbmZpZy5tYXhTaXplO1xuICAgIHRoaXMucm90YXRlID1cbiAgICAgIHR5cGVvZiB0aGlzLnJvdGF0ZSAhPT0gJ3VuZGVmaW5lZCcgPyB0aGlzLnJvdGF0ZSA6IHRoaXMuY29uZmlnLnJvdGF0ZTtcbiAgICB0aGlzLmJvdW5kYXJ5TGlua3MgPVxuICAgICAgdHlwZW9mIHRoaXMuYm91bmRhcnlMaW5rcyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgPyB0aGlzLmJvdW5kYXJ5TGlua3NcbiAgICAgICAgOiB0aGlzLmNvbmZpZy5ib3VuZGFyeUxpbmtzO1xuICAgIHRoaXMuZGlyZWN0aW9uTGlua3MgPVxuICAgICAgdHlwZW9mIHRoaXMuZGlyZWN0aW9uTGlua3MgIT09ICd1bmRlZmluZWQnXG4gICAgICAgID8gdGhpcy5kaXJlY3Rpb25MaW5rc1xuICAgICAgICA6IHRoaXMuY29uZmlnLmRpcmVjdGlvbkxpbmtzO1xuICAgIHRoaXMucGFnZUJ0bkNsYXNzID1cbiAgICAgIHR5cGVvZiB0aGlzLnBhZ2VCdG5DbGFzcyAhPT0gJ3VuZGVmaW5lZCdcbiAgICAgICAgPyB0aGlzLnBhZ2VCdG5DbGFzc1xuICAgICAgICA6IHRoaXMuY29uZmlnLnBhZ2VCdG5DbGFzcztcblxuICAgIC8vIGJhc2UgY2xhc3NcbiAgICB0aGlzLml0ZW1zUGVyUGFnZSA9XG4gICAgICB0eXBlb2YgdGhpcy5pdGVtc1BlclBhZ2UgIT09ICd1bmRlZmluZWQnXG4gICAgICAgID8gdGhpcy5pdGVtc1BlclBhZ2VcbiAgICAgICAgOiB0aGlzLmNvbmZpZy5pdGVtc1BlclBhZ2U7XG4gICAgdGhpcy50b3RhbFBhZ2VzID0gdGhpcy5jYWxjdWxhdGVUb3RhbFBhZ2VzKCk7XG4gICAgLy8gdGhpcyBjbGFzc1xuICAgIHRoaXMucGFnZXMgPSB0aGlzLmdldFBhZ2VzKHRoaXMucGFnZSwgdGhpcy50b3RhbFBhZ2VzKTtcbiAgICB0aGlzLmluaXRlZCA9IHRydWU7XG4gIH1cblxuICB3cml0ZVZhbHVlKHZhbHVlOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnBhZ2UgPSB2YWx1ZTtcbiAgICB0aGlzLnBhZ2VzID0gdGhpcy5nZXRQYWdlcyh0aGlzLnBhZ2UsIHRoaXMudG90YWxQYWdlcyk7XG4gIH1cblxuICBnZXRUZXh0KGtleTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gICAgcmV0dXJuICh0aGlzIGFzIGFueSlbYCR7a2V5fVRleHRgXSB8fCAodGhpcyBhcyBhbnkpLmNvbmZpZ1tgJHtrZXl9VGV4dGBdO1xuICB9XG5cbiAgbm9QcmV2aW91cygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wYWdlID09PSAxO1xuICB9XG5cbiAgbm9OZXh0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnBhZ2UgPT09IHRoaXMudG90YWxQYWdlcztcbiAgfVxuXG4gIHJlZ2lzdGVyT25DaGFuZ2UoZm46ICgpID0+IHt9KTogdm9pZCB7XG4gICAgdGhpcy5vbkNoYW5nZSA9IGZuO1xuICB9XG5cbiAgcmVnaXN0ZXJPblRvdWNoZWQoZm46ICgpID0+IHt9KTogdm9pZCB7XG4gICAgdGhpcy5vblRvdWNoZWQgPSBmbjtcbiAgfVxuXG4gIHNlbGVjdFBhZ2UocGFnZTogbnVtYmVyLCBldmVudD86IEV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGV2ZW50KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5kaXNhYmxlZCkge1xuICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50LnRhcmdldCkge1xuICAgICAgICAvLyB0c2xpbnQ6ZGlzYWJsZS1uZXh0LWxpbmU6bm8tYW55XG4gICAgICAgIGNvbnN0IHRhcmdldDogYW55ID0gZXZlbnQudGFyZ2V0O1xuICAgICAgICB0YXJnZXQuYmx1cigpO1xuICAgICAgfVxuICAgICAgdGhpcy53cml0ZVZhbHVlKHBhZ2UpO1xuICAgICAgdGhpcy5vbkNoYW5nZSh0aGlzLnBhZ2UpO1xuICAgIH1cbiAgfVxuXG4gIC8vIENyZWF0ZSBwYWdlIG9iamVjdCB1c2VkIGluIHRlbXBsYXRlXG4gIHByb3RlY3RlZCBtYWtlUGFnZShudW06IG51bWJlcixcbiAgICAgICAgICAgICAgICAgICAgIHRleHQ6IHN0cmluZyxcbiAgICAgICAgICAgICAgICAgICAgIGFjdGl2ZTogYm9vbGVhbik6IHsgbnVtYmVyOiBudW1iZXI7IHRleHQ6IHN0cmluZzsgYWN0aXZlOiBib29sZWFuIH0ge1xuICAgIHJldHVybiB7dGV4dCwgbnVtYmVyOiBudW0sIGFjdGl2ZX07XG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0UGFnZXMoY3VycmVudFBhZ2U6IG51bWJlciwgdG90YWxQYWdlczogbnVtYmVyKTogUGFnZXNNb2RlbFtdIHtcbiAgICBjb25zdCBwYWdlczogUGFnZXNNb2RlbFtdID0gW107XG5cbiAgICAvLyBEZWZhdWx0IHBhZ2UgbGltaXRzXG4gICAgbGV0IHN0YXJ0UGFnZSA9IDE7XG4gICAgbGV0IGVuZFBhZ2UgPSB0b3RhbFBhZ2VzO1xuICAgIGNvbnN0IGlzTWF4U2l6ZWQgPVxuICAgICAgdHlwZW9mIHRoaXMubWF4U2l6ZSAhPT0gJ3VuZGVmaW5lZCcgJiYgdGhpcy5tYXhTaXplIDwgdG90YWxQYWdlcztcblxuICAgIC8vIHJlY29tcHV0ZSBpZiBtYXhTaXplXG4gICAgaWYgKGlzTWF4U2l6ZWQpIHtcbiAgICAgIGlmICh0aGlzLnJvdGF0ZSkge1xuICAgICAgICAvLyBDdXJyZW50IHBhZ2UgaXMgZGlzcGxheWVkIGluIHRoZSBtaWRkbGUgb2YgdGhlIHZpc2libGUgb25lc1xuICAgICAgICBzdGFydFBhZ2UgPSBNYXRoLm1heChjdXJyZW50UGFnZSAtIE1hdGguZmxvb3IodGhpcy5tYXhTaXplIC8gMiksIDEpO1xuICAgICAgICBlbmRQYWdlID0gc3RhcnRQYWdlICsgdGhpcy5tYXhTaXplIC0gMTtcblxuICAgICAgICAvLyBBZGp1c3QgaWYgbGltaXQgaXMgZXhjZWVkZWRcbiAgICAgICAgaWYgKGVuZFBhZ2UgPiB0b3RhbFBhZ2VzKSB7XG4gICAgICAgICAgZW5kUGFnZSA9IHRvdGFsUGFnZXM7XG4gICAgICAgICAgc3RhcnRQYWdlID0gZW5kUGFnZSAtIHRoaXMubWF4U2l6ZSArIDE7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIFZpc2libGUgcGFnZXMgYXJlIHBhZ2luYXRlZCB3aXRoIG1heFNpemVcbiAgICAgICAgc3RhcnRQYWdlID1cbiAgICAgICAgICAoTWF0aC5jZWlsKGN1cnJlbnRQYWdlIC8gdGhpcy5tYXhTaXplKSAtIDEpICogdGhpcy5tYXhTaXplICsgMTtcblxuICAgICAgICAvLyBBZGp1c3QgbGFzdCBwYWdlIGlmIGxpbWl0IGlzIGV4Y2VlZGVkXG4gICAgICAgIGVuZFBhZ2UgPSBNYXRoLm1pbihzdGFydFBhZ2UgKyB0aGlzLm1heFNpemUgLSAxLCB0b3RhbFBhZ2VzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBBZGQgcGFnZSBudW1iZXIgbGlua3NcbiAgICBmb3IgKGxldCBudW0gPSBzdGFydFBhZ2U7IG51bSA8PSBlbmRQYWdlOyBudW0rKykge1xuICAgICAgY29uc3QgcGFnZSA9IHRoaXMubWFrZVBhZ2UobnVtLCBudW0udG9TdHJpbmcoKSwgbnVtID09PSBjdXJyZW50UGFnZSk7XG4gICAgICBwYWdlcy5wdXNoKHBhZ2UpO1xuICAgIH1cblxuICAgIC8vIEFkZCBsaW5rcyB0byBtb3ZlIGJldHdlZW4gcGFnZSBzZXRzXG4gICAgaWYgKGlzTWF4U2l6ZWQgJiYgIXRoaXMucm90YXRlKSB7XG4gICAgICBpZiAoc3RhcnRQYWdlID4gMSkge1xuICAgICAgICBjb25zdCBwcmV2aW91c1BhZ2VTZXQgPSB0aGlzLm1ha2VQYWdlKHN0YXJ0UGFnZSAtIDEsICcuLi4nLCBmYWxzZSk7XG4gICAgICAgIHBhZ2VzLnVuc2hpZnQocHJldmlvdXNQYWdlU2V0KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVuZFBhZ2UgPCB0b3RhbFBhZ2VzKSB7XG4gICAgICAgIGNvbnN0IG5leHRQYWdlU2V0ID0gdGhpcy5tYWtlUGFnZShlbmRQYWdlICsgMSwgJy4uLicsIGZhbHNlKTtcbiAgICAgICAgcGFnZXMucHVzaChuZXh0UGFnZVNldCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhZ2VzO1xuICB9XG5cbiAgLy8gYmFzZSBjbGFzc1xuICBwcm90ZWN0ZWQgY2FsY3VsYXRlVG90YWxQYWdlcygpOiBudW1iZXIge1xuICAgIGNvbnN0IHRvdGFsUGFnZXMgPVxuICAgICAgdGhpcy5pdGVtc1BlclBhZ2UgPCAxXG4gICAgICAgID8gMVxuICAgICAgICA6IE1hdGguY2VpbCh0aGlzLnRvdGFsSXRlbXMgLyB0aGlzLml0ZW1zUGVyUGFnZSk7XG5cbiAgICByZXR1cm4gTWF0aC5tYXgodG90YWxQYWdlcyB8fCAwLCAxKTtcbiAgfVxufVxuIl19