html的表單有很強大的功能,在web早期的時候,表單是頁面向服務器發起通訊的主要渠道。但有些表單元素的樣式沒辦法經過添加css樣式來達到滿意的效果,並且不一樣的瀏覽器之間設置的樣式還存在兼容問題,好比下拉框。javascript
本實例經過建立div和li等元素來生成一個模擬下拉框,以達到美化下拉框的效果。學習本教程以前,讀者須要具有html和css技能,同時須要有簡單的javascript基礎。css
先建立一個select元素,做爲美化下拉框的數據來源,以下所示:html
<div class="select_wrap" id="selectWrap"> <dl> <dt>請選擇:</dt> <dd> <select id="selectElem"> <option value="1">北京</option> <option value="2">上海</option> <option value="3">廣東</option> <option value="4">湖南</option> <option value="5">河北</option> <option value="6">黑龍江</option> </select> </dd> </dl> </div>
既然是作一個下拉框美化的效果,那確定是須要用一些css樣式來實現。讀者能夠根據本身有喜愛編寫,也能夠直接複製如下代碼:java
.select_wrap{ width:800px; margin:30px auto; } .select_wrap dt{ float:left; width:120px; line-height:36px; text-align:right; font-size:14px; } .select_wrap dd{ margin-left:130px; line-height:36px; } .select_wrap input[type=text],.select_wrap input[type=password]{ height:24px; line-height:22px; padding:0 5px; border:1px solid #aaa; border-radius:2px; } .select_wrap .btn{ padding:0 20px; color:#fff; cursor:pointer; line-height:30px; border:none; margin-right:20px; background:#108ee9; } .select_container{ position:relative; display:inline-block; } .input_container:{ position:relative; } .input_container::after{ content:""; position:absolute; top:15px; right:8px; display:inline-block; height:0px; border:6px solid transparent; border-top-color:#ccc; pointer-events:none; } .input_container input{ height:30px; line-height:28px; padding:0 5px; border:1px solid #aaa; border-radius:4px; } .input_container input:focus{ border-color:#129cff; outline:none; box-shadow:0 0 6px #65bfff; } .select_container ul{ position:absolute; top:35px; width:100%; margin:0; padding:0; background:#fff; border-radius:4px; box-shadow:0 0px 5px #ccc; } .select_container li{ list-style:none; font-size:12px; line-height:30px; padding:0 10px; cursor:pointer; } .select_container li:hover,.select_container li.cur{ background:#dbf0ff; }
前期工做作好以後,能夠開始編寫javascript代碼了。按照慣例,仍是把功能分析爲一個一個步驟,再寫具體的代碼,思路會很清晰。web
1. 獲取已有的下拉框元素瀏覽器
這裏須要獲取多個元素,首先經過id獲取select元素,再找到select元素的父元素。由於生成的美化下拉框須要放到父元素中。還要獲取到select全部的option子節點。以下所示:服務器
//獲取下拉框 var eSelect = document.getElementById('selectElem'); //獲取下拉框父節點 var eDd = eSelect.parentNode; //獲取下拉框選項 var aOptions = eSelect.getElementsByTagName('option');
2. 建立美化下拉框元素app
先看一下美化後的下拉框,以下圖所示:函數
想一下這個下拉框應該包含哪些元素,一個div元素把全部內容包含在裏面;一個input文本框,顯示選中的值;input元素還須要一個父級容器div元素;一個ul加一組li元素組成下拉列表。好,知道須要哪些元素了,先來建立文本框部分,以下所示:學習
//建立美化select容器 var eContainer = document.createElement('div'); eContainer.className = 'select_container'; //建立input父級容器 var eInputCon = document.createElement('div'); eInputCon.className = 'input_container'; //建立input文本框,顯示選中的值 var eInput = document.createElement('input'); //設置文本框不能輸入 eInput.readOnly = true; eInput.placeholder = '請選擇'; //把文本框放到容器中 eInputCon.appendChild(eInput);
再來建立下拉列表。下拉列表能夠建立一個ul元素,經過遍歷aOptions下拉框選項,組合成li列表的字符串,經過innerHTML放到ul元素中,實現代碼以下:
//建立ul元素,做爲下拉列表容器 var eUl = document.createElement('ul'); //聲明變量,用於組合下拉列表的字符串 var sLi = ''; //遍歷原有下拉框選項 for(let i=0;i<aOptions.length;i++){ //判斷是不是當前選中的選項 if(aOptions[i].selected){ //下拉選項組合到下拉列表字符串,當前選中的選項須要加上class添加當前樣式 sLi += '<li class="cur" data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>'; //當前選中的選項顯示到文本框中 eInput.value = aOptions[i].innerHTML; //eUl元素設置data-val屬性值爲當前選中選項的值 eUl.dataset.val = aOptions[i].value; }else{ //非當前選中的選項,直接組合到下拉列表字符串,值設置到data-val屬性中 sLi += '<li data-val="'+aOptions[i].value+'">'+aOptions[i].innerHTML+'</li>'; } } //下拉列表放到eUl元素中 eUl.innerHTML = sLi; //默認隱藏下拉列表 eUl.style.display = 'none';
把建立好的這些元素嵌套好,再添加到原下拉框的父元素中,並隱藏原有的下拉框,以下所示:
//把文本框放到eContainer容器中 eContainer.appendChild(eInputCon); //把下拉列表放到eContainer容器中 eContainer.appendChild(eUl); //把eContainer元素放到select元素後面 eDd.appendChild(eContainer); //隱藏原下拉框元素 eSelect.style.display = 'none';
如今效果是有了,但下拉框的功能還沒實現,還須要給這些美化後的元素添加事件。
3. 實現打開下拉框功能
下拉框原有的功能是在文本框上點擊鼠標,就會顯示下拉列表。因此在eInput元素上綁定click事件來顯示下拉列表,以下所示:
//設置下拉框打開狀態,0爲關閉,1爲打開 var status = 0; //綁定click事件,用於顯示下拉列表 eInput.addEventListener('click',event=>{ //判斷下拉框是否已打開 if(status){ //下拉框打開則關閉下拉框 eUl.style.display = 'none'; }else{ //下拉框關閉則打開下拉框 eUl.style.display = 'block'; } //修改下拉框狀態 status = +!status; },false);
能夠看到,在eInput元素上點擊,能夠打開和關閉下拉框了。但選擇下拉選項仍是無效的。在下拉選項上也綁定click事件
4. 下拉選項綁定click事件,點擊時修改下拉框的值,以下所示:
//獲取下拉選項列表元素的集合 var eLi = eUl.getElementsByTagName('li'); //遍歷下拉列表 for(let i=0;i<eLi.length;i++){ //給每個li元素綁定點擊事件 eLi[i].addEventListener('click',(event)=>{ //修改下拉框狀態爲已關閉狀態 status = 0; //清除全部列表的class for(let n=0;n<eLi.length;n++){ eLi[n].className = ''; } //激活當前列表選中樣式 eLi[i].className = 'cur'; //設置下拉框當前選中值 eUl.dataset.val = eLi[i].dataset.val; //還須要把值設置到原select元素上 eSelect.value = eUl.dataset.val; //觸發原select上的函數 typeof eSelect.onchange=='function'&&select.onchange(); //修改eInput元素顯示的值 eInput.value = eLi[i].innerHTML; //關閉下拉框 eUl.style.display = 'none'; },false); }
目前爲止,功能基本完成。不過只能在選擇選項後或再在文本框上點擊才能關閉下拉框。因此還須要修改一下功能,在頁面其餘位置點擊時也能關閉下拉框
5. 在document綁定點擊事件,用於關閉下拉框。
注意兩點:一是在下拉框關閉時須要取消document上的綁定事件;二是eContainer元素上點擊時須要阻止冒泡,不然下拉框會打不開了。修改後的代碼以下:
//設置下拉框打開狀態,0爲關閉,1爲打開 var status = 0; //綁定click事件,用於顯示下拉列表 eInput.addEventListener('click',event=>{ //判斷下拉框是否已打開 if(status){ //下拉框打開則關閉下拉框 eUl.style.display = 'none'; //取消document上的綁定事件 document.removeEventListener('click',closeUl); }else{ //下拉框關閉則打開下拉框 eUl.style.display = 'block'; //在document上綁定點擊事件,用於關閉下拉框 document.addEventListener('click',closeUl,false); } //修改下拉框狀態 status = +!status; },false); //獲取下拉選項列表元素的集合 var eLi = eUl.getElementsByTagName('li'); //遍歷下拉列表 for(let i=0;i<eLi.length;i++){ //給每個li元素綁定點擊事件 eLi[i].addEventListener('click',(event)=>{ //修改下拉框狀態爲已關閉狀態 status = 0; //清除全部列表的class for(let n=0;n<eLi.length;n++){ eLi[n].className = ''; } //激活當前列表選中樣式 eLi[i].className = 'cur'; //設置下拉框當前選中值 eUl.dataset.val = eLi[i].dataset.val; //還須要把值設置到原select元素上 eSelect.value = eUl.dataset.val; //觸發原select上的函數 typeof eSelect.onchange=='function'&&select.onchange(); //修改eInput元素顯示的值 eInput.value = eLi[i].innerHTML; //關閉下拉框 eUl.style.display = 'none'; //取消document上的綁定事件 document.removeEventListener('click',closeUl); },false); } //綁定到document上關閉下拉框的函數 function closeUl(){ //修改下拉框狀態爲已關閉狀態 status = 0; //關閉下拉框 eUl.style.display = 'none'; //取消document上的綁定事件 document.removeEventListener('click',closeUl); } //阻止冒泡,不然點擊時冒泡到document上,會致使下拉框剛打開就關閉 eContainer.addEventListener('click',event=>{ event.stopPropagation(); });
一個美化後的下拉框已經完成,若是動手一步一步實現它,理解應該會更深一些。