patternjavascriptMinor
Dropdown function
Viewed 0 times
functiondropdownstackoverflow
Problem
Is there a way to simplify this JavaScript function any further? Having to input 4 variables just for a drop-down menu seems a bit ridiculous, and it is hard to keep track of the variables when I want to have more than 1 button.
.dropbtn:hover, .dropbtn:focus {
background-color: #3e8e41;
}
.dropdown-content {
display: none;
position: absolute;
background-color: #f9f9f9;
}
.dropdown-content a {
padding: 12px 16px;
text-decoration: none;
display: block;
}
.dropdown a:hover {background-color: #f1f1f1}
.show {display:block;}
Clickable Dropdown
Click on the button to open the dropdown menu.
Dropdown
Home
About
Contact
/* When the user clicks on the button,
toggle between hiding and showing the dropdown content */
function myFunction(dropDownClass,dropDownId,show,dropbtnClass) {
var dropdowns = document.getElementsByClassName(dropDownClass);
var i;
var openDropdown = dropdowns[i];
document.getElementById(dropDownId).classList.toggle(show);
// Close the dropdown if the user clicks outside of it
window.onclick = function(event) {
if (!event.target.matches(dropbtnClass)) {
for (i = 0; i
Solution
First, your code will be easier to read if you separate you JS and your HTML completely. You can add your
You might also want to isolate your code by wrapping it in an anonymous function to avoid leaking informations in the global object.
Then, you can deduce everything you're currently passing as parameter from your context.
since the div is written just after your button
This gives us this:
Now, you can remove the onclick event and the id attribute in your html and add more dropdowns.
Here is the corresponding Plunker: https://plnkr.co/edit/3mdULmI2QEcWmpDCzXQb?p=preview
onclick event on your element this way:var dropDowns = document.getElementsByClassName('dropdown');
for(var i = 0; i < dropDowns.length; i++){
dropDowns[i].addEventListener('click', function(e){
// e contains your click data
});
}You might also want to isolate your code by wrapping it in an anonymous function to avoid leaking informations in the global object.
Then, you can deduce everything you're currently passing as parameter from your context.
.dropbtn: this is the button you clicked, which will be sent in your event data as e.targetdropdown-content: as far as I can tell, this will always be the name of your class, so I'd put it in a variable inside your functiondropDowns[i].addEventListener('click', function(e){
var dropdownClass = 'dropdown-content';
});myDropdown: this represents the div inside the dropdown element containing the button clicked by the user, which can be written ase.target.nextElementSiblingsince the div is written just after your button
show: again, a simple var in your function is enoughThis gives us this:
// namespace variables
(function(){
// classes used in your HTML
var dropDownClass = 'dropdown-content';
var showClass = 'show';
var dropDowns = document.getElementsByClassName('dropdown');
// this function will be called on click
var open = function(e){
var openDropDown = e.target.nextElementSibling;
var dropdowns = document.getElementsByClassName(dropDownClass);
openDropDown.classList.toggle(showClass);
var closeDropDown = function(event) {
if (event.target === e.target) {
return;
}
if (openDropDown.classList.contains(showClass)) {
openDropDown.classList.remove(showClass);
}
window.removeEventListener('click', closeDropDown);
};
window.addEventListener('click', closeDropDown);
}
for(var i = 0; i < dropDowns.length; i++){
dropDowns[i].children[0].addEventListener('click', open);
}
}());Now, you can remove the onclick event and the id attribute in your html and add more dropdowns.
Here is the corresponding Plunker: https://plnkr.co/edit/3mdULmI2QEcWmpDCzXQb?p=preview
Code Snippets
var dropDowns = document.getElementsByClassName('dropdown');
for(var i = 0; i < dropDowns.length; i++){
dropDowns[i].addEventListener('click', function(e){
// e contains your click data
});
}dropDowns[i].addEventListener('click', function(e){
var dropdownClass = 'dropdown-content';
});e.target.nextElementSibling// namespace variables
(function(){
// classes used in your HTML
var dropDownClass = 'dropdown-content';
var showClass = 'show';
var dropDowns = document.getElementsByClassName('dropdown');
// this function will be called on click
var open = function(e){
var openDropDown = e.target.nextElementSibling;
var dropdowns = document.getElementsByClassName(dropDownClass);
openDropDown.classList.toggle(showClass);
var closeDropDown = function(event) {
if (event.target === e.target) {
return;
}
if (openDropDown.classList.contains(showClass)) {
openDropDown.classList.remove(showClass);
}
window.removeEventListener('click', closeDropDown);
};
window.addEventListener('click', closeDropDown);
}
for(var i = 0; i < dropDowns.length; i++){
dropDowns[i].children[0].addEventListener('click', open);
}
}());Context
StackExchange Code Review Q#116098, answer score: 3
Revisions (0)
No revisions yet.