用JavaScript来美化HTML的select标签的下拉列表效果


Posted in Javascript onNovember 17, 2015

首先通过一个例子来回顾一下select标签的用法:

<html>

<body>

<form>
<select name="cars">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="fiat">Fiat</option>
<option value="audi">Audi</option>
</select>
</form>

</body>
</html>

然后效果一般时这样的:

用JavaScript来美化HTML的select标签的下拉列表效果

美与丑暂且不论...所有html元素中select算是比较坑爹的一个。他让人抓狂的地方主要是:
 
不同的浏览器显示的默认下拉框样子不完全相同
IE下无法手动设置select的高度(这是最坑爹的!),只能靠font-size撑起来
select右侧的下拉箭头是无法使用背景消除的,这就导致无法使用css进行美化
总结起来,解决办法主要有:

将select隐藏掉,而使用div进行模拟
将select透明度设置为0,然后使用相对定位在下方 加一个长得很像select又美化了的div

隐藏方案一般原理如下:
找到页面需要处理的select,将其隐藏
根据select的option,创建一个li列表(当然也可以是div),并隐藏。
在select的位置创建一个div,显示select的值(selected的option)。并使用css对其进行美化,使其看起来像一个select
添加事件,使点击“select”的时候,显示li列表。并使用相对定位,让这个列表显示在“select”下方
对li列表添加事件,模拟下拉框的选值过程(点击事件和键盘↑↓事件都要模拟)
选值完成后,要将选的值显示到上方的“select”,并设置真正的select的值
当然,如果你想做的更复杂点,还可以添加选项搜索、多选、多选后的选项删除等。当时一般原理都跟上面差不多。网上也有很多这样的插件。但使用网上的插件要注意测试浏览器的兼容性,功能越复杂的模拟select,兼容性越不好做
 
如果,你的程序不需要那么复杂的select,那么设置透明度的第二种方案也许适合你。今天要分享给大家的也是这个方案。
它的原理如下:
 
 
找到当前页面的select,将其透明度设置为0.使其看不见,但是可以点击并选值
创建一个div,使用相对定位,放置到select下方 ,并通过css控制使其看起来像一个select。为什么一定要放在下方呢?因为这样,我们可以点击真正的select,而用户看起来像是点击的这个模拟的select,因为真正的select是完全透明的。如果放置在上方,则用户点击的是这个模拟的select,真正的select不会展开!!!
设置div的text为select的值
添加事件,使真正的select选值后,将值显示到模拟的div上
 
 
先上代码吧:
 

( function ($){
var selectFix= function (){
var select=$( this );
//设置透明度为0 当然你也可以使用css控制 使用Jquery设置透明度可以屏蔽 透明度的 浏览器兼容性问题
$(select).css({
"opacity" :0
});
//找到select的选项
var sOptions= this .get(0).options;
//设置模拟select的值
var setFixDivText= function (selectValue){
var text= "" ;
for ( var i=0;i<sOptions.length;i++){
var option=sOptions[i];
if (option.value==selectValue){
text=$(option).text();
break ;
}
}
return text;
};
//模拟的select
//初始化时要将select的值传入
var selectFixDiv=$( '<div id="J_selectFix_' +select.attr("id ")+'" class = "selectFix" >'+setFixDivText($(select).val())+ '</div>' );
select.after(selectFixDiv);
var left=$(select).offset().left;
var top=$(select).offset().top-1; //因为一般select都有1px的边框,所以这里往上拉1px
$(selectFixDiv).css({
"top" : top,
"left" : left
});
//select选值时,将值显示到模拟的select上
$(select).bind( "change click" , function (){
$(selectFixDiv).text(setFixDivText($( this ).val()));
});
};
$.fn.selectFix=selectFix;
})(jQuery);
(function($){ 
  var selectFix=function(){ 
    var select=$(this); 
    //设置透明度为0 当然你也可以使用css控制 使用Jquery设置透明度可以屏蔽 透明度的 浏览器兼容性问题 
    $(select).css({ 
      "opacity":0 
    }); 
    //找到select的选项 
    var sOptions=this.get(0).options; 
    //设置模拟select的值 
    var setFixDivText=function(selectValue){ 
      var text=""; 
      for(var i=0;i<sOptions.length;i++){ 
        var option=sOptions[i]; 
        if(option.value==selectValue){ 
          text=$(option).text(); 
          break; 
        } 
      } 
      return text; 
    }; 
 
    //模拟的select 
    //初始化时要将select的值传入 
    var selectFixDiv=$('<div id="J_selectFix_'+select.attr("id")+'" class="selectFix">'+setFixDivText($(select).val())+'</div>'); 
    select.after(selectFixDiv); 
 
    var left=$(select).offset().left; 
    var top=$(select).offset().top-1;//因为一般select都有1px的边框,所以这里往上拉1px 
    $(selectFixDiv).css({ 
      "top" : top, 
      "left" : left 
    }); 
     
    //select选值时,将值显示到模拟的select上 
    $(select).bind("change click",function(){ 
      $(selectFixDiv).text(setFixDivText($(this).val())); 
    }); 
  }; 
  $.fn.selectFix=selectFix; 
})(jQuery);

 
 
