html的表单有很强大的功能,在web早期的时候,表单是页面向服务器发起通信的主要渠道。但有些表单元素的样式没办法通过添加css样式来达到满意的效果,而且不同的浏览器之间设置的样式还存在兼容问题,比如下拉框。
本实例通过创建div和li等元素来生成一个模拟下拉框,以达到美化下拉框的效果。学习本教程之前,读者需要具备html和css技能,同时需要有简单的javascript基础。
先创建一个select元素,作为美化下拉框的数据来源,如下所示:
[/span>div class="select_wrap" id="selectWrap"
[/span>dl
[/span>dt
[/span>dd
[/span>select id="selectElem"
[/span>option value="1"
[/span>option value="2"
[/span>option value="3"
[/span>option value="4"
[/span>option value="5"
[/span>option value="6"
既然是做一个下拉框美化的效果,那肯定是需要用一些css样式来实现。读者可以根据自己有喜好编写,也可以直接复制以下代码:
.select_wrap{
Width</span>:800px;
margin:30px auto;
}
.select_wrap dt{
float:left;
Width</span>:120px;
line-Height</span>:36px;
text-align:right;
font-size:14px;
}
.select_wrap dd{
margin-left:130px;
line-Height</span>:36px;
}
.select_wrap input【type=text】,.select_wrap input【type=password】{
Height</span>:24px;
line-Height</span>:22px;
padding:0 5px;
border:1px solid #aaa;
border-radius:2px;
}
.select_wrap .btn{
padding:0 20px;
color:#fff;
cursor:pointer;
line-Height</span>:30px;
border:none;
margin-right:20px;
background:#108ee9;
}
.select_container{
position:relative;
display:inline-block;
}
.input_container:{
position:relative;
}
.input_container::after{
content:"";
position:absolute;
top:15px;
right:8px;
display:inline-block;
Height</span>:0px;
border:6px solid transparent;
border-top-color:#ccc;
pointer-events:none;
}
.input_container input{
Height</span>:30px;
line-Height</span>:28px;
padding:0 5px;
border:1px solid #aaa;
border-radius:4px;
}
.input_container //代码效果参考:http://www.jhylw.com.cn/063729577.html
input:focus{border-color:#129cff;
outline:none;
box-shadow:0 0 6px #65bfff;
}
.select_container ul{
position:absolute;
top:35px;
Width</span>:100%;
margin:0;
padding:0;
background:#fff;
border-radius:4px;
box-shadow:0 0px 5px #ccc;
}
.select_container li{
list-style:none;
font-size:12px;
line-Height</span>:30px;
padding:0 10px;
cursor:pointer;
}
.select_container li:hover,.select_container li.cur{
background:#dbf0ff;
}
前期工作做好之后,可以开始编写javascript代码了。按照惯例,还是把功能分析为一个一个步骤,再写具体的代码,思路会很清晰。
1. 获取已有的下拉框元素
这里需要获取多个元素,首先通过id获取select元素,再找到select元素的父元素。因为生成的美化下拉框需要放到父元素中。还要获取到select所有的option子节点。如下所示:
//获取下拉框
var eSelect = document.getElementById('selectElem');
//获取下拉框父节点
var eDd = eSelect.parentNode;
//获取下拉框选项
var aOptions = //代码效果参考:http://www.jhylw.com.cn/562235531.html
eSelect.getElementsByTagName('option');2. 创建美化下拉框元素
先看一下美化后的下拉框,如下图所示:
想一下这个下拉框应该包含哪些元素,一个div元素把所有内容包含在里面;一个input文本框,显示选中的值;input元素还需要一个父级容器div元素;一个ul加一组li元素组成下拉列表。好,知道需要哪些元素了,先来创建文本框部分,如下所示:
//创建美化select容器
var eContainer = document.createElement('div');
eContainer.className = 'select_container';
//创建input父级容器
var eInputCon = document.createElement('div');
eInputCon.className = 'input_container';
//创建input文本框,显示选中的值
var eInput = document.createElement('input');
//设置文本框不能输入
eInput.readOnly = true;
eInput.placeholder = '请选择';
//把文本框放到容器中
eInputCon.appendChild(eInput);
再来创建下拉列表。下拉列表可以创建一个ul元素,通过遍历aOptions下拉框选项,组合成li列表的字符串,通过innerHTML放到ul元素中,实现代码如下:
//创建ul元素,作为下拉列表容器
var eUl = document.createElement('ul');
//声明变量,用于组合下拉列表的字符串
var sLi = '';
//遍历原有下拉框选项
for(let i=0;i{
//判断下拉框是否已打开
if(status){
//下拉框打开则关闭下拉框
eUl.style.display = 'none';
}else{
//下拉框关闭则打开下拉框
eUl.style.display = 'block';
}
//修改下拉框状态
status = +!status;
},false);
可以看到,在eInput元素上点击,可以打开和关闭下拉框了。但选择下拉选项还是无效的。在下拉选项上也绑定click事件
4. 下拉选项绑定click事件,点击时修改下拉框的值,如下所示:
//获取下拉选项列表元素的集合
var eLi = eUl.getElementsByTagName('li');
//遍历下拉列表
for(let i=0;i
//给每一个li元素绑定点击事件
eLi【i】.addEventListener('click',(event)=>{
//修改下拉框状态为已关闭状态
status = 0;
//清除所有列表的class
for(let n=0;n
eLi【n】.className = '';
}
//激活当前列表选中样式
eLi【i】.className = 'cur';
//设置下拉框当前选中值
eUl.dataset.val = eLi【i】.dataset.val;
//还需要把值设置到原select元素上
eSelect.value = eUl.dataset.val;
//触发原select上的函数
typeof eSelect.onchange=='function'&&select.onchange();
//修改eInput元素显示的值
eInput.value = eLi【i】.innerHTML;
//关闭下拉框
eUl.style.display = 'none';
},false);
}
目前为止,功能基本完成。不过只能在选择选项后或再在文本框上点击才能关闭下拉框。所以还需要修改一下功能,在页面其他位置点击时也能关闭下拉框
5. 在document绑定点击事件,用于关闭下拉框。
注意两点:一是在下拉框关闭时需要取消document上的绑定事件;二是eContainer元素上点击时需要阻止冒泡,否则下拉框会打不开了。修改后的代码如下:
//设置下拉框打开状态,0为关闭,1为打开
var status = 0;
//绑定click事件,用于显示下拉列表
eInput.addEventListener('click',event=>{
//判断下拉框是否已打开
if(status){
//下拉框打开则关闭下拉框
eUl.style.display = 'none';
//取消document上的绑定事件
document.removeEventListener('click',closeUl);
}else{
//下拉框关闭则打开下拉框
eUl.style.display = 'block';
//在document上绑定点击事件,用于关闭下拉框
document.addEventListener('click',closeUl,false);
}
//修改下拉框状态
status = +!status;
},false);
//获取下拉选项列表元素的集合
var eLi = eUl.getElementsByTagName('li');
//遍历下拉列表
for(let i=0;i
//给每一个li元素绑定点击事件
eLi【i】.addEventListener('click',(event)=>{
//修改下拉框状态为已关闭状态
status = 0;
//清除所有列表的class
for(let n=0;n
eLi【n】.className = '';
}
//激活当前列表选中样式
eLi【i】.className = 'cur';
//设置下拉框当前选中值
eUl.dataset.val = eLi【i】.dataset.val;
//还需要把值设置到原select元素上
eSelect.value = eUl.dataset.val;
//触发原select上的函数
typeof eSelect.onchange=='function'&&select.onchange();
//修改eInput元素显示的值
eInput.value = eLi【i】.innerHTML;
//关闭下拉框
eUl.style.display = 'none';
//取消document上的绑定事件
document.removeEventListener('click',closeUl);
},false);
}
//绑定到document上关闭下拉框的函数
function closeUl(){
//修改下拉框状态为已关闭状态
status = 0;
//关闭下拉框
eUl.style.display = 'none';
//取消document上的绑定事件
document.removeEventListener('click',closeUl);
}
//阻止冒泡,否则点击时冒泡到document上,会导致下拉框刚打开就关闭
eContainer.addEventListener('click',event=>{
event.stopPropagation();
});
一个美化后的下拉框已经完成,如果动手一步一步实现它,理解应该会更深一些。