|
|
|
|
|
// 立即执行函数,传入 window 对象(通常约定用 e 表示),开启严格模式,使代码遵循更严格的语法和语义规范,有助于发现潜在错误
|
|
|
;!function(e) {
|
|
|
"use strict";
|
|
|
|
|
|
// 获取文档对象,后续很多操作会基于此进行 DOM 相关操作
|
|
|
var t = document,
|
|
|
// 用于管理 layui 的各种内部状态和模块相关信息的对象
|
|
|
n = {
|
|
|
modules: {}, // 存放已加载或待加载的模块信息
|
|
|
status: {}, // 模块加载状态相关标记
|
|
|
timeout: 10, // 用于设置一些操作的超时时间相关阈值
|
|
|
event: {} // 事件管理相关对象,用于存储事件绑定等信息
|
|
|
},
|
|
|
// 构造函数,用于创建一个表示 layui 版本信息的对象实例,此处实例化后其 v 属性会被赋值为 "2.5.6"
|
|
|
r = function () {
|
|
|
this.v = "2.5.6"
|
|
|
},
|
|
|
// 获取当前脚本的源文件路径,通过判断 currentScript 以及遍历 scripts 集合等方式来确定路径
|
|
|
// 最终得到的是脚本所在目录路径(去除文件名部分)
|
|
|
o = function () {
|
|
|
var e = t.currentScript ? t.currentScript.src : function () {
|
|
|
for (var e, n = t.scripts, r = n.length - 1, o = r; o > 0; o--)
|
|
|
if ("interactive" === n[o].readyState) {
|
|
|
e = n[o].src;
|
|
|
break
|
|
|
}
|
|
|
return e || n[r].src
|
|
|
}();
|
|
|
return e.substring(0, e.lastIndexOf("/") + 1)
|
|
|
}(),
|
|
|
// 用于在控制台输出错误提示信息的函数,前提是 window.console 存在且有 console.error 方法可用
|
|
|
a = function (t) {
|
|
|
e.console && console.error && console.error("Layui hint: " + t)
|
|
|
},
|
|
|
// 判断是否是 Opera 浏览器(旧的判断方式,现在 Opera 已基于 Chromium 内核等情况可能不太常用了)
|
|
|
i = "undefined" != typeof opera && "[object Opera]" === opera.toString(),
|
|
|
// 定义了各个 layui 模块对应的路径映射关系,方便后续根据模块名去加载对应的模块文件
|
|
|
u = {
|
|
|
layer: "modules/layer",
|
|
|
laydate: "modules/laydate",
|
|
|
laypage: "modules/laypage",
|
|
|
laytpl: "modules/laytpl",
|
|
|
layim: "modules/layim",
|
|
|
layedit: "modules/layedit",
|
|
|
form: "modules/form",
|
|
|
upload: "modules/upload",
|
|
|
transfer: "modules/transfer",
|
|
|
tree: "modules/tree",
|
|
|
table: "modules/table",
|
|
|
element: "modules/element",
|
|
|
rate: "modules/rate",
|
|
|
colorpicker: "modules/colorpicker",
|
|
|
slider: "modules/slider",
|
|
|
carousel: "modules/carousel",
|
|
|
flow: "modules/flow",
|
|
|
util: "modules/util",
|
|
|
code: "modules/code",
|
|
|
jquery: "modules/jquery",
|
|
|
mobile: "modules/mobile",
|
|
|
"layui.all": "../layui.all"
|
|
|
};
|
|
|
|
|
|
// 将 n 对象(包含模块、状态等管理信息)挂载到 layui 实例的 cache 属性上,方便通过实例访问这些数据
|
|
|
r.prototype.cache = n;
|
|
|
|
|
|
// 用于定义模块的方法
|
|
|
r.prototype.define = function (e, t) {
|
|
|
var r = this,
|
|
|
// 判断传入的第一个参数是否是函数类型
|
|
|
o = "function" == typeof e,
|
|
|
// 内部函数,用于处理模块注册成功后的一些赋值和回调相关操作
|
|
|
a = function () {
|
|
|
var e = function (e, t) {
|
|
|
layui[e] = t,
|
|
|
n.status[e] = !0
|
|
|
};
|
|
|
return "function" == typeof t && t(function (r, o) {
|
|
|
e(r, o),
|
|
|
n.callback[r] = function () {
|
|
|
t(e)
|
|
|
}
|
|
|
}),
|
|
|
this
|
|
|
};
|
|
|
// 如果传入的第一个参数是函数,将第二个参数赋值给第一个参数,同时把第一个参数重置为空数组(处理参数顺序等情况)
|
|
|
return o && (t = e, e = []),
|
|
|
// 如果不存在 layui.all 且存在 layui.mobile,调用内部函数 a 进行模块相关处理,否则调用 use 方法来处理模块定义
|
|
|
!layui["layui.all"] && layui["layui.mobile"] ? a.call(r) : (r.use(e, a), r)
|
|
|
};
|
|
|
|
|
|
// 模块加载的核心方法,用于加载指定的 layui 模块
|
|
|
r.prototype.use = function (e, r, l) {
|
|
|
function c(e, t) {
|
|
|
var r = "PLaySTATION 3" === navigator.platform ? /^complete$/ : /^(complete|loaded)$/;
|
|
|
// 判断脚本是否加载完成(根据不同浏览器平台判断方式略有不同),加载完成后执行后续逻辑
|
|
|
("load" === e.type || r.test((e.currentTarget || e.srcElement).readyState)) && (n.modules[d] = t, y.removeChild(h), function o() {
|
|
|
return ++m > 1e3 * n.timeout / 4 ? a(d + " is not a valid module") : void (n.status[d] ? s() : setTimeout(o, 4))
|
|
|
}())
|
|
|
}
|
|
|
|
|
|
function s() {
|
|
|
l.push(layui[d]),
|
|
|
e.length > 1 ? p.use(e.slice(1), r, l) : "function" == typeof r && r.apply(layui, l)
|
|
|
}
|
|
|
|
|
|
var p = this,
|
|
|
f = n.dir = n.dir ? n.dir : o,
|
|
|
y = t.getElementsByTagName("head")[0];
|
|
|
// 将传入的模块名参数统一处理为数组形式(如果是字符串则转换为单元素数组)
|
|
|
e = "string" == typeof e ? [e] : e;
|
|
|
// 如果 window.jQuery 存在且有 on 方法,移除要加载的模块列表中的 jquery 模块(避免重复加载,假设已经全局存在了 jQuery)
|
|
|
window.jQuery && jQuery.fn.on && (p.each(e, function (t, n) {
|
|
|
"jquery" === n && e.splice(t, 1)
|
|
|
}), layui.jquery = layui.$ = jQuery);
|
|
|
|
|
|
var d = e[0],
|
|
|
m = 0;
|
|
|
// 如果传入的模块列表为空或者存在 layui.all 且对应的模块在 u 中有定义,或者不存在 layui.all 但存在 layui.mobile 且对应模块在 u 中有定义,直接执行后续逻辑(如执行回调等)
|
|
|
if (l = l || [], n.host = n.host || (f.match(/\/\/([\s\S]+?)\//) || ["//" + location.host + "/"])[0], 0 === e.length || layui["layui.all"] && u[d] || !layui["layui.all"] && layui["layui.mobile"] && u[d]) return s(), p;
|
|
|
|
|
|
var v = (u[d] ? f + "lay/" : /^\{\/\}/.test(p.modules[d]) ? "" : n.base || "") + (p.modules[d] || d) + ".js";
|
|
|
// 处理模块路径,如果模块路径已经存在于 modules 中则直接使用,否则根据一定规则拼接出完整的模块脚本路径
|
|
|
if (v = v.replace(/^\{\/\}/, ""), !n.modules[d] && layui[d] && (n.modules[d] = v), n.modules[d])
|
|
|
// 如果模块路径已经存在且模块状态已经是加载完成状态,直接执行后续逻辑,否则定时检查模块状态等待加载完成
|
|
|
!function g() {
|
|
|
return ++m > 1e3 * n.timeout / 4 ? a(d + " is not a valid module") : void ("string" == typeof n.modules[d] && n.status[d] ? s() : setTimeout(g, 4))
|
|
|
}();
|
|
|
else {
|
|
|
var h = t.createElement("script");
|
|
|
h.async = !0,
|
|
|
h.charset = "utf-8",
|
|
|
h.src = v + function () {
|
|
|
var e = n.version === !0 ? n.v || (new Date).getTime() : n.version || "";
|
|
|
return e ? "?v=" + e : ""
|
|
|
}(),
|
|
|
y.appendChild(h),
|
|
|
// 根据浏览器是否支持 attachEvent 以及其是否是原生代码等情况,选择合适的方式来监听脚本加载完成事件
|
|
|
!h.attachEvent || h.attachEvent.toString() && h.attachEvent.toString().indexOf("[native code") < 0 || i ? h.addEventListener("load", function (e) {
|
|
|
c(e, v)
|
|
|
}, !1) : h.attachEvent("onreadystatechange", function (e) {
|
|
|
c(e, v)
|
|
|
}),
|
|
|
n.modules[d] = v
|
|
|
}
|
|
|
return p
|
|
|
};
|
|
|
|
|
|
// 获取元素的样式属性值,兼容不同浏览器获取样式的方式(旧版 IE 用 currentStyle,现代浏览器用 getComputedStyle)
|
|
|
r.prototype.getStyle = function (t, n) {
|
|
|
var r = t.currentStyle ? t.currentStyle : e.getComputedStyle(t, null);
|
|
|
return r[r.getPropertyValue ? "getPropertyValue" : "getAttribute"](n)
|
|
|
};
|
|
|
|
|
|
// 用于加载 CSS 样式文件的方法,可传入样式文件路径、回调函数等,处理样式文件加载完成等相关逻辑并执行回调
|
|
|
r.prototype.link = function (e, r, o) {
|
|
|
var i = this,
|
|
|
u = t.createElement("link"),
|
|
|
l = t.getElementsByTagName("head")[0];
|
|
|
"string" == typeof r && (o = r);
|
|
|
var c = (o || e).replace(/\.|\//g, ""),
|
|
|
s = u.id = "layuicss-" + c,
|
|
|
p = 0;
|
|
|
return u.rel = "stylesheet",
|
|
|
u.href = e + (n.debug ? "?v=" + (new Date).getTime() : ""),
|
|
|
u.media = "all",
|
|
|
t.getElementById(s) || l.appendChild(u),
|
|
|
"function" != typeof r ? i : (function f() {
|
|
|
return ++p > 1e3 * n.timeout / 100 ? a(e + " timeout") : void (1989 === parseInt(i.getStyle(t.getElementById(s), "width")) ? function () {
|
|
|
r()
|
|
|
}() : setTimeout(f, 100))
|
|
|
}(), i)
|
|
|
};
|
|
|
|
|
|
// 根据模块名判断是否存在对应的模块以及相应的回调函数,并返回回调函数(如果存在)
|
|
|
r.prototype.factory = function (e) {
|
|
|
if (layui[e]) return "function" == typeof n.callback[e] ? n.callback[e] : null
|
|
|
};
|
|
|
|
|
|
// 辅助方法,用于添加指定的 CSS 文件,调用 link 方法并传入正确的路径来加载 CSS
|
|
|
r.prototype.addcss = function (e, t, r) {
|
|
|
return layui.link(n.dir + "css/" + e, t, r)
|
|
|
};
|
|
|
|
|
|
// 用于创建图片对象、处理图片加载完成、加载出错等不同情况并执行相应的回调函数
|
|
|
r.prototype.img = function (e, t, n) {
|
|
|
var r = new Image;
|
|
|
return r.src = e,
|
|
|
r.complete ? t(r) : (r.onload = function () {
|
|
|
r.onload = null,
|
|
|
"function" == typeof t && t(r)
|
|
|
},
|
|
|
void (r.onerror = function (e) {
|
|
|
r.onerror = null,
|
|
|
"function" == typeof n && n(e)
|
|
|
}))
|
|
|
};
|
|
|
|
|
|
// 用于配置 layui 的相关参数,将传入的配置对象属性赋值到内部管理的 n 对象对应的属性上
|
|
|
r.prototype.config = function (e) {
|
|
|
e = e || {};
|
|
|
for (var t in e) n[t] = e[t];
|
|
|
return this
|
|
|
};
|
|
|
|
|
|
// 返回定义的模块路径映射对象的副本,对外提供获取所有模块路径信息的方式
|
|
|
r.prototype.modules = function () {
|
|
|
var e = {};
|
|
|
for (var t in u) e[t] = u[t];
|
|
|
return e
|
|
|
}();
|
|
|
|
|
|
// 用于扩展 layui 的模块,添加新的模块路径映射,但会检查模块名是否已被占用,若已占用则输出错误提示
|
|
|
r.prototype.extend = function (e) {
|
|
|
var t = this;
|
|
|
e = e || {};
|
|
|
for (var n in e) t[n] || t.modules[n] ? a("模块名 " + n + " 已被占用") : t.modules[n] = e[n];
|
|
|
return t
|
|
|
};
|
|
|
|
|
|
// 用于解析 URL 的哈希部分,提取路径、查询参数和哈希值等信息,构建对应的对象返回
|
|
|
r.prototype.router = function (e) {
|
|
|
var t = this,
|
|
|
e = e || location.hash,
|
|
|
n = {
|
|
|
path: [],
|
|
|
search: {},
|
|
|
hash: (e.match(/[^#](#.*$)/) || [])[1] || ""
|
|
|
};
|
|
|
return /^#\//.test(e) ? (e = e.replace(/^#\//, ""), n.href = "/" + e, e = e.replace(/([^#])(#.*$)/, "$1").split("/") || [], t.each(e, function (e, t) {
|
|
|
/^\w+=/.test(t) ? function () {
|
|
|
t = t.split("="),
|
|
|
n.search[t[0]] = t[1]
|
|
|
}() : n.path.push(t)
|
|
|
}), n) : n
|
|
|
};
|
|
|
|
|
|
// 用于解析 URL,提取路径名、查询参数、哈希值等信息,构建包含这些信息的对象返回
|
|
|
r.prototype.url = function (e) {
|
|
|
var t = this,
|
|
|
n = {
|
|
|
pathname: function () {
|
|
|
var t = e ? function () {
|
|
|
var t = (e.match(/\.[^.]+?\/.+/) || [])[0] || "";
|
|
|
return t.replace(/^[^\/]+/, "").replace(/\?.+/, "")
|
|
|
}() : location.pathname;
|
|
|
return t.replace(/^\//, "").split("/")
|
|
|
}(),
|
|
|
search: function () {
|
|
|
var n = {},
|
|
|
r = (e ? function () {
|
|
|
var t = (e.match(/\?.+/) || [])[0] || "";
|
|
|
return t.replace(/\#.+/, "")
|
|
|
}() : location.search).replace(/^\?+/, "").split("&");
|
|
|
return t.each(r, function (e, t) {
|
|
|
var r = t.indexOf("="),
|
|
|
o = function () {
|
|
|
return r < 0 ? t.substr(0, t.length) : 0 !== r && t.substr(0, r)
|
|
|
}();
|
|
|
o && (n[o] = r > 0 ? t.substr(r + 1) : null)
|
|
|
}),
|
|
|
n
|
|
|
}(),
|
|
|
hash: t.router(function () {
|
|
|
return e ? (e.match(/#.+/) || [])[0] || "" : location.hash
|
|
|
}())
|
|
|
};
|
|
|
return n
|
|
|
};
|
|
|
|
|
|
// 用于在 localStorage 中存储或获取数据,支持以对象形式操作数据,可进行增删改查等操作,通过 JSON 序列化和反序列化来处理数据存储格式
|
|
|
r.prototype.data = function (t, n, r) {
|
|
|
if (t = t || "layui", r = r || localStorage, e.JSON && e.JSON.parse) {
|
|
|
if (null === n) return delete r[t];
|
|
|
n = "object" == typeof n ? n : {
|
|
|
key: n
|
|
|
};
|
|
|
try {
|
|
|
var o = JSON.parse(r[t])
|
|
|
} catch (a) {
|
|
|
var o = {}
|
|
|
}
|
|
|
return "value" in n && (o[n.key] = n.value),
|
|
|
n.remove && delete o[n.key],
|
|
|
r[t] = JSON.stringify(o),
|
|
|
n.key ? o[n.key] : o
|
|
|
}
|
|
|
};
|
|
|
|
|
|
// 类似于 data 方法,但操作的是 sessionStorage 而不是 localStorage,用于临时存储会话相关数据
|
|
|
r.prototype.sessionData = function (e, t) {
|
|
|
return this.data(e, t, sessionStorage)
|
|
|
};
|
|
|
|
|
|
// 用于检测设备相关信息,如操作系统类型、是否是 IE 浏览器、是否是微信浏览器、是否是安卓或 iOS 等移动端设备等情况
|
|
|
r.prototype.device = function (t) {
|
|
|
var n = navigator.userAgent.toLowerCase(),
|
|
|
r = function (e) {
|
|
|
var t = new RegExp(e + "/([^\\s\\_\\-]+)");
|
|
|
return e = (n.match(t) || [])[1],
|
|
|
e || !1
|
|
|
},
|
|
|
o = {
|
|
|
os: function () {
|
|
|
return /windows/.test(n) ? "windows" : /linux/.test(n) ? "linux" : /iphone|ipod|ipad|ios/.test(n) ? "ios" : /mac/.test(n) ? "mac" : void 0
|
|
|
}(),
|
|
|
ie: function () {
|
|
|
return !!(e.ActiveXObject || "ActiveXObject" in e) && ((n.match(/msie\s(\d+)/) || [])[1] || "11")
|
|
|
}(),
|
|
|
weixin: r("micromessenger")
|
|
|
};
|
|
|
return t && !o[t] && (o[t] = r(t)),
|
|
|
o.android = /android/.test(n),
|
|
|
o.ios = "ios" === o.os,
|
|
|
o.mobile = !(!o)
|
|
|
}
|
|
|
} |