2017-07-01 10 views
-1

私は同様の記事を見回し、この実装の周りのjavascriptがどのように機能するかにつきまとうようです。ドロップダウンを開始するボタンをクリックするフィルタがあるドロップダウンがあります。これは正常に動作します。ただし、このドロップダウンを解除する唯一の方法は、元のボタンをクリックすることです。私はドロップダウン以外の画面上の他の場所をクリックすると却下しようとしています。私はこれを近づいてきた方法ではJavaScriptを持つ癖があるかどうかわからないんだけど、次のコードは、私のアプローチを設定し、概念レベルで、私はこれが正常に動作すべきだと思う:ページのクリックでドロップダウンを閉じる

コード:

function myFunction() { 
 
    document.getElementById("myDropdown").classList.toggle("show"); 
 
} 
 

 
window.onclick = function(event) { 
 
    if (!event.target.matches('.dropbtn')) { 
 

 
    var dropdowns = document.getElementsByClassName("dropdown-content"); 
 
    var i; 
 
    for (i = 0; i < dropdowns.length; i++) { 
 
     var openDropdown = dropdowns[i]; 
 
     if (openDropdown.classList.contains('show')) { 
 
     openDropdown.classList.remove('show'); 
 
     } 
 
    } 
 
    } 
 
} 
 

 
function filterFunction() { 
 
    var input, filter, ul, li, a, i; 
 
    input = document.getElementById("myInput"); 
 
    filter = input.value.toUpperCase(); 
 
    div = document.getElementById("myDropdown"); 
 
    a = div.getElementsByTagName("a"); 
 
    for (i = 0; i < a.length; i++) { 
 
    if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) { 
 
     a[i].style.display = ""; 
 
    } else { 
 
     a[i].style.display = "none"; 
 
    } 
 
    } 
 
}
<div class="dropdown"> 
 
    <button onclick="myFunction()" class="dropbtn"><img src="bread.png" height="50" width="50" style="vertical-align:middle" align="left"><a>Testing</a></button> 
 
    <div id="myDropdown" class="dropdown-content"> 
 
    <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()"> 
 
    <a> Dropdown Content 1 </a> 
 
    <a> Dropdown Content 2 </a> 
 
    <a> Dropdown Content 3 </a> 
 
    </div> 
 
</div>

おかげさまであり、ありがとうございました!

+1

? –

+1

ボタンでないときに 'window.onclick'のこの要素からshowクラスを削除しないのはなぜですか? – amiramw

答えて

1

私は最近、ページクリック全体をターゲットにするこのテクニックについて、背景にとどまるマスクを導入してblog post - Evolution of Drop Down Menus and Exiting Themと書いています。

イベントリスナーの場合はjQueryを使用していますが、主なコンセプトはマスクです。これは、同様に開閉のための背後にあるロジックです:

click() { 
    if (other_dropdowns_open) { 
    close_others; 
    open_current; 
    } else { 
    if (current_dropdown_open) 
     close_current; 
    else 
     open_current; 
    } 
} 

コードここにある:

$(function() { 
 
    $(".dd-trigger").click(function (e) { 
 
    e.preventDefault(); 
 
    $("body").addClass("dd-open"); 
 
    $(this).closest(".dd").toggleClass("open"); 
 
    }); 
 
    $(".dd-mask").click(function() { 
 
    $("body").removeClass("dd-open"); 
 
    $(".open").removeClass("open"); 
 
    }); 
 
});
.dd {display: inline-block; position: relative;} 
 
