- 1.实现的效果
- 2.实现说明
- 3.完整代码
一、实现的效果:
二、实现说明:
1.由于无法修改原生select中的option样式,因此自己通过ul,li实现下拉列表,用input实现回显框;
input实现select回显注意2个地方:
1)使用 readonly=“readonly” 让input框无法实现输入 ,不获取焦点;
<input type="text" readonly="readonly" class="ec-input__value" placeholder="业务类型" value="" id="yewu-value">
2)当需要input框可以输入时,使用autocomplete=“new-password” 避免input框获取焦点时自动以下拉的方式弹出以前输入过的值,导致覆盖真正需要展示的下拉列表
<input type="text" autocomplete="new-password" class="ec-input__value" placeholder="请选择国家地区" value="" id="area-value" oninput="enterSearch(this)">
2.下拉框的弹出与隐藏
1)没有显示时点击input部分弹出(同时右侧三角箭头改变,朝上),当弹出框以及显示点击隐藏下拉弹出框(三角箭头方向恢复,朝下)
实现弹出下拉列表代码如下:
//自定义下拉框弹出事件
function openValue(obj, e){
e.stopPropagation(); //阻止冒泡
//阻止默认浏览器动作(W3C)
if ( e && e.preventDefault ){
e.preventDefault();
} else{
window.event.returnValue = false;
}
if ($(".dropdown-menus").is(":visible")) {
$('.dropdown-menus').hide();
$('.ec-input').removeClass('ec-input__open');
}else{
$(obj).addClass('ec-input__open');
$(obj).next().show();
}
}
右侧三角箭头
.caret{
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px dashed;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.ec-input .caret {
position: absolute;
top: 50%;
right: 12px;
margin-top: -2px;
vertical-align: middle;
}
.ec-input__open .caret{
transform: rotate(180deg);
}
2)选中下拉框的某一个值之后,值回显,弹出框隐藏;
注意:由于使用事件委托的方式,当点击某一个选项时,有可能点击的target不是li节点,而是li的子节点,此时可以取其父节点
// 点击的地方可能是li,也可能是li的子节点
if(e.target && e.target.nodeName == "LI"){
selectedDom = e.target;
}else{
selectedDom = $(e.target).parent();
}
事件的完整代码如下:
//点击某个下拉菜单的值之后的事件处理
function getValue(obj, e){
e.stopPropagation(); //阻止冒泡
var selectedDom;
// 点击的地方可能是li,也可能是li的子节点
if(e.target && e.target.nodeName == "LI"){
selectedDom = e.target;
}else{
selectedDom = $(e.target).parent();
}
var selectedValue = $(selectedDom).data('value');
var selectedLable = $(selectedDom).data('label');
var operId = $(obj).data('id');
$(selectedDom).siblings().removeClass('ec-active')
$(selectedDom).addClass('ec-active');
$('#'+operId+'-value').val(selectedLable);
$('#'+operId+'-label').val(selectedValue);
$('.ec-input').removeClass('ec-input__open');
$(obj).parent().hide();
}
3)当下拉弹出框显示时,点击下拉组件以外的部分,弹出框隐藏,代码如下:
// 自定义下拉框:点击其他部分收起下拉事件
document.addEventListener("click", (e) => {
if ($(".dropdown-menus").is(":visible")) {
$('.dropdown-menus').hide();
$('.ec-input').removeClass('ec-input__open');
}
});
3.带搜索的下拉框,当中文输入法输入中文时,让其回显中文时实现搜索,而非输入每次输入都执行一次搜索操作,代码如下:
// 中文输入法
$('.ec-input__value').on('compositionstart',function(event) {
isChinese = true;
})
// 输入中文之后
$('.ec-input__value').on('compositionend',function() {
isChinese = false;
enterSearch(this)
})
三、完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>自定义下拉组件</title>
</head>
<style>
body, p{
margin:0;
padding:0;
}
.container{
margin:100px;
}
.askForm{
margin:20px;
display: flex;
display: -webkit-flex;
background: #fff;
border:1px solid #e1e1e1;
border-radius: 6px;
height: 34px;
}
.select-left{
flex:2;
}
.select-right{
flex: 3;
padding-right: 10px;
}
.ec-select{
height: 34px;
}
.select-online{
width: 20px;
margin-right: 10px;
height: 20px;
margin-top:7px;
border-right: 1px solid #e1e1e1;
}
.ec-input{
width: 100%;
height: 34px;
line-height: 34px;
padding-left: 10px;
position: relative;
}
.ec-input .ec-input__value{
border: none;
outline: none;
width: 90%;
cursor: pointer;
}
.caret{
display: inline-block;
width: 0;
height: 0;
margin-left: 2px;
vertical-align: middle;
border-top: 4px dashed;
border-top: 4px solid;
border-right: 4px solid transparent;
border-left: 4px solid transparent;
}
.ec-input .caret {
position: absolute;
top: 50%;
right: 12px;
margin-top: -2px;
vertical-align: middle;
}
.ec-input__open .caret{
transform: rotate(180deg);
}
.dropdown-menus{
position: relative;
max-height: 200px;
width: 100%;
display: none;
border: 1px solid rgba(0,0,0,.15);
border-radius: 4px;
-webkit-box-shadow: 0 6px 12px rgb(0 0 0 / 18%);
box-shadow: 0 6px 12px rgb(0 0 0 / 18%);
overflow-y: scroll;
overflow: auto;
min-height: 42px;
}
.dropdown-menu{
padding:6px 0;
margin:0;
list-style: none;
}
.menu-item{
height: 30px;
cursor: pointer;
line-height: 30px;
padding-left: 10px;
}
.menu-item:hover{
outline: 0;
color:#FF9500;
background: rgba(255, 149, 0, 0.1);
}
.select-ok{
position: absolute;
display: inline-block;
right: 15px;
margin-top: 8px;
}
.ec-active .select-ok{
width: 14px;
height: 6px;
display: inline-block;
border: 1px solid #FF9500;
border-width: 0 0 2px 2px;
transform: rotate(-45deg);
-ms-transform: rotate(-45deg);
-moz-transform: rotate(-45deg);
-webkit-transform: rotate(-45deg);
-o-transform: rotate(-45deg);
vertical-align: baseline;
}
.no-result{
padding: 8px;
}
</style>
<body>
<div class="container">
<div class="askForm">
<div class="select-container select-left">
<div class="ec-input" onclick="openValue(this,event)">
<input type="hidden" value="" id="yewu-label">
<input type="text" readonly="readonly" class="ec-input__value" placeholder="业务类型" value="" id="yewu-value">
<span class="caret"></span>
</div>
<div class="dropdown-menus">
<ul class="dropdown-menu" onclick="getValue(this, event)" data-id="yewu">
<li class="menu-item" data-value="0" data-label="专线"><span class="text">专线</span><span class="select-ok"></span></li>
<li class="menu-item ec-active" data-value="1" data-label="系统通知"><span class="text">系统通知</span><span class="select-ok"></span></li>
<li class="menu-item" data-value="2" data-label="版本发布"><span class="text">版本发布</span><span class="select-ok"></span></li>
</ul>
</div>
</div>
<div class="select-online"></div>
<div class="select-container select-right">
<div class="ec-input" onclick="openValue(this,event)">
<input type="hidden" value="" id="area-label">
<input type="text" class="ec-input__value" autocomplete="new-password" placeholder="请选择国家地区" value="" id="area-value" oninput="enterSearch(this)">
<span class="caret"></span>
</div>
<div class="dropdown-menus area-menus">
</div>
</div>
</div>
</div>
</body>
<script src="http://cdn.staticfile.org/jquery/2.1.1/jquery.min.js" type="text/javascript"></script>
<script>
var earaData = [
{name:'中国'},
{name:'泰国'},
{name:'美国'},
{name:'英国'},
{name:'日本'},
{name:'澳大利亚'},
{name:'韩国'},
{name:'印度尼西亚'},
];
var filterArea = [];
var isChinese = false;
searchArea('');//初始化国家地区dom
//自定义下拉框弹出事件
function openValue(obj, e){
e.stopPropagation(); //阻止冒泡
//阻止默认浏览器动作(W3C)
if ( e && e.preventDefault ){
e.preventDefault();
} else{
window.event.returnValue = false;
}
if ($(".dropdown-menus").is(":visible")) {
$('.dropdown-menus').hide();
$('.ec-input').removeClass('ec-input__open');
}else{
$(obj).addClass('ec-input__open');
$(obj).next().show();
}
}
//点击某个下拉菜单的值之后的事件处理
function getValue(obj, e){
e.stopPropagation(); //阻止冒泡
var selectedDom;
// 点击的地方可能是li,也可能是li的子节点
if(e.target && e.target.nodeName == "LI"){
selectedDom = e.target;
}else{
selectedDom = $(e.target).parent();
}
var selectedValue = $(selectedDom).data('value');
var selectedLable = $(selectedDom).data('label');
var operId = $(obj).data('id');
$(selectedDom).siblings().removeClass('ec-active')
$(selectedDom).addClass('ec-active');
$('#'+operId+'-value').val(selectedLable);
$('#'+operId+'-label').val(selectedValue);
$('.ec-input').removeClass('ec-input__open');
$(obj).parent().hide();
}
//国家地区搜索框输入事件
function enterSearch(obj){
if(!isChinese){
var key = $(obj).val();
searchArea(key);
}
}
// 下拉搜索框搜索事件
function searchArea(key){
filterArea = [];
for(var j = 0,len=earaData.length;j<len;j++){
if(earaData[j].name.match(key)){
filterArea.push(earaData[j].name)
}
}
appendSelectArea(key);
}
// 中文输入法
$('.ec-input__value').on('compositionstart',function(event) {
isChinese = true;
})
// 输入中文之后
$('.ec-input__value').on('compositionend',function() {
isChinese = false;
enterSearch(this)
})
// 将搜索到的结果重新渲染到下拉框中
function appendSelectArea(key){
var areasHtml = '';
if(filterArea && filterArea.length>0){
areasHtml = '<ul class="dropdown-menu" οnclick="getValue(this, event)" data-id="area">';
for(var i = 0,len = filterArea.length ;i<len;i++){
areasHtml+='<li class="menu-item" data-value='+filterArea[i]+' data-label='+filterArea[i]+'><span class="text">'+filterArea[i]+'</span><span class="select-ok"></span></li>'
}
areasHtml+='</ul>';
}else{
areasHtml = '<div class="dropdown-menu no-result" data-id="area"> 很抱歉没有找到“'+key+'”相关结果!</div>';
}
$('.area-menus').html(areasHtml);
}
// 自定义下拉框:点击其他部分收起下拉事件
document.addEventListener("click", (e) => {
if ($(".dropdown-menus").is(":visible")) {
$('.dropdown-menus').hide();
$('.ec-input').removeClass('ec-input__open');
}
});
</script>
</html>