[英]How to close the Bootstrap navbar dropdown when the user clicks outside the menu?
[英]How to hide a dropdown when the user clicks outside of it
下面是我正在使用的輸入下拉列表的簡化版本。
其作用的基本摘要是:如果您專注於輸入,則會出現一個下拉列表。 如果您單擊下拉列表中的選項之一,該選項將填充輸入並且下拉列表消失。 這是使用onfocus
和我稱為dropdown();
的函數實現的dropdown();
和undropdown();
.
我處於兩難境地,當有人點擊其他地方時,我無法使下拉菜單消失。 如果我使用onblur
,它會成功隱藏下拉列表,但是如果您單擊一個選項,它不會填充輸入,這是因為onblur
函數首先運行,因此, input();
函數不會運行,因為下拉列表已經隱藏。
如果您在 body 標簽或其他父標簽上放置onclick
,它會將onfocus
視為單擊,在那里運行的是dropdown();
函數然后是undropdown();
立即運行,因此下拉菜單永遠不會出現,因為功能重疊。
我很感激幫助弄清楚如何對函數進行排序,以便它們以正確的順序執行而不會相互重疊。
function input(pos) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = li[pos].innerHTML; undropdown(0); } function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "none"; }
.drop { position: relative; display: inline-block; vertical-align: top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; } .content li { padding: 12px 16px; display: block; margin: 0; }
<div class="drop"> <input type="text" name="class" placeholder="Class" onfocus="dropdown(0)"/> <ul class="content"> <li onclick="input(0)">Option 1</li> <li onclick="input(1)">Option 2</li> <li onclick="input(2)">Option 3</li> <li onclick="input(3)">Option 4</li> </ul> </div>
PS:除了上述問題之外,我希望您能提出編輯建議以獲得更好的標題,以便遇到類似問題的人可以更容易地找到它。
在這種情況下,在onblur
你可以調用一個函數來觸發undropdown(0);
在一個非常小的 setTimeout 幾乎立即之后。 像這樣:
function set() {
setTimeout(function(){
undropdown(0);
}, 100);
}
HTML
<input type="text" name="class" placeholder="Class" onfocus="dropdown(0)" onblur="set()" />
不需要其他更改。
function input(pos) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = li[pos].innerHTML; undropdown(0); } function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display= "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display= "none"; } function set() { setTimeout(function(){ undropdown(0); }, 100); }
.drop { position: relative; display: inline-block; vertical-align:top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; } .content li { padding: 12px 16px; display: block; margin: 0; }
<div class="drop"> <input type="text" name="class" placeholder="Class" onfocus="dropdown(0)" onblur="set()" /> <ul class="content"> <li onclick="input(0)">Option 1</li> <li onclick="input(1)">Option 2</li> <li onclick="input(2)">Option 3</li> <li onclick="input(3)">Option 4</li> </ul> </div>
你可以做的下拉可聚焦與tabindex
,並在輸入的blur
事件偵聽器只隱藏下拉如果焦點沒有去下拉(見當的onblur時,我怎么能找出哪些元素焦點去了? )
<ul class="content" tabindex="-1"></ul>
input.addEventListener('blur', function(e) {
if(!e.relatedTarget || !e.relatedTarget.classList.contains('content')) {
undropdown(0);
}
});
function input(e) { var dropdown = document.getElementsByClassName('drop'); var li = dropdown[0].getElementsByTagName("li"); document.getElementsByTagName('input')[0].value = e.target.textContent; undropdown(0); } [].forEach.call(document.getElementsByTagName('li'), function(el) { el.addEventListener('click', input); }); function dropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "block" } function undropdown(pos) { document.getElementsByClassName('content')[pos].style.display = "none"; } var input = document.getElementsByTagName('input')[0]; input.addEventListener('focus', function(e) { dropdown(0); }); input.addEventListener('blur', function(e) { if(!e.relatedTarget || !e.relatedTarget.classList.contains('content')) { undropdown(0); } });
.drop { position: relative; display: inline-block; vertical-align: top; overflow: visible; } .content { display: none; list-style-type: none; border: 1px solid #000; padding: 0; margin: 0; position: absolute; z-index: 2; width: 100%; max-height: 190px; overflow-y: scroll; outline: none; } .content li { padding: 12px 16px; display: block; margin: 0; }
<div class="drop"> <input type="text" name="class" placeholder="Class" /> <ul class="content" tabindex="-1"> <li>Option 1</li> <li>Option 2</li> <li>Option 3</li> <li>Option 4</li> </ul> </div>
接受的答案是一種幼稚且不可靠的方法。 我在復雜的應用程序中遇到了一個難以捕捉的錯誤,因為我使用了setTimeout
來提供約 200 毫秒的延遲,以便瀏覽器可以在模糊事件發生之前處理下拉單擊。 雖然它在我測試過的每個設置上都運行良好,但一些用戶確實遇到了問題,尤其是機器速度較慢的用戶。
正確的方法是測試relatedTarget
對focusout
的事件:
input.addEventListener('focusout', function(event) {
if(!isDropdownElement(event.relatedTarget)) {
// hide dropdown
}
});
relatedTarget
用於focusout
包含一個元素的參考,這是接收焦點。 到目前為止,這在我測試過的每個瀏覽器中都可靠地工作(我沒有測試 IE10 及更低版本,只測試了 IE11 和 Edge)。
W3Schools 有一個很好的例子來說明如何創建自定義下拉列表: https : //www.w3schools.com/howto/howto_custom_select.asp
這是該示例中處理焦點的方式:
全局點擊處理程序處理下拉列表之外的點擊: document.addEventListener("click", closeAllSelect);
. 因此,只要用戶單擊文檔中的任意位置,所有下拉菜單都會關閉。
但是當用戶選擇下拉列表的一個元素時,點擊事件被e.stopPropagation();
選擇處理程序的內部。
這樣,您就不需要計時器解決方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.