jqPaginator.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313
  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. var $html = $(html);
  95. if (!$.isNumeric(pageData)) {
  96. $html.addClass('disabled');
  97. }
  98. return $html.attr({
  99. 'jp-role': type,
  100. 'jp-data': pageData
  101. }).jqPaginatorHTML();
  102. };
  103. self.setStatus = function () {
  104. var options = self.options;
  105. if (!self.isEnable('first') || options.currentPage === 1) {
  106. $('[jp-role=first]', self.$container).addClass(options.disableClass);
  107. }
  108. if (!self.isEnable('prev') || options.currentPage === 1) {
  109. $('[jp-role=prev]', self.$container).addClass(options.disableClass);
  110. }
  111. if (!self.isEnable('next') || options.currentPage >= options.totalPages) {
  112. $('[jp-role=next]', self.$container).addClass(options.disableClass);
  113. }
  114. if (!self.isEnable('last') || options.currentPage >= options.totalPages) {
  115. $('[jp-role=last]', self.$container).addClass(options.disableClass);
  116. }
  117. $('[jp-role=page]', self.$container).removeClass(options.activeClass);
  118. $('[jp-role=page][jp-data=' + options.currentPage + ']', self.$container).addClass(options.activeClass);
  119. };
  120. self.getPages = function () {
  121. var pages = [],
  122. visiblePages = self.options.visiblePages,
  123. currentPage = self.options.currentPage,
  124. totalPages = self.options.totalPages;
  125. if (visiblePages > totalPages) {
  126. visiblePages = totalPages;
  127. }
  128. var half = Math.floor(visiblePages / 2);
  129. var start = currentPage - half + 1 - visiblePages % 2;
  130. var end = currentPage + half;
  131. if (start < 1) {
  132. start = 1;
  133. end = visiblePages;
  134. }
  135. if (end > totalPages) {
  136. end = totalPages;
  137. start = 1 + totalPages - visiblePages;
  138. }
  139. var itPage = start;
  140. while (itPage <= end) {
  141. pages.push(itPage);
  142. itPage++;
  143. }
  144. if (start > 4) {
  145. pages.unshift('...')
  146. }
  147. if (start == 4) {
  148. pages.unshift(3);
  149. }
  150. if (start >= 3 ) {
  151. pages.unshift(2)
  152. }
  153. if (start >= 2) {
  154. pages.unshift(1);
  155. }
  156. if (self.options.totalPages - end > 3) {
  157. pages.push('...');
  158. pages.push(self.options.totalPages - 1);
  159. pages.push(self.options.totalPages);
  160. }
  161. switch(self.options.totalPages - end) {
  162. case 3:
  163. pages.push(self.options.totalPages - 2);
  164. pages.push(self.options.totalPages - 1);
  165. pages.push(self.options.totalPages);
  166. break;
  167. case 2:
  168. pages.push(self.options.totalPages - 1);
  169. pages.push(self.options.totalPages);
  170. break;
  171. case 1:
  172. pages.push(self.options.totalPages);
  173. break;
  174. }
  175. return pages;
  176. };
  177. self.isNumber = function (value) {
  178. var type = typeof value;
  179. return type === 'number' || type === 'undefined';
  180. };
  181. self.isEnable = function (type) {
  182. return self.options[type] && typeof self.options[type] === 'string';
  183. };
  184. self.switchPage = function (pageIndex) {
  185. self.options.currentPage = pageIndex;
  186. self.render();
  187. };
  188. self.fireEvent = function (pageIndex, type) {
  189. return (typeof self.options.onPageChange !== 'function') || (self.options.onPageChange(pageIndex, type) !== false);
  190. };
  191. self.callMethod = function (method, options) {
  192. switch (method) {
  193. case 'option':
  194. self.options = $.extend({}, self.options, options);
  195. self.verify();
  196. self.render();
  197. break;
  198. case 'destroy':
  199. self.$container.empty();
  200. self.$container.removeData('jqPaginator');
  201. break;
  202. default :
  203. throw new Error('[jqPaginator] method "' + method + '" does not exist');
  204. }
  205. return self.$container;
  206. };
  207. self.bindEvents = function () {
  208. var opts = self.options;
  209. self.$container.off();
  210. self.$container.on('click', '[jp-role]', function () {
  211. var $el = $(this);
  212. if ($el.hasClass(opts.disableClass) || $el.hasClass(opts.activeClass)) {
  213. return;
  214. }
  215. var pageIndex = +$el.attr('jp-data');
  216. if (self.fireEvent(pageIndex, 'change')) {
  217. self.switchPage(pageIndex);
  218. }
  219. });
  220. };
  221. self.init();
  222. return self.$container;
  223. };
  224. $.jqPaginator.defaultOptions = {
  225. wrapper: '',
  226. first: '<li class="first"><a href="javascript:;">First</a></li>',
  227. prev: '<li class="prev"><a href="javascript:;">Previous</a></li>',
  228. next: '<li class="next"><a href="javascript:;">Next</a></li>',
  229. last: '<li class="last"><a href="javascript:;">Last</a></li>',
  230. page: '<li class="page"><a href="javascript:;">{{page}}</a></li>',
  231. totalPages: 0,
  232. totalCounts: 0,
  233. pageSize: 0,
  234. currentPage: 1,
  235. visiblePages: 7,
  236. disableClass: 'disabled',
  237. activeClass: 'active',
  238. onPageChange: null
  239. };
  240. $.fn.jqPaginator = function () {
  241. var self = this,
  242. args = Array.prototype.slice.call(arguments);
  243. if (typeof args[0] === 'string') {
  244. var $instance = $(self).data('jqPaginator');
  245. if (!$instance) {
  246. throw new Error('[jqPaginator] the element is not instantiated');
  247. } else {
  248. return $instance.callMethod(args[0], args[1]);
  249. }
  250. } else {
  251. return new $.jqPaginator(this, args[0]);
  252. }
  253. };
  254. })(jQuery);