diff --git a/docs/form/index.md b/docs/form/index.md index 55ec52f8..5d080782 100644 --- a/docs/form/index.md +++ b/docs/form/index.md @@ -117,6 +117,7 @@ form 还可以借助*栅格*实现更灵活的响应式布局。 | lay-affix | [#详见](input.html#affix) | 输入框动态点缀,``元素 **私有属性** | | lay-skin | [#详见](checkbox.html#default) | 设置 UI 风格。 `` 元素 **私有属性** | | lay-search | 默认不区分大小写;设置`cs`区分大小写 | 给 `select` 组件开启搜索功能。`` 元素 **私有属性** | +| lay-creatable 2.9.7+ | 无需值 | 是否允许创建新条目,需要配合 `lay-search` 使用。`` 元素 **私有属性** } | | lay-submit | 无需值 | 设置元素(一般为`` 标签)触发 `submit` 提交事件 | | lay-ignore | 无需值 | 设置表单元素忽略渲染,即让元素保留系统原始 UI 风格 | diff --git a/docs/form/select.md b/docs/form/select.md index 5f297669..e71a4e13 100644 --- a/docs/form/select.md +++ b/docs/form/select.md @@ -161,6 +161,18 @@ toc: true + + + 可创建新的 option + AAA + aaa + BBB + bbb + ABC + abc + AbC + + diff --git a/src/modules/form.js b/src/modules/form.js index 604f4ff3..c6250278 100644 --- a/src/modules/form.js +++ b/src/modules/form.js @@ -375,6 +375,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){ var CLASS = 'layui-form-select'; var TITLE = 'layui-select-title'; var NONE = 'layui-select-none'; + var CREATE_OPTION = 'layui-select-create-option'; var initValue = ''; var thatInput; var selects = elem || elemForm.find('select'); @@ -382,14 +383,18 @@ layui.define(['lay', 'layer', 'util'], function(exports){ // 隐藏 select var hide = function(e, clear){ if(!$(e.target).parent().hasClass(TITLE) || clear){ - $('.'+CLASS).removeClass(CLASS+'ed ' + CLASS+'up'); + var elem = $('.' + CLASS); + elem.removeClass(CLASS+'ed ' + CLASS+'up'); + if(elem.hasClass('layui-select-creatable')){ + elem.children('dl').children('.' + CREATE_OPTION).remove(); + } thatInput && initValue && thatInput.val(initValue); } thatInput = null; }; // 各种事件 - var events = function(reElem, disabled, isSearch){ + var events = function(reElem, disabled, isSearch, isCreatable){ var select = $(this); var title = reElem.find('.' + TITLE); var input = title.find('input'); @@ -408,6 +413,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){ var showDown = function(){ var top = reElem.offset().top + reElem.outerHeight() + 5 - $win.scrollTop(); var dlHeight = dl.outerHeight(); + var dds = dl.children('dd'); index = select[0].selectedIndex; // 获取最新的 selectedIndex reElem.addClass(CLASS+'ed'); @@ -432,6 +438,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){ reElem.removeClass(CLASS+'ed ' + CLASS+'up'); input.blur(); nearElem = null; + isCreatable && dl.children('.' + CREATE_OPTION).remove(); if(choose) return; @@ -569,10 +576,18 @@ layui.define(['lay', 'layer', 'util'], function(exports){ // 检测值是否不属于 select 项 var notOption = function(value, callback, origin){ var num = 0; + var dds = dl.children('dd'); + var hasEquals = false; + var rawValue = value; layui.each(dds, function(){ var othis = $(this); var text = othis.text(); + // 需要区分大小写 + if(isCreatable && text === rawValue){ + hasEquals = true; + } + // 是否区分大小写 if(laySearch !== 'cs'){ text = text.toLowerCase(); @@ -583,17 +598,18 @@ layui.define(['lay', 'layer', 'util'], function(exports){ var not = text.indexOf(value) === -1; if(value === '' || (origin === 'blur') ? value !== text : not) num++; - origin === 'keyup' && othis[not ? 'addClass' : 'removeClass'](HIDE); + origin === 'keyup' && othis[(not && (isCreatable ? !othis.hasClass(CREATE_OPTION) : true)) ? 'addClass' : 'removeClass'](HIDE); }); // 处理 select 分组元素 origin === 'keyup' && layui.each(dts, function(){ - var othis = $(this) - ,thisDds = othis.nextUntil('dt').filter('dd') // 当前分组下的dd元素 - ,allHide = thisDds.length == thisDds.filter('.' + HIDE).length; // 当前分组下所有dd元素都隐藏了 + var othis = $(this); + var thisDds = othis.nextUntil('dt').filter('dd'); // 当前分组下的dd元素 + if(isCreatable) thisDds = thisDds.not('.' + CREATE_OPTION); + var allHide = thisDds.length == thisDds.filter('.' + HIDE).length; // 当前分组下所有dd元素都隐藏了 othis[allHide ? 'addClass' : 'removeClass'](HIDE); }); var none = num === dds.length; - return callback(none), none; + return callback(none, hasEquals), none; }; // 搜索匹配 @@ -607,11 +623,27 @@ layui.define(['lay', 'layer', 'util'], function(exports){ return false; } - notOption(value, function(none){ - if(none){ - dl.find('.'+NONE)[0] || dl.append('无匹配项'); - } else { - dl.find('.'+NONE).remove(); + notOption(value, function(none, hasEquals){ + if(isCreatable){ + if(hasEquals){ + dl.children('.' + CREATE_OPTION).remove(); + }else{ + // 和初始渲染保持行为一致 + var textVal = $('' + value +'').text(); + var createOptionElem = dl.children('.' + CREATE_OPTION); + if(createOptionElem[0]){ + createOptionElem.attr('lay-value', value); + createOptionElem.text(textVal); + }else{ + dl.append('' + textVal + ''); + } + } + }else{ + if(none){ + dl.find('.'+NONE)[0] || dl.append('无匹配项'); + } else { + dl.find('.'+NONE).remove(); + } } }, 'keyup'); @@ -622,6 +654,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){ dl.find('.'+ THIS).removeClass(THIS); (select[0].options[0] || {}).value || dl.children('dd:eq(0)').addClass(THIS); dl.find('.'+ NONE).remove(); + isCreatable && dl.children('.' + CREATE_OPTION).remove(); } followScroll(); // 定位滚动条 @@ -653,7 +686,7 @@ layui.define(['lay', 'layer', 'util'], function(exports){ } // 选择 - dds.on('click', function(){ + dl.on('click', 'dd', function(){ var othis = $(this), value = othis.attr('lay-value'); var filter = select.attr('lay-filter'); // 获取过滤器 @@ -666,6 +699,11 @@ layui.define(['lay', 'layer', 'util'], function(exports){ othis.addClass(THIS); } + if(isCreatable && othis.hasClass(CREATE_OPTION)){ + othis.removeClass(CREATE_OPTION); + select.append('' + value + ''); + } + othis.siblings().removeClass(THIS); select.val(value).removeClass('layui-form-danger'); @@ -698,13 +736,15 @@ layui.define(['lay', 'layer', 'util'], function(exports){ if(typeof othis.attr('lay-ignore') === 'string') return othis.show(); var isSearch = typeof othis.attr('lay-search') === 'string' + ,isCreatable = typeof othis.attr('lay-creatable') === 'string' && isSearch ,placeholder = optionsFirst ? ( optionsFirst.value ? TIPS : (optionsFirst.innerHTML || TIPS) ) : TIPS; // 替代元素 var reElem = $(['' + ,(disabled ? ' layui-select-disabled' : '') + ,(isCreatable ? ' layui-select-creatable' : '') + '">' ,'' ,('
无匹配项