Я пытаюсь отобразить раскрывающееся меню при щелчке значка. В настоящий момент при нажатии на значок, заключенный в тег anchor с функцией onclick, ничего не происходит, что можно увидеть в первом примере.

Я попытался обойти это, введя текст внутри тега привязки onclick, который говорит DOWNLOAD REPORT, при нажатии на текст раскрывающееся меню появляется, как и ожидалось, но если бы я был значок справа, раскрывающееся меню не не появиться.

Как сделать так, чтобы раскрывающееся меню отображалось при щелчке значка, а не текста?

Вот мои образцы кода:

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

function myFunction() {
    document.getElementById("myDropdown2").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-download");
        var i;
        for (i = 0; i < dropdowns.length; i++) {
            var openDropdown = dropdowns[i];
            if (openDropdown.classList.contains('show')) {
                openDropdown.classList.remove('show');
            }
        }
    }
}
a {
cursor: pointer;
}

.download-btn-container {
    display: inline-block;
    float: right;
   
}

.download-btn-container a {
    font-weight: 700;
    letter-spacing: .5px;
    color: #c94927;
}

/* Dropdown Content (Hidden by Default) */
.dropdown-download {
    display: none;
    position: absolute;
    background-color: #f1f1f1;
    min-width: 160px;
    box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
    z-index: 1;
}

    /* Links inside the dropdown */
    .dropdown-download a {
        color: black;
        padding: 12px 16px;
        text-decoration: none;
        display: block;
    }

        /* Change color of dropdown links on hover */
        .dropdown-download a:hover {
            background-color: #ddd
        }

/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */
.show {
    display: block;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons"
      rel="stylesheet">
    

<div class="download-btn-container">
<span>DOWNLOAD LIST </span>
    <a onclick="myFunction()" title="Download List"  class="dropbtn"><span class='material-icons'>save_alt</span></a>
            <div id="myDropdown" class="dropdown-download">
              <a href="#">Link 1</a>
              <a href="#">Link 2</a>
              <a href="#">Link 3</a>
            </div>
        </div>
        
 
<br/>
<br/>
<br/>
 
 <div class="download-btn-container">
    <a onclick="myFunction()" title="Download List"  class="dropbtn"> DOWNLOAD LIST<span class='material-icons'>save_alt</span></a>
            <div id="myDropdown2" class="dropdown-download">
              <a href="#">Link 1</a>
              <a href="#">Link 2</a>
              <a href="#">Link 3</a>
            </div>
        </div>
        
0
stepheniok 5 Май 2021 в 01:26

2 ответа

Лучший ответ

Я просмотрел ваш код и нашел пару ошибок.

Ошибка 1 в вашем примере у вас есть одна и та же функция с двойным именем, поэтому я предполагаю, что это только для тестирования, но убедитесь, что вы обновляете имена своих функций при тестировании, например. в вашем JS есть myFunction () и myFunction (), попробуйте myFunction () и myFunction2 ().

Ошибка 2 , ваше событие windows.onClick необходимо переписать примерно так:

// 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-download"),
            showEvent = 'show';
        for (var i = 0; i < dropdowns.length; i++) {
            var currentElement = dropdowns[i],
                currentElementAsString = dropdowns[i].toString();
            if (currentElementAsString.localeCompare(showEvent)) {
                currentElement.classList.remove('show');
            }
        }
    }
}

Объяснение : ваш исходный код уже перебирал ваш classList, поэтому вы по сути сравнивали символы, а именно эту строку:

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

Обратите внимание, как вы используете getElementsByClassName(), это вернет массив имен классов внутри элемента, к тому времени, когда вы дойдете до цикла for, вы уже находитесь в именах классов, поэтому, по сути, вы повторяете через строки в ваших индексах.

Ошибка 3 Ваш триггер события ищет класс .dropbtn, но в вашем теге привязки есть этот класс, а не ваш фактический значок. Вот строчка, о которой я говорю:

<a onclick="myFunction()" title="Download List"  class="dropbtn"><span class='material-icons'>save_alt</span></a>

Это следует переписать так:

<a onclick="myFunction()" title="Download List"  class="dropbtn material-icons">save_alt</a>

Если вы предпочитаете другой способ, вам нужно добавить класс dropbtn в диапазон значков материалов. Надеюсь, это имеет смысл, дайте мне знать, если вам понадобится помощь. :)

Codepen

1
ARLCode 4 Май 2021 в 23:10

Я немного реструктурировал javascript, удалив атрибут onclick из HTML и добавил функцию, которую можно запускать в цикле forEach. Вместо того, чтобы добавлять функцию с одинаковым именем myFunction() на обе кнопки, запросите элементы кнопки с помощью querySelectorAll и запустите nodeList через цикл. Запустите функцию, которая использует родительские элементы <▪event.targets, чтобы найти раскрывающийся элемент, а затем переключите класс show для этого элемента с помощью прослушивателя событий нажмите .

Вы можете использовать: e.target.parentNode.nextElementSibling.classList.toggle('show') event.target ( это ваш ЗНАЧОК ) => .parentNode => ( это ваш класс .dropbtn ) => .nextElementSibling => ( .dropdown-download - это ваш скрытый элемент ) => .classList.toggle('show') (< em> переключает класс .show )

<▪NOTE: Также не уверен, что вы намеревались включить в тег a второй DOWNLOAD LIST, в отличие от первого. В таком случае для запуска кода потребуется дополнительное условие, как я его изложил.

let btns = document.querySelectorAll('.dropbtn')
// This returns a nodeList which can use the forEach method to loop over the list of nodes

// simple one line function to get the event targets parent and nextElementsSibling
function showDrpDown(e) {
    e.target.parentNode.nextElementSibling.classList.toggle('show')
}

// loop and eventListener to handle each nodeLists click event
btns.forEach(btn => {
  btn.addEventListener('click', showDrpDown)
})
a {
  cursor: pointer;
}

.download-btn-container {
  display: inline-block;
  float: right;
}

.download-btn-container a {
  font-weight: 700;
  letter-spacing: .5px;
  color: #c94927;
}


/* Dropdown Content (Hidden by Default) */

.dropdown-download {
  display: none;
  position: absolute;
  background-color: #f1f1f1;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
  z-index: 1;
}


/* Links inside the dropdown */

.dropdown-download a {
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
}


/* Change color of dropdown links on hover */

.dropdown-download a:hover {
  background-color: #ddd
}


/* Show the dropdown menu (use JS to add this class to the .dropdown-content container when the user clicks on the dropdown button) */

.show {
  display: block;
}
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">


<div class="download-btn-container">
  <span>DOWNLOAD LIST </span>
  <a title="Download List" class="dropbtn"><span class='material-icons'>save_alt</span></a>
  <div id="myDropdown" class="dropdown-download">
    <a href="#">Link 1 - drpdown1</a>
    <a href="#">Link 2 - drpdown1</a>
    <a href="#">Link 3 - drpdown1</a>
  </div>
</div>


<br/>
<br/>
<br/>

<div class="download-btn-container">
  <span>DOWNLOAD LIST </span>
  <a title="Download List" class="dropbtn"><span class='material-icons'>save_alt</span></a>
  <div id="myDropdown2" class="dropdown-download">
    <a href="#">Link 1 - drpdown2</a>
    <a href="#">Link 2 - drpdown2</a>
    <a href="#">Link 3 - drpdown2</a>
  </div>
</div>
0
dale landry 4 Май 2021 в 23:20