首页 > 代码库 > 自定义样式的select下拉框深入探索

自定义样式的select下拉框深入探索

第一个版本:

首先实现自定义select下拉框应该具有的功能,我是选择将原来的select隐藏掉,自己在jquery代码中动态写进去<dl><dd><dt>这样的结构来模拟真正的select的操作。

用来模拟select框的div结构如下:

   <div class="selectbox">//包裹整个模拟框的盒子

       <div class="currentselected"></div>//用于当前默认显示的selected的元素

       <div class="selectoption"></div>//模拟弹出的select下拉框<dl><dd><dt>结构包裹在其中

   </div>

代码如下:

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  3 <head>  4   <title></title>  5   <meta http-equiv="content-type" content="text/html; charset=utf-8" />  6   <script type="text/javascript" src="jquery.min.js"></script>  7   8   <style>  9       p{float:left;margin:20px;font-size:14px} 10  11  12     .i_selectbox { 13       margin-top:20px; 14       height:32px; 15       position:relative; 16       font-size:14px 17     }  18     /* 默认显示的select框*/ 19     .i_selectbox .i_currentselected { 20       width:150px; 21       height:24px; 22       background:url(select.png) 176px 4px no-repeat; 23       border:1px solid #cdcdcd; 24       text-indent:10px; 25       line-height:24px; 26       cursor:pointer 27     }  28     /* 下拉选择框 */ 29     .i_selectbox .i_selectoption { 30       overflow-x:hidden; 31       overflow-y:hidden; 32       position:absolute; 33       left:0px; 34       top:17px; 35       padding:5px; 36       background-color:#fff; 37       background:rgba(255,255,255,.9); 38       border:1px solid #eee 39     }  40     .i_selectbox .i_selectoption dt { 41       height:24px; 42       background-color:#eee; 43       text-indent:5px; 44       font-style:italic; 45       color:#555; 46       line-height:24px; 47     }  48     .i_selectbox .i_selectoption dd{ 49       margin-left: -3px; 50       height:30px; 51       border-bottom:1px solid #cdcdcd; 52       cursor:pointer; 53       text-indent:2px; 54       line-height:30px 55     }  56     .i_selectbox .i_selectoption dd:hover{ 57       background-color:#cdcdcd; 58       color:#fff 59     } 60     .i_selectbox .i_selectoption dd.selected{ 61       background-color:#f17f36; 62       color:#fff 63     } 64      </style>  65 <head> 66 <body> 67       <select class="my_select"> 68      69           <option value="0">Alabama</option> 70           <option value="1">Alaska</option> 71           <option value="2">Arizona</option> 72  73           <option value="3">Arkansas</option> 74           <option value="4">California</option> 75           <option value="5">Colorado</option> 76    77           <option value="6">Connecticut</option> 78           <option value="7">Delaware</option> 79           <option value="8">Columbia</option> 80           <option value="9">Florida</option> 81       82         </select> 83         <script> 84        85              /*插件写法的函数*/ 86              $.fn.newStyle = function(){ 87               var set = { 88                 selectbox : i_selectbox, 89                 showselect : i_currentselected, 90                 selectoption : i_selectoption, 91                 curselect : selected, 92                 width : 200, 93                 height :150, 94                 zindex : 2 95               }; 96               /*让最初的select隐藏*/ 97               $(this).hide(); 98               /*动态写进去html替代原本的select*/ 99               var html = <div class="+set.selectbox+" style="zindex:+set.zindex+">100                          +<div class="+set.showselect+" style="width:+set.width+px;">+$(this).find(option:selected).text()+</div>101                          +<dl class="+set.selectoption+" style="display:none;width:+set.width+px" >;102               if($(this).find(optgroup).size()>0){103                   $(this).find(optgroup).each(function(){104                    html += <dt>+$(this).attr(label)+</dt>;105                           $(this).find(option).each(function(){106                               if($(this).is(:selected)){107                                 html += <dd class="+set.curselect+">+$(this).text()+</dd>;108                               }else{109                                 html += <dd>+$(this).text()+</dd>;110                               }111                           });112                   });113               }else{114                 $(this).find(option).each(function(){115                    if($(this).is(:selected)){116                      html += <dd class="+set.curselect+">+$(this).text()+</dd>;117                    }else{118                      html += <dd>+$(this).text()+</dd>;119                    }120                 });121 122               }123               /*将html插入到select框的后面*/124               $(select).after(html);125               console.log(0);126               /*添加事件*/127 128               /*默认显示框的选择事件toggle选择*/129               $(.+set.showselect).toggle(function(){130                  console.log(1);131                  /*$(‘.selectoption‘).hide();*/132                  $(.+set.selectbox).css(zindex,set.zindex);133                  $(.+set.selectoption).css(zindex,set.zindex+1);134                  $(.+set.selectoption).toggle();135               },function(){136                  $(.+set.selectoption).css(zindex,set.zindex);137                  $(.+set.selectoption).toggle();138               });139               /*下拉列表的选择事件*/140               $(.+set.selectoption).find(dd).click(function(){141                  console.log(2);142                  $(this).addClass(set.curselect).siblings().removeClass(set.curselect);143                  var index = $(.+set.selectoption).find(dd).index(this);144                  $(.+set.showselect).text($(this).text());145                  $(this).find(option).eq(index).attr(selected,selected);146                  $(.+set.selectoption).hide();147               });148               /*点击select框之外的其他部分的时候select框应该收起*/149                $(html,body).click(function(e){150                        /* 判断当前的点击事件目标不是set.selectoption这个class*/151                          if(e.target.className.indexOf(set.selectoption)==-1){152                               $(.+set.selectoption).hide();153                               $(.+set.selectbox).css(zIndex,set.zindex);154                           }155                 });156 157             }158       159         $(.my_select).newStyle();160                  161         </script>162 </body>163 </html>

 

TIPs:1.给默认显示的下拉框添加toggle事件而不是一般的click事件使得它的连续点击具有意义;

         2.给html,body添加事件,判断在点击自定义的下拉框之外的任何地方的时候,自定义下拉框收起。

 

本来我也以为,一段代码一个功能这样写完就可以了,但是继续改进下去,可以学到的东西真的很多。

 

第二个版本:

这里是给我自定义的select下拉框添加了键盘选择事件的版本,上下键选择,同时实时更新默认显示框中的内容,esc键实现自定义下拉框收起,此时上下键依然可以实时选择。

代码如下:

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  3 <head>  4   <title></title>  5   <meta http-equiv="content-type" content="text/html; charset=utf-8" />  6   <script type="text/javascript" src="jquery.min.js"></script>  7   8   <style>  9      10  11      /* 这里来定义你自己的select框的样式 */ 12     .i_selectbox { 13       margin-top:20px; 14       height:32px; 15       position:relative; 16       font-size:14px 17     }  18     /* 默认显示的select框*/ 19     .i_selectbox .i_currentselected { 20       width:150px; 21       height:24px; 22       background:url(select.png) 176px 4px no-repeat; 23       border:1px solid #cdcdcd; 24       text-indent:10px; 25       line-height:24px; 26       cursor:pointer 27     }  28     /* 这里是隐藏的input框 */ 29     #hiddenput { 30        display: block; 31        width:200px; 32        height:18px; 33        margin-top: -25px; 34        position: absolute; 35        z-index:-2; 36        opacity:0; 37        filter:alpha(opacity=0); 38     } 39     /* 下拉选择框 */ 40     .i_selectbox .i_selectoption { 41       overflow-x:hidden; 42       overflow-y:hidden; 43       position:absolute; 44       left:0px; 45       top:17px; 46       padding:5px; 47       background-color:#fff; 48       background:rgba(255,255,255,.9); 49       border:1px solid #eee 50     }  51     .i_selectbox .i_selectoption dt { 52       height:24px; 53       background-color:#eee; 54       text-indent:5px; 55       font-style:italic; 56       color:#555; 57       line-height:24px; 58     }  59     .i_selectbox .i_selectoption dd{ 60       margin-left: -3px; 61       height:30px; 62       border-bottom:1px solid #cdcdcd; 63       cursor:pointer; 64       text-indent:2px; 65       line-height:30px 66     }  67     .i_selectbox .i_selectoption dd:hover{ 68       background-color:#cdcdcd; 69       color:#fff 70     } 71     .i_selectbox .i_selectoption dd.selected{ 72       background-color:#f17f36; 73       color:#fff 74     } 75      </style>  76 <head> 77 <body> 78       <select class="my_select"> 79      80           <option value="0">Alabama</option> 81           <option value="1">Alaska</option> 82           <option value="2">Arizona</option> 83  84           <option value="3">Arkansas</option> 85           <option value="4">California</option> 86           <option value="5">Colorado</option> 87    88           <option value="6">Connecticut</option> 89           <option value="7">Delaware</option> 90           <option value="8">Columbia</option> 91           <option value="9">Florida</option> 92       93         </select> 94         <script> 95       (function($){ 96              /*插件写法的函数*/ 97              $.fn.newStyle = function(){ 98               var set = { 99                 selectbox : i_selectbox,100                 showselect : i_currentselected,101                 selectoption : i_selectoption,102                 curselect : selected,103                 width : 200,104                 height :150,105                 zindex : 2106               };107               /*让最初的select隐藏*/108               $(this).hide();109               /*动态写进去html替代原本的select*/110               var html = <div class="+set.selectbox+" style="zindex:+set.zindex+">111                          +<div class="+set.showselect+" style="width:+set.width+px;">+$(this).find(option:selected).text()+</div>112                          +<input type="text" id="hiddenput" name="hiddenput"/>113                          +<dl class="+set.selectoption+" style="display:none;width:+set.width+px" >;114               if($(this).find(optgroup).size()>0){115                   $(this).find(optgroup).each(function(){116                    html += <dt>+$(this).attr(label)+</dt>;117                           $(this).find(option).each(function(){118                               if($(this).is(:selected)){119                                 html += <dd class="+set.curselect+">+$(this).text()+</dd>;120                               }else{121                                 html += <dd>+$(this).text()+</dd>;122                               }123                           });124                   });125               }else{126                 $(this).find(option).each(function(){127                    if($(this).is(:selected)){128                      html += <dd class="+set.curselect+">+$(this).text()+</dd>;129                    }else{130                      html += <dd>+$(this).text()+</dd>;131                    }132                 });133 134               }135               /*将html插入到select框的后面*/136               $(select).after(html);137              138 139               /*为了写起来方便,给外围的box和当前显示的select框还有自定义的下拉框一个简单的变量*/140               thisbox = $(.+set.selectbox);141               thisselect = $(.+set.showselect);142               thisoption = $(.+set.selectoption);143               /*添加事件*/144 145               /*默认显示框的选择事件,点击默认显示框,下拉列表会在可见与不可见状态之间切换*/146               thisselect.toggle(function(){147                  /*$(‘.selectoption‘).hide();*/148                  thisbox.css(zindex,set.zindex);149                  thisoption.css(zindex,set.zindex+1);150                  thisoption.toggle();151               },function(){152                  thisoption.css(zindex,set.zindex);153                  thisoption.toggle();154               });155 156               /*下拉列表的选择事件*/157               thisoption.find(dd).click(function(){158                  $(this).addClass(set.curselect).siblings().removeClass(set.curselect);159                  var index = thisoption.find(dd).index(this);160                  thisselect.text($(this).text());161                  $(this).find(option).eq(index).prop(selected,true);162                  thisoption.hide();163               });164 165               /*点击默认显示框时要给我隐藏的input获得焦点*/166               thisselect.click(function(){167                 $(input)[0].focus();168               })169 170               var index = 0;171               /*下拉列表的键盘事件*/172               $("input").keyup(function(e){173                   var keycode = e.which;174                   console.log(keycode);175                   var ddtarget = thisoption.find(dd);176                   /*向下*/177                   if(keycode == 40){178                      index++;179                      console.log(index);180                      if(index == ddtarget.length){181                         index = 0;182                         console.log(index);183                      }184                     /* 设为当前选中项,同時在默认显示的select框中同步显示*/185                      thisoption.find(dd).eq(index).addClass(set.curselect).siblings().removeClass(set.curselect);186                      var ddindex = thisoption.find(dd).eq(index).index(this);187                      thisselect.text(thisoption.find(dd).eq(index).text());188                      $(this).find(option).eq(ddindex).prop(selected,true);189                      }190                   /*向上*/191                   if(keycode == 38){192                      193                      console.log(index);194                      if(index == 0){195                         index = ddtarget.length;196                         console.log(index);197                      }198                      index--;199                     /* 设为当前选中项,同時在默认显示的select框中同步显示*/200                      thisoption.find(dd).eq(index).addClass(set.curselect).siblings().removeClass(set.curselect);201                      var ddindex = thisoption.find(dd).eq(index).index(this);202                      thisselect.text(thisoption.find(dd).eq(index).text());203                      $(this).find(option).eq(ddindex).prop(selected,true);204                     }205                     /*按下Esc 隐藏弹出层*/206                   if (keycode == 27) {    207                      console.log(esc);208                     if (thisoption.is(":visible")) {209                         thisoption.hide();210                     }211                   }212               });213           214               215               /*点击select框之外的其他部分的时候select框应该收起*/216                $(html,body).click(function(e){217                        /* 判断当前的点击事件目标不是set.selectoption这个class*/218                          if(e.target.className.indexOf(set.selectoption)==-1){219                               thisoption.hide();220                               thisbox.css(zIndex,set.zindex);221                           }222                 });223 224                 /*取消下拉列表选择事件的冒泡*/225                 thisoption.find(dd).click(function(e){226                           e.stopPropagation();227                        });228 229             }230       })(jQuery);231         $(.my_select).newStyle();232                233         </script>234 </body>235 </html>

 

实现的思路是:将一个input框隐藏在默认显示的selected框下面,点击默认显示框时同时是它获得焦点,然后获得键盘事件,对自定义的select下拉框实现一系列的操作。

  关键代码:

1 /*点击默认显示框时要给我隐藏的input获得焦点*/2               thisselect.click(function(){3                 $(‘input‘)[0].focus();4               });

 

TIPS:1.要有输入,才有键盘的事件,不然怎么读取呢?

         2.键盘上下选择时最后一个和第一个的切换值得注意,要连贯

 

是的,到这里还不是结束,那么我还可以做点什么呢? 让我的代码更好看一点吧。

 

第三个版本:

    学习插件写法,让我的代码也可以暴露方法给别人用

    代码如下:

    

  1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">  2 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">  3 <head>  4   <title></title>  5   <meta http-equiv="content-type" content="text/html; charset=utf-8" />  6   <script type="text/javascript" src="jquery.min.js"></script>  7   8   <style>  9      10  11      /* 这里来定义你自己的select框的样式 */ 12     .i_selectbox { 13       margin-top:20px; 14       height:32px; 15       position:relative; 16       font-size:14px 17     }  18     /* 默认显示的select框*/ 19     .i_selectbox .i_currentselected { 20       width:150px; 21       height:24px; 22       background:url(select.png) 176px 4px no-repeat; 23       border:1px solid #cdcdcd; 24       text-indent:10px; 25       line-height:24px; 26       cursor:pointer 27     }  28     /* 这里是隐藏的input框 */ 29     #hiddenput { 30        display: block; 31        width:200px; 32        height:18px; 33        margin-top: -25px; 34        position: absolute; 35        z-index:-2; 36        opacity:0; 37        filter:alpha(opacity=0); 38     } 39     /* 下拉选择框 */ 40     .i_selectbox .i_selectoption { 41       overflow-x:hidden; 42       overflow-y:hidden; 43       position:absolute; 44       left:0px; 45       top:17px; 46       padding:5px; 47       background-color:#fff; 48       background:rgba(255,255,255,.9); 49       border:1px solid #eee 50     }  51     .i_selectbox .i_selectoption dt { 52       height:24px; 53       background-color:#eee; 54       text-indent:5px; 55       font-style:italic; 56       color:#555; 57       line-height:24px; 58     }  59     .i_selectbox .i_selectoption dd{ 60       margin-left: -3px; 61       height:30px; 62       border-bottom:1px solid #cdcdcd; 63       cursor:pointer; 64       text-indent:2px; 65       line-height:30px 66     }  67     .i_selectbox .i_selectoption dd:hover{ 68       background-color:#cdcdcd; 69       color:#fff 70     } 71     .i_selectbox .i_selectoption dd.selected{ 72       background-color:#f17f36; 73       color:#fff 74     } 75     /* 这里是新定义的按钮 */ 76     #optionShow { 77        display:block; 78        position: absolute; 79        margin-left: 300px; 80  81     } 82     #optionHide { 83        display:block; 84        position: absolute; 85        margin-left: 300px; 86        margin-top: 50px; 87     } 88     89      </style>  90      91 <head> 92 <body> 93       <select class="my_select"> 94      95           <option value="0">Alabama</option> 96           <option value="1">Alaska</option> 97           <option value="2">Arizona</option> 98  99           <option value="3">Arkansas</option>100           <option value="4">California</option>101           <option value="5">Colorado</option>102   103           <option value="6">Connecticut</option>104           <option value="7">Delaware</option>105           <option value="8">Columbia</option>106           <option value="9">Florida</option>107      108       </select>109       <input type="button" id="optionShow" name="optionShow" value="点击这里显示下拉框"/>110       <input type="button" id="optionHide" name="optionHide" value="点击这里隐藏下拉框"/>111         <script>112       (function($){113          /*这个对象定义的位置值得注意*/114          var set = {115                 selectbox : i_selectbox,116                 showselect : i_currentselected,117                 selectoption : i_selectoption,118                 curselect : selected,119                 width : 200,120                 height :150,121                 zindex : 2122               }123         $.fn.extend({124              125              /*插件写法的函数*/126             newStyle : function(){127                128               /*让最初的select隐藏*/129               $(this).hide();130               /*动态写进去html替代原本的select*/131               var html = <div class="+set.selectbox+" style="zindex:+set.zindex+">132                          +<div class="+set.showselect+" style="width:+set.width+px;">+$(this).find(option:selected).text()+</div>133                          +<input type="text" id="hiddenput" name="hiddenput"/>134                          +<dl class="+set.selectoption+" style="display:none;width:+set.width+px" >;135               if($(this).find(optgroup).size()>0){136                   $(this).find(optgroup).each(function(){137                    html += <dt>+$(this).attr(label)+</dt>;138                           $(this).find(option).each(function(){139                               if($(this).is(:selected)){140                                 html += <dd class="+set.curselect+">+$(this).text()+</dd>;141                               }else{142                                 html += <dd>+$(this).text()+</dd>;143                               }144                           });145                   });146               }else{147                 $(this).find(option).each(function(){148                    if($(this).is(:selected)){149                      html += <dd class="+set.curselect+">+$(this).text()+</dd>;150                    }else{151                      html += <dd>+$(this).text()+</dd>;152                    }153                 });154 155               }156               /*将html插入到select框的后面*/157               $(select).after(html);158              159 160               /*为了写起来方便,给外围的box和当前显示的select框还有自定义的下拉框一个简单的变量*/161               thisbox = $(.+set.selectbox);162               thisselect = $(.+set.showselect);163               thisoption = $(.+set.selectoption);164               /*添加事件*/165 166               /*默认显示框的选择事件,点击默认显示框,下拉列表会在可见与不可见状态之间切换*/167               thisselect.toggle(function(){168                  /*$(‘.selectoption‘).hide();*/169                  thisbox.css(zindex,set.zindex);170                  thisoption.css(zindex,set.zindex+1);171                  thisoption.toggle();172               },function(){173                  thisoption.css(zindex,set.zindex);174                  thisoption.toggle();175               });176 177               /*下拉列表的选择事件*/178               thisoption.find(dd).click(function(){179                  $(this).addClass(set.curselect).siblings().removeClass(set.curselect);180                  var index = thisoption.find(dd).index(this);181                  thisselect.text($(this).text());182                  $(this).find(option).eq(index).prop(selected,true);183                  thisoption.hide();184               });185 186               /*点击默认显示框时要给我隐藏的input获得焦点*/187               thisselect.click(function(){188                 /*这里面[0]起了很大作用喔*/189                 $(input)[0].focus();190               })191 192               var index = 0;193               /*下拉列表的键盘事件*/194               $("#hiddenput").keyup(function(e){195                   var keycode = e.which;196                   console.log(keycode);197                   var ddtarget = thisoption.find(dd);198                   /*向下*/199                   if(keycode == 40){200                      index++;201                      if(index == ddtarget.length){202                         index = 0;203                      }204                     /* 设为当前选中项,同時在默认显示的select框中同步显示*/205                      thisoption.find(dd).eq(index).addClass(set.curselect).siblings().removeClass(set.curselect);206                      var ddindex = thisoption.find(dd).eq(index).index(this);207                      thisselect.text(thisoption.find(dd).eq(index).text());208                      $(this).find(option).eq(ddindex).prop(selected,true);209                      }210                   /*向上*/211                   if(keycode == 38){212                      if(index == 0){213                         index = ddtarget.length;214                      }215                      index--;216                     /* 设为当前选中项,同時在默认显示的select框中同步显示*/217                      thisoption.find(dd).eq(index).addClass(set.curselect).siblings().removeClass(set.curselect);218                      var ddindex = thisoption.find(dd).eq(index).index(this);219                      thisselect.text(thisoption.find(dd).eq(index).text());220                      $(this).find(option).eq(ddindex).prop(selected,true);221                     }222                     /*按下Esc 隐藏弹出层*/223                   if (keycode == 27) {    224                      console.log(esc);225                     if (thisoption.is(":visible")) {226                         thisoption.hide();227                     }228                   }229               });230           231               232               /*点击select框之外的其他部分的时候select框应该收起*/233                $(html).click(function(e){234                        /* 判断当前的点击事件目标不是set.selectoption这个class*/235                          if(e.target.className.indexOf(set.selectoption)==-1){236                               thisoption.hide();237                               thisbox.css(zIndex,set.zindex);238                           }239                 });240 241                 /*取消下拉列表选择事件的冒泡*/242                 thisoption.find(dd).click(function(e){243                           e.stopPropagation();244                        });245               246            },/*newStyle函数结束*/247            showSelect : function(){248                   $(this).click(function(e){249                         $(".i_selectoption").show();250                         //$(‘.‘+set.selectoption).show();251                         /*之前曾给html添加过点击selectoption收起的事件啊!!不阻止冒泡的话会发生冲突啊!!问题找了好久啊!!!*/252                         e.stopPropagation();253                     });254               255            },256            hideSelect : function(){257                  $(this).click(function(){258                        $(.+set.selectoption).hide();259                     });260               } 261         })262       })(jQuery);263         264           $(.my_select).newStyle();265           $(#optionShow).showSelect();266           $(#optionHide).hideSelect();267      268         269    270            271         </script>272 </body>273 </html>

 

TIPS:1.如果你想定义一个对象供所有的插件方法可用的话,那么应该定义到上面代码中那样全局的位置;

         2.(function($){........})(jQuery);这样写法可以使得外部无法访问到函数内部的公共变量和对象的命名空间;

         3.注意可能冲突的事件之间有可能存在事件冒泡的影响!!

         4.可以多学习多参考各种各样的代码调试方法,这个真的很重要。

 

 

通过一个简单的功能,我学到的东西很多喔,事实证明,冷静的思考,不放弃的探索才是最好的学习办法。