laypage.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /**
  2. @Name : layui.laypage 分页组件
  3. @Author:贤心
  4. @License:MIT
  5. */
  6. layui.define(function(exports){
  7. "use strict";
  8. var doc = document
  9. ,id = 'getElementById'
  10. ,tag = 'getElementsByTagName'
  11. //字符常量
  12. ,MOD_NAME = 'laypage', DISABLED = 'layui-disabled'
  13. //构造器
  14. ,Class = function(options){
  15. var that = this;
  16. that.config = options || {};
  17. that.config.index = ++laypage.index;
  18. that.render(true);
  19. };
  20. //判断传入的容器类型
  21. Class.prototype.type = function(){
  22. var config = this.config;
  23. if(typeof config.elem === 'object'){
  24. return config.elem.length === undefined ? 2 : 3;
  25. }
  26. };
  27. //分页视图
  28. Class.prototype.view = function(){
  29. var that = this
  30. ,config = that.config
  31. ,groups = config.groups = 'groups' in config ? (config.groups|0) : 5; //连续页码个数
  32. //排版
  33. config.layout = typeof config.layout === 'object'
  34. ? config.layout
  35. : ['prev', 'page', 'next'];
  36. config.count = config.count|0; //数据总数
  37. config.curr = (config.curr|0) || 1; //当前页
  38. //每页条数的选择项
  39. config.limits = typeof config.limits === 'object'
  40. ? config.limits
  41. : [10, 20, 30, 40, 50];
  42. config.limit = (config.limit|0) || 10; //默认条数
  43. //总页数
  44. config.pages = Math.ceil(config.count/config.limit) || 1;
  45. //当前页不能超过总页数
  46. if(config.curr > config.pages){
  47. config.curr = config.pages;
  48. }
  49. //连续分页个数不能低于0且不能大于总页数
  50. if(groups < 0){
  51. groups = 1;
  52. } else if (groups > config.pages){
  53. groups = config.pages;
  54. }
  55. config.prev = 'prev' in config ? config.prev : '&#x4E0A;&#x4E00;&#x9875;'; //上一页文本
  56. config.next = 'next' in config ? config.next : '&#x4E0B;&#x4E00;&#x9875;'; //下一页文本
  57. //计算当前组
  58. var index = config.pages > groups
  59. ? Math.ceil( (config.curr + (groups > 1 ? 1 : 0)) / (groups > 0 ? groups : 1) )
  60. : 1
  61. //视图片段
  62. ,views = {
  63. //上一页
  64. prev: function(){
  65. return config.prev
  66. ? '<a href="javascript:;" class="layui-laypage-prev'+ (config.curr == 1 ? (' ' + DISABLED) : '') +'" data-page="'+ (config.curr - 1) +'">'+ config.prev +'</a>'
  67. : '';
  68. }()
  69. //页码
  70. ,page: function(){
  71. var pager = [];
  72. //数据量为0时,不输出页码
  73. if(config.count < 1){
  74. return '';
  75. }
  76. //首页
  77. if(index > 1 && config.first !== false && groups !== 0){
  78. pager.push('<a href="javascript:;" class="layui-laypage-first" data-page="1" title="&#x9996;&#x9875;">'+ (config.first || 1) +'</a>');
  79. }
  80. //计算当前页码组的起始页
  81. var halve = Math.floor((groups-1)/2) //页码数等分
  82. ,start = index > 1 ? config.curr - halve : 1
  83. ,end = index > 1 ? (function(){
  84. var max = config.curr + (groups - halve - 1);
  85. return max > config.pages ? config.pages : max;
  86. }()) : groups;
  87. //防止最后一组出现“不规定”的连续页码数
  88. if(end - start < groups - 1){
  89. start = end - groups + 1;
  90. }
  91. //输出左分割符
  92. if(config.first !== false && start > 2){
  93. pager.push('<span class="layui-laypage-spr">&#x2026;</span>')
  94. }
  95. //输出连续页码
  96. for(; start <= end; start++){
  97. if(start === config.curr){
  98. //当前页
  99. pager.push('<span class="layui-laypage-curr"><em class="layui-laypage-em" '+ (/^#/.test(config.theme) ? 'style="background-color:'+ config.theme +';"' : '') +'></em><em>'+ start +'</em></span>');
  100. } else {
  101. pager.push('<a href="javascript:;" data-page="'+ start +'">'+ start +'</a>');
  102. }
  103. }
  104. //输出输出右分隔符 & 末页
  105. if(config.pages > groups && config.pages > end && config.last !== false){
  106. if(end + 1 < config.pages){
  107. pager.push('<span class="layui-laypage-spr">&#x2026;</span>');
  108. }
  109. if(groups !== 0){
  110. pager.push('<a href="javascript:;" class="layui-laypage-last" title="&#x5C3E;&#x9875;" data-page="'+ config.pages +'">'+ (config.last || config.pages) +'</a>');
  111. }
  112. }
  113. return pager.join('');
  114. }()
  115. //下一页
  116. ,next: function(){
  117. return config.next
  118. ? '<a href="javascript:;" class="layui-laypage-next'+ (config.curr == config.pages ? (' ' + DISABLED) : '') +'" data-page="'+ (config.curr + 1) +'">'+ config.next +'</a>'
  119. : '';
  120. }()
  121. //数据总数
  122. ,count: '<span class="layui-laypage-count">共 '+ config.count +' 条</span>'
  123. //每页条数
  124. ,limit: function(){
  125. var options = ['<span class="layui-laypage-limits"><select lay-ignore>'];
  126. layui.each(config.limits, function(index, item){
  127. options.push(
  128. '<option value="'+ item +'"'
  129. +(item === config.limit ? 'selected' : '')
  130. +'>'+ item +' 条/页</option>'
  131. );
  132. });
  133. return options.join('') +'</select></span>';
  134. }()
  135. //刷新当前页
  136. ,refresh: ['<a href="javascript:;" data-page="'+ config.curr +'" class="layui-laypage-refresh">'
  137. ,'<i class="layui-icon layui-icon-refresh"></i>'
  138. ,'</a>'].join('')
  139. //跳页区域
  140. ,skip: function(){
  141. return ['<span class="layui-laypage-skip">&#x5230;&#x7B2C;'
  142. ,'<input type="text" min="1" value="'+ config.curr +'" class="layui-input">'
  143. ,'&#x9875;<button type="button" class="layui-laypage-btn">&#x786e;&#x5b9a;</button>'
  144. ,'</span>'].join('');
  145. }()
  146. };
  147. return ['<div class="layui-box layui-laypage layui-laypage-'+ (config.theme ? (
  148. /^#/.test(config.theme) ? 'molv' : config.theme
  149. ) : 'default') +'" id="layui-laypage-'+ config.index +'">'
  150. ,function(){
  151. var plate = [];
  152. layui.each(config.layout, function(index, item){
  153. if(views[item]){
  154. plate.push(views[item])
  155. }
  156. });
  157. return plate.join('');
  158. }()
  159. ,'</div>'].join('');
  160. };
  161. //跳页的回调
  162. Class.prototype.jump = function(elem, isskip){
  163. if(!elem) return;
  164. var that = this
  165. ,config = that.config
  166. ,childs = elem.children
  167. ,btn = elem[tag]('button')[0]
  168. ,input = elem[tag]('input')[0]
  169. ,select = elem[tag]('select')[0]
  170. ,skip = function(){
  171. var curr = input.value.replace(/\s|\D/g, '')|0;
  172. if(curr){
  173. config.curr = curr;
  174. that.render();
  175. }
  176. };
  177. if(isskip) return skip();
  178. //页码
  179. for(var i = 0, len = childs.length; i < len; i++){
  180. if(childs[i].nodeName.toLowerCase() === 'a'){
  181. laypage.on(childs[i], 'click', function(){
  182. var curr = this.getAttribute('data-page')|0;
  183. if(curr < 1 || curr > config.pages) return;
  184. config.curr = curr;
  185. that.render();
  186. });
  187. }
  188. }
  189. //条数
  190. if(select){
  191. laypage.on(select, 'change', function(){
  192. var value = this.value;
  193. if(config.curr*value > config.count){
  194. config.curr = Math.ceil(config.count/value);
  195. }
  196. config.limit = value;
  197. that.render();
  198. });
  199. }
  200. //确定
  201. if(btn){
  202. laypage.on(btn, 'click', function(){
  203. skip();
  204. });
  205. }
  206. };
  207. //输入页数字控制
  208. Class.prototype.skip = function(elem){
  209. if(!elem) return;
  210. var that = this, input = elem[tag]('input')[0];
  211. if(!input) return;
  212. laypage.on(input, 'keyup', function(e){
  213. var value = this.value
  214. ,keyCode = e.keyCode;
  215. if(/^(37|38|39|40)$/.test(keyCode)) return;
  216. if(/\D/.test(value)){
  217. this.value = value.replace(/\D/, '');
  218. }
  219. if(keyCode === 13){
  220. that.jump(elem, true)
  221. }
  222. });
  223. };
  224. //渲染分页
  225. Class.prototype.render = function(load){
  226. var that = this
  227. ,config = that.config
  228. ,type = that.type()
  229. ,view = that.view();
  230. if(type === 2){
  231. config.elem && (config.elem.innerHTML = view);
  232. } else if(type === 3){
  233. config.elem.html(view);
  234. } else {
  235. if(doc[id](config.elem)){
  236. doc[id](config.elem).innerHTML = view;
  237. }
  238. }
  239. config.jump && config.jump(config, load);
  240. var elem = doc[id]('layui-laypage-' + config.index);
  241. that.jump(elem);
  242. if(config.hash && !load){
  243. location.hash = '!'+ config.hash +'='+ config.curr;
  244. }
  245. that.skip(elem);
  246. };
  247. //外部接口
  248. var laypage = {
  249. //分页渲染
  250. render: function(options){
  251. var o = new Class(options);
  252. return o.index;
  253. }
  254. ,index: layui.laypage ? (layui.laypage.index + 10000) : 0
  255. ,on: function(elem, even, fn){
  256. elem.attachEvent ? elem.attachEvent('on'+ even, function(e){ //for ie
  257. e.target = e.srcElement;
  258. fn.call(elem, e);
  259. }) : elem.addEventListener(even, fn, false);
  260. return this;
  261. }
  262. }
  263. exports(MOD_NAME, laypage);
  264. });