layui-laypage模块代码详解
/** layui-v2.4.0 MIT License By https://www.layui.com */
;
layui.define(function(e) {
"use strict";
var a = document,
t = "getElementById",
n = "getElementsByTagName",
i = "laypage",
r = "layui-disabled",
u = function(e) {
var a = this;
// 实例化的时候调用了render方法,layui.laypage不存在,即接口还未对外exports时,index为0
console.log("初次索引:%c" + s.index, "color: red;");
// u是一个构造函数,此处的this将为u实例化后的实例。
// 并且索引在每次render之后增一。
// 并render,!0代表初次render。
a.config = e || {}, a.config.index = ++s.index, a.render(!0)
};
u.prototype.type = function() {
var e = this.config;
console.log("判断分页容器元素是否为对象:%c" + ("object" == typeof e.elem ? 'yes' : 'no'), 'color: blue;');
if ("object" == typeof e.elem) {
console.log("分页容器元素:", e.elem);
// document.getElementById的length是undefin,而jquery的是数值。
return void 0 === e.elem.length ? 2 : 3
} else {
console.log("分页容器元素:%c" + e.elem, "color: blue;");
}
}, u.prototype.view = function() {
var e = this,
a = e.config,
// 判断是否传入了groups,是则对其逻辑或运算,目的转为数字,否则赋默认值5
t = a.groups = "groups" in a ? 0 | a.groups : 5;
// layout 如果已赋值且为对象,使用它,否则为默认["prev", "page", "next"], 其他配置参数也进行逻辑或运算,保证为数字或有默认值
// 逻辑或还能向上取整,3.4214 | 1,对groups进行处理,负数或者大于页码数
a.layout = "object" == typeof a.layout ? a.layout : ["prev", "page", "next"], a.count = 0 | a.count, a.curr = 0 | a.curr || 1, a.limits = "object" == typeof a.limits ? a.limits : [10, 20, 30, 40, 50], a.limit = 0 | a.limit || 10, a.pages = Math.ceil(a.count / a.limit) || 1, a.curr > a.pages && (a.curr = a.pages), t < 0 ? t = 1 : t > a.pages && (t = a.pages), a.prev = "prev" in a ? a.prev : "上一页", a.next = "next" in a ? a.next : "下一页";
var n = a.pages > t ? Math.ceil((a.curr + (t > 1 ? 1 : 0)) / (t > 0 ? t : 1)) : 1,
i = {
prev: function() {
return a.prev ? '<a href="javascript:;" class="layui-laypage-prev' + (1 == a.curr ? " " + r : "") + '" data-page="' + (a.curr - 1) + '">' + a.prev + "</a>" : ""
}(),
page: function() {
var e = [];
if (a.count < 1) return "";
n > 1 && a.first !== !1 && 0 !== t && e.push('<a href="javascript:;" class="layui-laypage-first" data-page="1" title="首页">' + (a.first || 1) + "</a>");
var i = Math.floor((t - 1) / 2),
r = n > 1 ? a.curr - i : 1,
u = n > 1 ?
function() {
var e = a.curr + (t - i - 1);
return e > a.pages ? a.pages : e
}() : t;
for (u - r < t - 1 && (r = u - t + 1), a.first !== !1 && r > 2 && e.push('<span class="layui-laypage-spr">…</span>'); r <= u; r++) r === a.curr ? e.push('<span class="layui-laypage-curr"><em class="layui-laypage-em" ' + (/^#/.test(a.theme) ? 'style="">+ a.theme + ';"' : "") + "></em><em>" + r + "</em></span>") : e.push('<a href="javascript:;" data-page="' + r + '">' + r + "</a>");
return a.pages > t && a.pages > u && a.last !== !1 && (u + 1 < a.pages && e.push('<span class="layui-laypage-spr">…</span>'), 0 !== t && e.push('<a href="javascript:;" class="layui-laypage-last" title="尾页" data-page="' + a.pages + '">' + (a.last || a.pages) + "</a>")), e.join("")
}(),
next: function() {
return a.next ? '<a href="javascript:;" class="layui-laypage-next' + (a.curr == a.pages ? " " + r : "") + '" data-page="' + (a.curr + 1) + '">' + a.next + "</a>" : ""
}(),
count: '<span class="layui-laypage-count">共 ' + a.count + " 条</span>",
limit: function() {
var e = ['<span class="layui-laypage-limits"><select lay-ignore>'];
return layui.each(a.limits, function(t, n) {
e.push('<option value="' + n + '"' + (n === a.limit ? "selected" : "") + ">" + n + " 条/页</option>")
}), e.join("") + "</select></span>"
}(),
refresh: ['<a href="javascript:;" data-page="' + a.curr + '" class="layui-laypage-refresh">', '<i class="layui-icon layui-icon-refresh"></i>', "</a>"].join(""),
skip: function() {
return ['<span class="layui-laypage-skip">到第', '<input type="text" min="1" value="' + a.curr + '" class="layui-input">', '页<button type="button" class="layui-laypage-btn">确定</button>', "</span>"].join("")
}()
};
return ['<div class="layui-box layui-laypage layui-laypage-' + (a.theme ? /^#/.test(a.theme) ? "molv" : a.theme : "default") + '" id="layui-laypage-' + a.index + '">', function() {
var e = [];
return layui.each(a.layout, function(a, t) {
i[t] && e.push(i[t])
}), e.join("")
}(), "</div>"].join("")
}, u.prototype.jump = function(e, a) {
// e是配置或获取到的page元素
console.log("跳转后传入渲染元素:", e);
// render之后执行jump,做的事儿有:
// 1. 初始化则获取输入框值,渲染翻页。
// 2. 对所有a元素进行事件绑定。
// 3. select的事件绑定。
// 4. button的事件绑定。
if (e) {
var t = this,
i = t.config,
r = e.children,
// 点击按钮,即输入后的确认按钮
u = e[n]("button")[0],
// 输入框
l = e[n]("input")[0],
// 下拉菜单
p = e[n]("select")[0],
c = function() {
// 替换掉输入框中非数字部分,确保为数字。
var e = 0 | l.value.replace(/\s|\D/g, "");
// 将curr赋值,并render,即跳转后再次render
// 此处render是实例化对象上的render
// 即点击确认按钮/或初次加载后重新渲染page
e && (i.curr = e, t.render())
};
// 如果a为true,进行render,即标示了input,执行到此
if (a) return c();
// 循环给a元素加第点击事件。
for (var o = 0, y = r.length; o < y; o++)"a" === r[o].nodeName.toLowerCase() && s.on(r[o], "click", function() {
// 获取到页码数,点击的当前页码页码数赋值给配置对象的curr,指示当前所在页码,并重渲染。
var e = 0 | this.getAttribute("data-page");
// 当前页码数小于1或者大于总页码数,则不执行赋值和重渲染。
// 只有既不小于1又不大于总页码数,才赋值和重新渲染。
e < 1 || e > i.pages || (i.curr = e, t.render())
});
// select事件
p && s.on(p, "change", function() {
var e = this.value;
// 当前页码*所选值如果大于总数,则当前页码赋值为总页码/每页显示数的乡下取值。
// 然后重新渲染。
i.curr * e > i.count && (i.curr = Math.ceil(i.count / e)), i.limit = e, t.render()
}),
// 输入后的button确认事件
u && s.on(u, "click", function() {
c()
})
}
}, u.prototype.skip = function(e) {
// e为传入的分页元素对象。
if (e) {
var a = this,
t = e[n]("input")[0];
// chrome下会支持回调传入参数。
t && s.on(t, "keyup", function(t) {
console.log("keyup传入参数:", t);
// keyup的调用对象是t
var n = this.value,
i = t.keyCode;
// 上下左右键,或者输入框值为非数字,则将非数字替换为空
// 如果为确认,执行jump方法,且传入真。。
/^(37|38|39|40)$/.test(i) || (/\D+/.test(n) && (this.value = n.replace(/\D/, "")), 13 === i && a.jump(e, !0))
})
}
}, // 当前render在实例化期间被调用,在s对象中render则成为实例化对象。
u.prototype.render = function(e) {
var n = this,
// 传入的配置对象
i = n.config,
// 获取类型
r = n.type(),
// 生成view
u = n.view();
console.log("判断传入类型:%c" + r, "color: blue;");
// console.log("render获取到的配置:", i);
// 判断是原生js对象还是jquery对象,否则就调用document上的getElementById获取dom元素,
// 将生成的视图赋值给它,跳转回调存在则调用它,也即在render的时候就已经实施了对jump的调用。因此有初次调用一说。
2 === r ? i.elem && (i.elem.innerHTML = u) : 3 === r ? i.elem.html(u) : a[t](i.elem) && (a[t](i.elem).innerHTML = u),
// 此处调用意欲何为?此处jump是用户传入的回调函数,e标示是否第一次,第一次render的时候e是!0,即真
console.log("是否第一次:", e ? '是' : '否'),
i.jump && i.jump(i, e);
// i.index是不断累加的。下面的jump是构造函数上的jump
// 在view方法中以下元素已经被渲染出来了。
var s = a[t]("layui-laypage-" + i.index);
// 执行jump方法并且追加hash
n.jump(s), i.hash && !e && (location.hash = "!" + i.hash + "=" + i.curr), n.skip(s)
};
// e 为传入render的配置对象
// u 为
// function(e) {
// var a = this;
// a.config = e || {}, a.config.index = ++s.index, a.render(!0)
// };
// render 创建了一个实例,返回了索引。
var s = {
render: function(e) {
var a = new u(e);
console.log("laypage原始索引:%c" + s.index, "color: red;");
console.log("laypage配置索引:%c" + a.config.index, "color: red;");
// 返回的index已经是增1以后的。
return a.index
},
index: layui.laypage ? layui.laypage.index + 1e4 : 0,
on: function(e, a, t) {
// e是dom元素对象,a是事件名,t是回调
return e.attachEvent ? e.attachEvent("on" + a, function(a) {
// 此处a是事件对象, 两个的区别是:ie下支持e.srcElement,ff支持e.target。
// 指向触发事件的元素
a.target = a.srcElement, t.call(e, a)
// 禁止冒泡
}) : e.addEventListener(a, t, !1), this
}
};
e(i, s); /**
* 初次进入页面
* 调用:
* laypage.render({
elem: document.getElementById('laypage'), // 'laypage', $('#laypage'), document.getElementById('laypage');
count: count,
limit: limit,
limits: [5, 10, 20, 30, 50],
curr: page,
groups: 5,
prev: '上一页',
next: '下一页',
first: '首页',
last: '尾页',
layout: ['prev', 'page', 'next', 'first', 'last', 'limit', 'refresh', 'skip', 'count'],
theme: '#1E9FFF',
hash: 'curr',
jump: function (obj, first) {
console.log("jump后的配置:", obj);
if (!first) {
pageTurn(obj.curr, obj.limit);
}
}
})
* 即s对象上的render方法
* 实例化函数u,并将配置作为参数传递给u。
* 将配置对象赋值给是实例化对象。
* 给该配置对象设置索引,为s对象上的index加1。
* exports向外暴露的接口laypage在use或者作为依赖引入的时候,进入内存,初始化index,为0。
* 执行后面扩展到构造函数u上的方法render,传入参数!0,即真,表示第一次。
* 执行原型上的type方法,根据传入配置对象的elem来决定类型,2(原生dom对象),3(jquery对象),undefined(字符串)。
* 构造view html。
* 根据上面的类型赋值给elem元素html。
* 如果用户设置了jump回调,第一次不执行,传入配置对象及是否为第一次,此时为真,毫无疑问。
* 用原生js方法取到当前page元素。
* 执行render里的jump方法。
* 如果该元素存在。
* 获取到该元素的子元素button,input和select。
* 如果参数a为真,仅执行内部函数c,但此时为undefined,不执行c函数。执行c函数的情况是在skip中按下了enter键之后才会执行,前提条件是按下了上下左右方向键或者非数字,执行了input输入框非数字过滤之后,再按下enter键,渲染page。
* 对a元素进行循环绑定click事件,其中回调是获取到a上的data-page页码,比对是否大于总页码或者小于1,对配置对象的curr重新赋值,并执行render。render不传参,因此会执行用户回调。table会重新渲染,page容器的id也会随之而变。
* 对select进行事件绑定,计算curr值及limit值,配置对象发生改变,然后执行无参数render,自然table会被重新渲染,执行用户回调。
* button确认点击事件同理。
* 然后render方法中改变hash值。
* render中执行skip函数,传入page元素。
* 如果page为真,获取到input元素。
* 给他绑定keyup事件,目的是检测按下了上下左右方向键或者非数字,执行input输入框非数字过滤之后,再按下enter键,执行jump。
* 此时jump第二个参数为真。不在jump里执行button,a及seelct的绑定。会执行内部函数c,render的参数为空,即非第一次调用。
* render会调用用户回调,并再执行jump,此时jump的第二个参数为空。执行select,a,button的事件绑定及在skip函数里执行input的keyup事件绑定。
* 结束
*
* 模拟点击页码3
* 此时初次render已经结束。
* 点击页码3发生,即执行了a上绑定的click事件。
* 此时获取到页码3。
* 判断页码是否小于1大于总页码,不是,赋值给配置对象的curr,执行render,不传参数。
* this赋值给n。
* 配置对象赋值给i。
* 获取到type值为undefined,假设配置中写的是字符串。
* 生成view。
* 将view结果赋值给指定id元素。
* 判断是否设置了用户回调。
* 是,执行回调。此时render传入参数为空,即假。回调中如果设置了if(!first){}则会执行。
* 当前系统中会重新渲染table。
* 获取当前page容器元素。因为点击过后,执行了用户回调,而用户回调中再次调用了laypage.render,所以index会增1。
* 执行jump函数,传入此容器元素。
* 此时jump的第二个参数为假,因此在这一步就执行了button,select及a元素的事件绑定。
* 然后hash值赋值。
* 执行skip,为input绑定keyup事件。
* keyup事件中检测输入是否为上下左右键以及非数字,则input中值自动过滤掉这些字符,如果按下enter,则执行jump。
* 因为传入第二个参数为真,因此会先执行render,因为在keyup中可能输入的数字合法,必须要重新render。
* 结束。
*/
});
layui-laypage模块代码详解的更多相关文章
- opencart 模块开发详解
opencart 模块开发详解 由 xiekanxiyang » 2013年 7月 11日 10:17 pm opencart 将页面分成若干模块, 每个模块可以有多个实例(可能这样说不是很恰当) 每 ...
- AngularJS模块的详解
AngularJS模块的详解 在讲angularjs的模块之前,我们先介绍一下angular的一些知识点: AngularJS是纯客户端技术,完全用Javascript编写的.它使用的是网页开发的常规 ...
- [转帖]Nginx rewrite模块深入浅出详解
Nginx rewrite模块深入浅出详解 https://www.cnblogs.com/beyang/p/7832460.html rewrite模块(ngx_http_rewrite_modul ...
- Github-jcjohnson/torch-rnn代码详解
Github-jcjohnson/torch-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2016-3- ...
- DeepLearning tutorial(3)MLP多层感知机原理简介+代码详解
本文介绍多层感知机算法,特别是详细解读其代码实现,基于python theano,代码来自:Multilayer Perceptron,如果你想详细了解多层感知机算法,可以参考:UFLDL教程,或者参 ...
- springboot扫描自定义的servlet和filter代码详解_java - JAVA
文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 这几天使用spring boot编写公司一个应用,在编写了一个filter,用于指定编码的filter,如下: /** ...
- BM算法 Boyer-Moore高质量实现代码详解与算法详解
Boyer-Moore高质量实现代码详解与算法详解 鉴于我见到对算法本身分析非常透彻的文章以及实现的非常精巧的文章,所以就转载了,本文的贡献在于将两者结合起来,方便大家了解代码实现! 算法详解转自:h ...
- ASP.NET MVC 5 学习教程:生成的代码详解
原文 ASP.NET MVC 5 学习教程:生成的代码详解 起飞网 ASP.NET MVC 5 学习教程目录: 添加控制器 添加视图 修改视图和布局页 控制器传递数据给视图 添加模型 创建连接字符串 ...
- Github-karpathy/char-rnn代码详解
Github-karpathy/char-rnn代码详解 zoerywzhou@gmail.com http://www.cnblogs.com/swje/ 作者:Zhouwan 2016-1-10 ...
随机推荐
- AJAX 跨域问题 php
原生ajax请求方式: var xhr = new XMLHttpRequest(); xhr.open("POST", "http://xxxx.com/demo/b/ ...
- SpringBoot(五)_表单验证
SpringBoot(五)_表单验证 参数校验在我们日常开发中非常常见,最基本的校验有判断属性是否为空.长度是否符合要求等,在传统的开发模式中需要写一堆的 if else 来处理这些逻辑,很繁琐,效率 ...
- HDU2883_kebab
很好的题目. 有不多于200个任务,每个任务要在si到ei这个时间段内完成,每个任务的任务量是ti*ni,只有一台机器,且其单位时间内可完成的任务量为m. 现在问你,能否使所有的任务全部在规定的时间段 ...
- 在动作类上加上SkipValidation 在反射时候会获取到该反射信息 就不会执行validate方法
在动作类上加上SkipValidation 在反射时候会获取到该反射信息 就不会执行validate方法
- NOI2017 退役记
OI生涯最后一篇游记写点不开心的让大家开心一下 Day -2(7.16) 上午的模拟赛奥妙重重. 下午也没怎么改题,看了一些新题,发现都不会,都看了下题解,发现大部分没看懂,好慌. 发现板子还没怎么复 ...
- springmvc+json 前后台数据交互
1. 配置(1) 文件配置参考这里(2) 导入jackson相关包:jackson-annotations-2.9.4.jar,jackson-core-2.9.4.jar,jackson-datab ...
- python爬虫headers设置后无效解决方案
此次遇到的是一个函数使用不熟练造成的问题,但有了分析工具后可以很快定位到问题(此处推荐一个非常棒的抓包工具fiddler) 正文如下: 在爬取某个app数据时(app上的数据都是由http请求的),用 ...
- mysql查看表中列信息
查看所有数据库中所有表的数据库名和表名 SELECT `TABLES`.`TABLE_SCHEMA`, `TABLES`.`TABLE_NAME` FROM `information_schema`. ...
- System Board Replacement Notice
System Board Replacement Notice System Board Replacement Notice for TP 770E and TP 600 Restoring the ...
- 遇到问题----gradle-----myeclipse的gradle插件导入项目报错nsupported major.minor version 51.0
装好了gradle插件之后 想要导入gradle类型的项目,然后在 build model的过程中发现: 报错nsupported major.minor version 51.0 查了下发现是jdk ...