2017-11-17 77 views
2

我正嘗試使用HTML,CSS和Vanilla Javascript創建自定義下拉菜單。創建自定義下拉菜單並將數據集的值放入輸入

我設法讓菜單在用戶點擊「from」輸入字段時出現,但是當我嘗試點擊一個選項時,它不會讓你添加存儲在「code」中的值,數據集。

我確實通過使用setTimeout方法得到了它的工作,但它有時候有點碰撞和錯過,似乎不是一個好的解決方案。

有沒有其他的方法來使它工作?

function app() { 
 

 
    var messages = document.querySelector(".messages"); 
 

 
    var inputFrom = document.querySelector(".input-from"); 
 

 
    var inputTo = document.querySelector(".input-to"); 
 

 
    var nearestContainer = document.querySelector(".nearest-container"); 
 

 
    inputFrom.addEventListener("focus", inputToFocusIn, false); 
 

 
    function inputToFocusIn(e) { 
 

 
    messages.innerHTML = "focusin event triggered on input-from"; 
 

 
    // add class 
 
    inputFrom.classList.add("input-from--focusin"); 
 
    nearestContainer.classList.add("nearest-container--active"); 
 

 
    // remove class 
 
    inputFrom.classList.remove("input-from--focusout"); 
 
    nearestContainer.classList.remove("nearest-container--hidden"); 
 

 
    } 
 

 
    inputFrom.addEventListener("focusout", inputToFocusOut, false); 
 

 
    function inputToFocusOut(e) { 
 

 
    messages.innerHTML = "focusout event triggered on input-from"; 
 

 

 
     // add class 
 
     inputFrom.classList.remove("input-from--focusin"); 
 
     nearestContainer.classList.remove("nearest-container--active"); 
 

 
     // remove class 
 
     inputFrom.classList.add("input-from--focusout"); 
 
     nearestContainer.classList.add("nearest-container--hidden"); 
 

 
    } 
 

 
    var nearestStations = document.querySelectorAll(".nearest-station"); 
 

 
    // add event listener to buttons 
 
    for(var nearestStation of nearestStations) { 
 

 
    nearestStation.addEventListener("click", addToInputFrom, false); 
 

 
    } 
 

 
    function addToInputFrom(e) { 
 

 
    inputFrom.classList.add("input-from--focusout"); 
 
    nearestContainer.classList.add("nearest-container--hidden"); 
 

 
    inputFrom.classList.remove("input-from--focusin") 
 
    nearestContainer.classList.remove("nearest-container--active") 
 

 
    var targetDataset = e.currentTarget.dataset.code; 
 

 
    messages.innerHTML = "station added to input from field" 
 

 
    inputFrom.value = ""; 
 
    inputFrom.value = targetDataset; 
 

 
    } 
 

 
    var switchButton = document.querySelector(".button-switch"); 
 

 
    switchButton.addEventListener("click", clickSwitch, false); 
 

 
    function clickSwitch(e) { 
 

 
    var inputFromValue = inputFrom.value; 
 
    var inputToValue = inputTo.value; 
 

 
    inputFrom.value = inputToValue; 
 
    inputTo.value = inputFromValue; 
 

 
    } 
 

 
} 
 

 
window.onload = app();
/* stylesheet */ 
 

 
body { 
 
\t font-family: "GRAPHIK"; 
 
\t font-style: normal; 
 
\t font-weight: 400; 
 
\t font-size: 16px; 
 
\t color: #242424; 
 
} 
 

 
* { 
 
\t box-sizing: border-box; 
 
\t outline: none; 
 
} 
 

 
.container { 
 
\t display: flex; 
 
\t flex-direction: column; 
 
\t justify-content: center; 
 
\t align-items: center; 
 
\t width: 100vw; 
 
\t height: 100vh; 
 
\t background-color: #FF4136; 
 
} 
 

 
.search-container { 
 
\t display: flex; 
 
\t flex-direction: column; 
 
\t flex-shrink: 0; 
 
\t width: 300px; 
 
\t padding: 10px; 
 
\t background-color: #FFF; 
 
\t border-radius: 10px; 
 
} 
 

 
.form-container { 
 
\t display: flex; 
 
\t flex-direction: row; 
 
\t width: 100%; 
 
} 
 

 
.input-container { 
 
\t width: 100%; 
 
} 
 

 
.input { 
 
\t width: 100%; 
 
\t border: none; 
 
\t border-radius: 10px; 
 
\t background-color: #f1f1f1; 
 
\t padding: 10px; 
 
} 
 

 
.input-from { 
 
\t margin-bottom: 5px; 
 
} 
 

 
.input-from--focusout { 
 
\t border-radius: 10px; 
 
} 
 

 
.input-from--focusin { 
 
\t border-radius: 10px 10px 0 0; 
 
} 
 

 
.input-to { 
 
\t margin-bottom: 5px; 
 
} 
 

 
.switch-container { 
 
\t \t margin-bottom: 5px; 
 
} 
 

 
.button { 
 
\t border: none; 
 
\t background-color: transparent; 
 
} 
 

 
.button-switch { 
 
\t height: 100%; 
 
\t width: 38px; 
 
\t margin-left: 5px; 
 
\t background-color: #f1f1f1; 
 
\t border-radius: 10px; 
 
\t background-image: url(../assets/images/switch.svg); 
 
\t background-position: center; 
 
\t background-size: 20px; 
 
\t background-repeat: no-repeat; 
 
} 
 

 
.button-switch:hover { 
 
\t background-image: url(../assets/images/switch-hover.svg); 
 
} 
 

 
.button-search { 
 
\t padding: 10px; 
 
\t background-color: #2ECC40; 
 
\t color: #FFF; 
 
\t border-radius: 10px; 
 
\t width: 100%; 
 
\t transition: background-color 0.5s ease; 
 
} 
 

 
.button-search:hover { 
 
\t background-color: #33e147; 
 
} 
 

 
.input-container-to { 
 
\t \t position: relative; 
 

 
} 
 

 
.nearest-container { 
 
\t position: absolute; 
 
\t top: 38px; 
 
\t background-color: #f1f1f1; 
 
\t padding: 5px; 
 
\t border-radius: 0 0 10px 10px; 
 
\t width: 100%; 
 
\t z-index: 100; 
 
} 
 

 
.messages { 
 
\t width: 300px; 
 
\t background-color: #FFF; 
 
\t padding: 5px; 
 
\t border-radius: 10px; 
 
\t text-align: center; 
 
\t margin-bottom: 5px; 
 
\t font-size: 10px; 
 
} 
 

 
.finding, .show-more { 
 
\t width: 100%; 
 
\t font-size: 10px; 
 
\t font-style: italic; 
 
\t margin: 0; 
 
\t padding: 5px; 
 
} 
 

 
.show-more { 
 
\t text-align: center; 
 
} 
 

 
.nearest-station { 
 
\t font-size: 10px; 
 
\t padding: 5px; 
 
\t border-radius: 10px; 
 
} 
 

 
.nearest-container--hidden { 
 
\t display: none; 
 
} 
 

 
.nearest-station--active { 
 
\t display: flex; 
 
} 
 

 
.nearest-station:hover { 
 
\t background-color: #FFF; 
 
\t cursor: pointer; 
 
} 
 

 
.logo { 
 
\t margin-right: 5px; 
 
} 
 

 
.nr-logo { 
 
\t width: 15px; 
 
} 
 

 
.station-distance { 
 
\t font-style: italic; 
 
\t float: right; 
 
}
<div class="container"> 
 

 
\t \t \t <div class="messages">messages here</div> 
 

 
\t \t \t <div class="search-container"> 
 

 
\t \t \t \t <div class="form-container"> 
 

 
\t \t \t \t \t <div class="input-container"> 
 

 
\t \t \t \t \t <div class="input-container-to"> 
 

 
\t \t \t \t \t \t <input type="text" class="input input-from" placeholder="From"> 
 

 
\t \t \t \t \t \t <div class="nearest-container nearest-container--hidden"> 
 

 

 

 
\t \t \t \t \t \t \t <div class="stations-container"> 
 

 
\t \t \t \t \t \t \t \t <p class="finding">Finding stations closest to you...</p> 
 

 
\t \t \t \t \t \t \t \t <!-- stations here--> 
 

 
\t \t \t \t \t \t \t \t <div class="nearest-station" data-code="Leigh-on-Sea"> 
 

 
\t \t \t \t \t \t \t \t \t <span class="logo"><img class="nr-logo" src="assets/images/nr-logo.svg"></span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-name">Leigh-on-Sea</span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-distance">0.6km</span> 
 

 
\t \t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t \t <div class="nearest-station" data-code="Chalkwell"> 
 

 
\t \t \t \t \t \t \t \t \t <span class="logo"><img class="nr-logo" src="assets/images/nr-logo.svg"></span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-name">Chalkwell</span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-distance">1.5km</span> 
 

 
\t \t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t \t <div class="nearest-station" data-code="Westcliff"> 
 

 
\t \t \t \t \t \t \t \t \t <span class="logo"><img class="nr-logo" src="assets/images/nr-logo.svg"></span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-name">Westcliff</span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-distance">2.7km</span> 
 

 
\t \t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t \t <div class="nearest-station" data-code="Southend Central"> 
 

 
\t \t \t \t \t \t \t \t \t <span class="logo"><img class="nr-logo" src="assets/images/nr-logo.svg"></span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-name">Southend Central</span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-distance">3.6km</span> 
 

 
\t \t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t \t <div class="nearest-station" data-code="Southend Victoria"> 
 

 
\t \t \t \t \t \t \t \t \t <span class="logo"><img class="nr-logo" src="assets/images/nr-logo.svg"></span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-name">Southend Victoria</span> 
 