.dd .dd-trigger {display: block; text-decoration: none; border: 1px solid #ccf; padding: 5px; border-radius: 5px; color: #000; min-width: 100px;} 
 
.dd .dd-trigger img {margin-top: 5px; float: right;} 
 
.dd .dd-menu, 
 
.dd .dd-menu li {margin: 0; padding: 0; list-style: none;} 
 
.dd .dd-menu {display: none; position: absolute; z-index: 2; background-color: #f5f5f5; border: 1px solid #ccf; left: 0; right: 0; margin-top: -3px; border-top: 0;} 
 
.dd .dd-menu a {display: block; text-decoration: none; line-height: 1; padding: 5px; color: #000; margin: 2px 0;} 
 
.dd .dd-menu a:hover {background-color: #fff;} 
 
.dd.open .dd-menu {display: block;} 
 
.dd-mask {position: fixed; z-index: 1; left: 0; top: 0; bottom: 0; right: 0; display: none;} 
 
.dd-open .dd-mask {display: block;} 
 
input {width: 90%; margin: 5px; border: 1px solid #ccc; padding: 3px 5px;} 
 
li:first-child input {margin-bottom: 0;}
<script src="https://code.jquery.com/jquery-2.2.4.js"></script> 
 
<div class="dd-mask"></div> 
 
<div class="dd"> 
 
    <a href="#" class="dd-trigger"> 
 
    Account 
 
    <img src="https://www.mydemenageur.com/images/caret_open.png" alt="Drop Down" /> 
 
    </a> 
 
    <ul class="dd-menu"> 
 
    <li><a href="">Profile</a></li> 
 
    <li><a href="">Settings</a></li> 
 
    <li><a href="">Logout</a></li> 
 
    </ul> 
 
</div> 
 
<div class="dd"> 
 
    <a href="#" class="dd-trigger"> 
 
    Help 
 
    <img src="https://www.mydemenageur.com/images/caret_open.png" alt="Drop Down" /> 
 
    </a> 
 
    <ul class="dd-menu"> 
 
    <li><a>Empty Clicker</a></li> 
 
    <li><a href="">Questions</a></li> 
 
    <li><a href="">Support</a></li> 
 
    </ul> 
 
</div> 
 
<div class="dd"> 
 
    <a href="#" class="dd-trigger"> 
 
    Search 
 
    <img src="https://www.mydemenageur.com/images/caret_open.png" alt="Drop Down" /> 
 
    </a> 
 
    <ul class="dd-menu"> 
 
    <li><label><input type="search" /></label></li> 
 
    <li><input type="submit" value="Search" /></li> 
 
    </ul> 
 
</div>

注:私だけのためのjQueryを使用していますクラスの追加または削除。純粋なJavaScriptを使用してそれを行う方法については、以下を参照してください:

element.classList.add("className");  // Adding 
element.classList.remove("className"); // Removing 

は、オリジナルのポストで簡単に見て持っていて、CSSを実装する方法を理解することができるかもしれません。

ボーナス:私の記事は検索ボタンのクリックを避けるために、正確にどのように説明し、あまりにもメニュー問題を却下!上のデモを見て、それを実際に見て、それを学ぶために私の記事を見てください。

1

問題が発生しているのは、イベントのバブリングです。ボタンをクリックすると、イベントはwindowオブジェクトに飛び出し、メニューを閉じる関数が実行されます。

これを防ぐにはevent.stopPropagation()myFunction()に電話することができます。

window.onclick関数をdocument.querySelectorAll()に変更したので、ループ内でclassList.contains()を呼び出す代わりに、表示されているドロップダウンをループするだけです。

function myFunction(event) { 
 
    document.getElementById("myDropdown").classList.toggle("show"); 
 
    event.stopPropagation(); 
 
} 
 

 
window.onclick = function(event) { 
 
    if (!event.target.matches('.dropbtn')) { 
 

 
    var dropdowns = document.querySelectorAll(".dropdown-content.show"); 
 
    for (var i = 0; i < dropdowns.length; i++) { 
 
     var openDropdown = dropdowns[i]; 
 
     openDropdown.classList.remove('show'); 
 
    } 
 
    } 
 
} 
 

 
function filterFunction() { 
 
    var input, filter, ul, li, a, i; 
 
    input = document.getElementById("myInput"); 
 
    filter = input.value.toUpperCase(); 
 
    div = document.getElementById("myDropdown"); 
 
    a = div.getElementsByTagName("a"); 
 
    for (i = 0; i < a.length; i++) { 
 
    if (a[i].innerHTML.toUpperCase().indexOf(filter) > -1) { 
 
     a[i].style.display = ""; 
 
    } else { 
 
     a[i].style.display = "none"; 
 
    } 
 
    } 
 
}
.dropdown-content { 
 
    display: none; 
 
} 
 

 
.dropdown-content.show { 
 
    display: block; 
 
}
<div class="dropdown"> 
 
    <button onclick="myFunction(event)" class="dropbtn"><img src="bread.png" height="50" width="50" style="vertical-align:middle" align="left"><a>Testing</a></button> 
 
    <div id="myDropdown" class="dropdown-content"> 
 
    <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()"> 
 
    <a> Dropdown Content 1 </a> 
 
    <a> Dropdown Content 2 </a> 
 
    <a> Dropdown Content 3 </a> 
 
    </div> 
 
</div>

+0

この方法では、検索ボタンでも対話ができません。 –

+0

私はこの方法を使用しましたが、問題を実際に解決していませんでしたか?私はあなたがイベントバブリングの意味を理解することができますが、上記のコードはそれに添付されている手本の例で意図したとおりに実行されているようです? – NickvR

+1

それから、Praveen Kumarの答えが役に立つかもしれません。 – Barmar

0

私は2つのonclickイベントを追加しています。 window.onclickは、クリックがオンでないことを認識します。あなたはjQueryのを使用することはできません

var button = document.getElementById("myDropdown"); 
 

 
window.onclick = function(event) { 
 
    if (event.target.tagName !== "BUTTON") { 
 
    if (button.style.display != "none") { 
 
     button.style.display = "none"; 
 
    } 
 
    } 
 
} 
 

 
function myFunction() { 
 
    window.click = false; 
 
    if (button.style.display != "none") { 
 
    button.style.display = "none"; 
 
    } else { 
 
    button.style.display = ""; 
 
    } 
 
}
<div class="dropdown"> 
 
    <button onclick="myFunction()" class="dropbtn"> 
 
    <img src="bread.png" height="50" width="50" style="vertical-align:middle" align="left"> 
 
    <a>Testing</a></button> 
 
    <div id="myDropdown" class="dropdown-content"> 
 
    <input type="text" placeholder="Search.." id="myInput" onkeyup="filterFunction()"> 
 
    <a> Dropdown Content 1 </a> 
 
    <a> Dropdown Content 2 </a> 
 
    <a> Dropdown Content 3 </a> 
 
    </div> 
 
</div>

関連する問題