Закрытие раскрывающегося списка, щелкнув снаружи в Javascript (разъяснение в руководстве)

salamander спросил: 28 апреля 2018 в 09:02 в: javascript

Я попытался реализовать метод открытия и закрытия раскрывающегося списка с помощью Javascript через этот учебник по w3schools.com. Хотя функция "показывать" раскрывающиеся работы, тот, кто ее закрывает, не делает. Кроме того, нет никакого объяснения рядом с этим кодом, чтобы объяснить, почему он должен работать, что затрудняет отладку.

/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction() {
    document.getElementById("myDropdown").classList.toggle("show");
}// Close the dropdown menu if the user clicks outside of it
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');
      }
    }
  }
}

Поэтому мои вопросы являются

1) работает ли код в учебнике с целью закрытия раскрывающегося списка. (ANSWERED)

2) Может ли кто-то прояснить, как / почему это должно работать, ради ясности для себя и будущих новичков, которые сталкиваются с одним и тем же учебником и проблемой? (UNANSWERED)

Изменить (MY ATTEMPT):

HTML:

<div class="sharedown">     
    <p onclick="shareVis()" class="sharebtn">&nbsp Share</p>
    <div id="mySharedown" class="sharedown-content">
        <a href="#">Self</a>
        <p>User</p><input type="text" name="user-name" placeholder="Share to">
        <a href="#">Community</a>
    </div> 
</div>

JS:

function shareVis() {
    document.getElementById("mySharedown").className = "show";
}window.onclick = function(event) {
    if (!event.target.matches('sharebtn')) {        var sharedowns = document.getElementsByClassName("sharedown-content");
        var i;
        for (i = 0; i < sharedowns.length; i++) {
            var openSharedown = sharedowns[i];
            if (openSharedown.classList.contains('show')) {
                openSharedown.classList.remove('show');
            }
        }
    }   
}

2 ответа

Thum Choon Tat ответил: 01 мая 2018 в 06:45

Проблема заключается в функции shareVis. Здесь

document.getElementById("mySharedown").className = "show";

вы заменяете имя класса #mySharedown на show. Затем в window.onclick

var sharedowns = document.getElementsByClassName("sharedown-content");

вы не получаете никакого sharedowns, поскольку вы уже заменили имя класса на show .


Вы можете добавить класс show в classList
document.getElementById("mySharedown").classList.add("show");

или заменить имя класса sharedown-content show

document.getElementById("mySharedown").className = "sharedown-content show";

Рабочее решение ниже:

function shareVis() {
    //document.getElementById("mySharedown").className = "sharedown-content show";
    document.getElementById("mySharedown").classList.add("show");
}

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

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

document.getElementById("mySharedown").addEventListener('click',function(event){
    event.stopPropagation();
});
#mySharedown{
  display: none;
  border: 1px solid black;
}

#mySharedown.show {
  display: block;
}
<div class="sharedown">     
    <p onclick="shareVis()" class="sharebtn">&nbsp Share</p>
    <div id="mySharedown" class="sharedown-content">
        <a href="#">Self</a>
        <p>User</p><input type="text" name="user-name" placeholder="Share to">
        <a href="#">Community</a>
    </div> 
</div>

Обновить

Чтобы избежать скрытия второго кода внутри #mySharedown #mySharedown, вы должны добавить еще один click для #mySharedown и не допустить его всплытия, например, это

document.getElementById("mySharedown").addEventListener('click',function(event){
    event.stopPropagation();
});

Обновления включены в рабочее решение

salamander ответил: 28 апреля 2018 в 04:47
Теперь выпадающий список остается открытым; однако он закрывается, когда я нажимаю в любом месте, в том числе и внутри него. Любая помощь?
Thum Choon Tat ответил: 28 апреля 2018 в 11:45
Вы хотите закрыть его после другого нажатия кнопки Поделиться?
salamander ответил: 01 мая 2018 в 06:31
Я хочу, чтобы он закрылся после щелчка в любом случае, кроме как внутри самого меню.
Thum Choon Tat ответил: 01 мая 2018 в 06:45
Привет @salamander Я обновил ответ
salamander ответил: 06 мая 2018 в 06:28
Обновление отлично работало. Теперь мое раскрывающееся меню работает так, как я хочу. Тем не менее, я до сих пор не совсем понимаю, как работает этот function(event) и содержащийся для цикла (также часть моего исходного вопроса). Возможно, я поработаю над документацией.
shontek ответил: 28 апреля 2018 в 09:30

Пример полностью функциональный и должен работать. Скопируйте следующий код ниже:

   <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.dropbtn {
    background-color: #3498DB;
    color: white;
    padding: 16px;
    font-size: 16px;
    border: none;
    cursor: pointer;
}.dropbtn:hover, .dropbtn:focus {
    background-color: #2980B9;
}.dropdown {
    position: relative;
    display: inline-block;
}.dropdown-content {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    overflow: auto;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}.dropdown-content a {
    color: black;
    padding: 12px 16px;
    text-decoration: none;
    display: block;
}.dropdown a:hover {background-color: #ddd}.show {display:block;}
</style>
</head>
<body><h2>Clickable Dropdown</h2>
<p>Click on the button to open the dropdown menu.</p><div class="dropdown">
<button onclick="myFunction()" class="dropbtn">Dropdown</button>
  <div id="myDropdown" class="dropdown-content">
    <a href="#home">Home</a>
    <a href="#about">About</a>
    <a href="#contact">Contact</a>
  </div>
</div><script>
/* When the user clicks on the button, 
toggle between hiding and showing the dropdown content */
function myFunction() {
    document.getElementById("myDropdown").classList.toggle("show");
}// Close the dropdown if the user clicks outside of it
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');
      }
    }
  }
}
</script></body>
</html>