crossPage.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. !function ($) {
  2. var pageEvent = {
  3. pageClicked: 'pageClicked',
  4. jumpClicked: 'jumpClicked',
  5. pageSizeChanged: 'pageSizeChanged'
  6. }
  7. var Page = function (element, options) {
  8. var defaultOption = {
  9. total: 0,
  10. pageSize: 10,
  11. pageBtnCount: 11,
  12. showFirstLastBtn: true,
  13. firstBtnText: null,
  14. lastBtnText: null,
  15. layouts : 'left',
  16. prevBtnText: "\u4e0a\u4e00\u9875",
  17. nextBtnText: "\u4e0b\u4e00\u9875",
  18. loadFirstPage: true,
  19. remote: {
  20. url: null,
  21. params: null,
  22. callback: null,
  23. success: null,
  24. beforeSend: null,
  25. complete: null,
  26. pageIndexName: 'pageIndex',
  27. pageSizeName: 'pageSize',
  28. totalName: 'total'
  29. },
  30. showInfo: false,
  31. showStat : true,
  32. infoFormat: '{start} ~ {end} of {total} entires',
  33. showJump: true,
  34. jumpBtnText: '\u786e\u5b9a',
  35. showPageSizes: false,
  36. pageSizeItems: null,
  37. debug: false,
  38. databuffer : false,
  39. pageShow: null
  40. }
  41. this.$element = $(element);
  42. this.$page = $('<ul class="c-pagination-page"></ul>');
  43. this.$size = $('<div class="c-pagination-size"></div>');
  44. this.$jump = $('<div class="c-pagination-jump"></div>');
  45. this.$info = $('<div class="c-pagination-info"></div>');
  46. this.$stat = $('<ul class="c-pagination-stat"></ul>');
  47. this.options = $.extend(true, {}, defaultOption, $.fn.crossPage.defaults, options);
  48. this.total = this.options.total || 0;
  49. this.options.pageSizeItems = this.options.pageSizeItems || [5, 10, 15, 20],
  50. this.currentPageIndex = 0;
  51. this.currentPageSize = this.options.pageSize;
  52. this.pageCount = getPageCount(this.total, this.currentPageSize);
  53. this.clicked = [];
  54. if (this.options.remote.success == null) {
  55. this.options.remote.success = this.options.remote.callback;
  56. }
  57. var init = function (obj) {
  58. var that = obj;
  59. //init size module
  60. var html = $('<select data-page-btn="size"></select>');
  61. for (var i = 0; i < that.options.pageSizeItems.length; i++) {
  62. html.append('<option value="' + that.options.pageSizeItems[i] + '">' + that.options.pageSizeItems[i] + '</option>')
  63. }
  64. html.val(that.currentPageSize);
  65. that.$size.append(html);
  66. //init jump module
  67. var jumpHtml = '<div class="c-pagination-group"><input type="text"><button data-page-btn="jump" type="button">' + that.options.jumpBtnText + '</button></div>';
  68. that.$jump.append(jumpHtml);
  69. that.$jump.find('input').change(function () {
  70. if (!checkIsPageNumber(this.value, that.pageCount))
  71. this.value = null;
  72. });
  73. that.$element.append(that.$page.hide());
  74. that.$element.append(that.$size.hide());
  75. that.$element.append(that.$stat.hide());
  76. that.$element.append(that.$jump.hide());
  77. that.$element.append(that.$info.hide());
  78. that._remoteOrRedner(0);
  79. that.$element
  80. .on('click', { page: that }, function (event) { eventHandler(event); })
  81. .on('change', { page: that }, function (event) { eventHandler(event); });
  82. switch(that.options.layouts)
  83. {
  84. case 'left':
  85. that.$element.addClass('fl');
  86. break;
  87. case 'center':
  88. that.$element.addClass('fl').css('padding-left',that.$element.outerWidth()/2-100);
  89. break;
  90. case 'right':
  91. that.$element.addClass('fr');
  92. break;
  93. }
  94. }
  95. var eventHandler = function (event) {
  96. var that = event.data.page;
  97. var $target = $(event.target);
  98. if (event.type === 'click' && $target.data('pageIndex') !== undefined && !$target.parent().hasClass('active')) {
  99. var pageIndex = $(event.target).data("pageIndex");
  100. that.$element.trigger(pageEvent.pageClicked, pageIndex);
  101. that.debug('event[ pageClicked ] : pageIndex = ' + (pageIndex));
  102. that._remoteOrRedner(pageIndex);
  103. }
  104. else if (event.type === 'click' && $target.data('pageBtn') === 'jump') {
  105. var pageIndexStr = that.$jump.find('input').val();
  106. if (checkIsPageNumber(pageIndexStr, that.pageCount)) {
  107. var pageIndex = pageIndexStr - 1;
  108. that.$element.trigger(pageEvent.jumpClicked, pageIndex);
  109. that.debug('event[ jumpClicked ] : pageIndex = ' + (pageIndex));
  110. that._remoteOrRedner(pageIndex);
  111. }
  112. that.$jump.find('input').val(null);
  113. }
  114. else if (event.type === 'change' && $target.data('pageBtn') === 'size') {
  115. var pageSize = that.$size.find('select').val();
  116. that.currentPageSize = pageSize;
  117. that.$element.trigger(pageEvent.pageSizeChanged, pageSize);
  118. that.debug('event[ pageSizeChanged ] : pageSize = ' + pageSize);
  119. that._remoteOrRedner(0);
  120. }
  121. }
  122. if (typeof this.options.total === 'undefined' && this.options.remote.url === null) {
  123. console && console.error("[init error] : the options must have the parameter of 'remote.url' or 'total'.");
  124. }
  125. else if (typeof this.options.total === 'undefined' && !this.options.loadFirstPage) {
  126. console && console.error("[init error] : if you don't remote the first page. you must set the options or 'total'.");
  127. }
  128. else {
  129. init(this);
  130. }
  131. }
  132. Page.prototype = {
  133. _remoteOrRedner: function (pageIndex) {
  134. var that=this,b=true;
  135. if(this.options.databuffer){
  136. $(this.clicked).each(function(i,n){
  137. if(pageIndex==n){
  138. that.renderPagination(pageIndex);
  139. if (typeof that.options.pageShow === 'function') that.options.pageShow(pageIndex);
  140. b=false;
  141. }
  142. });
  143. }
  144. if(b){
  145. if (this.options.remote.url != null && (this.options.loadFirstPage || pageIndex > 0)){
  146. this.remote(pageIndex);
  147. }
  148. else{
  149. this.renderPagination(pageIndex);
  150. if (typeof that.options.pageShow === 'function') that.options.pageShow(pageIndex);
  151. }
  152. }
  153. },
  154. remote: function (pageIndex, params) {
  155. var that = this;
  156. if (isNaN(parseInt(pageIndex)) || typeof pageIndex === "object") {
  157. params = pageIndex;
  158. pageIndex = null;
  159. }
  160. if (isNaN(parseInt(pageIndex))) {
  161. pageIndex = that.currentPageIndex;
  162. }
  163. var pageParams = {};
  164. pageParams[this.options.remote.pageIndexName] = pageIndex;
  165. pageParams[this.options.remote.pageSizeName] = this.currentPageSize;
  166. this.options.remote.params = deserializeParams(this.options.remote.params);
  167. if (params) {
  168. params = deserializeParams(params);
  169. this.options.remote.params = $.extend({}, this.options.remote.params, params);
  170. }
  171. var requestParams = $.extend({}, this.options.remote.params, pageParams);
  172. $.ajax({
  173. url: this.options.remote.url,
  174. dataType: 'json',
  175. data: requestParams,
  176. contentType: 'application/Json',
  177. async: false,
  178. beforeSend: function (XMLHttpRequest) {
  179. if (typeof that.options.remote.beforeSend === 'function') that.options.remote.beforeSend(XMLHttpRequest);
  180. },
  181. complete: function (XMLHttpRequest, textStatu) {
  182. if (typeof that.options.remote.complete === 'function') that.options.remote.complete(XMLHttpRequest, textStatu);
  183. },
  184. success: function (result) {
  185. that.debug("ajax request : params = " + JSON.stringify(requestParams), result);
  186. var total = GetCustomTotalName(result, that.options.remote.totalName);
  187. if (total == null || total == undefined) {
  188. console && console.error("the response of totalName : '" + that.options.remote.totalName + "' not found");
  189. } else {
  190. that._updateTotal(total);
  191. if (typeof that.options.remote.success === 'function') that.options.remote.success(result, pageIndex);
  192. that.renderPagination(pageIndex);
  193. }
  194. that.clicked.push(pageIndex);
  195. }
  196. })
  197. },
  198. renderPagination: function (pageIndex) {
  199. this.currentPageIndex = pageIndex;
  200. var pages = renderPages(this.currentPageIndex, this.currentPageSize, this.total, this.options.pageBtnCount,
  201. this.options.firstBtnText, this.options.lastBtnText, this.options.prevBtnText, this.options.nextBtnText, this.options.showFirstLastBtn);
  202. this.$page.empty().append(pages);
  203. this.$info.text(renderInfo(this.currentPageIndex, this.currentPageSize, this.total, this.options.infoFormat));
  204. if(this.options.showStat){
  205. this.$stat.show();
  206. }
  207. if (this.pageCount > 1) {
  208. this.$page.show();
  209. if (this.options.showPageSizes) this.$size.show();
  210. if (this.options.showJump) this.$jump.show();
  211. if (this.options.showInfo) this.$info.show();
  212. }
  213. else if (this.pageCount == 1) {
  214. if (this.options.showInfo) this.$info.show();
  215. }
  216. else {
  217. this.$page.hide();
  218. this.$size.hide();
  219. this.$jump.hide();
  220. this.$info.hide();
  221. }
  222. },
  223. _updateTotal: function (total) {
  224. this.total = total;
  225. this.pageCount = getPageCount(total, this.currentPageSize);
  226. this.$stat.html('<li><span>\u5171<em>'+this.pageCount+'</em>\u9875</span></li><li><li><span>\u8df3\u8f6c\u81f3</span></li>');
  227. },
  228. destroy: function () {
  229. this.$element.unbind().data("page", null).empty();
  230. },
  231. debug: function (message, data) {
  232. if (this.options.debug && console) {
  233. message && console.info(message);
  234. data && console.info(data);
  235. }
  236. }
  237. }
  238. var renderInfo = function (currentPageIndex, currentPageSize, total, infoFormat) {
  239. var startNum = (currentPageIndex * currentPageSize) + 1;
  240. var endNum = (currentPageIndex + 1) * currentPageSize;
  241. endNum = endNum >= total ? total : endNum;
  242. return infoFormat.replace('{start}', startNum).replace('{end}', endNum).replace('{total}', total);
  243. }
  244. var renderPages = function (pageIndex, pageSize, total, pageBtnCount, firstBtnText, lastBtnText, prevBtnText, nextBtnText, showFirstLastBtn) {
  245. pageIndex = pageIndex == undefined ? 1 : parseInt(pageIndex) + 1; //set pageIndex from 1, convenient calculation page
  246. var pageCount = getPageCount(total, pageSize);
  247. var html = [];
  248. if (pageCount <= pageBtnCount) {
  249. html = renderPage(1, pageCount, pageIndex);
  250. }
  251. else {
  252. var firstPage = renderPerPage(firstBtnText || 1, 0);
  253. var lastPage = renderPerPage(lastBtnText || pageCount, pageCount - 1);
  254. var prevPage = renderPerPage(prevBtnText, pageIndex - 2);
  255. var nextPage = renderPerPage(nextBtnText, pageIndex);
  256. //button count of both sides
  257. var symmetryBtnCount = (pageBtnCount - 1 - 4) / 2;
  258. if (!showFirstLastBtn)
  259. symmetryBtnCount = symmetryBtnCount + 1;
  260. var frontBtnNum = (pageBtnCount + 1) / 2;
  261. var behindBtnNum = pageCount - ((pageBtnCount + 1) / 2);
  262. symmetryBtnCount = symmetryBtnCount.toString().indexOf('.') == -1 ? symmetryBtnCount : symmetryBtnCount + 0.5;
  263. frontBtnNum = frontBtnNum.toString().indexOf('.') == -1 ? frontBtnNum : frontBtnNum + 0.5;
  264. behindBtnNum = behindBtnNum.toString().indexOf('.') == -1 ? behindBtnNum : behindBtnNum + 0.5;
  265. if (pageIndex <= frontBtnNum) {
  266. if (showFirstLastBtn) {
  267. html = renderPage(1, pageBtnCount - 2, pageIndex);
  268. html.push(nextPage);
  269. html.push(lastPage);
  270. } else {
  271. html = renderPagenderPage(1, pageBtnCount - 1, pageIndex);
  272. html.push(nextPage);
  273. }
  274. }
  275. else if (pageIndex > behindBtnNum) {
  276. if (showFirstLastBtn) {
  277. html = renderPage(pageCount - pageBtnCount + 3, pageBtnCount - 2, pageIndex);
  278. html.unshift(prevPage);
  279. html.unshift(firstPage);
  280. } else {
  281. html = renderPage(pageCount - pageBtnCount + 2, pageBtnCount - 1, pageIndex);
  282. html.unshift(prevPage);
  283. }
  284. }
  285. else {
  286. if (showFirstLastBtn) {
  287. html = renderPage(pageIndex - symmetryBtnCount, pageBtnCount - 4, pageIndex);
  288. html.unshift(prevPage);
  289. html.push(nextPage);
  290. html.unshift(firstPage);
  291. html.push(lastPage);
  292. } else {
  293. html = renderPage(pageIndex - symmetryBtnCount, pageBtnCount - 2, pageIndex);
  294. html.unshift(prevPage);
  295. html.push(nextPage);
  296. }
  297. }
  298. }
  299. return html;
  300. }
  301. var renderPage = function (beginPageNum, count, currentPage) {
  302. var html = [];
  303. for (var i = 0; i < count; i++) {
  304. var page = renderPerPage(beginPageNum, beginPageNum - 1);
  305. if (beginPageNum == currentPage)
  306. page.addClass("active");
  307. html.push(page);
  308. beginPageNum++;
  309. }
  310. return html;
  311. }
  312. var renderPerPage = function (text, value) {
  313. return $("<li><a data-page-index='" + value + "'>" + text + "</a></li>");
  314. }
  315. var getPageCount = function (total, pageSize) {
  316. var pageCount = 0;
  317. var total = parseInt(total);
  318. var i = total / pageSize;
  319. pageCount = i.toString().indexOf('.') != -1 ? parseInt(i.toString().split('.')[0]) + 1 : i;
  320. return pageCount;
  321. }
  322. var deserializeParams = function (params) {
  323. var newParams = {};
  324. if (typeof params === 'string') {
  325. var arr = params.split('&');
  326. for (var i = 0; i < arr.length; i++) {
  327. var a = arr[i].split('=');
  328. newParams[a[0]] = decodeURIComponent(a[1]);
  329. }
  330. }
  331. else if (params instanceof Array) {
  332. for (var i = 0; i < params.length; i++) {
  333. newParams[params[i].name] = decodeURIComponent(params[i].value);
  334. }
  335. }
  336. else if (typeof params === 'object') {
  337. newParams = params;
  338. }
  339. return newParams;
  340. }
  341. var checkIsPageNumber = function (pageIndex, maxPage) {
  342. var reg = /^\+?[1-9][0-9]*$/;
  343. return reg.test(pageIndex) && parseInt(pageIndex) <= parseInt(maxPage);
  344. }
  345. var GetCustomTotalName = function (object, totalName) {
  346. var arr = totalName.split('.');
  347. var temp = object;
  348. var total = null;
  349. for (var i = 0; i < arr.length; i++) {
  350. temp = mapObjectName(temp, arr[i]);
  351. if (!isNaN(parseInt(temp))) {
  352. total = temp;
  353. break;
  354. }
  355. if (temp == null) {
  356. break;
  357. }
  358. }
  359. return total;
  360. }
  361. var mapObjectName = function (data, mapName) {
  362. for (var i in data) {
  363. if (i == mapName) {
  364. return data[i];
  365. }
  366. }
  367. return null;
  368. }
  369. $.fn.crossPage = function (option) {
  370. var args = arguments;
  371. return this.each(function () {
  372. var $this = $(this);
  373. var data = $this.data('page');
  374. if (!data && (typeof option === 'object' || typeof option === 'undefined')) {
  375. var options = typeof option == 'object' && option;
  376. var data_api_options = $this.data();
  377. options = $.extend(options, data_api_options);
  378. $this.data('page', (data = new Page(this, options)));
  379. }
  380. else if (data && typeof option === 'string') {
  381. data[option].apply(data, Array.prototype.slice.call(args, 1));
  382. }
  383. else if (!data) {
  384. console && console.error("jQuery Pagination Plugin is uninitialized.");
  385. }
  386. });
  387. }
  388. }(window.jQuery)