This is a beginner question. I just cannot figure out the answer as simple as it may be.
I have two files: One with a JavaScript function and the other with the HTML code. The JavaScript should build the elements of a menu.
This is what I have:
JavaScript (mynaivesdk.js):
async function buildMenu(element){
const webElements = [{"name": "Home", "href": "index.html"}, {"name": "Works", "href": "works.html"}, {"name": "Contact", "href": "contact.html"}]
var menu = document.getElementById(element);
webElements.forEach((webelement) => {
const row = '<li><a href="' + webelement.href + '">' + webelement.name + '</a></li>';
menu.innerHTML += row;
});
}
HTML:
<html>
<head>
<script type="module" src="mynaivesdk.js"></script>
<title>My Menu</title>
</head>
<body>
<h1>This is my menu</h1>
<ul id="mymenu" onload="buildMenu('mymenu')">
</ul>
</body>
</html>
The result is that nothing is displayed. There is no error. I am concluding my HTML is not invoking the JavaScript function at all.
This is what I would expect to have:
<html>
<head>
<script type="module" src="mynaivesdk.js"></script>
<title>My Menu</title>
</head>
<body>
<h1>This is my menu</h1>
<ul id="mymenu">
<li><a href=ïndex.html">Home</a></li>
<li><a href=works.html">Works</a></li>
<li><a href=contact.html">Contact</a></li>
</ul>
</body>
</html>
I know this should be extremely simple. I just cannot figure out the correct way of doing this.
Thank you!
Call your function when the JS file loads and it will build your menu for you.
You'll need to add the defer attribute to your <script> tag. This simple attribute replaces the need to do the DOMContentLoaded thing.
Here you go:
function buildMenu(menu) {
const webElements = [{
"name": "Home",
"href": "index.html"
}, {
"name": "Works",
"href": "works.html"
}, {
"name": "Contact",
"href": "contact.html"
}]
webElements.forEach((webelement) => {
const row = '<li><a href="' + webelement.href + '">' + webelement.name + '</a></li>';
menu.innerHTML += row;
});
}
buildMenu(document.getElementById('mymenu'));
<html>
<head>
<script defer type="module" src="mynaivesdk.js"></script>
<title>My Menu</title>
</head>
<body>
<h1>This is my menu</h1>
<ul id="mymenu">
</ul>
</body>
</html>
There are a couple of things to know:
As epascarello pointed out in a comment, the UL element doesn't have a load event, so the buildMenu() function will never fire.
So, you need to call the buildMenu function, based on some event (a button press, hovering over a specific element, or - in this case - the document load event.
The document load event (DOMContentLoaded) is important because it is fired as soon as the elements are all present in the DOM. Before that, if you ran the buildMenu function, the #mymenu element might not be there yet, and nothing will happen.
This method is easily expanded, and you can add more function calls, etc, as you build-out your app. It is also worth noting that this is the standard way of structuring the loading/calling of JavaScript functions.
Here's what it looks like:
document.addEventListener('DOMContentLoaded', () => {
const myUl = document.getElementById('mymenu');
buildMenu(myUl);
});
function buildMenu(myEl){
const webElements = [{"name": "Home", "href": "index.html"}, {"name": "Works", "href": "works.html"}, {"name": "Contact", "href": "contact.html"}]
//var menu = document.getElementById('mymenu'); //not needed
webElements.forEach((webelement) => {
const row = '<li><a href="' + webelement.href + '">' + webelement.name + '</a></li>';
myEl.innerHTML += row;
});
}
<html>
<head>
<script type="module" src="mynaivesdk.js"></script>
<title>My Menu</title>
</head>
<body>
<h1>This is my menu</h1>
<ul id="mymenu" onload="buildMenu('mymenu')">
</ul>
</body>
</html>
Element doesn't have onload event.async keyword.Please read about JavaScript Asynchronous
</body> inside a <script> tag or just make a new js file.<body>
.....
<!-- Here your change -->
<script>buildMenu("mymenu");</script>
</body>
const row = `<li><a href="${element.href}">${element.name}</a></li>`;
In your script.js file:
function buildMenu(menuID) {
const webElements = [
{ name: "Home", href: "index.html" },
{ name: "Works", href: "works.html" },
{ name: "Contact", href: "contact.html" }
];
var menu = document.getElementById(menuID);
webElements.forEach((element) => {
const row = `<li><a href="${element.href}">${element.name}</a></li>`;
menu.innerHTML += row;
});
}
In your index.html file
<html>
<head>
<title>My Menu</title>
</head>
<body>
<h1>This is my menu</h1>
<ul id="mymenu">
</ul>
<script src="script.js"></script>
<script>
buildMenu("mymenu")
</script>
</body>
</html>