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

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

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

  1. <div class="select_wrap" id="selectWrap">
  2. <dl>
  3. <dt>请选择:</dt>
  4. <dd>
  5. <select id="selectElem">
  6. <option value="1">北京</option>
  7. <option value="2">上海</option>
  8. <option value="3">广东</option>
  9. <option value="4">湖南</option>
  10. <option value="5">河北</option>
  11. <option value="6">黑龙江</option>
  12. </select>
  13. </dd>
  14. </dl>
  15. </div>

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

  1. .select_wrap{
  2. width:800px;
  3. margin:30px auto;
  4. }
  5. .select_wrap dt{
  6. float:left;
  7. width:120px;
  8. line-height:36px;
  9. text-align:right;
  10. font-size:14px;
  11. }
  12. .select_wrap dd{
  13. margin-left:130px;
  14. line-height:36px;
  15. }
  16. .select_wrap input[type=text],.select_wrap input[type=password]{
  17. height:24px;
  18. line-height:22px;
  19. padding:0 5px;
  20. border:1px solid #aaa;
  21. border-radius:2px;
  22. }
  23. .select_wrap .btn{
  24. padding:0 20px;
  25. color:#fff;
  26. cursor:pointer;
  27. line-height:30px;
  28. border:none;
  29. margin-right:20px;
  30. background:#108ee9;
  31. }
  32. .select_container{
  33. position:relative;
  34. display:inline-block;
  35. }
  36. .input_container:{
  37. position:relative;
  38. }
  39. .input_container::after{
  40. content:"";
  41. position:absolute;
  42. top:15px;
  43. right:8px;
  44. display:inline-block;
  45. height:0px;
  46. border:6px solid transparent;
  47. border-top-color:#ccc;
  48. pointer-events:none;
  49. }
  50. .input_container input{
  51. height:30px;
  52. line-height:28px;
  53. padding:0 5px;
  54. border:1px solid #aaa;
  55. border-radius:4px;
  56. }
  57. .input_container input:focus{
  58. border-color:#129cff;
  59. outline:none;
  60. box-shadow:0 0 6px #65bfff;
  61. }
  62. .select_container ul{
  63. position:absolute;
  64. top:35px;
  65. width:100%;
  66. margin:0;
  67. padding:0;
  68. background:#fff;
  69. border-radius:4px;
  70. box-shadow:0 0px 5px #ccc;
  71. }
  72. .select_container li{
  73. list-style:none;
  74. font-size:12px;
  75. line-height:30px;
  76. padding:0 10px;
  77. cursor:pointer;
  78. }
  79. .select_container li:hover,.select_container li.cur{
  80. background:#dbf0ff;
  81. }

前期工作做好之后,可以开始编写javascript代码了。按照惯例,还是把功能分析为一个一个步骤,再写具体的代码,思路会很清晰。

1. 获取已有的下拉框元素

这里需要获取多个元素,首先通过id获取select元素,再找到select元素的父元素。因为生成的美化下拉框需要放到父元素中。还要获取到select所有的option子节点。如下所示:

  1. //获取下拉框
  2. var eSelect = document.getElementById('selectElem');
  3. //获取下拉框父节点
  4. var eDd = eSelect.parentNode;
  5. //获取下拉框选项
  6. var aOptions = eSelect.getElementsByTagName('option');

2. 创建美化下拉框元素

先看一下美化后的下拉框,如下图所示:

想一下这个下拉框应该包含哪些元素,一个div元素把所有内容包含在里面;一个input文本框,显示选中的值;input元素还需要一个父级容器div元素;一个ul加一组li元素组成下拉列表。好,知道需要哪些元素了,先来创建文本框部分,如下所示:

  1. //创建美化select容器
  2. var eContainer = document.createElement('div');
  3. eContainer.className = 'select_container';
  4. //创建input父级容器
  5. var eInputCon = document.createElement('div');
  6. eInputCon.className = 'input_container';
  7. //创建input文本框,显示选中的值
  8. var eInput = document.createElement('input');
  9. //设置文本框不能输入
  10. eInput.readOnly = true;
  11. eInput.placeholder = '请选择';
  12. //把文本框放到容器中
  13. eInputCon.appendChild(eInput);

