// 立即执行函数,传入 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) } }