最近作的一个项目有下拉框 同事都是用的是美化控件,可是用美化控件固然是好 可是网上找的一个控件不知道扩展性怎么样?对之后的维护会不会形成有影响?好比我想增长一个功能或者减小一个功能会不会影响?还有就是假如 一个小小的功能要引入控件上千行代码 我本身写个简单的控件也能知足当时的需求 只须要百行代码 这样的话 加载JS的时候 性能就相对来讲更好点,由于网上的控件并不会像淘宝的kissy控件同样常常有人维护,扩展性固然不赖 性能也考虑了不少,因此也借着这个机会研究了下 用JS模拟下拉框 固然kissy中的也研究了下,我这个只是考虑了原审的下拉框,没有像kissy中下拉框内部还考虑了有单选框或者复选框的状况!javascript
模拟下拉框的原理:css
遍历页面当中全部select下拉框 初始化时 隐藏起来 接着遍历下拉框 获取option内容 遍历 建立li列表 分别渲染数据到li上去 也就是说 select option分别用ul li代替 表现形式上 下拉框用背景图片 这样看起来像是下拉框 可是咱们操做的其实是无序列表。html
先来看看效果图:java
下面先看看页面上HTML代码 以下:app
一:如上作的demo 假如页面上有2个select下拉框 只须要如上写代码就ok!记住 select 中的属性 name必定要加上 而且不一样的select name必定不同,由于我js取名class或者id是根据name分别渲染上去的。ide
二: 接着能够看看我用JS初始化的时候 页面上代码是个什么样的变化!以下图所示:函数
能够看到 select 中的name叫tips2 div ul li的class 后缀都带有tips2 因此我是根据select中的name来取名class 来区分是那个下拉框的。性能
三: 可是当下拉框内容不少的时候 咱们应该要有个滚动条 因此在代码配置时候 有个配置属性"height" 来配置当前的高度 经过计算一个li的高度 X(乘以) li的长度 保存到一个临时变量里 而后这个临时变量高度和我设置的高度是否大于仍是小于 若是设置的高度小于临时变量的高度的话 那么出现滚动条,以下效果:this
可是这个滚动条只是默认的 有时候设计师设计一个很好看的滚动条时候 这个滚动条就不行了,这个先不急,下一篇博客我想研究下 "JS模拟滚动条"来实现这个效果。编码
下面先来看看配置项代码吧!编码风格仍是和之前同样!
this.config = { container : '.J_Select', // 渲染容器 isShowSelectValue : true, // 选中某个选项后 是否显示该值 selectHoverCls : 'tag_select_hover', // 鼠标移上select去 类名 optionHoverCls : 'hover', // option移上去 类名 selectItemCls : 'open_selected', // option 选择一项时的类名 eventType : 'click', // 触发下拉框事件 默认为click height : 200, // 高度 超过设定高度有滚动条 不设置自适应 type:{number} isHideBoxBySelected : false, // 用户选中某一项后 是否关闭下拉框 getTextCallBack : null, // 获取选中下拉框的文本 {return obj} getSelectedOptionsIndex : null, // 获取当前下拉框选中的索引 {return obj} selectCallBack : null, // 选中完后的回调函数 render : null, // 下拉框内容渲染完后的回调 };
如上 每一个配置项都有相应的注释!很少加解释了!
HTML代码以下:
<div class="selectCls J_Select"> <select name="tips"> <option value="js文字特效">js文字特效</option> <option value="js文字滚动">js文字滚动</option> <option value="js文字闪烁">js文字闪烁</option> <option value="js文字切换">js文字切换</option> <option value="js文字数量">js文字数量</option> <option value="js文字改变">js文字改变</option> <option value="js文字数量">js文字数量</option> <option value="js文字改变">js文字改变</option> <option value="js文字数量">js文字数量</option> <option value="js文字改变">js文字改变</option> </select> </div> <div class="selectCls J_Select"> <select name="tips2"> <option value="js文字特效">js文字特效2</option> <option value="js文字滚动">js文字滚动2</option> <option value="js文字闪烁">js文字闪烁2</option> <option value="js文字切换">js文字切换2</option> <option value="js文字数量">js文字数量2</option> <option value="js文字改变">js文字改变2</option> <option value="js文字数量">js文字数量2</option> <option value="js文字改变">js文字改变2</option> <option value="js文字数量">js文字数量2</option> <option value="js文字改变">js文字改变2</option> </select> </div>
下面是CSS代码:
<style> *{margin:0;padding:0;} ul,li{list-style:none;} .selectCls {margin:20px auto 0;width:200px;float:left;} .box_Cls,.tag_select_hover{background:url("select.png") no-repeat;} .select_Cls {width:102px;height:22px;} .box_Cls {width:82px;padding:0 10px;height:22px;line-height:22px;color:#000;background-position:0 0;font-size:12px;cursor:pointer;} .tag_select_hover {background-position:0 -22px;} .tag_Cls {width:98px;border:1px solid #4ea0d1; border-top:none;} .tag_Cls li{color:#333;height:22px; padding-left:8px; line-height:21px;font-size:12px;color:#000;text-decoration:none;cursor:pointer;overflow:hidden;} .tag_Cls li.open_selected{color:#19555F;background:#92d3f0;} .tag_Cls li.hover{background:#dfdfdf;} .hidden{display:none;} </style>
JS全部代码以下:
/** * select美化控件 * @author tugenhua * @email 879083421@qq.com * @date 2013-11-12 */ function SimulateSelect(options) { this.config = { container : '.J_Select', // 渲染容器 isShowSelectValue : true, // 选中某个选项后 是否显示该值 selectHoverCls : 'tag_select_hover', // 鼠标移上select去 类名 optionHoverCls : 'hover', // option移上去 类名 selectItemCls : 'open_selected', // option 选择一项时的类名 eventType : 'click', // 触发下拉框事件 默认为click height : 200, // 高度 超过设定高度有滚动条 不设置自适应 type:{number} isHideBoxBySelected : false, // 用户选中某一项后 是否关闭下拉框 getTextCallBack : null, // 获取选中下拉框的文本 {return obj} getSelectedOptionsIndex : null, // 获取当前下拉框选中的索引 {return obj} selectCallBack : null, // 选中完后的回调函数 render : null, // 下拉框内容渲染完后的回调 }; this.cache = { selectNames : [] // 存放全部select name }; this.init(options); } SimulateSelect.prototype = { init: function(options) { this.config = $.extend(this.config,options || {}); var self = this, _config = self.config, _cache = self.cache; $(_config.container).each(function(index,item){ self._renderUl(index,item); }); }, // 渲染下拉框 ul 结构 _renderUl: function(index,item){ var self = this, _cache = self.cache; var selectName = $('select',item).attr('name'), HTML = ''; _cache.selectNames.push(selectName); !$('select',item).hasClass('hidden') && $('select',item).addClass('hidden'); HTML += '<div class="select_'+selectName+' select_Cls">' + '<div class="box_'+selectName+' box_Cls"></div>'+ '<ul class="tag_'+selectName+' hidden tag_Cls" id="select_'+selectName+'">'+ '</ul>'+ '</div>'; $(item).append(HTML); self._renderLi(item,selectName); }, // 渲染li结构 _renderLi: function(item,selectName){ var self = this, _config = self.config; var optionAlls = $('select option',item); for(var i = 0, ilen = optionAlls.length; i < ilen; i+=1) { var li = '<li class="item_'+selectName+'" data-value = "'+$.trim($(optionAlls[i]).html())+'">'+$.trim($(optionAlls[i]).html())+'</li>'; // 默认取第一项 $('.box_'+selectName).html($.trim($(optionAlls[0]).html())); $('.tag_'+selectName,item).append(li); } /* * 获取li的高度乘以li的个数 获得高度值 而后判断 若是外层ul容器设置了高度的话 且大于ul的高度 那么 出现滚动条 */ var itemLen = $('.item_'+selectName,item).length, itemHeight = $('.item_'+selectName,item).height(), tempHeight = itemLen * (itemHeight*1); if(_config.height > 0) { if(_config.height < tempHeight) { $("#select_"+selectName,item).css({'height':_config.height,'overflow':'auto'}); }else { $("#select_"+selectName,item).css({'height':'auto','overflow':'auto'}); } } // 渲染时 默认第一项addClass 高亮选中状态 var first = $('.item_'+selectName)[0]; !$(first).hasClass(_config.selectItemCls) && $(first).addClass(_config.selectItemCls); // 渲染完后的回调函数 _config.render && $.isFunction(_config.render) && _config.render(); // 绑定事件 self._bindEvent(item,selectName); }, // 绑定事件 _bindEvent: function(item,selectName) { var self = this, _config = self.config, _cache = self.cache; /* * 事件 判断是不是点击事件 仍是鼠标移上去事件 */ if(_config.eventType == 'click') { $('.box_'+selectName,item).off(_config.eventType); $('.box_'+selectName,item).on(_config.eventType,function(){ var top = $(this).offset().top + $(this).height(), left = $(this).offset().left; $('#select_'+selectName).css({'position':'absolute',"top":top,"left":left,'z-index':999}); $('#select_'+selectName).slideToggle('slow'); }); }else { if($('#select_'+selectName).hasClass('hidden')) { $('.box_'+selectName,item).off(_config.eventType); $('.box_'+selectName,item).on(_config.eventType,function(){ $('#select_'+selectName).slideDown('slow'); }); } } // 点击文档时候 隐藏下拉菜单 $(document).off('click'); $(document).on('click',function(e){ var target = e.target; $.each(_cache.selectNames,function(index,item) { if(!$(target).hasClass("box_"+item) && !$(target).hasClass('item_'+item)) { $('#select_'+item).slideUp('slow'); } }); }); // hover事件 下拉框target元素 $('.box_'+selectName,item).hover(function(){ !$(this).hasClass(_config.selectHoverCls) && $(this).addClass(_config.selectHoverCls); },function(){ $(this).hasClass(_config.selectHoverCls) && $(this).removeClass(_config.selectHoverCls); }); $('.item_'+selectName,item).hover(function(){ if($(this).hasClass(_config.selectItemCls)){ return; } !$(this).hasClass(_config.optionHoverCls) && $(this).addClass(_config.optionHoverCls); },function(){ $(this).hasClass(_config.optionHoverCls) && $(this).removeClass(_config.optionHoverCls); }); // 点击下拉框某一项的时候 $('.item_'+selectName,item).off('click'); $('.item_'+selectName,item).on('click',function(){ var curValue = $(this).attr('data-value'); $(".box_"+selectName,item).html(curValue); !$(this).hasClass(_config.selectItemCls) && $(this).addClass(_config.selectItemCls). siblings().removeClass(_config.selectItemCls); if(_config.isHideBoxBySelected) { $('#select_'+selectName).slideUp('slow'); } var curIndex = $('.item_'+selectName,item).index($(this)); // 获取选中的文本 回调函数 _config.getTextCallBack && $.isFunction(_config.getTextCallBack) && _config.getTextCallBack({'text':curValue,"selectName":selectName,"container":item}); // 获取选中的索引 回调函数 _config.getSelectedOptionsIndex && $.isFunction(_config.getSelectedOptionsIndex) && _config.getSelectedOptionsIndex({"curIndex":curIndex,"selectName":selectName,"container":item}); // 选择完后的回调函数 _config.selectCallBack && $.isFunction(_config.selectCallBack) && _config.selectCallBack(); }); } }; // 初始化 $(function(){ var obj = new SimulateSelect({}); });
初始化方式以下:
// 初始化 $(function(){ var obj = new SimulateSelect({}); });
初始化默认状况空对象 固然能够传参数进去,须要什么传什么!也提供几个回调函数 根据具体的需求具体调用的!
提问:
我在博客后台一直有个问题很纠结,我看到其余博客都有demo提供能够下载的功能 我博客后台我就没有看到有提供上传demo的地方,原本想把相应的demo也穿上去,可是一直没有看到 能不能上传demo?