再来创建下拉列表。下拉列表可以创建一个ul元素,通过遍历aOptions下拉框选项,组合成li列表的字符串,通过innerHTML放到ul元素中,实现代码如下:

  1. //创建ul元素,作为下拉列表容器
  2. var eUl = document.createElement('ul');
  3. //声明变量,用于组合下拉列表的字符串
  4. var sLi = '';
  5. //遍历原有下拉框选项
  6. for(let i=0;i<aOptions.length;i++){
  7. //判断是否是当前选中的选项
  8. if(aOptions[i].selected){
  9. //下拉选项组合到下拉列表字符串,当前选中的选项需要加上class添加当前样式
  10. sLi += '<li class="cur" data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>';
  11. //当前选中的选项显示到文本框中
  12. eInput.value = aOptions[i].innerHTML;
  13. //eUl元素设置data-val属性值为当前选中选项的值
  14. eUl.dataset.val = aOptions[i].value;
  15. }else{
  16. //非当前选中的选项,直接组合到下拉列表字符串,值设置到data-val属性中
  17. sLi += '<li data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>';
  18. }
  19. }
  20. //下拉列表放到eUl元素中
  21. eUl.innerHTML = sLi;
  22. //默认隐藏下拉列表
  23. eUl.style.display = 'none';

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

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

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

3. 实现打开下拉框功能

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

  1. //设置下拉框打开状态,0为关闭,1为打开
  2. var status = 0;
  3. //绑定click事件,用于显示下拉列表
  4. eInput.addEventListener('click',event=>{
  5. //判断下拉框是否已打开
  6. if(status){
  7. //下拉框打开则关闭下拉框
  8. eUl.style.display = 'none';
  9. }else{
  10. //下拉框关闭则打开下拉框
  11. eUl.style.display = 'block';
  12. }
  13. //修改下拉框状态
  14. status = +!status;
  15. },false);

可以看到,在eInput元素上点击,可以打开和关闭下拉框了。但选择下拉选项还是无效的。在下拉选项上也绑定click事件

4. 下拉选项绑定click事件,点击时修改下拉框的值,如下所示:

  1. //获取下拉选项列表元素的集合
  2. var eLi = eUl.getElementsByTagName('li');
  3. //遍历下拉列表
  4. for(let i=0;i<eLi.length;i++){
  5. //给每一个li元素绑定点击事件
  6. eLi[i].addEventListener('click',(event)=>{
  7. //修改下拉框状态为已关闭状态
  8. status = 0;
  9. //清除所有列表的class
  10. for(let n=0;n<eLi.length;n++){
  11. eLi[n].className = '';
  12. }
  13. //激活当前列表选中样式
  14. eLi[i].className = 'cur';
  15. //设置下拉框当前选中值
  16. eUl.dataset.val = eLi[i].dataset.val;
  17. //还需要把值设置到原select元素上
  18. eSelect.value = eUl.dataset.val;
  19. //触发原select上的函数
  20. typeof eSelect.onchange=='function'&&select.onchange();
  21. //修改eInput元素显示的值
  22. eInput.value = eLi[i].innerHTML;
  23. //关闭下拉框
  24. eUl.style.display = 'none';
  25. },false);
  26. }

目前为止,功能基本完成。不过只能在选择选项后或再在文本框上点击才能关闭下拉框。所以还需要修改一下功能,在页面其他位置点击时也能关闭下拉框

5. 在document绑定点击事件,用于关闭下拉框。

