最近经常与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. 一个寻找.jar 和.zip文件中class文件的工具

    相信很多人跟我一样,苦于在各种包之间,不知道Class存在什么地方,为此,自己写了一个小工具,来寻找目录下的Class文件 支持 目录查询,支持带包路径查询 入口Entrance.java packa ...

  2. ElasticSearch怎样加入,检索数据

    Elasticsearch是一个分布式的文档(document)存储引擎.它能够实时存储并检索复杂数据结构--序列化的JSON文档.换言说,一旦文档被存储在Elasticsearch中,它就能够在集群 ...

  3. Python调用C可执行程序(subprocess) 分类: python 服务器搭建 C/C++ shell 2015-04-13 21:03 87人阅读 评论(0) 收藏

    从Python 2.4开始,Python引入subprocess模块来管理子进程,以取代一些旧模块的方法:如 os.system.os.spawn.os.popen.popen2.commands. ...

  4. JavaScript中七种函数调用方式及对应 this 的含义

    this 在 JavaScript 开发中占有相当重要的地位,不过很多人对this这个东西都感觉到琢磨不透.要真正理解JavaScript的函数机制,就非常有必要搞清楚this到底是怎么回事. 函数调 ...

  5. 如何判断Android系统的版本

    随着Android版本的增多,在不同的版本中使用不同的设计是必须的,根据程序运行的版本来提供不同的功能.这涉及到如何在程序中判断Android系统的版本. 在Android api中的android. ...

  6. memcpy的使用方法总结

    1.memcpy 函数用于 把资源内存(src所指向的内存区域) 复制到目标内存(dest所指向的内存区域):拷贝多少个?有一个size变量控制拷贝的字节数:函数原型:void *memcpy(voi ...

  7. Android 疑难杂症之获取listView Item上面组件的值

    事实上思路就是又一次findById一次 获取当中组建的值.比方应用场景是 长按点击事件 获取目录名字 @Override public boolean onItemLongClick(Adapter ...

  8. android 5.0开发环境搭建

    Android 5.0 是 Google 于 2014 年 10 月 15 日发布的全新 Android 操作系统.本文将就最新的Android 5.0 开发环境搭建做详细介绍. 工具/原料 jdk- ...

  9. careercup-栈与队列 3.2

    3.2 请设计一个栈,除pop与push方法,还支持min方法,可返回栈元素中的最小值.push.pop和min三个方法的时间复杂度必须为O(1). 我们假设除了用一个栈s1来保存数据,还用另一个栈s ...

  10. HttpModule HttpHandler HttpHandlerFactory 学习笔记

    1.HttpModule 最常见的是使用HttpModule来做页面权限控制. 在新建类库添加如下代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ...