2017-07-01 41 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

不能使用jQuery? –

+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

我已经添加了两个onclick事件。 window.onclick认识到点击不在按钮上。

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>