注意两点:一是在下拉框关闭时需要取消document上的绑定事件;二是eContainer元素上点击时需要阻止冒泡,否则下拉框会打不开了。修改后的代码如下:

  1. //设置下拉框打开状态,0为关闭,1为打开
  2. var status = 0;
  3. //绑定click事件,用于显示下拉列表
  4. eInput.addEventListener('click',event=>{
  5. //判断下拉框是否已打开
  6. if(status){
  7. //下拉框打开则关闭下拉框
  8. eUl.style.display = 'none';
  9. //取消document上的绑定事件
  10. document.removeEventListener('click',closeUl);
  11. }else{
  12. //下拉框关闭则打开下拉框
  13. eUl.style.display = 'block';
  14. //在document上绑定点击事件,用于关闭下拉框
  15. document.addEventListener('click',closeUl,false);
  16. }
  17. //修改下拉框状态
  18. status = +!status;
  19. },false);
  20.  
  21. //获取下拉选项列表元素的集合
  22. var eLi = eUl.getElementsByTagName('li');
  23. //遍历下拉列表
  24. for(let i=0;i<eLi.length;i++){
  25. //给每一个li元素绑定点击事件
  26. eLi[i].addEventListener('click',(event)=>{
  27. //修改下拉框状态为已关闭状态
  28. status = 0;
  29. //清除所有列表的class
  30. for(let n=0;n<eLi.length;n++){
  31. eLi[n].className = '';
  32. }
  33. //激活当前列表选中样式
  34. eLi[i].className = 'cur';
  35. //设置下拉框当前选中值
  36. eUl.dataset.val = eLi[i].dataset.val;
  37. //还需要把值设置到原select元素上
  38. eSelect.value = eUl.dataset.val;
  39. //触发原select上的函数
  40. typeof eSelect.onchange=='function'&&select.onchange();
  41. //修改eInput元素显示的值
  42. eInput.value = eLi[i].innerHTML;
  43. //关闭下拉框
  44. eUl.style.display = 'none';
  45. //取消document上的绑定事件
  46. document.removeEventListener('click',closeUl);
  47. },false);
  48. }
  49.  
  50. //绑定到document上关闭下拉框的函数
  51. function closeUl(){
  52. //修改下拉框状态为已关闭状态
  53. status = 0;
  54. //关闭下拉框
  55. eUl.style.display = 'none';
  56. //取消document上的绑定事件
  57. document.removeEventListener('click',closeUl);
  58. }
  59.  
  60. //阻止冒泡,否则点击时冒泡到document上,会导致下拉框刚打开就关闭
  61. eContainer.addEventListener('click',event=>{
  62. event.stopPropagation();
  63. });

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

纯原生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. Springboot 使用logback直接将日志写入Elasticsearch

    正常情况下,一般组合为elk 即日志会通过logstash写入es,但本文主要为轻量级项目直接利用appender写入es 首先需要引入包 <dependency> <groupId ...

  2. centos7 安装netstat命令工具

    [root@node01 yum.repos.d]# yum install -y net-tools Loaded plugins: fastestmirror Loading mirror spe ...

  3. C++ string常见函数总结

    基础概念 对照功能列表:不能直接回答的再去看相应解析说明. begin 得到指向字符串开头的 Iterator end 得到指向字符串结尾的 Iterator rbegin 得到指向反向字符串开头的 ...

  4. C# 多态virtual标记重写 以及EF6 查询性能AsNoTracking

    首先你如果不用baivirtual重写的话,系统默认会为du你加new关键字,他zhi的作用是覆盖,而virtual的关键作用在dao于实现多态 virtual 代表在继承了这个类的子类里面可以使用o ...

  5. SonarQube学习(一)- 使用Docker安装SonarQube(亲测可用)

    一.前言 不得不吐槽下,现在的博客写的真太扯淡了,就网上写的使用docker安装SonarQube而言,搜到十篇文章,最少9篇照着操作配置都不可用,卡在SonarQube无法启动.自然,我也是被折磨的 ...

  6. Python-对比参考目录查找多个文件夹中不同的文件

    改完文件名称后,Dr.he 发现分别保存5个状态的jpg 文件的文件夹出现缺少文件的情况.为了让他少熬夜查找缺失文件,结合网友分享的脚本,写了查找以下代码,满足他的需求,也以防自己忘记.以下代码能解决 ...

  7. 10天,从.Net转Java,并找到月薪2W的工作(一)

    大学学的是Java,但是工作一直都是.Net方面的工作. 看到各种各样的大厂都是招Java,工资比.Net高,岗位多.而.Net大多都是维护老系统,传统行业这类的工作.甚至发现工作经验不足我一半的薪水 ...

  8. JS实现JSON数组合并和去重

    var a=[{"id":"1001","name":"张三","age":"18&quo ...

  9. 本地TOMCAT启动打包项目(WAR)

    首先打个包,右击项目-->Export...   选择WEB-->WAR file-->Next   选个放置地址,勾选红框处-->finish   找到自己的tomcat目录 ...

  10. easyui 动态添加input标签

    动态添加easyui控件<input class=" easyui-textbox" > 这样是无效的,因为easyui没有实时监控,所以必须动态渲染$.parser. ...