最近做的一个项目有下拉框 同事都是用的是美化控件,但是用美化控件当然是好 但是网上找的一个控件不知道扩展性怎么样?对以后的维护会不会造成有影响?比如我想增加一个功能或者减少一个功能会不会影响?还有就是假如 一个小小的功能要引入控件上千行代码 我自己写个简单的控件也能满足当时的需求 只需要百行代码 这样的话 加载JS的时候 性能就相对来说更好点,因为网上的控件并不会像淘宝的kissy控件一样经常有人维护,扩展性当然不赖 性能也考虑了很多,所以也借着这个机会研究了下 用JS模拟下拉框 当然kissy中的也研究了下,我这个只是考虑了原审的下拉框,没有像kissy中下拉框内部还考虑了有单选框或者复选框的情况!

模拟下拉框的原理:

  遍历页面当中所有select下拉框 初始化时 隐藏起来 接着遍历下拉框 获取option内容 遍历 创建li列表 分别渲染数据到li上去 也就是说 select option分别用ul li代替 表现形式上 下拉框用背景图片 这样看起来像是下拉框 但是我们操作的实际上是无序列表。

先来看看效果图:

下面先看看页面上HTML代码 如下:

一:如上做的demo 假如页面上有2个select下拉框 只需要如上写代码就ok!记住 select 中的属性 name一定要加上 并且不同的select name一定不一样,因为我js取名class或者id是根据name分别渲染上去的。

二: 接着可以看看我用JS初始化的时候 页面上代码是个什么样的变化!如下图所示:

可以看到 select 中的name叫tips2 div ul li的class 后缀都带有tips2 所以我是根据select中的name来取名class 来区分是那个下拉框的。

三: 但是当下拉框内容很多的时候 我们应该要有个滚动条 所以在代码配置时候 有个配置属性"height" 来配置当前的高度 通过计算一个li的高度 X(乘以) li的长度 保存到一个临时变量里 然后这个临时变量高度和我设置的高度是否大于还是小于 如果设置的高度小于临时变量的高度的话 那么出现滚动条,如下效果:

但是这个滚动条只是默认的 有时候设计师设计一个很好看的滚动条时候 这个滚动条就不行了,这个先不急,下一篇博客我想研究下 "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?

JS模拟下拉框下载

JS模拟下拉框select的更多相关文章

  1. js模拟下拉框

    html <label class="selectGroup"> <span class="selectP"></span> ...

  2. jquery模拟下拉框单选框复选Select,Checkbox,Radio

    在项目中,你会发现设计稿中常常会有单选框,复选框,但都不是系统默认的样式,这就可以用jquery来模拟它们:如图所示,实现它们所需要的代码如下: 首先需要引入的代码: <link rel=&qu ...

  3. JQuery操作下拉框 select

    要实现这种效果: html代码 1<script src="js/jquery-1.7.2.min.js"></script> 2 <table> ...

  4. js改变下拉框内容

      js改变下拉框内容 CreateTime--2018年4月8日18:47:38 Author:Marydon 适用场景:通常情况下,级联菜单.通过ajax异步获取后台数据改写下拉框内容会有这种需求 ...

  5. 【jQuery获取下拉框select、单选框radio、input普通框的值和checkbox选中的个数】

    radio单选框:name属性相同 <input type="radio" id="sp_type" name="p_type" va ...

  6. jQuery+css模拟下拉框模糊搜索的实现

    html: @*输入框*@ <div> <input type="text" style="width: 85%; height: 34px;" ...

  7. JS 实现下拉框去重

    JS 实现下拉框去重 学习内容: 需求 总结: 学习内容: 需求 用 JS 下拉框去重 实现代码 <html> <head> <meta http-equiv=" ...

  8. JS 实现下拉框回显

    JS 实现下拉框回显 学习内容: 需求 总结: 学习内容: 需求 用 JS 实现下拉框回显 实现代码 <!DOCTYPE html> <html lang="en" ...

  9. Js获取下拉框选定项的值和文本

    Js获取下拉框的值和文本网上提供了2种方法:但有些人很不负责任,他们根本没考虑到浏览器之间的差异导致的错误,导致很多新手琢磨了半天找不出错误! 下面我总结下Firefox和IE下获取下拉框选定项的值和 ...

随机推荐

  1. 【JavaFx教程】第五部分:将数据用 XML 格式存储

    第5部分的主题 持久化数据为XML 使用JavaFX的FileChooser 使用JavaFX的菜单 在用户设置中保存最后打开的文件路径. 现在我们的地址应用程序的数据只保存在内存中.每次我们关闭应用 ...

  2. 【读书笔记】iOS-发布你的促销消息-推动通知

    推送通知可以在应用没有启动或者在后台运行的时候给用户一些提示.因此,很多应用开发者和公司用它来推销自己的产品.通过这个渠道推送自己的产品是不错的选择,但是一定要遵守起码的道德规范(不要在用户睡觉的时候 ...

  3. IDEA想创建package,却只有directory 解决办法

    只有directory,而我想的是new package 这是因为java是普通的文件夹,要设置为source root 就可以啦

  4. Nodejs 使用特定版本的SSL/TLS协议版本

    var options = { key: fs.readFileSync('./bin/privatekey.pem'), cert: fs.readFileSync('./bin/certifica ...

  5. 微信小程序开发1-入门知识准备

    注:一个物联网专业的学生狗,平时学习较多的是嵌入式编程方面的知识,最近可能是闲的蛋疼,想要研究研究客户端开发,对于网页,手机Android客户端从来没有接触过,因此所有东西都要从头来过,慢慢学习.不过 ...

  6. 开发之道——读《移山之道——VSTS开发之道》后感

    开发之道——读<移山之道——VSTS开发之道>后感 <移山之道——VSTS开发之道>(下简称<移山之道>)是邹欣老师的另一本书.相传很有名的<构建之法> ...

  7. C#安全加密类

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.S ...

  8. windows10如何打开vhd文件

    本人电脑安装了Visual Studio 2017,但是由于项目需求需要Core SDK(2.0)的版本支持,也就是2017最新版.所以现在需要利用visual Studio 2017最新版本的安装包 ...

  9. 关于 Azure Windows VM 的磁盘和 VHD

    就像其他任何计算机一样,Azure 中的虚拟机将磁盘用作存储操作系统.应用程序和数据的位置. 所有 Azure 虚拟机都至少有两个磁盘,即 Windows 操作系统磁盘和临时磁盘. 操作系统磁盘基于映 ...

  10. Oracle EBS FA 资产编号跳号