html的表单有很强大的功能,在web早期的时候,表单是页面向服务器发起通信的主要渠道。但有些表单元素的样式没办法通过添加css样式来达到满意的效果,而且不同的浏览器之间设置的样式还存在兼容问题,比如下拉框。

本实例通过创建div和li等元素来生成一个模拟下拉框,以达到美化下拉框的效果。学习本教程之前,读者需要具备html和css技能,同时需要有简单的javascript基础。

先创建一个select元素,作为美化下拉框的数据来源,如下所示:

<div class="select_wrap" id="selectWrap">
<dl>
<dt>请选择:</dt>
<dd>
<select id="selectElem">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">广东</option>
<option value="4">湖南</option>
<option value="5">河北</option>
<option value="6">黑龙江</option>
</select>
</dd>
</dl>
</div>

既然是做一个下拉框美化的效果,那肯定是需要用一些css样式来实现。读者可以根据自己有喜好编写,也可以直接复制以下代码:

.select_wrap{
width:800px;
margin:30px auto;
}
.select_wrap dt{
float:left;
width:120px;
line-height:36px;
text-align:right;
font-size:14px;
}
.select_wrap dd{
margin-left:130px;
line-height:36px;
}
.select_wrap input[type=text],.select_wrap input[type=password]{
height:24px;
line-height:22px;
padding:0 5px;
border:1px solid #aaa;
border-radius:2px;
}
.select_wrap .btn{
padding:0 20px;
color:#fff;
cursor:pointer;
line-height: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:0px;
border:6px solid transparent;
border-top-color:#ccc;
pointer-events:none;
}
.input_container input{
height:30px;
line-height:28px;
padding:0 5px;
border:1px solid #aaa;
border-radius:4px;
}
.input_container input:focus{
border-color:#129cff;
outline:none;
box-shadow:0 0 6px #65bfff;
}
.select_container ul{
position:absolute;
top:35px;
width: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: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 = 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<aOptions.length;i++){
//判断是否是当前选中的选项
if(aOptions[i].selected){
//下拉选项组合到下拉列表字符串,当前选中的选项需要加上class添加当前样式
sLi += '<li class="cur" data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>';
//当前选中的选项显示到文本框中
eInput.value = aOptions[i].innerHTML;
//eUl元素设置data-val属性值为当前选中选项的值
eUl.dataset.val = aOptions[i].value;
}else{
//非当前选中的选项,直接组合到下拉列表字符串,值设置到data-val属性中
sLi += '<li data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>';
}
}
//下拉列表放到eUl元素中
eUl.innerHTML = sLi;
//默认隐藏下拉列表
eUl.style.display = 'none';

把创建好的这些元素嵌套好,再添加到原下拉框的父元素中,并隐藏原有的下拉框,如下所示:

//把文本框放到eContainer容器中
eContainer.appendChild(eInputCon);
//把下拉列表放到eContainer容器中
eContainer.appendChild(eUl);
//把eContainer元素放到select元素后面
eDd.appendChild(eContainer);
//隐藏原下拉框元素
eSelect.style.display = 'none';

现在效果是有了,但下拉框的功能还没实现,还需要给这些美化后的元素添加事件。

3. 实现打开下拉框功能

下拉框原有的功能是在文本框上点击鼠标,就会显示下拉列表。所以在eInput元素上绑定click事件来显示下拉列表,如下所示:

