zoukankan      html  css  js  c++  java
  • JS模拟下拉框select

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

    如上 每个配置项都有相应的注释!不多加解释了!

    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>
    View Code

    下面是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>
    View Code

    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({});
    });
    View Code

    初始化方式如下:

    // 初始化
    $(function(){
    	var obj = new SimulateSelect({});
    });
    

     初始化默认情况空对象 当然可以传参数进去,需要什么传什么!也提供几个回调函数 根据具体的需求具体调用的!

    提问:

           我在博客后台一直有个问题很纠结,我看到其他博客都有demo提供可以下载的功能 我博客后台我就没有看到有提供上传demo的地方,本来想把相应的demo也穿上去,但是一直没有看到 能不能上传demo?

    JS模拟下拉框下载

  • 相关阅读:
    jQuery插件开发模式
    优化布局
    jquery easyui 选项卡
    easy ui 点击行展开与折叠
    考拉海购技术支持的前世今生
    跑的好好的 Java 进程,怎么突然就瘫痪了
    Dubbo 如何成为连接异构微服务体系的最佳服务开发框架
    微服务治理实践:如何对单点异常进行自动摘除
    盘点阿里巴巴 15 款开发者工具
    千万创业者的自白:踩过坑才明白这些真相!
  • 原文地址:https://www.cnblogs.com/tugenhua0707/p/3424529.html
Copyright © 2011-2022 走看看