\t \t \t \t \t \t \t \t \t <span class="station-distance">3.8km</span> 
 

 
\t \t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t \t <div class="stations-show-more"> 
 
<!-- 
 
\t \t \t \t \t \t \t \t <p class="show-more">Show more stations</p> --> 
 

 
\t \t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t \t </div> 
 

 
\t \t \t \t \t </div> 
 

 
\t \t \t \t \t <div class="input-container-to"> 
 

 
\t \t \t \t \t \t <input type="text" class="input input-to" placeholder="To"> 
 

 
\t \t \t \t \t </div> 
 

 
\t \t \t \t </div> 
 

 
\t \t \t \t <div class="switch-container"> 
 

 
\t \t \t \t \t <input type="button" class="button button-switch"> 
 

 
\t \t \t \t </div> 
 

 
\t \t \t </div> 
 

 
\t \t \t <div class="button-search-container"> 
 

 
\t \t \t \t <input type="button" class="button button-search" value="Search"> 
 

 
\t \t \t </div> 
 

 
\t \t </div> 
 

 
\t \t </div>

回答

1

inputToFocusOut()功能使用setTimeout確實取得理想效果的正確方法:菜單隱藏必須被延遲,使得菜單項上點擊將註冊和其回調會着火。應該沒有什麼關於它的想法,只需將延遲設置爲一個合理的值,比如說300ms,並從addToInputFrom()回調中刪除菜單的隱藏。實際上,你可以刪除後面所有的函數的類切換調用,因爲它們在那裏是多餘的,可能會產生干擾。該菜單將顯示/隱藏inputFrom獲得/失去焦點。

順便說一句,你爲什麼要用focusout而不是blur

0

使用這裏

inputFrom.addEventListener("focusout", inputToFocusOut, false);

focusout事件是不正確的。因爲它會在click事件之前觸發。 當執行功能inputToFocusOut.nearest-container成爲隱藏:

nearestContainer.classList.add("nearest-container--hidden");

,這就是爲什麼click事件爲它及其所有子節點(我們感興趣的是.nearest-station元素)將不會觸發。使用mousedown事件代替focusout。隨着blur事件它將無法正常工作。