jqPaginator.js 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. (function ($) {
  2. 'use strict';
  3. $.jqPaginator = function (el, options) {
  4. if(!(this instanceof $.jqPaginator)){
  5. return new $.jqPaginator(el, options);
  6. }
  7. var self = this;
  8. self.$container = $(el);
  9. self.$container.data('jqPaginator', self);
  10. self.init = function () {
  11. if (options.first || options.prev || options.next || options.last || options.page) {
  12. options = $.extend({}, {
  13. first: '',
  14. prev: '',
  15. next: '',
  16. last: '',
  17. page: ''
  18. }, options);
  19. }
  20. self.options = $.extend({}, $.jqPaginator.defaultOptions, options);
  21. self.verify();
  22. self.extendJquery();
  23. self.render();
  24. self.fireEvent(this.options.currentPage, 'init');
  25. };
  26. self.verify = function () {
  27. var opts = self.options;
  28. if (!self.isNumber(opts.totalPages)) {
  29. throw new Error('[jqPaginator] type error: totalPages');
  30. }
  31. if (!self.isNumber(opts.totalCounts)) {
  32. throw new Error('[jqPaginator] type error: totalCounts');
  33. }
  34. if (!self.isNumber(opts.pageSize)) {
  35. throw new Error('[jqPaginator] type error: pageSize');
  36. }
  37. if (!self.isNumber(opts.currentPage)) {
  38. throw new Error('[jqPaginator] type error: currentPage');
  39. }
  40. if (!self.isNumber(opts.visiblePages)) {
  41. throw new Error('[jqPaginator] type error: visiblePages');
  42. }
  43. if (!opts.totalPages && !opts.totalCounts) {
  44. throw new Error('[jqPaginator] totalCounts or totalPages is required');
  45. }
  46. if (!opts.totalPages && !opts.totalCounts) {
  47. throw new Error('[jqPaginator] totalCounts or totalPages is required');
  48. }
  49. if (!opts.totalPages && opts.totalCounts && !opts.pageSize) {
  50. throw new Error('[jqPaginator] pageSize is required');
  51. }
  52. if (opts.totalCounts && opts.pageSize) {
  53. opts.totalPages = Math.ceil(opts.totalCounts / opts.pageSize);
  54. }
  55. if (opts.currentPage < 1 || opts.currentPage > opts.totalPages) {
  56. throw new Error('[jqPaginator] currentPage is incorrect');
  57. }
  58. if (opts.totalPages < 1) {
  59. throw new Error('[jqPaginator] totalPages cannot be less currentPage');
  60. }
  61. };
  62. self.extendJquery = function () {
  63. $.fn.jqPaginatorHTML = function (s) {
  64. return s ? this.before(s).remove() : $('<p>').append(this.eq(0).clone()).html();
  65. };
  66. };
  67. self.render = function () {
  68. self.renderHtml();
  69. self.setStatus();
  70. self.bindEvents();
  71. };
  72. self.renderHtml = function () {
  73. var html = [];
  74. var pages = self.getPages();
  75. for (var i = 0, j = pages.length; i < j; i++) {
  76. html.push(self.buildItem('page', pages[i]));
  77. }
  78. self.isEnable('prev') && html.unshift(self.buildItem('prev', self.options.currentPage - 1));
  79. self.isEnable('first') && html.unshift(self.buildItem('first', 1));
  80. self.isEnable('statistics') && html.unshift(self.buildItem('statistics'));
  81. self.isEnable('next') && html.push(self.buildItem('next', self.options.currentPage + 1));
  82. self.isEnable('last') && html.push(self.buildItem('last', self.options.totalPages));
  83. if (self.options.wrapper) {
  84. self.$container.html($(self.options.wrapper).html(html.join('')).jqPaginatorHTML());
  85. } else {
  86. self.$container.html(html.join(''));
  87. }
  88. };
  89. self.buildItem = function (type, pageData) {
  90. var html = self.options[type]
  91. .replace(/{{page}}/g, pageData)
  92. .replace(/{{totalPages}}/g, self.options.totalPages)
  93. .replace(/{{totalCounts}}/g, self.options.totalCounts);
  94. return $(html).attr({
  95. 'jp-role': type,
  96. 'jp-data': pageData
  97. }).jqPaginatorHTML();
  98. };
  99. self.setStatus = function () {
  100. var options = self.options;
  101. if (!self.isEnable('first') || options.currentPage === 1) {
  102. $('[jp-role=first]', self.$container).addClass(options.disableClass);
  103. }
  104. if (!self.isEnable('prev') || options.currentPage === 1) {
  105. $('[jp-role=prev]', self.$container).addClass(options.disableClass);
  106. }
  107. if (!self.isEnable('next') || options.currentPage >= options.totalPages) {
  108. $('[jp-role=next]', self.$container).addClass(options.disableClass);
  109. }
  110. if (!self.isEnable('last') || options.currentPage >= options.totalPages) {
  111. $('[jp-role=last]', self.$container).addClass(options.disableClass);
  112. }
  113. $('[jp-role=page]', self.$container).removeClass(options.activeClass);
  114. $('[jp-role=page][jp-data=' + options.currentPage + ']', self.$container).addClass(options.activeClass);
  115. };
  116. self.getPages = function () {
  117. var pages = [],
  118. visiblePages = self.options.visiblePages,
  119. currentPage = self.options.currentPage,
  120. totalPages = self.options.totalPages;
  121. if (visiblePages > totalPages) {
  122. visiblePages = totalPages;
  123. }
  124. var half = Math.floor(visiblePages / 2);
  125. var start = currentPage - half + 1 - visiblePages % 2;
  126. var end = currentPage + half;
  127. if (start < 1) {
  128. start = 1;
  129. end = visiblePages;
  130. }
  131. if (end > totalPages) {
  132. end = totalPages;
  133. start = 1 + totalPages - visiblePages;
  134. }
  135. var itPage = start;
  136. while (itPage <= end) {
  137. pages.push(itPage);
  138. itPage++;
  139. }
  140. return pages;
  141. };
  142. self.isNumber = function (value) {
  143. var type = typeof value;
  144. return type === 'number' || type === 'undefined';
  145. };
  146. self.isEnable = function (type) {
  147. return self.options[type] && typeof self.options[type] === 'string';
  148. };
  149. self.switchPage = function (pageIndex) {
  150. self.options.currentPage = pageIndex;
  151. self.render();
  152. };
  153. self.fireEvent = function (pageIndex, type) {
  154. return (typeof self.options.onPageChange !== 'function') || (self.options.onPageChange(pageIndex, type) !== false);
  155. };
  156. self.callMethod = function (method, options) {
  157. switch (method) {
  158. case 'option':
  159. self.options = $.extend({}, self.options, options);
  160. self.verify();
  161. self.render();
  162. break;
  163. case 'destroy':
  164. self.$container.empty();
  165. self.$container.removeData('jqPaginator');
  166. break;
  167. default :
  168. throw new Error('[jqPaginator] method "' + method + '" does not exist');
  169. }
  170. return self.$container;
  171. };
  172. self.bindEvents = function () {
  173. var opts = self.options;
  174. self.$container.off();
  175. self.$container.on('click', '[jp-role]', function () {
  176. var $el = $(this);
  177. if ($el.hasClass(opts.disableClass) || $el.hasClass(opts.activeClass)) {
  178. return;
  179. }
  180. var pageIndex = +$el.attr('jp-data');
  181. if (self.fireEvent(pageIndex, 'change')) {
  182. self.switchPage(pageIndex);
  183. }
  184. });
  185. };
  186. self.init();
  187. return self.$container;
  188. };
  189. $.jqPaginator.defaultOptions = {
  190. wrapper: '',
  191. first: '<li class="first"><a href="javascript:;">First</a></li>',
  192. prev: '<li class="prev"><a href="javascript:;">Previous</a></li>',
  193. next: '<li class="next"><a href="javascript:;">Next</a></li>',
  194. last: '<li class="last"><a href="javascript:;">Last</a></li>',
  195. page: '<li class="page"><a href="javascript:;">{{page}}</a></li>',
  196. totalPages: 0,
  197. totalCounts: 0,
  198. pageSize: 0,
  199. currentPage: 1,
  200. visiblePages: 7,
  201. disableClass: 'disabled',
  202. activeClass: 'active',
  203. onPageChange: null
  204. };
  205. $.fn.jqPaginator = function () {
  206. var self = this,
  207. args = Array.prototype.slice.call(arguments);
  208. if (typeof args[0] === 'string') {
  209. var $instance = $(self).data('jqPaginator');
  210. if (!$instance) {
  211. throw new Error('[jqPaginator] the element is not instantiated');
  212. } else {
  213. return $instance.callMethod(args[0], args[1]);
  214. }
  215. } else {
  216. return new $.jqPaginator(this, args[0]);
  217. }
  218. };
  219. })(jQuery);