最近做的一個專案有下拉框 同事都是用的是美化控制元件,但是用美化控制元件當然是好 但是網上找的一個控制元件不知道擴充套件性怎麼樣?對以後的維護會不會造成有影響?比如我想增加一個功能或者減少一個功能會不會影響?還有就是假如 一個小小的功能要引入控制元件上千行程式碼 我自己寫個簡單的控制元件也能滿足當時的需求 只需要百行程式碼 這樣的話 載入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?