Home > Net >  Invoke javascript function upon HTML element on page load
Invoke javascript function upon HTML element on page load

Time:11-10

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!

CodePudding user response:

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>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

There are a couple of things to know:

  1. As epascarello pointed out in a comment, the UL element doesn't have a load event, so the buildMenu() function will never fire.

  2. 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.

  3. 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.

  4. 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>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

  1. Element doesn't have onload event.
  2. You don't have to add the async keyword.

Please read about JavaScript Asynchronous

  1. You can either put your javaScript code before </body> inside a <script> tag or just make a new js file.
<body>
.....

<!-- Here your change -->
<script>buildMenu("mymenu");</script>
</body>
  1. Please use template literals, it's better than string concatenation.

JavaScript Template literals

const row = `<li><a href="${element.href}">${element.name}</a></li>`;

The final code will be something like this.

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>

Live Example

  • Related