统一下拉列表样式并实现select样式高度自定义的jQuery插件

好像很久没有更新过博客了,哈~
发布一款最近写的jQuery小插件,用于统一下拉表样式并实现select样式高度自定义。select样式如同input[type=file]一样,各系统平台各浏览器显示的都不一样,特别是ie~一切影响美感的东西较真的UI设计狮们是不会妥协的。兵来将挡,水来土淹,为了保持最近一个公司项目中部分下拉列表的美观统一,用一种变通的方式为select穿上一套标准的新衣:不论平台不论浏览器样式统一、样式高度自定义、不破坏select原有结构与功能(这意味着后端程序仍可像调用普通select那样取值)。

原理无须多讲,在需要改变样式的select后插入一个div容器,同时隐藏掉select。然后把select的相关信息(optgroup/option/value/selected等)取出来用dl展现,如此一来,改变div容器中元素样式即可。记得前年写过一个用input[type=hidden]存值,用dl模拟下拉列表的插件。两者原理差不多,只是本文中的可能更人性化,使用起来更方便些。
jQuery代码:点此查看样列

;(function($){
    /*
     * 统一select样式并实现样式高度自定义的jQuery插件@Mr.Think(http://mrthink.net/)
     */
    $.fn.iSimulateSelect=function(iSet){
        iSet=$.extend({
            selectBoxCls:'i_selectbox', //string类型,外围class名
            curSCls:'i_currentselected',//string类型,默认显示class名
            optionCls:'i_selectoption',//string类型,下拉列表class名
            selectedCls:'selected',//string类型,当前选中class名
            width:222,//number类型,模拟select的宽度
            height:300,//number类型,模拟select的最大高度
            zindex:20//层级顺序
        },iSet||{});
        this.hide();
        return this.each(function(){
           var self=this;
           var thisCurVal,thisSelect,cIndex=0;
           //计算模拟select宽度
           if(iSet.width==0){
              iSet.width=$(self).width();
           }
           var html='<div class="'+iSet.selectBoxCls+'" style="z-index:'+iSet.zindex+'"><div class="'+iSet.curSCls+'" style="width:'+iSet.width+'px">'+$(self).find('option:selected').text()+'</div><dl class="'+iSet.optionCls+'" style="display:none;width:'+iSet.width+'px">';
           //判断select中是否有optgroup
           //用dt替代optgroup,用dd替代option
           if($(self).find('optgroup').size()>0){
               $(this).find('optgroup').each(function(){
                   html+='<dt>'+$(this).attr('label')+'</dt>';
                   $(this).find('option').each(function(){
                        if($(this).is(':selected')){
                          html+='<dd class="'+iSet.selectedCls+'">'+$(this).text()+'</dd>';
                       }else{
                          html+='<dd>'+$(this).text()+'</dd>';
                       }
                   });
               });
           }else{
               $(this).find('option').each(function(){
                   if($(this).is(':selected')){
                      html+='<dd class="'+iSet.selectedCls+'">'+$(this).text()+'</dd>';
                   }else{
                      html+='<dd>'+$(this).text()+'</dd>';
                   }
               });
           }
           //将模拟dl插入到select后面
           $(self).after(html);
           //当前模拟select外围box元素
           thisBox=$(self).next('.'+iSet.selectBoxCls);
           //当前模拟select初始值元素
           thisCurVal=thisBox.find('.'+iSet.curSCls);
           //当前模拟select列表
           thisSelect=thisBox.find('.'+iSet.optionCls);
           /*
           若同页面还有其他原生select,请前往https://github.com/brandonaaron/bgiframe下载bgiframe,同时在此处调用thisSelect.bgiframe()
            */
           //thisSelect.bgiframe();

           //弹出模拟下拉列表
           thisCurVal.click(function(){
              $('.'+iSet.optionCls).hide();
              $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
              $(self).next('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex+1);
              thisSelect.show();
           });
           //若模拟select高度超出限定高度,则自动overflow-y:auto
           if(thisSelect.height()>iSet.height){
               thisSelect.height(iSet.height);
           }
           //模拟列表点击事件-赋值-改变y坐标位置-...
           thisSelect.find('dd').click(function(){
               $(this).addClass(iSet.selectedCls).siblings().removeClass(iSet.selectedCls);
               cIndex=thisSelect.find('dd').index(this);
               thisCurVal.text($(this).text());
               $(self).find('option').eq(cIndex).attr('selected','selected');
               $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
               thisSelect.hide();
           });
           //非模拟列表处点击隐藏模拟列表
           //$(document)点击事件不兼容部分移动设备
           $('html,body').click(function(e){
                if(e.target.className.indexOf(iSet.curSCls)==-1){
                  thisSelect.hide();
                  $('.'+iSet.selectBoxCls).css('zIndex',iSet.zindex);
              }
           });
           //取消模块列表处取消默认事件
           thisSelect.click(function(e){
              e.stopPropagation();
           });
        });
    }
})(jQuery);

如何调用?
1、在页面中引入上面的插件代码;
2、$(select).iSimulateSelect({…});
3、相关参数及功能,请参考插件中的注释说明。

若在ie6下,同页面中有未调用插件元素,为避免被原生select遮盖,请下载bgiframe插件,并在代码中关于bgiframe调用的公位置取消注释。另外,在调用插件的select后面插入的是一个相对定位元素,如果select前后还有其他行内元素,尽量使用float定位,或者给select外围加一个容器再进行绝对定位。


渔夫科技