jquery插件,美化select标签

时间:2022-09-06 17:02:49

最近经常与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插件,美化select标签jquery插件,美化select标签jquery插件,美化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);