原生 select 带搜索功能
随着前端功能的不断完善带搜索的选择框也是迫切需要的,但是原生的搜索框不支持这个功能,所以就开发了一个
思考:怎么将代码可以封装到很完善,很简洁,是函数的闭包加回调函数好,还是要面向对象的写法好(此案例采用第一种)
重点:select 标签 html5 新增的 size 属性
只要将此代码复制粘贴即可查看效果
实现思路:select方法,向外暴露了两个方法,一个是setData 填充数据,一个是curData 查看选中数据,
select有两个参数,一个是dom元素,一个是配置内容
初始时,会将固定的内容拼接到dom元素下面,配置内容分为两种,一种是固定的内容,一种是回调函数的内容,我还为了省事,将dom元素下的input 元素 及 select 元素暴露出去,
从而进行dom操作来满足大部分的业务需求,
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> <style> *{ margin: 0; padding: 0; } #demo1{ margin-top: 20px; margin-left: 20px; width: 300px; height: 20px; } </style> </head> <body> <button onclick="fn()"> 获取 </button> <div id="demo1"></div> </body> <script> // dom 元素,obj 配置 function select(dom, obj){ function init(){ if(!window.selectSearchInput){ window.selectSearchInput = 500; } window.selectSearchInput -= 2; var selectSearchInput = window.selectSearchInput if(obj.selectSearchInput){ selectSearchInput = obj.selectSearchInput } var style = document.createElement('style'); style.innerHTML = '#'+dom.id +' .select-search{\ position: relative;\ height: 100%;\ }\ #'+dom.id +' .select-search .select-search-input{\ width: 100%;\ height: 100%;\ position: absolute;\ z-index: ' + selectSearchInput + '; \ box-sizing: border-box;\ top: 0;\ left: 0;\ }\ #'+dom.id +' .select-search .select-search-select{\ width: 100%;\ position: absolute;\ z-index: ' + selectSearchInput + '; \ top: 0;\ left: 0;\ outline: none;\ }\ #'+dom.id +' .select-search .select-search-select option{\ height: '+ dom.offsetHeight +'px;\ cursor: pointer;\ }\ #'+dom.id +' .select-search .select-search-select option:hover{\ color: #fff;\ background: #5897fb;\ }' var ref = document.querySelector('script'); ref.parentNode.insertBefore(style, ref); var str = ''; str += '<div class="select-search">\ <select size="0" class="select-search-select"></select>\ <input type="text" class="select-search-input">\ </div>' dom.innerHTML = str; } init(); // input 元素操作 var input = dom.getElementsByClassName('select-search-input')[0]; // select 元素操作 var select = dom.getElementsByClassName('select-search-select')[0]; // 数据源 var datasoure = []; // 当前数据 var currsoure = []; // 事件触发 var time = null; if(obj.input){ obj.input(input); } if(obj.select){ obj.select(select); } // 填充select的数据 function selectData(data){ var str = '<option> 占位符 </option>'; for(var i=0;i<data.length;i++){ str += '<option value='+data[i].id+' indexKey='+ data[i].indexKey +'> '+ data[i].text +' </option>'; } select.innerHTML = str; } // 设置 data function setData(data){ for(var i=0;i<data.length;i++){ data[i].indexKey = i; } datasoure = data; if(obj.isSelectHtml){ select.innerHTML = data; } else { selectData(data); } } // 获取当前选中状态 function curData(){ return currsoure; } // 点击展开select标签 input.onfocus = function(e){ select.setAttribute('size', obj.size? obj.size : '7'); } // input失焦关闭select标签 input.onblur = function(e){ setTimeout(function() { select.setAttribute('size', ''); }, 250) } // 实时获取input值 input.oninput = function(e){ // 延迟执行,防止一直调接口 if(time!=null){ clearTimeout(time) } time=setTimeout(function(){ var val = e.target.value; currsoure = []; if(obj.isRequest){ obj.search(val); } else { var patty = new RegExp(val); var arr = [] for(var i=0;i<datasoure.length;i++){ if(patty.test(datasoure[i].text)){ arr.push(datasoure[i]) } } selectData(arr); } },obj.delay? obj.delay: 500) } // 获取选择是值 select.onchange = function(e){ var option = dom.getElementsByTagName('option'); var str = '' currsoure = []; for(var i=1;i<option.length;i++){ if(option[i].selected){ var indexKey = option[i].getAttribute('indexKey') currsoure.push(datasoure[indexKey]); str += datasoure[indexKey].text + ','; } } input.value = str.slice(0,str.length-1); this.setAttribute('size', '0'); } return { setData, // 设置数据 curData, // 获取选中内容 } } var arr = []; for(var i=0;i<50;i++){ arr.push({ id: i+'', text: '这是对应的值'+i }) } var config = select(document.getElementById('demo1'), { size: '7', // 展示的数据 selectSearchInput: 500, // 自定义z-index delay: 500, // 延迟时间 isRequest: false, // 是否自定义搜索 isSelectHtml: false, // 是否自定义option内容 input: function(e){ // input 的dom操作 // console.log(e) e.setAttribute('placeholder','请选择内容') }, select: function(e){ // select 的dom操作 // console.log(e); }, search: function(e){ // 带搜索 config.setData(arr); }, }) config.setData(arr); function fn(){ console.log(config.curData()); } </script> </html>
在安利一个小技巧
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title></title> </head> <body> <input type="text" id="input"> </body> <script> var input = document.getElementById('input'); function fn(dom) { function on(event, handler){ dom[event] = handler } return { on }; } var f = fn(input); f.on('oninput',function(e){ console.log(e); }) </script> </html>