最近做的一个项目有下拉框 同事都是用的是美化控件,但是用美化控件当然是好 但是网上找的一个控件不知道扩展性怎么样?对以后的维护会不会造成有影响?比如我想增加一个功能或者减少一个功能会不会影响?还有就是假如 一个小小的功能要引入控件上千行代码 我自己写个简单的控件也能满足当时的需求 只需要百行代码 这样的话 加载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. Java三大特性:封装,继承,多态

    java提高篇(一)-----理解java的三大特性之封装 概念: 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独 ...

  2. python-状态模式

    源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 在软件开发过程中,各种应用程序可能会根据不同的情况做出不同的处理.最直接的方案就 ...

  3. Intellij Idea出现 unable to establish loopback connection

    项目一运行就出现这个情况,好几次了,最后发现只要防火墙关闭,项目就可以运行成功.错误提示:“C:\Program Files\Java\jdk1.8.020\bin\java” -Xmx700m -D ...

  4. JS 数组对象根据下标拆分成新的数组

    真为难啊! var arr = [ {guigeArr:['蓝色','XL','3','S']}, {guigeArr:['蓝色','L','6','S']}, {guigeArr:['蓝色','L' ...

  5. TensorFlow数据读取方式:Dataset API

    英文详细版参考:https://www.cnblogs.com/jins-note/p/10243716.html Dataset API是TensorFlow 1.3版本中引入的一个新的模块,主要服 ...

  6. Windows应用程序进程级别统一监控实践

    一般的系统级别指标监控,更多关注CPU.内存.磁盘.网络等运行情况,对应用程序运行时的进程指标关注不够,导致不能深入了解系统运行状态.本文根据笔者应用实践,探讨一下进程级别监控涉及到的监控内容以及监控 ...

  7. Android:Error:Execution failed for task ':app:clean'. > Unable to delete directory

    as  clean项目之后有时候会报错. 可以找得到目录删掉,然后重启as,但是下次clean可能又会报类似的错误. 解决方法如下: 进入File-Setting-Build,Execution,De ...

  8. 字符串匹配常见算法(BF,RK,KMP,BM,Sunday)

    今日了解了一下字符串匹配的各种方法. 并对sundaysearch算法实现并且单元. 字符串匹配算法,是在实际工程中经常遇到的问题,也是各大公司笔试面试的常考题目.此算法通常输入为原字符串(strin ...

  9. Android热修复之 - 收集崩溃信息上传服务器

    1.概述 大致的流程就是在用户崩溃的时候,我们获取崩溃信息.应用当前的信息和手机信息,然后把它保存到手机内存卡,再找我就直接找出来看看.后来衍生到上线后某些奇葩机型会有部分问题,所以不得不上传到服务器 ...

  10. Java语言的特点以及Java与C/C++的异同

    Java语言的特点 1. Java为纯面向对象的语言,能够直接反应现实生活中的对象,容易理解,编程更容易. 2.跨平台,java是解释性语言,编译器会把java代码变成中间代码,然后在JVM上解释执行 ...