//设置下拉框打开状态,0为关闭,1为打开
var status = 0;
//绑定click事件,用于显示下拉列表
eInput.addEventListener('click',event=>{
//判断下拉框是否已打开
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<eLi.length;i++){
//给每一个li元素绑定点击事件
eLi[i].addEventListener('click',(event)=>{
//修改下拉框状态为已关闭状态
status = 0;
//清除所有列表的class
for(let n=0;n<eLi.length;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<eLi.length;i++){
//给每一个li元素绑定点击事件
eLi[i].addEventListener('click',(event)=>{
//修改下拉框状态为已关闭状态
status = 0;
//清除所有列表的class
for(let n=0;n<eLi.length;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();
});

一个美化后的下拉框已经完成,如果动手一步一步实现它,理解应该会更深一些。

纯原生javascript下拉框表单美化实例教程的更多相关文章

  1. Jquery实现下拉联动表单

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. JavaScript下拉框去除重复内容

    下拉框去除重复内容 <script type="text/javascript" src="http://www.joleye.com/libraries/java ...

  3. JavaScript 下拉框 左边添加至右边

    关于如何实现右边下拉框中选项的排序一时没有好的解决方法,等想到了回来补充 <!DOCTYPE html> <html> <head> <meta charse ...

  4. jQuery下拉框扩展和美化插件Chosen

    Chosen 是一个支持jquery的select下拉框美化插件,它能让丑陋的.很长的select选择框变的更好看.更方便.不仅如此,它更扩展了select,增加了自动筛选的功能.它可对列表进行分组, ...

  5. Jquery制作--美化下拉框

    平常我们用的原生select下拉框,大部分样式没办法修改,导致在不同的浏览器里面会跟设计图的风格大相径庭.所以为了能让它美化起来,就用JQ模拟了一个下拉框,可以随意定义样式.原生的下拉框也保留在div ...

  6. div自定义下拉框

    因为原生的下拉框不能修改其属性,很难美化下拉框. 所以自己用div简单自定义了一下下拉框,想美化直接修改css即可 <!DOCTYPE html> <html lang=" ...

  7. Android 第三方开源下拉框:NiceSpinner

    Android原生的下拉框Spinner基本上可以满足Android开发对于下拉选项的设计需求,但现在越来越流行的下拉框不满足于Android原生提供的下拉框Spinner所提供的设计样式,而改用自定 ...

  8. jQuery插件实现select下拉框左右选择_交换内容(multiselect2side)

    效果图: 使用jQuery插件---multiselect2side做法: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitio ...

  9. select下拉框左右变换

    效果图: 使用jQuery插件---multiselect2side做法: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ...

随机推荐

  1. 十、TestNG分组测试

    使用 groups 属性 package com.lc.tesgFenZu; import org.testng.annotations.AfterGroups; import org.testng. ...

  2. 关于Java Integer和Long直接比较

    Integer和Long不能直接equals比较会返回False Long.class源码 ` public boolean equals(Object obj) { if (obj instance ...

  3. html 08-HTML5详解(二)

    08-HTML5详解(二) #本文主要内容 拖拽 历史 地理位置 全屏 #拖拽 如上图所示,我们可以拖拽博客园网站里的图片和超链接. 在HTML5的规范中,我们可以通过为元素增加 draggable= ...

  4. GitHub 上的大佬们打完招呼,会聊些什么?

    你好 GitHub!每一位开源爱好者的好朋友「HelloGitHub」 大家好,今儿 HG 有幸邀请到:Lanking 一位亚马逊 AI 软件工程师.开源爱好者和贡献者.他是亚马逊开源的 Java 深 ...

  5. javascript之原型、原型链

    一.原型: 1. 任何函数都有prototype属性(对象才有属性,函数也是对象): 2. 函数的prototype属性的值是个对象,这个对象就是原型(对象): 3. 作用:通过构造函数创建出来的对象 ...

  6. iOS 自定义tabBarController(中间弧形)

    效果图 1.在继承自UITabBarController的自定义controller中调用以下方法(LZCustomTabbar为自定义的tabbar) - (void)viewDidAppear:( ...

  7. (六)、mv-一个具备更改文件名和移动文件的命令

    一.mv的命令格式和作用 既可以在不同目录之间移动文件和目录,也可以在同一目录下对文件或者目录重命名,如果目标文件已经存在,则可覆盖他,若 目标文件或者目录不存在,则创建他:移动的dst必须为目录 命 ...

  8. HBase内存配置及JVM优化

    前言 本文从HBase的内存布局说起,先充分了解HBase的内存区的使用与分配,随后给出了不同业务场景下的读写内存分配规划,并指导如何分析业务的内存使用情况,以及在使用当中写内存Memstore及读内 ...

  9. VC维相关知识

    假设空间H(Hypothesis Set) 输入空间D(X1...Xn) 1.增长函数(grown function) 是关于输入空间尺寸n的函数 假设空间对于D中所有实例实现分类(赋予标记)的分类方 ...

  10. [LeetCode]160. Intersection of Two Linked Lists判断交叉链表的交点

    方法要记住,和判断是不是交叉链表不一样 方法是将两条链表的路径合并,两个指针分别从a和b走不同路线会在交点处相遇 public ListNode getIntersectionNode(ListNod ...