最近经常与select打交道,因为ie下的select实在太丑了,css怎么搞都搞不好看,因为程序已经写得差不多了,要再去模拟select改动太大,就想着能否不改动select,同时美化它。借鉴一下这篇文章js美化select,然后自己写了一个jquery插件,补充了一些功能。

原理(这里就直接copy啦):

第一步:将表单中的select隐藏起来。 

   第二步:用脚本找到select标签在网页上的绝对位置。 我们在那个位置上用DIV标签做个假的、好看点的来当他的替身。 

   第三步:用脚本把select标签中的值读出来。 虽然藏起来了,但它里边的options我们还有用呢,统统取出来。

   第四步:当用户点击select标签的替身,也就是div的时候。我们再用一个div浮在上一个div的下边,这个就是options的替身了。

说白了,就是弄一个div把原来的select完整遮住,然后实现弹出层和原来的option交互,难点就是交互。

本文不打算讲怎么实现,源码里有注释,主要是分享,顺便说下几个需要注意的问题以及使用方法,小弟语文渣,凑合着看吧。。。

所有代码全部打包在csdn下载那里,无需积分,下载地址

    先贴张效果图chrome,ff,ie,电脑上还是ie11的,ie大家不用说吧,做兼容性,select万恶啊。

 
  

   使用方法

    包含jquery.js,我用的1.8,然后包含jquery.beautifySelect.js,完整html测试代码

    html代码: 

1
2
3
4
5
<div style="margin:20px;">
     <select id="sel1"></select>
     <select id="sel2"></select>
     <button onclick="redraw()">重绘</button>
</div>

    sel1是要覆盖的select,sel2作为对比。button测试select内容发生变化重新覆盖。

   

    js代码: 
  

    添加select

1
2
3
4
5
6
var _html = "";
for(var i = 0;i<22;++i){
    _html += "<option>" +i+"闲来无事写插件"+"</option>";
}
document.getElementById("sel1").innerHTML = _html;
document.getElementById("sel2").innerHTML = _html;

      调用

1
2
3
4
5
6
7
8
$("#sel1").beautifySelect({
    "maxShowItemNum" : 9,
    "downIcon" "url(down.png)  right  no-repeat",
    "upIcon" "url(up.png) right  no-repeat"
});
$("#sel1").change(function(){
    console.log(this.value+"改变");//观察事件
});

顺带测试select内容发生变化后的重绘

1
2
3
4
5
6
7
8
9
10
11
12
13
function redraw(){
    //如果select内容发生变化,相应重绘部分
    var _html = "";
    for(var i = 0 ;i<13;++i){
        _html += "<option>" +i+"内容改变啦""</option>";
    }
    document.getElementById("sel1").innerHTML = _html;
    $("#sel1").beautifySelect({
        "sDivStyle" : {
            "border" "1px solid red"
        }
    });
}
        调用方法很简单,基本上使用过插件就知道,这里简单说下,maxShowItemNum是下拉框最大显示条数
downIcon是向下折叠图标,upIcon是向上折叠图标。这里就是css样式,可以修改select样式,下面是全部样式,有注释就不细说了。

       可供选择入参
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
var defaultParObj = {
    "maxShowItemNum" : 10,//默认最多显示10条
    "sDivStyle" : {//select覆盖层样式
        "border" "1px solid #A5A5A5",
        "fontSize" "12px",
        "cursor" "default"
    },
    "hDivStyle" : {//弹出层,即下拉样式
        "border" "1px solid #7C99B7",
        "backgroundColor" "#FFF",
        "maxHeight" "200px",
        "overflowY" "auto"
    },
    "ulStyle" : {//因为用ul,li模拟的下拉,这里是ul的样式
        "fontSize" "12px"
    },
    "liStyle" : {//这是li的样式,就是每一条目
        "textIndent" "4px",
        "height" "20px",
        "lineHeight" "20px",
        "cursor" "default"
    },
    "liOnStyle": {//鼠标移上去的样式
        "backgroundColor" "#1E90FF",
        "color" "#FFF"
    },
    "liOffStyle" : {//鼠标移开的样式
        "backgroundColor" "#FFF",
        "color" "#000"
    }
    // "downIcon" : "url(...) 0 0",//向上图标
    // "upIcon" : "url(...) 0 0"//向下图标
};
注意:
因为使用的div模拟的select,浏览器上,select失去焦点后会关闭下拉,这个暂时还没想到办法实现,以前做过笨方法,
给body添加click事件,判断target,但是很慢。暂时不管吧,再来项目用模拟的,这个只是为了不改写好的事件做的美化。