插件代码运行:
 

jQuery(document).ready( function () {
var selects=$( "select.selectInput" );
if (selects.length){
selects.each( function (){
$( this ).selectFix();
});
}
});

jQuery(document).ready(function() { 
  var selects=$("select.selectInput"); 
  if(selects.length){ 
    selects.each(function(){ 
      $(this).selectFix(); 
    }); 
  } 
});

下面是html代码:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
< HTML >
< HEAD >
< TITLE > New Document </ TITLE >
< META NAME = "Generator" CONTENT = "EditPlus" >
< META NAME = "Author" CONTENT = "" >
< META NAME = "Keywords" CONTENT = "" >
< META NAME = "Description" CONTENT = "" >
< script type = text /javascript src = "http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js" > </ script >
< script type = text /javascript src = "temp.js" > </ script >
< style >
html {font-family: "宋体";font-size: 12px;line-height: 25px;color: #6F6F6F;}
.dn {display: none;}
select{cursor: pointer;}
input,
select,
textarea,
.selectFix {background: white;border: 1px solid #E0E0E0;hide-focus: expression( this.hideFocus = true ); outline: none;}
.formText,
.selectInput,
.text,
.selectFix{border: 1px solid #CCC;width: 180px;height: 30px;line-height:30px;padding: 0 3px;}
.selectInput {width: 248px; font-size:13px; position: relative; z-index: 2;}
.selectFix{width:248px; background: url(selectBg.png) no-repeat; background-position: right; background-color: #fff; position:absolute; z-index: 1;}
</ style >
</ HEAD >
< BODY >
< div id = "main" >
< select id = "sex" class = "selectInput" name = "sex" >
< option value = "0" > 男 </ option >
< option value = "1" > 女 </ option >
</ select >
</ div >
</ BODY >
</ HTML >

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> 
<HTML> 
<HEAD> 
<TITLE> New Document </TITLE> 
<META NAME="Generator" CONTENT="EditPlus"> 
<META NAME="Author" CONTENT=""> 
<META NAME="Keywords" CONTENT=""> 
<META NAME="Description" CONTENT=""> 
 <script type=text/javascript src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js"></script> 
 <script type=text/javascript src="temp.js"></script> 
 
 <style> 
html {font-family: "宋体";font-size: 12px;line-height: 25px;color: #6F6F6F;} 
.dn {display: none;} 
select{cursor: pointer;} 
input, 
select, 
textarea, 
.selectFix {background: white;border: 1px solid #E0E0E0;hide-focus: expression(this.hideFocus=true); outline: none;} 
.formText, 
.selectInput, 
.text, 
.selectFix{border: 1px solid #CCC;width: 180px;height: 30px;line-height:30px;padding: 0 3px;} 
.selectInput {width: 248px; font-size:13px; position: relative; z-index: 2;} 
.selectFix{width:248px; background: url(selectBg.png) no-repeat; background-position: right; background-color: #fff; position:absolute; z-index: 1;} 
 </style> 
</HEAD> 
 
<BODY> 
<div id="main"> 
  <select id="sex" class="selectInput" name="sex"> 
    <option value="0">男</option> 
    <option value="1">女</option> 
  </select> 
</div> 
</BODY> 
</HTML>

兼容主流浏览器。
 
 
但也还是有个重大的缺陷,在老版本的ie中,真正select的高度还是无法撑开。所以,用户点击模拟的select的靠下方的位置会发现select无法展开!!
不过设计的艺术在于平衡,如果你无法忍受这个缺陷,可以使用第一种解决方案。
 
 
另外,在测试后,发现如果select处于一个隐藏的容器中,那么显示后,select的位置是一个空白!!
这是怎么回事呢?!
原来,html元素隐藏后是无法获取他的屏幕坐标的!!! 所以这时候显示出来,真正的select完全透明了,而模拟的select跑到屏幕的左上角去了。因为他获取select的坐标为(0,0)
 
 
不要着急,这个问题有下面的解决办法:
1、单独写代码触发select的美化程序
首先,你需要将上面的美化程序运行代码做以下修改:
 

jQuery(document).ready( function () {
var selects=$( "select.selectInput" );
if (selects.length){
selects.each( function (){
if (!($( this ).attr( "autoFix" )== "false" )){
$( this ).selectFix();
}
});
}
});

jQuery(document).ready(function() { 
  var selects=$("select.selectInput"); 
  if(selects.length){ 
    selects.each(function(){ 
      if(!($(this).attr("autoFix")=="false")){ 
        $(this).selectFix(); 
      } 
    }); 
  } 
});

然后,在隐藏的select上加属性autoFix="false":

< select id = "sex" class = "selectInput" name = "sex" autoFix = "false" >
< option value = "0" > 男 </ option >
< option value = "1" > 女 </ option >
</ select >

<select id="sex" class="selectInput" name="sex" autoFix="false"> 
    <option value="0">男</option> 
    <option value="1">女</option> 
  </select>

然后,在外部容器显示的时候,手动调用$("#sex").selectFix()
 
2、如果容器的显示或者隐藏是第三方插件控制,修改不方便可考虑下面的方案:
在美化程序中,先判断select是否隐藏,如果否逻辑不变,如果隐藏,则加入一个timer,循环判断元素是否被显示,在其显示的时候再自动调用fix,然后将timer移除
代码如下:
 

//加上隐藏select的操作
( function ($){
var selectFix= function (){
var select=$( this );
//设置透明度为0 当然你也可以使用css控制 使用Jquery设置透明度可以屏蔽 透明度的 浏览器兼容性问题
$(select).css({
"opacity" :0
});
if (!select.is( ":hidden" )){
var sOptions= this .get(0).options;
var setFixDivText= function (selectValue){
var text= "" ;
for ( var i=0;i<sOptions.length;i++){
var option=sOptions[i];
if (option.value==selectValue){
text=$(option).text();
break ;
}
}
return text;
};
var selectFixDiv=$( '<div id="J_selectFix_' +select.attr("id ")+'" class = "selectFix" status= "close" >'+setFixDivText($(select).val())+ '</div>' );
select.after(selectFixDiv);
var selectWidth=$(select).innerWidth();
var selectFixDivWidth=$(selectFixDiv).innerWidth();
var left=$(select).offset().left;
var top=$(select).offset().top-1;
$(selectFixDiv).css({
"top" : top,
"left" : left,
"margin" : 0
});
$(select).bind( "change click" , function (){
$(selectFixDiv).text(setFixDivText($( this ).val()));
});
} else {
var tasks = function (){
if (!$(select).is( ":hidden" )){
$(select).selectFix();
clearInterval(timer);
}
};
var timer=setInterval(tasks,500)
}
};
$.fn.selectFix=selectFix;
})(jQuery);
//加上隐藏select的操作 
(function($){ 
  var selectFix=function(){ 
    var select=$(this); 
    //设置透明度为0 当然你也可以使用css控制 使用Jquery设置透明度可以屏蔽 透明度的 浏览器兼容性问题 
    $(select).css({ 
      "opacity":0 
    }); 
 
    if(!select.is(":hidden")){ 
      var sOptions=this.get(0).options; 
 
      var setFixDivText=function(selectValue){ 
        var text=""; 
        for(var i=0;i<sOptions.length;i++){ 
          var option=sOptions[i]; 
          if(option.value==selectValue){ 
            text=$(option).text(); 
            break; 
          } 
        } 
        return text; 
      }; 
 
      var selectFixDiv=$('<div id="J_selectFix_'+select.attr("id")+'" class="selectFix" status="close">'+setFixDivText($(select).val())+'</div>'); 
      select.after(selectFixDiv); 
 
      var selectWidth=$(select).innerWidth(); 
      var selectFixDivWidth=$(selectFixDiv).innerWidth(); 
      var left=$(select).offset().left; 
 
      var top=$(select).offset().top-1; 
      $(selectFixDiv).css({ 
        "top" : top, 
        "left" : left, 
        "margin" : 0 
      }); 
 
      $(select).bind("change click",function(){ 
        $(selectFixDiv).text(setFixDivText($(this).val())); 
      }); 
    }else{ 
      var tasks = function(){ 
        if(!$(select).is(":hidden")){ 
          $(select).selectFix(); 
          clearInterval(timer); 
        } 
      }; 
      var timer=setInterval(tasks,500) 
    } 
  }; 
  $.fn.selectFix=selectFix; 
})(jQuery);

运行代码跟原来的不变。

Javascript 相关文章推荐
浅谈EasyUI中编辑treegrid的方法
Mar 01 Javascript
浅谈JS中逗号运算符的用法
Jun 12 Javascript
JS基础随笔(菜鸟必看篇)
Jul 13 Javascript
jQuery中deferred对象使用方法详解
Jul 14 Javascript
Javascript中document.referrer隐藏来源的方法
Jan 16 Javascript
Vue.js对象转换实例
Jun 07 Javascript
基于构造函数的五种继承方法小结
Jul 27 Javascript
分析JS中this引发的bug
Dec 12 Javascript
JS中Map和ForEach的区别
Feb 05 Javascript
Vue登录注册并保持登录状态的方法
Aug 17 Javascript
VUE实现移动端列表筛选功能
Aug 23 Javascript
vue中利用three.js实现全景图的完整示例
Dec 07 Vue.js
基于Jquery easyui 选中特定的tab
Nov 17 #Javascript
jquery实现简单的表单验证
Nov 17 #Javascript
将JavaScript的jQuery库中表单转化为JSON对象的方法
Nov 17 #Javascript
基于jquery实现可定制的web在线富文本编辑器附源码下载
Nov 17 #Javascript
Jquery ajax 同步阻塞引起的UI线程阻塞问题
Nov 17 #Javascript
jquery判断密码强度的验证代码
Apr 22 #Javascript
jquery实现邮箱自动填充提示功能
Nov 17 #Javascript
You might like
用PHP实现ODBC数据分页显示一例
2006/10/09 PHP
php+ajax实现图片文件上传功能实例
2014/06/17 PHP
PHP关于htmlspecialchars、strip_tags、addslashes的解释
2014/07/04 PHP
PHP获取mysql数据表的字段名称和详细信息的方法
2014/09/27 PHP
PHP向浏览器输出内容的4个函数总结
2014/11/17 PHP
PHP简单生成缩略图相册的方法
2015/07/29 PHP
浅谈php中的访问修饰符private、protected、public的作用范围
2016/11/20 PHP
php封装的验证码类分享
2017/02/26 PHP
PHP实时统计中文字数和区别
2019/02/28 PHP
用js实现in_array的方法
2013/11/05 Javascript
js函数模拟显示桌面.scf程序示例
2014/04/20 Javascript
js实现3D图片逐张轮播幻灯片特效代码分享
2015/09/09 Javascript
仅9张思维导图帮你轻松学习Javascript 就这么简单
2016/06/01 Javascript
微信小程序  modal详解及实例代码
2016/11/09 Javascript
javascript基本数据类型及类型检测常用方法小结
2016/12/14 Javascript
MvcPager分页控件 适用于Bootstrap
2017/06/03 Javascript
JavaScript方法_动力节点Java学院整理
2017/06/28 Javascript
webpack使用 babel-loader 转换 ES6代码示例
2017/08/21 Javascript
vue3.0 CLI - 3.2 路由的初级使用教程
2018/09/20 Javascript
vue父组件给子组件的组件传值provide inject的方法
2019/10/23 Javascript
javascript设计模式 ? 适配器模式原理与应用实例分析
2020/04/13 Javascript
JavaScript如何实现监听键盘输入和鼠标监点击
2020/07/20 Javascript
[02:23]2018DOTA2亚洲邀请赛趣味视频——反应测试
2018/04/04 DOTA
编写Python CGI脚本的教程
2015/06/29 Python
Python文件和流(实例讲解)
2017/09/12 Python
Python字符串格式化常用手段及注意事项
2020/06/17 Python
python利用google翻译方法实例(翻译字幕文件)
2020/09/21 Python
html5 postMessage前端跨域并前端监听的方法示例
2018/11/01 HTML / CSS
好的自荐信包括什么内容
2013/11/07 职场文书
营业员演讲稿
2013/12/30 职场文书
数控技术专科生自我评价
2014/01/08 职场文书
访谈节目策划方案
2014/05/15 职场文书
职务任命书范本
2014/06/05 职场文书
2015年环卫工作总结
2015/04/28 职场文书
2015年度电厂个人工作总结
2015/05/13 职场文书
基于CSS3画一个iPhone
2021/04/21 HTML / CSS