这个下拉菜单存在于body中,不会受select父级overflow的影响,同样依赖于jquery。
缺陷是如果select上的样式不是定义在class上的,不能完全获取select上的样式。
不过,皮肤的样式可以通过css来修改。
直接上代码:
html:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>select 皮肤</title> <link rel="stylesheet" type="text/css" href="css/main.css" /> </head> <body> <div class="mydiv1 mydiv cl" id="mydiv1"> <select class="select1"> <option>1111111</option> <option>1111112</option> <option>1111113</option> </select> <select class="select2"> <option>2111111</option> <option>2111112</option> <option>2111113</option> </select> </div> <div class="mydiv2 mydiv cl" id="mydiv2"> <select class="select1"> <option>1211111</option> <option>1211112</option> <option>1211113</option> </select> <select class="select2"> <option>2211111</option> <option>2211112</option> <option>2211113</option> </select> </div> <script type="text/javascript" src="js/entry.js"></script> </body> </html>
main.css:
html,body,div,p,span,i,dl,dt,dd,ul,ol,li,a,select,input,textarea{ margin:0; padding:0; } body{ font: 'Mircosoft Yahei' 14px/1.5; color: #333; } ul,ol,li{ list-style: none; } a:link,a:visited,a:active,a:hover{ text-decoration: none; color: #333; } input,select,textarea{ outline: none; } .cl{ zoom:1; } .cl:after{ clear: both; display: table; content: ""; } .mydiv select{ float: left; margin:10px; width: 300px; height: 40px; line-height: 40px; } /*select 模拟*/ .js-select-top{ border: 1px solid #dfdfdf; display: inline-block; height: 40px; line-height: 40px; position: relative; cursor: pointer; } .js-sel-arr{ display: inline-block; width: 0; height: 0; border:6px dashed transparent; border-top:6px solid #555; right: 10px; position: absolute; top:50%; margin-top:-6px; } .js-select-top .js-select-tit{ display: block; height: 100%; padding: 0 30px 0 10px; } .js-select-top .default{ color: #999; } .js-sel-list{ position: absolute; z-index: 9999; border: 1px solid #ddd; background: #fff; overflow-y: auto; } .js-sel-list li{ height: 30px; line-height: 30px; } .js-sel-list li a{ padding: 0 10px; display: block; } .js-sel-list li.active a{ background: #eee; }
css文件中,主要的是select模拟的那段样式,可以根据自己的需求更改。
entry.js:
function selectFun(obj,i,dom){this.obj = $.extend({ liHeight: "30px", ulHeight: "300px", liClass: "active" }, obj || {}); this.dom = $(dom); this.index = i; this._width = this.dom.outerWidth();//宽度 this.addSkin(); $(document).click(function(e){ var tag = $(e.target); $("ul.js-sel-list").not(":hidden").hide(); }); } selectFun.init = function(obj,fn,i,dom){ return new selectFun(obj,fn,i,dom); } selectFun.prototype.addSkin = function(){//添加皮肤 var _class = this.dom.attr("class"); var self = this; //ie不能直接用css("margin") var marginTop = this.dom.css("marginTop"); var marginRht = this.dom.css("marginRight"); var marginBtm = this.dom.css("marginBottom"); var marginLft = this.dom.css("marginLeft"); var margin = marginTop + " " + marginRht + " " + marginBtm + " " + marginLft; this.topDom = $("<div class='js-select-top "+ _class +"' style='"+ this._width +"px; float:"+ this.dom.css("float") +"; margin:"+ margin +"' data-id='js-sel"+ this.index +"'><i class='js-sel-arr'></i></div>");//头部div this.titDom = $("<span class='js-select-tit'></span>"); this.dom.hide().after(this.topDom.append(this.titDom)); this.getVal(); this.topDom.on("click",function(e){ e.stopPropagation(); var menu = $("#js-sel"+ self.index); if(menu.length > 0 && menu.is(":hidden")){ menu.siblings("ul.js-sel-list").hide(); menu.show(); }else if(menu.length === 0){ $("ul.js-sel-list").hide(); self.addMenu($(this)); }else{ menu.hide(); } }); } selectFun.prototype.position = function(t){//获取菜单位置 var screenh = $(window).height(); var dt = t.offset().top; var df = t.offset().left; var dh = t.outerHeight(); var ulh, clih, culh; culh = parseInt(this.obj.ulHeight); clih = parseInt(this.obj.liHeight); var opth = this.dom.find("option").length * clih; if(opth >= culh){ ulh = culh; }else{ ulh = opth; } if((dt + dh + ulh) >= screenh && (dt - ulh) > 0){ return {"left":df,"top":(dt - ulh)}; }else{ return {"left":df,"top":(dt + dh)}; } } selectFun.prototype.addMenu = function(t){//添加下拉菜单 var pos = this.position(t); var listDom = $("<ul class='js-sel-list' id='js-sel"+ this.index +"' style='"+ this._width +"px; left:"+ pos.left +"px; top:"+ pos.top +"px; max-height:"+ this.obj.ulHeight +"'></ul>"); var listStr = ''; var opts = this.dom.find("option"); var liClass = ''; var self = this; for(var n=0; n<opts.length; n++){ if(opts.eq(n).val() === self.dom.val()){ liClass = self.obj.liClass; }else{ liClass = ''; } listStr += '<li data-val="'+opts.eq(n).val()+'" class="'+ liClass +'" style="height:'+ self.obj.liHeight +'; line-height:'+ self.obj.liHeight +'"><a href="javascript:;">'+ opts.eq(n).html() +'</a></li>' } listDom.html(listStr); $("body").append(listDom); this.liClick('#js-sel'+ this.index); this.keyEvent(listDom); } selectFun.prototype.getVal = function(){//头部获取值 var val = this.dom.val(); var txt = this.dom.find("option:selected").text(); this.titDom.text(txt).data("val",val); } selectFun.prototype.setVal = function(t){//设置头部值 t:li var val = t.data("val"); var txt = t.text(); this.titDom.text(txt).data("val",val); this.dom.find("option").eq(t.index()).attr("selected",true); this.dom.trigger("change"); t.parents("ul.js-sel-list").hide(); } selectFun.prototype.liClick = function(tp){//点击li事件 var self = this; $("body").on("click",tp+" li",function(e){ e.stopPropagation(); var $t = $(this); self._addClass($t); self.setVal($t); }); } selectFun.prototype.keyEvent = function(menu){//键盘事件,ul的节点,当前class的名称 var lis = menu.find("li"); var len = lis.length; var self = this; $(document).keyup(function(e){ if(menu.is(":hidden")){ return; } var code = e.keyCode; var nowDom = menu.find("li." + self.obj.liClass); var nowIndex = nowDom.index(); switch(code){ case 38: nowIndex --; if(nowIndex < 0){ nowIndex = len - 1; } self._addClass(lis.eq(nowIndex)); break; case 40: nowIndex ++; if(nowIndex >= len){ nowIndex = 0; } self._addClass(lis.eq(nowIndex)); break; case 13: self.setVal(nowDom); break; case 27: menu.hide(); break; } }); } selectFun.prototype._addClass = function(t){//添加当前class t.addClass(this.obj.liClass).siblings("li").removeClass(this.obj.liClass); } $.fn.extend({ selecter: function(obj){ this.each(function(i,dom){ selectFun.init(obj,i,dom); }); } }); $("select").selecter(); $(".select1").change(function(){ alert($(this).val()); });
js中的selecter方法可以传递一个json格式的数据,其中liHeight指的是li的高度,ulHeight指的是下拉菜单的高度,liClass是当前li的状态class。
例如,我想改变li的高度为25px:
$("select").selecter({"liHeight":"25px"});
其中select的原有事件change可以正常使用。