特点:
除了上面说的不能失去焦点关闭,其他事件基本上都实现了,因为参照chrome的样式做的,不过提供属性,可以改样式。




最后附上插件源码,第一次弄,格式老不对,就直接粘了吧,代码打个包放在那啥下载那儿,亲们,欢迎吐槽!
下载链接csdn源代码下载
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/**
 * @author 小余
 * 2014-08-30
 * 本插件基于jquery,为了美化select下拉框
 * 原理:
 * 第一步:将表单中的select隐藏起来。 
 * 第二步:用脚本找到select标签在网页上的绝对位置。 我们在那个位置上用DIV标签做个假的、好看点的来当他的替身。 
 * 第三步:用脚本把select标签中的值读出来。 虽然藏起来了,但它里边的options我们还有用呢,统统取过来。
 * 第四步:当用户点击select标签的替身,也就是div的时候。我们再用一个div浮在上一个div的下边,这个就是options的替身了。 
 * 调用举例:$("#selid").beautifySelect({
 *   
        "downIconUrl" : "ulr..",
 *           
"upIconUrl"  : "url.."
 *       
    "sDivStyle" : {
 *           
 *       
     }
 * });
 * */
;
(function ($) {
  $.fn.beautifySelect = function (attrObj) {
    var defaultParObj = {
      'maxShowItemNum': 10,
      //默认最多显示10条
      'sDivStyle': {
        'border''1px solid #A5A5A5',
        'fontSize''12px',
        'cursor''default'
      },
      'hDivStyle': {
        'border''1px solid #7C99B7',
        'backgroundColor''#FFF',
        'maxHeight''200px',
        'overflowY''auto'
      },
      'ulStyle': {
        'fontSize''12px'
      },
      'liStyle': {
        'textIndent''4px',
        'height''20px',
        'lineHeight''20px',
        'cursor''default'
      },
      'liOnStyle': {
        'backgroundColor''#1E90FF',
        'color''#FFF'
      },
      'liOffStyle': {
        'backgroundColor''#FFF',
        'color''#000'
      }
      // "downIcon" : "url(...) 0 0",//可入参
      // "upIcon" : "url(...) 0 0"
 
    };
    if (attrObj != undefined) {
      //合并
      for (var in attrObj) {
        if (typeof (attrObj[i]) != 'object') {
          defaultParObj[i] = attrObj[i];
        
        else defaultParObj[i] = $.extend(defaultParObj[i], attrObj[i]);
      }
    }
    //console.log(JSON.stringify(defaultParObj));
 
    var attrObj = defaultParObj;
    //设置弹出层高度
    var liHeight = attrObj.liStyle.lineHeight;
    //px
    attrObj.hDivStyle.maxHeight = attrObj.maxShowItemNum * parseInt(liHeight.slice(0, liHeight.indexOf('p'))) + 'px';
    var selectDom = this.get(0);
    //判断当前dom是否是select,不是提示使用错误
    if (selectDom.tagName != 'SELECT') {
      alert('使用错误,dom不是select对象');
      return ;
    }
    var selectPosObj = $.getAbsolutePos(selectDom);
    selectDom.style.visibility = 'hidden';
    //隐藏select,要占据位置
    //sDiv表示show的div,hDiv表示会hide的div,如果已经有,清空dom,删除事件,重新创建
    if (document.getElementById('selectOf' + selectDom.id) != null) {
      $('#selectOf' + selectDom.id) .remove();
      $('#selectChild' + selectDom.id) .remove();
    }
    var sDiv = document.createElement('div');
    sDiv.id = 'selectOf' + selectDom.id;
    sDiv.style.position = 'absolute';
    sDiv.style.width = selectPosObj.width + 'px';
    sDiv.style.height = selectPosObj.height + 'px';
    sDiv.style.top = selectPosObj.top + 'px';
    sDiv.style.left = selectPosObj.left + 'px';
    sDiv.style.lineHeight = selectPosObj.height + 'px';
    sDiv.style.cursor = 'default';
    for (var in attrObj.sDivStyle) {
      sDiv.style[i] = attrObj.sDivStyle[i];
    }
    if (attrObj.downIcon != undefined) {
      sDiv.style.background = attrObj.downIcon;
    }
    document.body.appendChild(sDiv);
    if (selectDom.selectedIndex == - 1) {
      alert('select未初始化');
      return ;
    }
    //select默认值传递给div
 
    sDiv.innerHTML = selectDom.options[selectDom.selectedIndex].innerHTML;
    var ifCreateHDiv = false;
    //是否创建过弹出层 
       
    sDiv.onclick = function () {
      if (ifCreateHDiv) {
        var hDiv = document.getElementById('selectChild' + selectDom.id);
        if (hDiv.style.display == 'none') {
          var index = selectDom.selectedIndex;
          for (var in attrObj.liOnStyle) {
            $(hDiv) .find('li:eq(' + index + ')') .get(0) .style[i] = attrObj.liOnStyle[i];
          };
          hDiv.style.display = '';
          //马上弹出
          if (attrObj.upIcon != undefined) sDiv.style.background = attrObj.upIcon;
          //向上折叠
        else {
          hDiv.style.display = 'none';
          if (attrObj.downIcon != undefined) sDiv.style.background = attrObj.downIcon;
          //向下折叠
        };
      else {
        //没有创建过,创建
        var hDiv = document.createElement('div');
        hDiv.id = 'selectChild' + selectDom.id;
        hDiv.style.position = 'absolute';
        hDiv.style.width = selectPosObj.width + 'px';
        hDiv.style.top = (selectPosObj.top + selectPosObj.height + 2) + 'px';
        hDiv.style.left = selectPosObj.left + 'px';
        for (var in attrObj.hDivStyle) {
          hDiv.style[i] = attrObj.hDivStyle[i];
        };
        //创建ul
        var ul = document.createElement('ul');
        ul.style.listStyle = 'none';
        ul.style.margin = '0';
        ul.style.padding = '0';
        for (var in attrObj.ulStyle) {
          ul.style[i] = attrObj.ulStyle[i];
        };
        hDiv.appendChild(ul);
        document.body.appendChild(hDiv);
        ifCreateHDiv = true;
        if (attrObj.upIcon != undefined) sDiv.style.background = attrObj.upIcon;
        //向上折叠
        for (var i = 0; i < selectDom.options.length; ++i) {
          var li = document.createElement('li');
          li.name = 'li' + i;
          //后面会用到
          li.innerHTML = selectDom.options[i].innerHTML;
          for (var in attrObj.liStyle) {
            li.style[j] = attrObj.liStyle[j];
          };
          ul.appendChild(li);
        };
        //默认填充第一个,那么默认第一个有样式
        for (var in attrObj.liOnStyle) {
          $(hDiv) .find('li:eq(0)') .get(0) .style[i] = attrObj.liOnStyle[i];
        }
        $(ul) .on('click''li'function () {
          document.getElementById('selectChild' + selectDom.id) .style.display = 'none';
          sDiv.innerHTML = this.innerHTML;
          var index = parseInt(this.name.slice(2));
          if (index != selectDom.selectedIndex) {
            selectDom.options[parseInt(this.name.slice(2))].selected = true;
            $(selectDom) .trigger('change');
          }
        });
        $(ul) .on('mouseenter''li'function () {
          var liDom = this;
          for (var in attrObj.liOnStyle) {
            liDom.style[i] = attrObj.liOnStyle[i];
          }
          //找到选中的li,弄掉样式,如果当前的li就是选中的li,就不弄掉
 
          var index = selectDom.selectedIndex;
          if (parseInt(liDom.name.slice(2)) != index) {
            for (var in attrObj.liOffStyle) {
              $(ul) .find('li:eq(' + selectDom.selectedIndex + ')') .get(0) .style[i] = attrObj.liOffStyle[i];
            }
          }
        });
        $(ul) .on('mouseleave''li'function () {
          var liDom = this;
          for (var in attrObj.liOffStyle) {
            liDom.style[i] = attrObj.liOffStyle[i];
          }
        });
      }
    }
  };
  $.getAbsolutePos = function (dom) {
    //取标签的绝对位置,高度是内容高度
    var t = dom.offsetTop;
    var l = dom.offsetLeft;
    var w = dom.offsetWidth;
    var h = dom.offsetHeight - 2;
    //offsetHeight包括border
    while (dom = dom.offsetParent) {
      t += dom.offsetTop;
      l += dom.offsetLeft;
    }
    return {
      'top': t,
      'left': l,
      'width': w,
      'height': h
    }
  };
}) (jQuery);





jquery插件,美化select标签的更多相关文章

  1. jquery插件-自定义select

        由于原生select在各个浏览器的样式不统一,特别是在IE67下直接不可以使用样式控制,当PM让你做一个样式的时候,那是相当的痛苦.最好的办法就是使用自定义样式仿select效果.这里写了一个 ...

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

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

  3. jquery插件:select、checkbox、radio的美化

    引用文件:  <script src=”/InputPick/jqInputFormat.js” type=”text/javascript”></script> <li ...

  4. jquery插件之tab标签页或滑动门

    该插件乃本博客作者所写,目的在于提升作者的js能力,也给一些js菜鸟在使用插件时提供一些便利,老鸟就悠然地飞过吧. 此插件旨在实现目前较为流行的tab标签页或滑动门特效,在此插件中默认使用的是鼠标滑过 ...

  5. 网站开发常用jQuery插件总结(八)标签编辑插件Tagit

    一.Tagit插件功能 提高网站交互性,增加用户体验.至于其它的功能,还真没有.用一个input text就可以替换了它.但是text没有输入提示功能,而tagit拥有这个功能.官方示例如下图: 将关 ...

  6. css美化select标签,兼容ie10 ie10+,chrome。但不支持ie9 ie9-

    让ie9 ie9+ 和非ie的浏览器加载这个hack.ie8,ie8- 就用自己的默认样式 <!-- email:416960428@qq.com author:李可 --> <!- ...

  7. jQuery插件综合应用(三)发布文章页面

    一.使用的插件 一个折叠的功能导航,由Akordeon插件实现.Nanoscroller插件与Tagit插件主要用于美化页面.这里只是测试,其实还可以综合使用其它的插件,例如将Akordeon插件换成 ...

  8. 美化select的jquery插件

    自己写的一个美化select插件,浏览器自带的实在太丑,还不能用css自定义. 插件主要原理是隐藏原生的select控件,支持select上设置change事件. 脚本 /* * iSelect * ...

  9. JQCloud: 一个前端生成美化标签云的简单JQuery插件

    本文原文地址:https://jiang-hao.com/articles/2018/blog-JQCloud.html 因为博客需要,发现了一个生成美化简约风格的标签云的JQuery插件. 官网地址 ...

随机推荐

  1. 有n个台阶,如果一次只能上1个或2个台阶,求一共有多少种上法

    // n级台阶,求多少种跳法.cpp : Defines the entry point for the console application. // /* 思路: 如果只有一级台阶,n=1,很明显 ...

  2. TortoiseSVN客户端重新设置用户名和密码[转]

    在第一次使用TortoiseSVN从服务器CheckOut的时候,会要求输入用户名和密码,这时输入框下面有个选项是保存认证信息,如果选了这个选项,那么以后就不用每次都输入一遍用户名密码了. 不过,如果 ...

  3. mysql查询随机几条数据(速度快)

    MySql查询随机几条数据 想到了 Max RAND 这几个函数 用以下2种办法都可以实现查询. 速度还行. 几十万数据左右, 没有什么问题. SELECT * FROM `news` WHERE i ...

  4. John(博弈)

    Description Little John is playing very funny game with his  younger brother. There  is one big box ...

  5. python学习笔记--Django入门0 安装dangjo

    经过这几天的折腾,经历了Django的各种报错,翻译的内容虽然不错,但是与实际的版本有差别,会出现各种奇葩的错误.现在终于找到了解决方法:查看英文原版内容:http://djangobook.com/ ...

  6. 程序员带你学习安卓开发,十天快速入-对比C#学习java语法

    关注今日头条-做全栈攻城狮,学代码也要读书,爱全栈,更爱生活.提供程序员技术及生活指导干货. 如果你真想学习,请评论学过的每篇文章,记录学习的痕迹. 请把所有教程文章中所提及的代码,最少敲写三遍,达到 ...

  7. HTML+CSS基础学习笔记(2)

    一.无序列表标签ul <ul> <li>信息</li> <li>信息</li> ...... </ul> 代码解释:每项< ...

  8. LAMP网站架构方案分析

    本文引自:http://www.williamlong.info/archives/1908.html LAMP(Linux-Apache-MySQL-PHP)网站架构是目前国际流行的Web框架,该框 ...

  9. 手机端的表单验证和PC端的不同

    1.手机端:由于页面小的局限性,表单验证从上到下依次进行,如果上一个验证不通过,则给出错误提示,代码中return回去,不必进行下一个的校验: 2.PC端:页面范围大,一般是在表单的后面或者下面,提示 ...

  10. exists查询中子表可以是

    exists查询中子表可以是’或则具体某一列 ,查询结果一致,因为exists只会返回 true或者false,一个boolean型的值