今天遇到一个问题,就是layui.js
的下拉框模糊查询功能并不能满足我的需求,因此我动手自己写了一个下拉框。
实现思路其实就是,模仿layui.js
的下拉框样式,然后监听input
的输入事件,一旦输入,就调接口,让后台返给我查到的数据。
还是上代码吧:
html:
<form action="">
<div class="box">
<div class="select-container">
<div class="select-title">
<input type="text" class="select-search-input" />
<i class="select-down select-icon"></i>
</div>
<ul class="select-items"></ul>
</div>
</div>
<button class="submit" type="submit">提交</button>
</form>
css:
body {
background-color: #dcdbdb;
}
.box {
width: 150px;
}
.select-container {
position: relative;
}
.select-container > ul,
.select-container > ul li {
list-style: none;
}
.select-container > .select-title {
position: relative;
}
.select-container > .select-title > .select-search-input {
height: 38px;
border: 1px solid #e6e6e6;
background-color: #ffffff;
outline: none;
border-radius: 2px;
cursor: pointer;
padding-left: 10px;
padding-right: 22px;
width: 100%;
display: block;
box-sizing: border-box;
}
.select-icon {
position: relative;
display: inline-block;
vertical-align: middle;
width: 0;
height: 0;
border-width: 6px;
border-style: dashed;
border-color: transparent;
overflow: hidden;
}
.select-container > .select-title > .select-icon {
position: absolute;
right: 10px;
top: 50%;
cursor: pointer;
border-top-color: #c2c2c2;
border-top-style: solid;
transition: all 0.3s;
margin-top: -3px;
}
.select-container > .select-title > .select-up {
margin-top: -9px;
transform: rotate(180deg);
}
.select-container > .select-items {
position: absolute;
left: 0;
top: 32px;
padding: 5px 0;
z-index: 899;
min-width: 100%;
border: 1px solid #d2d2d2;
max-height: 300px;
overflow-y: auto;
background-color: #fff;
border-radius: 2px;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.12);
box-sizing: border-box;
}
.select-container > .select-items {
display: none;
}
.select-container > .select-items .select-option {
padding: 0 10px;
line-height: 36px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
cursor: pointer;
transition: 0.5s all;
background-color: #f2f2f2;
}
.select-container > .select-items .select-option:hover {
background-color: #5fb878;
color: #fff;
}
.select-container > .select-items > .select-this {
background-color: #5fb878;
color: #fff;
}
js:
/*
* function:the ajax
* params:interface url,request method,paramns,callback function
*/
function ewAjax(url, method, params, callback) {
method = method.toUpperCase() === "GET" ? "GET" : "POST";
var xhr = new XMLHttpRequest();
if (method.toUpperCase() === "GET") {
if (params) {
url = url + params;
}
xhr.open(method, url);
xhr.send();
} else {
if (typeof params === "string" && params) {
xhr.open(method, url + "?" + params);
xhr.send(JSON.stringify(params));
} else if (params) {
xhr.open(method, url);
xhr.send(JSON.stringify(params));
}
}
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
callback(JSON.parse(xhr.responseText));
}
};
}
/*
* function:Serialization parameters
* params:params
*/
function ewParam(params) {
var keys = Object.keys(params),
key_len = keys.length;
var str = "";
for (var key in params) {
str += key + "=" + params[key];
if (key === keys[key_len - 1]) {
break;
} else {
str += "&";
}
}
return str;
}
/*
* function:create the select component
* params:params
*/
function createSelect(el1, el2, callback) {
el1.oninput = function(e) {
// get data
ewAjax(url,"POST",ewParam({name: e.target.value}),function(res) {
if (res.status === "200") {
callback(res.data, el1, el2);
}
});
};
}
var search_input = document.getElementsByClassName(
"select-search-input"
)[0],
select_items = document.getElementsByClassName("select-items")[0];
createSelect(search_input, select_items, function(data, el1, el2) {
var li;
if (data.length > 0) {
el2.style.display = "block";
el2.innerHTML = "";
el1.nextElementSibling.classList.add("select-up");
// click the select arrow
el1.nextElementSibling.onclick = function() {
this.classList.toggle("select-up");
if (this.className.indexOf("select-up") > -1) {
el2.style.display = "block";
} else {
el2.style.display = "none";
}
};
data.map(function(d, index) {
li = document.createElement("li");
// the value need to subbmit
li.setAttribute("data-value", d.id);
// maybe you need to save the data by search
li.setAttribute("data-info", JSON.stringify(d));
li.textContent = d.name;
li.className = "select-option";
// the default select value
if (index === 0) {
li.classList.add("select-this");
}
li.onclick = function() {
el2.style.display = "none";
el1.value = this.textContent;
el1.nextElementSibling.classList.remove("select-up");
//change the value about submit the form data,so create a hidden input element
var sm_input = document.createElement("input");
sm_input.style.display = "none";
sm_input.name = "name";
sm_input.value = this.getAttribute("data-value");
el1.parentElement.appendChild(sm_input);
};
el2.appendChild(li);
});
}
});
其实整体思路也不算太难,无非就是当后台返给了数据之后,然后列表显示,给列表项添加点击事件,关于这个,给下拉箭头添加事件,控制列表的显隐,然后就没有什么了,分享出来,希望能帮助到跟我碰到一样的情况无法着手的人。代码已上传至git源码,觉得不错希望点个star,多谢。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。