diff --git a/src/layui.js b/src/layui.js index f21ef1c..24d6307 100644 --- a/src/layui.js +++ b/src/layui.js @@ -232,6 +232,21 @@ return that; }; + Layui.prototype.unuse = function (apps) { + var that = this; + apps = that.isArray(apps) ? apps : [apps]; + that.each(apps, function (index, item) { + if (!config.status[item]) { + return error('module ' + item + ' is not exist'); + } + delete that[item]; + delete modules[item]; + delete that.modules[item]; + delete config.status[item]; + delete config.modules[item]; + }) + } + //获取节点的 style 属性值 Layui.prototype.getStyle = function(node, name){ var style = node.currentStyle ? node.currentStyle : win.getComputedStyle(node, null); diff --git a/src/modules/form.js b/src/modules/form.js index ea8ab4b..043948e 100644 --- a/src/modules/form.js +++ b/src/modules/form.js @@ -145,19 +145,19 @@ layui.define('layer', function(exports){ }()) ,items = { //输入框 - input: function(){ - var inputs = elemForm.find('input,textarea'); - + input: function(elem){ + var inputs = elem || elemForm.find('input,textarea'); + //初始化全局的 autocomplete options.autocomplete && inputs.attr('autocomplete', options.autocomplete); } //下拉选择框 - ,select: function(){ + ,select: function(elem){ var TIPS = '请选择', CLASS = 'layui-form-select', TITLE = 'layui-select-title' ,NONE = 'layui-select-none', initValue = '', thatInput - ,selects = elemForm.find('select') - + ,selects = elem || elemForm.find('select') + //隐藏 select ,hide = function(e, clear){ if(!$(e.target).parent().hasClass(TITLE) || clear){ @@ -480,13 +480,13 @@ layui.define('layer', function(exports){ } //复选框/开关 - ,checkbox: function(){ + ,checkbox: function(elem){ var CLASS = { checkbox: ['layui-form-checkbox', 'layui-form-checked', 'checkbox'] ,_switch: ['layui-form-switch', 'layui-form-onswitch', 'switch'] } - ,checks = elemForm.find('input[type=checkbox]') - + ,checks = elem || elemForm.find('input[type=checkbox]') + ,events = function(reElem, RE_CLASS){ var check = $(this); @@ -552,10 +552,10 @@ layui.define('layer', function(exports){ } //单选框 - ,radio: function(){ + ,radio: function(elem){ var CLASS = 'layui-form-radio', ICON = ['', ''] - ,radios = elemForm.find('input[type=radio]') - + ,radios = elem || elemForm.find('input[type=radio]') + ,events = function(reElem){ var radio = $(this), ANIM = 'layui-anim-scaleSpring'; @@ -611,34 +611,58 @@ layui.define('layer', function(exports){ }); } }; - type ? ( - items[type] ? items[type]() : hint.error('不支持的 "'+ type + '" 表单渲染') - ) : layui.each(items, function(index, item){ - item(); - }); + if (layui._typeof(type) === 'object') { + // jquery对象 + type.each(function (index, item) { + var elem = $(item); + if (!elem.closest(ELEM).length) { + // 如果不是存在layui-form中的直接跳过 + return; + } + if (item.tagName === 'SELECT') { + items['select'](elem); + } else if (item.tagName === 'INPUT') { + var itemType = item.type; + if (itemType === 'checkbox' || itemType === 'radio') { + items[itemType](elem); + } else { + items['input'](elem); + } + } + }); + } else { + type ? ( + items[type] ? items[type]() : hint.error('不支持的 "'+ type + '" 表单渲染') + ) : layui.each(items, function(index, item){ + item(); + }); + } return that; }; - - //表单提交校验 - var submit = function(){ + + // verifyElem: 要验证的节点或者范围 返回:验证通过返回true,否则返回false + Form.prototype.doVerify = function(verifyElem){ var stop = null //验证不通过状态 - ,verify = form.config.verify //验证规则 - ,DANGER = 'layui-form-danger' //警示样式 - ,field = {} //字段集合 - ,button = $(this) //当前触发的按钮 - ,elem = button.parents(ELEM).eq(0) //当前所在表单域 - ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 - ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 - ,filter = button.attr('lay-filter'); //获取过滤器 - - + ,verify = form.config.verify //验证规则 + ,DANGER = 'layui-form-danger' //警示样式 + + if (layui.type(verifyElem) !== 'object') { // 不符合要求的格式直接判通过 + hint.error('doVerify: 参数错误'); + return true; + } + if (!verifyElem.attr('lay-verify')) { + // 验证某个容器内的节点 + verifyElem = verifyElem.find('*[lay-verify]'); + } + //开始校验 layui.each(verifyElem, function(_, item){ var othis = $(this) - ,vers = othis.attr('lay-verify').split('|') - ,verType = othis.attr('lay-verType') //提示方式 - ,value = othis.val(); - + ,verifyStr = othis.attr('lay-verify') || '' + ,vers = verifyStr.split('|') + ,verType = othis.attr('lay-verType') //提示方式 + ,value = othis.val(); + othis.removeClass(DANGER); //移除警示样式 //遍历元素绑定的验证规则 @@ -687,7 +711,7 @@ layui.define('layer', function(exports){ } else { //移动设备定位 $dom.scrollTop(function(){ try { - return (isForm2Elem ? othis.next() : othis).offset().top - 15 + return (isForm2Elem ? othis.next() : othis).focus().offset().top - 15 } catch(e){ return 0; } @@ -701,9 +725,22 @@ layui.define('layer', function(exports){ }); if(stop) return stop; }); - - if(stop) return false; - + + return !stop; + } + + //表单提交校验 + var submit = function(){ + var field = {} //字段集合 + ,button = $(this) //当前触发的按钮 + ,elem = button.parents(ELEM).eq(0) //当前所在表单域 + ,verifyElem = elem.find('*[lay-verify]') //获取需要校验的元素 + ,formElem = button.parents('form')[0] //获取当前所在的 form 元素,如果存在的话 + ,filter = button.attr('lay-filter'); //获取过滤器 + + //开始校验 + if(!form.doVerify(verifyElem)) return false; + //获取当前表单值 field = form.getValue(null, elem); diff --git a/src/modules/table.js b/src/modules/table.js index 41b1cb4..56b8eba 100644 --- a/src/modules/table.js +++ b/src/modules/table.js @@ -53,6 +53,9 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ ,reload: function(options, deep){ that.reload.call(that, options, deep); } + ,reloadData: function(options, deep){ + table.reloadData(id, options, deep); + } ,setColsWidth: function(){ that.setColsWidth.call(that); } @@ -251,6 +254,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ ,loading: true //请求数据时,是否显示 loading ,escape: true // 是否开启 HTML 编码功能,即转义 html 原文 ,cellMinWidth: 60 //所有单元格默认最小宽度 + ,editTrigger: 'click' //单元格编辑的触发方式 ,defaultToolbar: ['filter', 'exports', 'print'] //工具栏右侧图标 ,autoSort: true //是否前端自动排序。如果否,则需自主排序(通常为服务端处理好排序) ,text: { @@ -694,7 +698,11 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ that.layMain.find('tbody').html(''); that.layMain.append(that.layNone = layNone); - + + // 异常情况下对page和total的内容处理 + that.layPage && that.layPage.addClass(HIDE).find('>div').html(''); + that.layTotal && that.layTotal.addClass(HIDE).find('tbody').html(''); + table.cache[that.key] = []; //格式化缓存数据 }; @@ -941,6 +949,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ //正常初始化数据渲染 render(); //渲染数据 that.renderTotal(data, totalRowData); //数据合计 + that.layTotal && that.layTotal.removeClass(HIDE); //同步分页状态 if(options.page){ @@ -1697,7 +1706,7 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ }); //单元格单击事件 - that.layBody.on('click', 'td', function(e){ + that.layBody.on(options.editTrigger, 'td', function(e){ var othis = $(this) ,field = othis.data('field') ,editType = othis.data('edit') @@ -1982,8 +1991,6 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ //表格导出 table.exportFile = function(id, data, type){ - var that = this; - data = data || table.clearCacheKey(table.cache[id]); type = type || 'csv'; @@ -2023,8 +2030,8 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ } var content = item1[item3.field] - ,td = that.layBody.find('tr[data-index="'+ i1 +'"]>td'); - + ,td = thatTable.layBody.find('tr[data-index="'+ i1 +'"]>td'); + if(content === undefined || content === null) content = ''; i1 == 0 && dataTitle.push(item3.title || ''); @@ -2046,14 +2053,14 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ }); //表合计 - layui.each(that.dataTotal, function(key, value){ + thatTable && layui.each(thatTable.dataTotal, function(key, value){ fieldsIsHide[key] || dataTotal.push(value); }); return dataTitle.join(',') + '\r\n' + dataMain.join('\r\n') + '\r\n' + dataTotal.join(','); }()); - - alink.download = (config.title || 'table_'+ (config.index || '')) + '.' + type; + + alink.download = (config.title || 'table_'+ (config.index || new Date().getTime())) + '.' + type; document.body.appendChild(alink); alink.click(); document.body.removeChild(alink); @@ -2085,7 +2092,51 @@ layui.define(['laytpl', 'laypage', 'layer', 'form', 'util'], function(exports){ return thisTable.call(that); }; - + + //需要重新render的参数名单 + var dataParams = ['data', 'url', 'where', 'page', 'request', 'response']; + //重载数据 options只允许跟数据请求相关的配置信息 + table.reloadData = function(id, options, deep){ + var config = getThisTableConfig(id); //获取当前实例配置项 + if (!config) return; + + var that = thisTable.that[id]; + options = options || {}; + + if (options.page !== undefined && !!options.page !== !!config.page) { + // 如果是否分页发生了改变 + hint.error('reloadData不允许对是否分页进行切换(从不分页到分页的切换,反之亦然),如果需要请使用reload重载'); + delete options.page; + } + //过滤options只留下跟数据请求相关的参数 + layui.each(options, function (_key, _value) { + if (dataParams.indexOf(_key) === -1) { + delete options[_key]; + } + }); + if (options.page !== undefined) { // 针对page组件的特殊处理 + if (typeof options.page === 'object') { + options.page.curr && (that.page = options.page.curr); + delete options.elem; + delete options.jump; + } else if (options.page) { + options.page = {}; + } + $.extend(true, that.config, {page: options.page}); + delete options.page; + } + + if (options.data && options.data.constructor === Array) delete that.config.data; + deep ? $.extend(true, that.config, options) : $.extend(that.config, options); + if (!that.config.page) { + that.page = 1; + } + that.loading(); + that.pullData(that.page); + return thisTable.call(that); + } + + //核心入口 table.render = function(options){ var inst = new Class(options);