简单易用,绑定一个div就能生成下拉列表
new Selector()的参数1:HTMLDivElement或div元素的id:,参数2(可选):选项数据的数组,参数3(可选):文本框值或选项改变时的回调函数(value, index, selector),下面有例子
方法介绍,除getValue()方法外的其他方法都支持链式调用Selector的自定义方法
方法 | 方法作用 | 其它说明 |
---|---|---|
setBoxCss(json) | 修改文本框样式 | 可传入任意div支持的样式 |
setPanelCss(json) | 修改下拉列表面板样式 | 可传入任意div支持的样式 |
setItemCss(json) | 修改下拉列表选项正常样式 | 可传入任意div支持的样式 |
setItemHoverCss(json) | 修改下拉列表选项正hover样式 | 可传入任意div支持的样式 |
setOptions(array,bool) | 设置选项 | 参数2为true代表临时设置,主要是过滤器用的 |
setCallback(function) | 设置文本框值改变或选项改变时的回调方法 | 回调有三个参数,对应值和索引和Selector本身引用,可在此调用它的方法 |
setFilter(function, bool) | 设置选项过滤器 | 回调返回选项值,返回false移除该选项,第一个参数传null不会修改过滤器,第二个参数可为true关闭过滤器 |
getOptsFromServer(json, function) | 通过url加载选项 | json是请求选项{url,method(可选),参数(可选)}回调作为数据适配器返回url请求响应的数据,默认适配器把data作为选项数据,可以在此对数据进行处理确保返回一个数组作为选项数据 |
updatePostParams(json) | 更新搜素参数,根据关键字重新索索 | |
doFilter(string) | 主动过滤选项 | string是过滤关键字,在过滤器关闭时无效 |
showPanel() | 主动显示下拉面板 | |
hidePanel() | 主动隐藏下拉面板 | |
getValue() | 获取文本框的值 | 返回string不可以在其后链式调Selector其它自定义方法 |
setValue(string) | 设置文本框的值 |
效果图:
注:需依赖jquery,我用的是jquery1.11.3.min.js
Selectord代码
function Selector(id, options, callback) { this.options = options || []; // 选项数据数 this.tempOptions = []; this.callback = callback || function () {}; // 选项改变或文本框内容改变时的回调处理函数 this.urlOp = {}; // 请求,包含地址:url,请求方式:method,参数:data this.dataAdapter = function () {}; // 数据适配器,如果返回数据不是数组需用此方法转化为数组做为选项数据 this.runFilter = false; // 文本输入时是否对选项进行过滤 this.filter = function (value, key) { value = value || ''; key = key || ''; return value.indexOf(key) >= 0 || key.indexOf(value) >= 0; }; // 选项过滤器,默认关闭 if(id && id.constructor == HTMLDivElement) { this.ele = id; } else { this.ele = document.getElementById(id); } if(!this.ele || this.ele.constructor != HTMLDivElement) { console.error('error id of div element bing on selector'); return {}; } if(this.ele.tagName != 'DIV') { console.error('please bind on div element'); return {}; } this.defBoxCss = { 'padding-right':'20px', 'background':'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8cmVjdCB4PSItMSIgeT0iLTEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMiIgaWQ9ImNhbnZhc19iYWNrZ3JvdW5kIiBmaWxsPSJub25lIi8+CiA8L2c+CiA8Zz4KICA8cG9seWdvbiBwb2ludHM9IjEyLjcxNDYwNzY4NTgwNDM2Nyw3LjYyOTAyMjU5ODI2NjYwMiA4LjI4Mzk2NjUxMTQ4Nzk2LDEzLjA2OTEwMzI0MDk2Njc5NyAzLjg1MzMyNzcyMTM1NzM0NTYsNy42MjkwMjI1OTgyNjY2MDIgIiBpZD0ic3ZnXzEiIHN0cm9rZT0ibnVsbCIvPgogPC9nPgo8L3N2Zz4=) no-repeat 100% center' }; this.defPanelCss = { 'position': 'absolute', 'background-color': '#fff', 'z-index': '999999999', 'padding': '1px', 'transition': 'width 0.5s', 'overflow': 'auto' }; this.defListItemCss = { 'background-color': '#fff', 'height': '30px', 'veritical-align': 'middle', 'padding' : '3px', 'margin-top': '1px', 'cursor': 'pointer' }; this.defListItemHoverCss = { 'background-color': '#0ebebe' }; var w = $(this.ele).innerWidth(); var h = $(this.ele).innerHeight(); this.input = document.createElement('input'); $(this.selectorListPanel).css(this.defPanelCss); this.input.style.width = w+'px'; this.input.style.height = h+'px'; this.input.style.padding = '3px'; $(this.input).css(this.defBoxCss); this.ele.appendChild(this.input); this.selectorListPanel = document.createElement('div'); $(this.selectorListPanel).css(this.defPanelCss); this.selectorListPanel.style.position = 'fixed'; this.selectorListPanel.style.display = 'none'; this.selectorListPanel.tabIndex = '0'; this.ele.appendChild(this.selectorListPanel); this.listItems = []; this.index = 0; var value = this.input.value || ''; var obj = this; var hoverIndex = 0; this.input.addEventListener('blur', function () { if(value || obj.options[hoverIndex] == value || obj.tempOptions[hoverIndex] == value) { obj.selected(hoverIndex); if(obj.callback && obj.callback.constructor == Function) { obj.callback(value, obj.index, obj); obj.doFilter(value); } } obj.selectorListPanel.style.display = 'none'; }); this.input.addEventListener('focus', function (e) { obj.showPanel(); }); this.input.addEventListener('input', function () { value = obj.input.value; if(obj.callback && obj.callback.constructor == Function) { obj.callback(value, -1, obj); obj.doFilter(value); } }); this.setBoxCss = function (css) { for (var p in css) { obj.defBoxCss[p] = css[p]; } $(this.input).css(obj.defBoxCss); return obj; }; this.setPanelCss = function (css) { for (var p in css) { obj.defPanelCss[p] = css[p]; } $(obj.selectorListPanel).css(obj.defPanelCss); return obj; }; this.setItemCss = function(css) { for (var p in css) { obj.defListItemCss[p] = css[p]; } obj.setOptions(obj.options); return obj; } this.setItemHoverCss = function(hoverCss) { for (var p in hoverCss) { obj.defListItemHoverCss[p] = hoverCss[p]; } return obj; }; this.setOptions = function (opts, isTemp) { if(!opts || opts.constructor != Array) { return obj; } if(!isTemp) { obj.options = opts.slice(0); } else { obj.tempOptions = opts.slice(0); } obj.selectorListPanel.innerHTML = ''; obj.listItems = []; for(var i in opts) { var listItem = document.createElement('div'); $(listItem).css(obj.defListItemCss); listItem.textContent = opts[i]; listItem.addEventListener('click', function (e) { obj.selected(hoverIndex); obj.selectorListPanel.style.display = 'none'; }); listItem.addEventListener('mouseover', function (e) { $(this).css(obj.defListItemHoverCss); if(!obj.defListItemHoverCss['line-height']) { this.style.lineHeight = listItem.clientHeight + 'px'; } value = this.textContent; hoverIndex = this.getAttribute('index'); }); listItem.addEventListener('mouseout', function (e) { if(obj.index == this.getAttribute('index')) { return; } $(this).css(obj.defListItemCss); value = obj.input.value; }); listItem.setAttribute('index', i); obj.selectorListPanel.appendChild(listItem); obj.listItems.push(listItem); } if(!isTemp && !obj.input.value && opts.length > 0) { obj.selected(0); } return obj; }; this.setCallback = function(calllback){ if(calllback && calllback.constructor == Function) { obj.callback = calllback; } else { console.error('Selector ERR: callback not is Function'); } return obj; }; this.setFilter = function(filter, isOff) { obj.runFilter = !isOff; if(filter && filter) { obj.filter = filter; } return obj; } this.getOptsFromServer = function (op, dataAdapter) { if(!op) { console.error('Selector ERR: invalid parameter'); return obj; } obj.urlOp = op; $.ajax({ url: op.url, type: op.method || 'GET', dataType: 'json', data: op.data || {}, async: false, success: function (data) { var arr = null; if(dataAdapter && dataAdapter.constructor == Function) { obj.dataAdapter = dataAdapter; arr = obj.dataAdapter(data); } else { arr = data; } if(arr && arr.dataAdapter.constructor == Array) { obj.setOptions(arr); } else { console.error('Selector ERR: invalid data'); } }, error: function (err) { console.error('Selector ERR:'); console.error(err); } }); return obj; }; //用以搜索 this.updatePostParams = function(data) { obj.urlOp.data = data; obj.getOptsFromServer(obj.urlOp, obj.dataAdapter); } this.selected = function(idx) { if(idx >= 0 && idx < obj.options.length) { $(obj.listItems[obj.index]).css(obj.defListItemCss); $(obj.listItems[idx]).css(obj.defListItemHoverCss); obj.input.value = value = this.options[idx]; obj.input.value = obj.listItems[idx].textContent; obj.index = idx; } return obj; }; this.getValue = function () { return obj.input.value; }; this.setValue = function (text) { obj.input.value = text; }; this.showPanel= function() { if(obj.options.length == 0) { return obj; } var w = $(obj.input).innerWidth(); var h = $(obj.input).innerHeight(); var ch = this.ele.clientHeight; var left = $(obj.input).offset().left - document.documentElement.scrollLeft; var top = $(obj.input).offset().top - document.documentElement.scrollTop; var panelHeight = $(this.selectorListPanel).height(); obj.selectorListPanel.style.width = w+'px'; obj.selectorListPanel.style.maxHeight = $(window).height()/2+'px'; var panelTop = top+5+h; obj.selectorListPanel.style.top = panelTop+'px'; obj.selectorListPanel.style.boxShadow= '1px 1px 3px rgba(1, 1, 1, 0.77)'; if(panelTop+panelHeight > $(window).height()) { var panelTop = top-5-$(obj.selectorListPanel).height(); obj.selectorListPanel.style.top = panelTop+'px'; obj.selectorListPanel.style.boxShadow= '1px -1px 3px rgba(1, 1, 1, 0.77)'; } obj.selectorListPanel.style.display = 'block'; return obj; }; this.hidePanel = function() { obj.selectorListPanel.style.display = 'none'; } this.doFilter = function (key) { if(obj.runFilter && obj.filter && obj.filter.constructor == Function) { obj.setOptions(obj.options.filter(function (item) { return obj.filter(item, key); }), true); obj.index = hoverIndex = 0; obj.showPanel(); } return obj; } window.addEventListener('resize', function (ev) { if(obj.selectorListPanel.style.display == 'block') { obj.showPanel(); } }); window.addEventListener('scroll', function (ev) { if(obj.selectorListPanel.style.display == 'block') { obj.showPanel(); } }); this.setOptions(obj.options); }
下面是包含示例代码和说明的网页源码
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <style type="text/css"> .sele { margin-left: 400px; width: 200px; height: 30px; margin-top: 100px; } </style> </head> <body> <div style="height: 600px;background-color: #efefef; overflow: scroll;"> <div>简单易用,绑定一个div就能生成下拉列表</div> <div>new Selector()的参数1:HTMLDivElement或div元素的id:,参数2:选项数据的数组,参数3:文本框值或选项改变时的回调函数(value, index),下面有例子</div> <table border="1" cellpadding="0"> <title>Selector的方法介绍,除getValue()方法外的其他方法都支持链式调用Selector的自定义方法</title> <thead> <th>方法</th> <th>方法作用</th> <th>其它说明</th> </thead> <tbody> <tr> <td>setBoxCss(json)</td> <td>修改文本框样式</td> <td>可传入任意div支持的对象</td> </tr> <tr> <td>setPanelCss(json)</td> <td>修改下拉列表面板样式</td> <td>可传入任意div支持的对象</td> </tr> <tr> <td>setItemCss(json)</td> <td>修改下拉列表选项正常样式</td> <td>可传入任意div支持的对象</td> </tr> <tr> <td>setItemHoverCss(json)</td> <td>修改下拉列表选项正hover样式</td> <td>可传入任意div支持的对象</td> </tr> <tr> <td>setOptions(array,bool)</td> <td>设置选项</td> <td>参数2为true代表临时设置,主要是过滤器用的</td> </tr> <tr> <td>setCallback(function)</td> <td>设置文本框值改变或选项改变时的回调方法</td> <td>回调有三个参数,对应值和索引和Selector本身引用,可在此调用它的方法</td> </tr> <tr> <td>setFilter(function, bool)</td> <td>设置选项过滤器</td> <td>回调返回选项值,返回false移除该选项,第一个参数传null不会修改过滤器,第二个参数可为true关闭过滤器</td> </tr> <tr> <td>getOptsFromServer(json, function)</td> <td>通过url加载选项</td> <td>json是请求选项{url,method(可选),参数(可选)}回调作为数据适配器返回url请求响应的数据,默认适配器把data作为选项数据,可以在此对数据进行处理确保返回一个数组作为选项数据</td> </tr> <tr> <td>updatePostParams(json)</td> <td>更新搜素参数,根据关键字重新索索</td> </tr> <tr> <td>doFilter(string)</td> <td>主动过滤选项</td> <td>string是过滤关键字,在过滤器关闭时无效</td> </tr> <tr> <td>showPanel()</td> <td>主动显示下拉面板</td> </tr> <tr> <td>hidePanel()</td> <td>主动隐藏下拉面板</td> </tr> <tr> <td>getValue()</td> <td>获取文本框的值</td> <td>返回string不可以在其后链式调Selector其它自定义方法</td> </tr> <tr> <td>setValue(string)</td> <td>设置文本框的值</td> <td></td> </tr> </tbody> </table> <h3>注:需依赖jquary</h3> <h5>Selector使用例子1</h5> <pre> //Selector的参数1:HTMLDivElement或div元素的id:,参数2:选项数据的数组,参数3:文本框值或选项改变时的回调函数(value, index) var st1 = new Selector(s1, ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7'], function (value, index, selector) { console.log(value, index); }).selected(3); //重置opations //st1.setOptions(['a','v','c']); </pre> <h5>Selector使用例子2</h5> <pre> new Selector('s2').setBoxCss({'width':'300px', 'height':'50px'}).setOptions(['1','2','3','4']) .setItemCss({'height':'60px'}).setItemHoverCss({'background':'#0d71bb'}) .setCallback(function (value, index) { console.log(value, index); }); </pre> <h5>Selector使用例子3</h5> <pre> new Selector('s3').getOptsFromServer({'url':'https:xxxx'}).setCallback(function (value, index) { console.log(value, index); }); </pre> <h5>Selector使用例子4(搜索)</h5> <pre> //搜索例子 new Selector('s4').getOptsFromServer({'url':'https:xxxx'}, function (data) { return data.list; //数据适配器对data进行处理,返回数组做为选项 }).setCallback(function (value, index, selector) { //选项发送变化 selector.updatePostParams({key:value}); //更新参数重新请求 console.log(value, index); }); </pre> <h5>Selector使用例子5(使用默认过滤器和自定义选项过滤器)</h5> <pre> new Selector('s5', ['a1', 'a2', 'a3', 'a4']).setCallback(function (v,i) { console.log(v+','+i); }).selected(1).setFilter(null); //打开默认选项过滤器 new Selector(s6, ['','a1', 'a2', 'a3', 'a4']).setCallback(function (v,i) { console.log(v+','+i); }).setFilter(function (item, key) { //选项过滤器 return (item || '').indexOf(key) >= 0; }); </pre> </div> <div id='s1' class="sele"></div> <div id='s2' class="sele"></div> <div id='s3' class="sele"></div> <div id='s4' class="sele"></div> <div id='s5' class="sele"></div> <div id='s6' class="sele"></div> <div style="height: 1000px; width: 20px;background-color: #0d71bb"></div> <script type="text/javascript" src="jquery1.11.3.min.js"></script> <script type="text/javascript"> new Selector(s1, ['a1', 'a2', 'a3', 'a4', 'a5', 'a6', 'a7']).setCallback(function (v,i) { console.log(v+','+i); }).selected(2); new Selector('s2').setOptions(['1','2','3','4']).setCallback(function (value, index) { console.log(value, index); }).setBoxCss({'width':'300px', 'height':'50px', 'border-radius':'5px'}).setItemCss({'height':'60px'}).setItemHoverCss({'background':'#75b4bb'}); new Selector('s3').getOptsFromServer({url:'https:xxxx', method:'post', data:{key:''}}).setCallback(function (value, index) { console.log(value, index); }); //搜索例子 new Selector('s4').getOptsFromServer({'url':'https:xxxx'}, function (data) { return data.list; //数据适配器对data进行处理,返回数组做为选项 }).setCallback(function (value, index, selector) { //选项发送变化 selector.updatePostParams({key:value}); //更新参数重新请求 console.log(value, index); }); new Selector('s5', ['a1', 'a2', 'a3', 'a4']).setCallback(function (v,i) { console.log(v+','+i); }).selected(2).setFilter(null); //打开默认选项过滤器 new Selector(s6, ['a1', 'a2', 'a3', 'a4']).setCallback(function (v,i) { console.log(v+','+i); }).setFilter(function (item, key) { //自定义选项过滤器 return (item || '').indexOf(key) >= 0; }); function Selector(id, options, callback) { this.options = options || []; // 选项数据数 this.tempOptions = []; this.callback = callback || function () {}; // 选项改变或文本框内容改变时的回调处理函数 this.urlOp = {}; // 请求,包含地址:url,请求方式:method,参数:data this.dataAdapter = function () {}; // 数据适配器,如果返回数据不是数组需用此方法转化为数组做为选项数据 this.runFilter = false; // 文本输入时是否对选项进行过滤 this.filter = function (value, key) { value = value || ''; key = key || ''; return value.indexOf(key) >= 0 || key.indexOf(value) >= 0; }; // 选项过滤器,默认关闭 if(id && id.constructor == HTMLDivElement) { this.ele = id; } else { this.ele = document.getElementById(id); } if(!this.ele || this.ele.constructor != HTMLDivElement) { console.error('error id of div element bing on selector'); return {}; } if(this.ele.tagName != 'DIV') { console.error('please bind on div element'); return {}; } this.defBoxCss = { 'padding-right':'20px', 'background':'url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiA8Zz4KICA8cmVjdCB4PSItMSIgeT0iLTEiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyMiIgaWQ9ImNhbnZhc19iYWNrZ3JvdW5kIiBmaWxsPSJub25lIi8+CiA8L2c+CiA8Zz4KICA8cG9seWdvbiBwb2ludHM9IjEyLjcxNDYwNzY4NTgwNDM2Nyw3LjYyOTAyMjU5ODI2NjYwMiA4LjI4Mzk2NjUxMTQ4Nzk2LDEzLjA2OTEwMzI0MDk2Njc5NyAzLjg1MzMyNzcyMTM1NzM0NTYsNy42MjkwMjI1OTgyNjY2MDIgIiBpZD0ic3ZnXzEiIHN0cm9rZT0ibnVsbCIvPgogPC9nPgo8L3N2Zz4=) no-repeat 100% center' }; this.defPanelCss = { 'position': 'absolute', 'background-color': '#fff', 'z-index': '999999999', 'padding': '1px', 'transition': 'width 0.5s', 'overflow': 'auto' }; this.defListItemCss = { 'background-color': '#fff', 'height': '30px', 'veritical-align': 'middle', 'padding' : '3px', 'margin-top': '1px', 'cursor': 'pointer' }; this.defListItemHoverCss = { 'background-color': '#0ebebe' }; var w = $(this.ele).innerWidth(); var h = $(this.ele).innerHeight(); this.input = document.createElement('input'); $(this.selectorListPanel).css(this.defPanelCss); this.input.style.width = w+'px'; this.input.style.height = h+'px'; this.input.style.padding = '3px'; $(this.input).css(this.defBoxCss); this.ele.appendChild(this.input); this.selectorListPanel = document.createElement('div'); $(this.selectorListPanel).css(this.defPanelCss); this.selectorListPanel.style.position = 'fixed'; this.selectorListPanel.style.display = 'none'; this.selectorListPanel.tabIndex = '0'; this.ele.appendChild(this.selectorListPanel); this.listItems = []; this.index = 0; var value = this.input.value || ''; var obj = this; var hoverIndex = 0; this.input.addEventListener('blur', function () { if(value || obj.options[hoverIndex] == value || obj.tempOptions[hoverIndex] == value) { obj.selected(hoverIndex); if(obj.callback && obj.callback.constructor == Function) { obj.callback(value, obj.index, obj); obj.doFilter(value); } } obj.selectorListPanel.style.display = 'none'; }); this.input.addEventListener('focus', function (e) { obj.showPanel(); }); this.input.addEventListener('input', function () { value = obj.input.value; if(obj.callback && obj.callback.constructor == Function) { obj.callback(value, -1, obj); obj.doFilter(value); } }); this.setBoxCss = function (css) { for (var p in css) { obj.defBoxCss[p] = css[p]; } $(this.input).css(obj.defBoxCss); return obj; }; this.setPanelCss = function (css) { for (var p in css) { obj.defPanelCss[p] = css[p]; } $(obj.selectorListPanel).css(obj.defPanelCss); return obj; }; this.setItemCss = function(css) { for (var p in css) { obj.defListItemCss[p] = css[p]; } obj.setOptions(obj.options); return obj; } this.setItemHoverCss = function(hoverCss) { for (var p in hoverCss) { obj.defListItemHoverCss[p] = hoverCss[p]; } return obj; }; this.setOptions = function (opts, isTemp) { if(!opts || opts.constructor != Array) { return obj; } if(!isTemp) { obj.options = opts.slice(0); } else { obj.tempOptions = opts.slice(0); } obj.selectorListPanel.innerHTML = ''; obj.listItems = []; for(var i in opts) { var listItem = document.createElement('div'); $(listItem).css(obj.defListItemCss); listItem.textContent = opts[i]; listItem.addEventListener('click', function (e) { obj.selected(hoverIndex); obj.selectorListPanel.style.display = 'none'; }); listItem.addEventListener('mouseover', function (e) { $(this).css(obj.defListItemHoverCss); if(!obj.defListItemHoverCss['line-height']) { this.style.lineHeight = listItem.clientHeight + 'px'; } value = this.textContent; hoverIndex = this.getAttribute('index'); }); listItem.addEventListener('mouseout', function (e) { if(obj.index == this.getAttribute('index')) { return; } $(this).css(obj.defListItemCss); value = obj.input.value; }); listItem.setAttribute('index', i); obj.selectorListPanel.appendChild(listItem); obj.listItems.push(listItem); } if(!isTemp && !obj.input.value && opts.length > 0) { obj.selected(0); } return obj; }; this.setCallback = function(calllback){ if(calllback && calllback.constructor == Function) { obj.callback = calllback; } else { console.error('Selector ERR: callback not is Function'); } return obj; }; this.setFilter = function(filter, isOff) { obj.runFilter = !isOff; if(filter && filter) { obj.filter = filter; } return obj; } this.getOptsFromServer = function (op, dataAdapter) { if(!op) { console.error('Selector ERR: invalid parameter'); return obj; } obj.urlOp = op; $.ajax({ url: op.url, type: op.method || 'GET', dataType: 'json', data: op.data || {}, async: false, success: function (data) { var arr = null; if(dataAdapter && dataAdapter.constructor == Function) { obj.dataAdapter = dataAdapter; arr = obj.dataAdapter(data); } else { arr = data; } if(arr && arr.dataAdapter.constructor == Array) { obj.setOptions(arr); } else { console.error('Selector ERR: invalid data'); } }, error: function (err) { console.error('Selector ERR:'); console.error(err); } }); return obj; }; //用以搜索 this.updatePostParams = function(data) { obj.urlOp.data = data; obj.getOptsFromServer(obj.urlOp, obj.dataAdapter); } this.selected = function(idx) { if(idx >= 0 && idx < obj.options.length) { $(obj.listItems[obj.index]).css(obj.defListItemCss); $(obj.listItems[idx]).css(obj.defListItemHoverCss); obj.input.value = value = this.options[idx]; obj.input.value = obj.listItems[idx].textContent; obj.index = idx; } return obj; }; this.getValue = function () { return obj.input.value; }; this.setValue = function (text) { obj.input.value = text; }; this.showPanel= function() { if(obj.options.length == 0) { return obj; } var w = $(obj.input).innerWidth(); var h = $(obj.input).innerHeight(); var ch = this.ele.clientHeight; var left = $(obj.input).offset().left - document.documentElement.scrollLeft; var top = $(obj.input).offset().top - document.documentElement.scrollTop; var panelHeight = $(this.selectorListPanel).height(); obj.selectorListPanel.style.width = w+'px'; obj.selectorListPanel.style.maxHeight = $(window).height()/2+'px'; var panelTop = top+5+h; obj.selectorListPanel.style.top = panelTop+'px'; obj.selectorListPanel.style.boxShadow= '1px 1px 3px rgba(1, 1, 1, 0.77)'; if(panelTop+panelHeight > $(window).height()) { var panelTop = top-5-$(obj.selectorListPanel).height(); obj.selectorListPanel.style.top = panelTop+'px'; obj.selectorListPanel.style.boxShadow= '1px -1px 3px rgba(1, 1, 1, 0.77)'; } obj.selectorListPanel.style.display = 'block'; return obj; }; this.hidePanel = function() { obj.selectorListPanel.style.display = 'none'; } this.doFilter = function (key) { if(obj.runFilter && obj.filter && obj.filter.constructor == Function) { obj.setOptions(obj.options.filter(function (item) { return obj.filter(item, key); }), true); obj.index = hoverIndex = 0; obj.showPanel(); } return obj; } window.addEventListener('resize', function (ev) { if(obj.selectorListPanel.style.display == 'block') { obj.showPanel(); } }); window.addEventListener('scroll', function (ev) { if(obj.selectorListPanel.style.display == 'block') { obj.showPanel(); } }); this.setOptions(obj.options); } </script> </body> </html>