-1

I am making a Physics engine that utilizes JavaScript to create boxes that have the properties of physics applied to them in scale of the window size. However, the class called box that contains all the physical properties of these boxes cannot be found by the function document.getElementByClassName("box").

I am trying to assign a variable boxelem to contain the location properties of each individual box so that I can integrate mouse manipulation into my program in the future. I have tried doing this through the code:
var boxelem = document.getElementsByClassName("box"); and then adding a mouse over event listener to boxelem.

Necessary Code:

var canvas;
var ctx;
var box = [];
var boxelem;

//Startup Code
window.onload = function(e) {
    canvas = document.getElementById("c");
    ctx = canvas.getContext("2d");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    box = [new box(10, 20, "cyan"), new box(299, 40, "red"), new box(90, 50,
      "black"), new box(29, 20, "turquoise")];
    boxelem = document.getElementsByClassName("box");
    noscroll();
    update();
  }

  //Physic Clock (For real-time physics)
var clock = {
    lasttick: 0,
    tick: function() {
      var td = performance.now() - this.lasttick;
      this.lasttick = performance.now();
      return td / 1000;
    },
    reset: function() {

    }
  }

  //Box objects be created here (Box Class)
var box = function(x, y, color) {
  var _this = this;
  //First Spawn Physics and Settings
  _this.x = Math.random() * (canvas.width - 50);
  _this.y = Math.random() * (canvas.height - 50);
  _this.vx = 0;
  _this.vy = Math.random() * 150;
  _this.ax = 0;
  _this.ay = 440;
  _this.color = color;

  _this.draw = function() {
      ctx.fillStyle = _this.color;
      ctx.fillRect(_this.x, _this.y, 50, 50);
    }

    //Normal Physics
  _this.update = function(t, mX, mY) {
    if (mX != 0) {
      _this.x += _this.vx * t;
      _this.vx += mX * t;
    } else {
      _this.x += _this.vx * t;
      _this.vx += _this.ax * t;
    }
    _this.y += _this.vy * t;
    _this.vy += _this.ay * t;

    //Boundary Creation
    if ((_this.y + 55) > canvas.height) {
      _this.vy -= _this.ay * t;
      _this.vy = 0;

    }
    if ((_this.x + 55) > canvas.width) {
      _this.vx -= _this.ax * t;
      _this.vx = 0;
    }
    if ((_this.y) < 0) {
      _this.vy -= _this.ay * t;
      _this.vy = 0;
      _this.y = (canvas.height + 20);
    }
    if ((_this.x) < 0) {
      _this.vx -= _this.ax * t;
      _this.vx = 0;
    }
  }
}

//Get mouse position if over a box
var pageX = 0;
var pageY = 0;
for (var z = 0; z < box.length; z++) {
  boxelem.addEventListener("mouse", mPos, false);
}

The event listener at the bottom gives an error because boxelem is not defined due to the elements not being found by getElementsByClassName. HTML Code:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
     <script type=text/javascript src="Physics.js"></script>
     <meta charset="utf-8" />
     <title>Physics Engine of Boxes</title>
 </head>
 <body>
     <canvas id="c"></canvas>
</body>
</html>

I have looked at (Unobtrusive Javascript-Basic Implementation: How do I bind all elements of a particular class to a function in Javascript?) and (Change an element's class with JavaScript) but am unsure how to apply it to my issue.

spanky
  • 2,768
  • 8
  • 9
Kharonos
  • 17
  • 8
  • I don't see an element with the class `box`. So the method `document.getElementsByClassName("box")` always returns an empty array. – JSON Derulo Sep 01 '17 at 16:11
  • Possible duplicate of [What do querySelectorAll, getElementsByClassName and other getElementsBy\* methods return?](https://stackoverflow.com/questions/10693845/what-do-queryselectorall-getelementsbyclassname-and-other-getelementsby-method) – Andrew Li Sep 01 '17 at 16:12
  • Could `document.getElementByClassName()` reference the class instantiated inside the JS rather than HTML? @D.Simon – Kharonos Sep 01 '17 at 16:14
  • `document.getElementsByClassName("box")` looks for HTML elements with the given class. It's not possible to find JavaScript `classes` since JS has no real classes. – JSON Derulo Sep 01 '17 at 16:18
  • I understand now, although how would I reference the elements of the box class without making a class in the HTML? – Kharonos Sep 01 '17 at 16:23

1 Answers1

0

This body of your loop is not accessing the index. Also, the .length you're using is from the box function instead of the boxelem collection.

This:

for (var z = 0; z < box.length; z++) 
{
  boxelem.addEventListener("mouse", mPos, false);
}

should be this:

for (var z = 0; z < boxelem.length; z++) 
{
  boxelem[z].addEventListener("mouse", mPos, false);
}

As D Simon pointed out below, boxelem is undefined because you're not populating that variable until after the DOM loads. You should be sure to fetch those items before trying to use that variable.


If you move all the code to window.onload, it should work. Note that window.onload doesn't run until all resources are loaded. You may want to use a different event that fires sooner, but that's another topic.

//Startup Code
window.onload = function(e) {
    var canvas = document.getElementById("c");
    var ctx = canvas.getContext("2d");
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    var box = [new box(10, 20, "cyan"), new box(299, 40, "red"), new box(90, 50,
      "black"), new box(29, 20, "turquoise")];
    var boxelem = document.getElementsByClassName("box");
    noscroll();
    update();

    //Physic Clock (For real-time physics)
    var clock = {
        lasttick: 0,
        tick: function() {
          var td = performance.now() - this.lasttick;
          this.lasttick = performance.now();
          return td / 1000;
        },
        reset: function() {

        }
      }

    //Box objects be created here (Box Class)
    var box = function(x, y, color) {
      // ...implementation...
    }

    //Get mouse position if over a box
    var pageX = 0;
    var pageY = 0;
    for (var z = 0; z < boxelem.length; z++) {
      boxelem[z].addEventListener("mouse", mPos, false);
    }
}
spanky
  • 2,768
  • 8
  • 9
  • You're right. But the actual issue is that `boxelem` is undefined. – JSON Derulo Sep 01 '17 at 16:15
  • 1
    @D.Simon: Thanks, I added a note regarding that too. – spanky Sep 01 '17 at 16:17
  • This would mean moving the fetch statement before the window.onload function, correct? – Kharonos Sep 01 '17 at 16:21
  • @KyleMyott: If you do that, and if the script is located at the top of the page, then it will return an empty collection. You could move all the code inside the `window.onload`, or another event that runs when the page loads – spanky Sep 01 '17 at 16:23