交通管理局公文项目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

756 lines
22 KiB

/*!
@Title: layui
@Description:经典模块化前端 UI 框架
@Site: www.layui.com
@Author: 贤心
@License:MIT
*/
!(function (win) {
'use strict';
var doc = document;
var config = {
modules: {}, // 记录模块物理路径
status: {}, // 记录模块加载状态
timeout: 10, // 符合规范的模块请求最长等待秒数
event: {}, // 记录模块自定义事件
version: '30233', // 系统版本号 为了解决浏览器的缓存问题; 系统中的js、html文件路径都会拼上此版本号
};
var Layui = function () {
this.v = '2.5.5'; // 版本号
};
// 获取layui所在目录
var getPath = (function () {
var jsPath = doc.currentScript
? doc.currentScript.src
: (function () {
var js = doc.scripts;
var last = js.length - 1;
var src;
for (var i = last; i > 0; i--) {
if (js[i].readyState === 'interactive') {
src = js[i].src;
break;
}
}
return src || js[last].src;
})();
return jsPath.substring(0, jsPath.lastIndexOf('/') + 1);
})();
// 异常提示
var error = function (msg) {
win.console && console.error && console.error('Layui hint: ' + msg);
};
var isOpera = typeof opera !== 'undefined' && opera.toString() === '[object Opera]';
// 内置模块
var modules = {
layer: 'modules/layer', // 弹层
laydate: 'modules/laydate', // 日期
laypage: 'modules/laypage', // 分页
laytpl: 'modules/laytpl', // 模板引擎
layim: 'modules/layim', // web通讯
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', // DOM库(第三方)
mobile: 'modules/mobile', // 移动大模块 | 若当前为开发目录,则为移动模块入口,否则为移动模块集合
'layui.all': '../layui.all', // PC模块合并版
};
// 记录基础数据
Layui.prototype.cache = config;
// 定义模块
Layui.prototype.define = function (deps, factory) {
var that = this;
var type = typeof deps === 'function';
var callback = function () {
var setApp = function (app, exports) {
layui[app] = exports;
config.status[app] = true;
};
typeof factory === 'function' &&
factory(function (app, exports) {
setApp(app, exports);
config.callback[app] = function () {
factory(setApp);
};
});
return this;
};
type && ((factory = deps), (deps = []));
if (!layui['layui.all'] && layui['layui.mobile']) {
return callback.call(that);
}
that.use(deps, callback);
return that;
};
// 使用特定模块
Layui.prototype.use = function (apps, callback, exports) {
var that = this;
var dir = (config.dir = config.dir ? config.dir : getPath);
var head = doc.getElementsByTagName('head')[0];
apps = typeof apps === 'string' ? [apps] : apps;
// 如果页面已经存在jQuery1.7+库且所定义的模块依赖jQuery,则不加载内部jquery模块
if (window.jQuery && jQuery.fn.on) {
that.each(apps, function (index, item) {
if (item === 'jquery') {
apps.splice(index, 1);
}
});
layui.jquery = layui.$ = jQuery;
}
var item = apps[0];
var timeout = 0;
exports = exports || [];
// 静态资源host
config.host = config.host || (dir.match(/\/\/([\s\S]+?)\//) || ['//' + location.host + '/'])[0];
// 加载完毕
function onScriptLoad (e, url) {
var readyRegExp =
navigator.platform === 'PLaySTATION 3' ? /^complete$/ : /^(complete|loaded)$/;
if (e.type === 'load' || readyRegExp.test((e.currentTarget || e.srcElement).readyState)) {
config.modules[item] = url;
head.removeChild(node);
(function poll () {
if (++timeout > (config.timeout * 1000) / 4) {
return error(item + ' is not a valid module');
}
config.status[item] ? onCallback() : setTimeout(poll, 4);
})();
}
}
// 回调
function onCallback () {
exports.push(layui[item]);
apps.length > 1
? that.use(apps.slice(1), callback, exports)
: typeof callback === 'function' && callback.apply(layui, exports);
}
// 如果引入了完整库(layui.all.js),内置的模块则不必再加载
if (
apps.length === 0 ||
(layui['layui.all'] && modules[item]) ||
(!layui['layui.all'] && layui['layui.mobile'] && modules[item])
) {
return onCallback(), that;
}
// 首次加载模块
if (!config.modules[item]) {
var node = doc.createElement('script');
// 如果是内置模块,则按照 dir 参数拼接模块路径
// 如果是扩展模块,则判断模块路径值是否为 {/} 开头,
// 如果路径值是 {/} 开头,则模块路径即为后面紧跟的字符。
// 否则,则按照 base 参数拼接模块路径
var url =
(modules[item]
? dir + 'lay/'
: /^\{\/\}/.test(that.modules[item])
? ''
: config.base || '') +
(that.modules[item] || item) +
'.js';
url = url.replace(/^\{\/\}/, '');
node.async = true;
node.charset = 'utf-8';
node.src =
url +
(function () {
var version =
config.version === true ? config.v || new Date().getTime() : config.version || '';
return version ? '?v=' + version : '';
})();
head.appendChild(node);
if (
node.attachEvent &&
!(node.attachEvent.toString && node.attachEvent.toString().indexOf('[native code') < 0) &&
!isOpera
) {
node.attachEvent('onreadystatechange', function (e) {
onScriptLoad(e, url);
});
} else {
node.addEventListener(
'load',
function (e) {
onScriptLoad(e, url);
},
false
);
}
config.modules[item] = url;
} else {
// 缓存
(function poll () {
if (++timeout > (config.timeout * 1000) / 4) {
return error(item + ' is not a valid module');
}
typeof config.modules[item] === 'string' && config.status[item]
? onCallback()
: setTimeout(poll, 4);
})();
}
return that;
};
// 获取节点的style属性值
Layui.prototype.getStyle = function (node, name) {
var style = node.currentStyle ? node.currentStyle : win.getComputedStyle(node, null);
return style[style.getPropertyValue ? 'getPropertyValue' : 'getAttribute'](name);
};
// css外部加载器
Layui.prototype.link = function (href, fn, cssname) {
var that = this;
var link = doc.createElement('link');
var head = doc.getElementsByTagName('head')[0];
if (typeof fn === 'string') {
cssname = fn;
}
var app = (cssname || href).replace(/\.|\//g, '');
var id = (link.id = 'layuicss-' + app);
var timeout = 0;
link.rel = 'stylesheet';
link.href = href + (config.debug ? '?v=' + new Date().getTime() : '');
link.media = 'all';
if (!doc.getElementById(id)) {
head.appendChild(link);
}
if (typeof fn !== 'function') {
return that;
}
// 轮询css是否加载完毕
(function poll () {
if (++timeout > (config.timeout * 1000) / 100) {
return error(href + ' timeout');
}
parseInt(that.getStyle(doc.getElementById(id), 'width')) === 1989
? (function () {
fn();
})()
: setTimeout(poll, 100);
})();
return that;
};
// 存储模块的回调
config.callback = {};
// 重新执行模块的工厂函数
Layui.prototype.factory = function (modName) {
if (layui[modName]) {
return typeof config.callback[modName] === 'function' ? config.callback[modName] : null;
}
};
// css内部加载器
Layui.prototype.addcss = function (firename, fn, cssname) {
return layui.link(config.dir + 'css/' + firename, fn, cssname);
};
// 图片预加载
Layui.prototype.img = function (url, callback, error) {
var img = new Image();
img.src = url;
if (img.complete) {
return callback(img);
}
img.onload = function () {
img.onload = null;
typeof callback === 'function' && callback(img);
};
img.onerror = function (e) {
img.onerror = null;
typeof error === 'function' && error(e);
};
};
// 全局配置
Layui.prototype.config = function (options) {
options = options || {};
for (var key in options) {
config[key] = options[key];
}
return this;
};
// 记录全部模块
Layui.prototype.modules = (function () {
var clone = {};
for (var o in modules) {
clone[o] = modules[o];
}
return clone;
})();
// 拓展模块
Layui.prototype.extend = function (options) {
var that = this;
// 验证模块是否被占用
options = options || {};
for (var o in options) {
if (that[o] || that.modules[o]) {
error('\u6A21\u5757\u540D ' + o + ' \u5DF2\u88AB\u5360\u7528');
} else {
that.modules[o] = options[o];
}
}
return that;
};
// 路由解析
Layui.prototype.router = function (hash) {
var that = this;
var hash = hash || location.hash;
var data = {
path: [],
search: {},
hash: (hash.match(/[^#](#.*$)/) || [])[1] || '',
};
if (!/^#\//.test(hash)) {
return data;
} // 禁止非路由规范
hash = hash.replace(/^#\//, '');
data.href = '/' + hash;
hash = hash.replace(/([^#])(#.*$)/, '$1').split('/') || [];
// 提取Hash结构
that.each(hash, function (index, item) {
/^\w+=/.test(item)
? (function () {
item = item.split('=');
data.search[item[0]] = item[1];
})()
: data.path.push(item);
});
return data;
};
// 本地持久性存储
Layui.prototype.data = function (table, settings, storage) {
table = table || 'layui';
storage = storage || localStorage;
if (!win.JSON || !win.JSON.parse) {
return;
}
// 如果settings为null,则删除表
if (settings === null) {
return delete storage[table];
}
settings = typeof settings === 'object' ? settings : { key: settings };
try {
var data = JSON.parse(storage[table]);
} catch (e) {
var data = {};
}
if ('value' in settings) {
data[settings.key] = settings.value;
}
if (settings.remove) {
delete data[settings.key];
}
storage[table] = JSON.stringify(data);
return settings.key ? data[settings.key] : data;
};
// 本地会话性存储
Layui.prototype.sessionData = function (table, settings) {
return this.data(table, settings, sessionStorage);
};
// 设备信息
Layui.prototype.device = function (key) {
var agent = navigator.userAgent.toLowerCase();
// 获取版本号
var getVersion = function (label) {
var exp = new RegExp(label + '/([^\\s\\_\\-]+)');
label = (agent.match(exp) || [])[1];
return label || false;
};
// 返回结果集
var result = {
os: (function () {
// 底层操作系统
if (/windows/.test(agent)) {
return 'windows';
} else if (/linux/.test(agent)) {
return 'linux';
} else if (/iphone|ipod|ipad|ios/.test(agent)) {
return 'ios';
} else if (/mac/.test(agent)) {
return 'mac';
}
})(),
ie: (function () {
// ie版本
return !!win.ActiveXObject || 'ActiveXObject' in win
? (agent.match(/msie\s(\d+)/) || [])[1] || '11' // 由于ie11并没有msie的标识
: false;
})(),
weixin: getVersion('micromessenger'), // 是否微信
};
// 任意的key
if (key && !result[key]) {
result[key] = getVersion(key);
}
// 移动设备
result.android = /android/.test(agent);
result.ios = result.os === 'ios';
return result;
};
// 提示
Layui.prototype.hint = function () {
return {
error: error,
};
};
// 遍历
Layui.prototype.each = function (obj, fn) {
var key;
var that = this;
if (typeof fn !== 'function') {
return that;
}
obj = obj || [];
if (obj.constructor === Object) {
for (key in obj) {
if (fn.call(obj[key], key, obj[key])) {
break;
}
}
} else {
for (key = 0; key < obj.length; key++) {
if (fn.call(obj[key], key, obj[key])) {
break;
}
}
}
return that;
};
// 将数组中的对象按其某个成员排序
Layui.prototype.sort = function (obj, key, desc) {
var clone = JSON.parse(JSON.stringify(obj || []));
if (!key) {
return clone;
}
// 如果是数字,按大小排序,如果是非数字,按字典序排序
clone.sort(function (o1, o2) {
var isNum = /^-?\d+$/;
var v1 = o1[key];
var v2 = o2[key];
if (isNum.test(v1)) {
v1 = parseFloat(v1);
}
if (isNum.test(v2)) {
v2 = parseFloat(v2);
}
if (v1 && !v2) {
return 1;
} else if (!v1 && v2) {
return -1;
}
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
} else {
return 0;
}
});
desc && clone.reverse(); // 倒序
return clone;
};
// 阻止事件冒泡
Layui.prototype.stope = function (thisEvent) {
thisEvent = thisEvent || win.event;
try {
thisEvent.stopPropagation();
} catch (e) {
thisEvent.cancelBubble = true;
}
};
// 自定义模块事件
Layui.prototype.onevent = function (modName, events, callback) {
if (typeof modName !== 'string' || typeof callback !== 'function') {
return this;
}
return Layui.event(modName, events, null, callback);
};
// 执行自定义模块事件
Layui.prototype.event = Layui.event = function (modName, events, params, fn) {
var that = this;
var result = null;
var filter = events.match(/\((.*)\)$/) || []; // 提取事件过滤器字符结构,如:select(xxx)
var eventName = (modName + '.' + events).replace(filter[0], ''); // 获取事件名称,如:form.select
var filterName = filter[1] || ''; // 获取过滤器名称,,如:xxx
var callback = function (_, item) {
var res = item && item.call(that, params);
res === false && result === null && (result = false);
};
// 添加事件
if (fn) {
config.event[eventName] = config.event[eventName] || {};
// 这里不再对多次事件监听做支持,避免更多麻烦
// config.event[eventName][filterName] ? config.event[eventName][filterName].push(fn) :
config.event[eventName][filterName] = [fn];
return this;
}
// 执行事件回调
layui.each(config.event[eventName], function (key, item) {
// 执行当前模块的全部事件
if (filterName === '{*}') {
layui.each(item, callback);
return;
}
// 执行指定事件
key === '' && layui.each(item, callback);
filterName && key === filterName && layui.each(item, callback);
});
return result;
};
// 加载自定义事件
NodeList.prototype.forEach = Array.prototype.forEach;
window.customEvent = {
rootScope: {
name: 'document',
handleEvent: {},
events: {},
children: [],
},
/**
* @description: 用于处理模板解析
* @param {String} template 传递已经被latpl编译的模板
* @param {String} locationId id
* @return {String} 返回已经被latpl编译的模板
*/
parse: function (template, locationId) {
var $ = layui.$;
// 查找父级组件
var that = this;
var currentScope = null;
if (!locationId) {
// 根节点初始化Scope
currentScope = that.rootScope;
} else {
var parentId = $("*[edoc='" + locationId + "']")
.parents('*[edoc]')
.first()
.attr('edoc');
var parentScope = that.findScope(parentId, that.rootScope) || that.rootScope;
var currentScope = that.findScope(locationId, that.rootScope);
if (!currentScope) {
currentScope = {
name: locationId,
handleEvent: {},
events: {},
};
parentScope.children
? parentScope.children.push(currentScope)
: (parentScope.children = [currentScope]);
}
}
// 匹配模板内部存在 @ 绑定事件的DOM
return template.replace(/<[^<]*(@\w*=\w*(\(\S*\))?\s*)+[^>]*>/gi, function (domStr) {
var randomFlag = 'data-ident=' + Math.floor(Math.random() * 1000);
while (currentScope.handleEvent[randomFlag]) {
randomFlag = 'data-ident=' + Math.floor(Math.random() * 1000);
}
// 初始化handleEvent
currentScope.handleEvent[randomFlag] = {};
// 替换生成唯一标记 然后匹配DOM上的绑定事件
// (\((?<=\()[^\)]+\))?
return domStr
.replace('>', ' ' + randomFlag + ' >')
.replace(/@\w*=\w*(\([^\)]+\))?\s*/gi, function (subStr) {
// 生成绑定事件的格式
var event = subStr.replace('@', '').trim().split('=');
currentScope.handleEvent[randomFlag][event[0]] = event[1];
return '';
});
});
},
/**
* @description: 用于绑定监听事件,并触发相关的回调
* @param {Object} data data
* @param {String} locationId id
* @return {Object} null
*/
bindEvent: function (data, locationId) {
var $ = layui.$;
var currentScope = this.findScope(locationId, this.rootScope) || this.rootScope;
var filter = $(locationId ? '*[edoc="' + currentScope.name + '"]' : 'body');
try {
Object.keys(currentScope.handleEvent).forEach(function (event) {
if (currentScope.handleEvent[event].bindStatus) {return null;}
var _EventDOM = filter.find('*[' + event + ']');
var _Events = currentScope.handleEvent[event.trim()];
Object.keys(_Events).forEach(function (_EventName) {
var _FnTemp = _Events[_EventName].split('(');
var _FnName = _FnTemp[0];
var _FnArgs = _FnTemp[1] ? _FnTemp[1].replace(')', '') : data;
try {
if (typeof _FnArgs === 'string' && isNaN(_FnArgs)) {
_FnArgs = JSON.parse(_FnArgs);
}
} catch (e) {
console.error(_FnArgs, '参数无法转化为对象', e);
}
_EventDOM.on(_EventName, function (event) {
currentScope.events[_FnName](_FnArgs, event.currentTarget);
});
Object.defineProperty(currentScope.handleEvent[event], 'bindStatus', {
value: true,
});
});
});
} catch (error) {
console.error(error);
}
},
/**
* @description: 用于提供回调以挂载给绑定事件调用
* @param {String} name 回调函数名称
* @param {Function} callback 回调函数
* @return {Object} null
*/
toggleEvent: function (name, callback) {
var customEvent = window.customEvent;
var currentScope =
this.constructor.name === 'Object'
? customEvent.rootScope
: customEvent.findScope(this.id, customEvent.rootScope);
if (currentScope && currentScope.events) {currentScope.events[name] = callback;}
},
//
refresh:function(locationId){
var that=this
try {
var node=that.findScope(locationId,that.rootScope)
if(node){
node.handleEvent={},
node.events={}
}
} catch (error) {
console.log(error);
}
},
// 依赖方法
/**
* @description:数组去重
* @param {Array} arr 重复数组
* @return {Array} 去重数组
*/
unique: function (arr) {
var obj = {};
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (obj[arr[i]] === undefined) {
newArr.push(arr[i]);
obj[arr[i]] = 1;
}
}
return newArr;
},
/**
* @description: 查找作用域(不查根节点)
* @param {String} scopeName 作用域名词
* @param {Object} scopeTree 作用域树
* @return {Object} scope
*/
findScope: function (scopeName, scopeTree) {
try {
var childScopes = scopeTree.children;
for (var index = 0; index < childScopes.length; index++) {
var scope = childScopes[index];
if (scope.name === scopeName) {
return scope;
}
if (scope.children) {
var result = window.customEvent.findScope(scopeName, scope);
if (result) {
return result;
}
}
}
return null;
} catch (error) {
console.log(error);
}
},
};
win.layui = new Layui();
})(window);