pagination.component.js 33 KB

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