paginated_list.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. app.views.PaginatedList = class PaginatedList extends app.View {
  2. static PER_PAGE = app.config.max_results;
  3. constructor(data) {
  4. super();
  5. this.data = data;
  6. this.constructor.events = this.constructor.events || {};
  7. if (this.constructor.events.click == null) {
  8. this.constructor.events.click = "onClick";
  9. }
  10. }
  11. renderPaginated() {
  12. this.page = 0;
  13. if (this.totalPages() > 1) {
  14. this.paginateNext();
  15. } else {
  16. this.html(this.renderAll());
  17. }
  18. }
  19. // render: (dataSlice) -> implemented by subclass
  20. renderAll() {
  21. return this.render(this.data);
  22. }
  23. renderPage(page) {
  24. return this.render(
  25. this.data.slice(
  26. (page - 1) * PaginatedList.PER_PAGE,
  27. page * PaginatedList.PER_PAGE,
  28. ),
  29. );
  30. }
  31. renderPageLink(count) {
  32. return this.tmpl("sidebarPageLink", count);
  33. }
  34. renderPrevLink(page) {
  35. return this.renderPageLink((page - 1) * PaginatedList.PER_PAGE);
  36. }
  37. renderNextLink(page) {
  38. return this.renderPageLink(
  39. this.data.length - page * PaginatedList.PER_PAGE,
  40. );
  41. }
  42. totalPages() {
  43. return Math.ceil(this.data.length / PaginatedList.PER_PAGE);
  44. }
  45. paginate(link) {
  46. $.lockScroll(link.nextSibling || link.previousSibling, () => {
  47. $.batchUpdate(this.el, () => {
  48. if (link.nextSibling) {
  49. this.paginatePrev(link);
  50. } else {
  51. this.paginateNext(link);
  52. }
  53. });
  54. });
  55. }
  56. paginateNext() {
  57. if (this.el.lastChild) {
  58. this.remove(this.el.lastChild);
  59. } // remove link
  60. if (this.page >= 2) {
  61. this.hideTopPage();
  62. } // keep previous page into view
  63. this.page++;
  64. this.append(this.renderPage(this.page));
  65. if (this.page < this.totalPages()) {
  66. this.append(this.renderNextLink(this.page));
  67. }
  68. }
  69. paginatePrev() {
  70. this.remove(this.el.firstChild); // remove link
  71. this.hideBottomPage();
  72. this.page--;
  73. this.prepend(this.renderPage(this.page - 1)); // previous page is offset by one
  74. if (this.page >= 3) {
  75. this.prepend(this.renderPrevLink(this.page - 1));
  76. }
  77. }
  78. paginateTo(object) {
  79. const index = this.data.indexOf(object);
  80. if (index >= PaginatedList.PER_PAGE) {
  81. for (
  82. let i = 0, end = Math.floor(index / PaginatedList.PER_PAGE);
  83. i < end;
  84. i++
  85. ) {
  86. this.paginateNext();
  87. }
  88. }
  89. }
  90. hideTopPage() {
  91. const n =
  92. this.page <= 2 ? PaginatedList.PER_PAGE : PaginatedList.PER_PAGE + 1; // remove link
  93. for (let i = 0, end = n; i < end; i++) {
  94. this.remove(this.el.firstChild);
  95. }
  96. this.prepend(this.renderPrevLink(this.page));
  97. }
  98. hideBottomPage() {
  99. const n =
  100. this.page === this.totalPages()
  101. ? this.data.length % PaginatedList.PER_PAGE || PaginatedList.PER_PAGE
  102. : PaginatedList.PER_PAGE + 1; // remove link
  103. for (let i = 0, end = n; i < end; i++) {
  104. this.remove(this.el.lastChild);
  105. }
  106. this.append(this.renderNextLink(this.page - 1));
  107. }
  108. onClick(event) {
  109. const target = $.eventTarget(event);
  110. if (target.tagName === "SPAN") {
  111. // link
  112. $.stopEvent(event);
  113. this.paginate(target);
  114. }
  115. }
  116. };