'Is there a reason why my html refuses to call the javascript function from external .js file?

EDIT: Thankyou for the instructive responses, however, nothing has been succesful. Everything works as it is supposed to otherwise, but for some reason the <body onmousemove = coordinate(event)> does not call the functions from index.js (my external javascript file). I am using codesandbox.io, could this be the problem?

The javascript is succesfully called by the HTML to draw on the canvas, but whenever I try to refer to a function it does not call it. >:(

enter image description here

As the title suggest, I have been pulling my hair out trying to understand why the coordinate(event) function refuses to be called from my src file.

The idea is a simple one, as the cursor moves across the screen the x and y coordinates of the cursor should be logged in the text boxes. However, when I run this nothing happens.

Javascript:

let canvas = document.getElementById("gameScreen");
let ctx = canvas.getContext('2d'); //ctx = context

ctx.clearRect(0,0,800,800)

function coordinate(event) {
      
  var x = event.clientX;       
  var y = event.clientY;
  document.getElementById("txt_iX").value = x;
  document.getElementById("txt_iY").value = y;
}

// Box width
var bw = 800;
// Box height
var bh = 800;
//Square size
var sq = 20
// Padding
var p = 0;


for (var x = 0; x <= bh; x += sq) {
  
  for (var y = 0; y <= bw; y += sq) {
  ctx.fillStyle = 'black';
  ctx.moveTo(p, 0.5 + x + p);
  ctx.fillRect(x,y,sq,sq)

}}

function drawBoard(){
    for (var x1 = 0; x1 <= bw; x1 += sq) {
        ctx.moveTo(0.5 + x1 + p, p);
        ctx.lineTo(0.5 + x1 + p, bh + p);
    }

    for (var x2 = 0; x2 <= bh; x2 += sq) {
        ctx.moveTo(p, 0.5 + x2 + p);
        ctx.lineTo(bw + p, 0.5 + x2 + p);
    }
    ctx.strokeStyle = "green";
    ctx.stroke();
}
drawBoard();

HTML:

<html>
<head>

  <title>EXCEL_DM</title>
  <meta charset="UTF-8" />
   
  <script type=”text/javascript” src = "src/index.js"> </script>
  
  </head>
      
   <body onmousemove = coordinate(event)>              
        
        <canvas id = "gameScreen" width="800" height = "800" ></canvas>
        <br><br>
        <input id = "txt_ix" placeholder="txt_ix">
        <br><br>
        <input id = "txt_iy" placeholder="txt_iy">
       
   </body>  
   </html>


Solution 1:[1]

To fix your issue, there are three options. All of them will work, but you can choose which one you like the best.


1. Moving script tag in body

Right now, you are loading the JavaScript before the canvas element. This makes it difficult for JavaScript to find the element.

To fix this, simply move the script tag to the last line (before the </body> tag).

An example is below:

<head>
  <!-- No more JavaScript here! -->
</head>
<body>
  <!-- Other HTML code here... -->

  <script src="src/index.js"></script>
</body>

2. Adding the defer attribute

If you didn't know, the script tag has an attribute called defer.

According to MDN Web Docs:

This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed, but before firing DOMContentLoaded.

To add this, simply leave your script tag in the head, but change it so it looks like below.

<head>
  <!-- Still in the head! -->
  <script defer src="src/index.js"></script>
</head>

3. Add an addEventListener call to JavaScript

If you don't want to change your HTML, then you can add an event listener in JavaScript, using the DOMContentLoaded event. For more information, visit MDN Web Docs.

To implement this feature in your JavaScript code, simply add the following:

// You can also use the function keyword if you're targeting older browsers.
document.addEventListener("DOMContentLoaded", (event) => {
  console.log("Hello, world! I'm loading after the DOM!");
});

Keep in mind: DOMContentLoaded fires once the DOM has loaded, not after images, stylesheets, etc. have loaded.

If you only want your script to run after everything has been loaded (images, stylesheets, etc.), then use the load event (MDN reference), like below:

// You can also use the function keyword if you're targeting older browsers.
window.addEventListner("load", (event) => {
  console.log("Hello, world! I'm loading after everything!");
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1