Ik heb deze JS die in de head geladen wordt, maar er gebeurt niets:
var x = document.createElement("button");
x.setAttribute("name", " + ");
document.getElementById("mobile-nav").getElementsByClassName("menu-item-has-children").appendChild(x);
Waarschijnlijk omdat de "head" er eerder is dan het menu zelf. Op het moment dat bovenstaande code loopt is er dus nog geen menu (de HTML parser is pas in de "head"), en gebeurt er ook niks.
Het makkelijkst is om je JS-code gewoon helemaal onderaan te hangen (net voor de </body> tag). als dat niet gaat (je de JS dus alleen in de head toe kunt voegen), dan de volgende event listener er "omheen":
document.addEventListener('DOMContentLoaded', function() {
//hocus pocus hier
}, false);
De "hocus pocus" wordt dan pas uitgevoerd als het document (en dus ook het menu) helemaal is geladen.
Dank, goed punt.
Het werkt overigens nog niet, als ik "mijn" JS binnen deze functie zet zou het uitgevoerd moeten worden, lijkt me? Of is mijn JS niet juist?
Guido
?Onbekende gebruiker
16-04-2021 21:48
gewijzigd op 16-04-2021 21:52
Wat je nog moet doen is door de lijst van nodes van getElementsByTagName() gaan met een lus. En je moet de <ul> van het submenu insluiten in de <li> tag:
<!DOCTYPE html>
<html>
<head>
<script>
window.addEventListener('DOMContentLoaded', function() {
let button = document.createElement('button');
button.innerHTML = '+';
button.addEventListener('click', function() {
let ul = this.parentNode.getElementsByTagName('ul')[0];
ul.style.display = (ul.style.display == '') ? 'none' : '';
});
let list = document.getElementById('mobile-nav')
.getElementsByClassName('menu-item-has-children');
for (let index = 0; index < list.length; index++) {
let li = list[index];
let ul = li.parentNode.getElementsByTagName('ul')[0];
li.insertBefore(button, ul);
}
});
</script>
</head>
<body>
<ul id="mobile-nav">
<li>Item 1</li>
<li class="menu-item-has-children">Item 2
<ul>
<li>Subitem 1</li>
<li>Subitem 2</li>
</ul>
</li>
<li>Item 3</li>
</ul>
</body>
</html>
Insluiten van submenu in de li is een domme fout van me. Had ik moeten weten.
Bedankt voor dit werkende voorbeeld, ik had niet verwacht dat er nog zo veel extra code benodigd is om dit voor elkaar te krijgen.
Guido
?Onbekende gebruiker
17-04-2021 10:59
Als je liever geen gebruik maakt van JavaScript, dan kan je ook menu's maken met alleen HTML en CSS.
Iemand die daar al jarenlang mee bezig is, heeft allerlei voorbeelden op z'n site die je zo kan overnemen.
Zie http://www.cssplay.co.uk/menus
Ik heb na veel werk en met het voorbeeld hierboven een werkend script gemaakt:
<script>
// Verberg submenu
window.addEventListener('DOMContentLoaded', function() {
var div = document.getElementById("mobile-nav");
var sub = div.getElementsByClassName("sub-menu");
for (let i = 0; i < sub.length; ++i) {
sub[i].style.display = "none";
}
});
// Voeg klik button toe en toon submenu
window.addEventListener('DOMContentLoaded', function() {
var x = document.getElementById("mobile-nav").querySelectorAll('.menu-item-has-children > a');
for( let index = 0; index < x.length; index++ ) {
var button = document.createElement('button'); button.className = 'subnav-toggle'; button.innerHTML = '+';
x[index].parentNode.insertBefore(button, x[index].nextSibling);
button.addEventListener('click', function() {
var ul = this.parentNode.getElementsByTagName('ul')[0];
ul.style.display = (ul.style.display == 'block') ? 'none' : 'block';
});
};
});
</script>
<div id="mobile-nav">
<ul>
<li>Item 1</li>
<li class="menu-item-has-children"><a>Item 2</a>
<ul class="sub-menu">
<li><a>Subitem 1</a></li>
<li><a>Subitem 2</a></li>
</ul>
</li>
<li><a>Item 3</a></li>
<li class="menu-item-has-children"><a>Item 4</a>
<ul class="sub-menu">
<li><a>Subitem 3</a></li>
<li><a>Subitem 4</a></li>
</ul>
</li>
</ul>
</div>
Zou je die eens kunnen nakijken op fouten en verbeteringen, want ben nog een echte leek ;-)
Guido
?Onbekende gebruiker
20-04-2021 09:59
gewijzigd op 20-04-2021 10:00
Als het werkt is het goed toch?
Er zijn een paar dingetjes:
- JavaScript kan met CSS werken, en die eerste functie kan in 1 regel CSS
- Verder gebruik ik bij voorkeur let boven var, vanwege de variabele scope
- Als laatste zou ik de namen van variabelen zinvolle namen geven, dus liever "list" in plaats van "x"
1) Ik weet dat ik het kan verbergen met CSS (ga ik ook doen, als fall-back), maar ik wou alles ook via JS regelen. Of is dat geen best-practice?
2) Ik begreep dat let alleen binnen de betreffende loop werkt. In mijn 2 functies wordt de var/let niet opnieuw aangeroepen buiten de loop, dus betekent dit dat ik alle var door let kan vervangen?