JS模擬下拉框select

      最近作的一個項目有下拉框 同事都是用的是美化控件,可是用美化控件固然是好 可是網上找的一個控件不知道擴展性怎麼樣?對之後的維護會不會形成有影響?好比我想增長一個功能或者減小一個功能會不會影響?還有就是假如 一個小小的功能要引入控件上千行代碼 我本身寫個簡單的控件也能知足當時的需求 只須要百行代碼 這樣的話 加載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,               // 下拉框內容渲染完後的回調
        
    };
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模擬下拉框下載

相關文章
相關標籤/搜索