Why is my onclick property not working in the Choredoor poject?

I was attempting this project but got stuck at the 10th exercise because my first onclick property that is meant to change the first door doesn’t work and i can’t seem to figure out why it’s not woking, since my code seems correct.

Here’s my HTML, CSS and JavaScript codes respectively.

HTML

<!DOCTYPE html>
<html>
  <head>
    <title>Chore Door!</title>
    <link href="./style.css" rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/css?family=Work+Sans" rel="stylesheet" type="text/css">
  </head>

  <body>
    <div class="door-row"><img id="door1" src="https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg"></div>

    <script type="text/javascipt" src="script.js"></script>
  </body>
</html>

CSS

body {
  background-color: #010165;
  margin: 0px;
}

#door1 {
  cursor: pointer;
}

JavaScript

let doorImage1 = document.getElementById("door1");
let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";

doorImage1.onclick = () => {
  doorImage1 = botDoorPath;
};

I also followed the video walkthrough and did exactly what instructor did upto the 10th number but it still didn’t work.

Can anyone kindly tell me what might be wrong.
Thanks.

Should this have a .src attribute?

1 Like

Consider what the above actually does.
doorImage1 was assigned to document.getElementById("door1").
doorImage1 is a variable. Your code assigns a new value to the variable. It no longer refers to the html element. It instead is assigned to a path. To keep from accidentally reassigning values to variables that are assigned to DOM elements, I’d consider using const instead of let.

I also tried the src attribute and yet it didn’t work.

By the way, why do we have to append the src attribute to doorImages1?

Should it not be a case of simply re-assigning a previously assigned variable to a new variable?

Appending a src attribute here is a bit unfamiliar.

Kindly explain in a bit more detail why this is so.

Thanks.

You use the variable, doorImage1, to keep from having to type document.getElementById("door1") every time you want to refer to the DOM element with the id door1. It not only saves typing, it is more effiecient than repeatedly calling the .getElementById() method. What makes door1 look like a closed door in the first place? It’s here:

The src attribute of the <img> element determines what the image displays. As @mtf pointed out, that is what needs to change.

You can do that like this:

doorImage1.src = botDoorPath;
1 Like

I have figured out the solution to the problem.

The problem was with my type attribute. It was a typo, I had type=“text/javascipt”, instead of type=“text/javascript”.

I omitted the “r” in the javascript.

Now if i write the codes with the src attribute, it all works fine.

But the remaining trouble is knowing why we have to use the src attribute in this case.

Why are we appending an src to our new variable instead of writing only our new variable and simply assigning it to the other already assigned variable?

Thanks.

It’s important to note what we have assigned to doorImage1… An HTML element node. Elements are objects, and objects have attributes. If the node is IMG then it will have global attributes such as id and src and alt.

1 Like

What you are describing is equivalent to this:

const cat = {
  name: "Morris",
  color: "gray"
}
let animal = cat; //animal is assigned to the cat object
console.log('animal:', animal); //confirmation that animal is assigned to the cat object
console.log('cat:', cat); //when we log cat, we see that animal and cat refer to the same object
//I want to change the color from gray to white
animal.color = "white"; 
console.log('animal with new color:', animal); //the new color has been successfully assigned
console.log('cat with new color:', cat); //the change affected the original object
//you are suggesting this should work:
animal = "orange"; //animal is no longer assigned to the cat object
console.log('animal:', animal); //it is now assigned to the string literal "orange"
console.log('cat:', cat); //cat is still intact, and its attributes remain unchanged

Output:

animal: { name: ‘Morris’, color: ‘gray’ }
cat: { name: ‘Morris’, color: ‘gray’ }
animal with new color: { name: ‘Morris’, color: ‘white’ }
cat with new color: { name: ‘Morris’, color: ‘white’ }
animal: orange
cat: { name: ‘Morris’, color: ‘white’ }

Now the point that @midlindner is making is that botDoorPath is a string object, an URL, to be exact. When we assign that directly to doorImage1 it replaces what it was originally, a cached DOM node, with a plain string. That object does not have the same attributes our IMG element has, so it breaks the program.

const doorImage1 = document.getElementById('door1');

Having cached an element node, we can access all its attributes and text nodes for either polling (getting) or for setting. This cached node remains in memory for the full session so that we can exact changes to the attributes as often as we wish. By including a const declaration we prevent something like this,

doorImage1 = botDoorPath

since JS won’t allow reassignment of a constant. However, it will allow us to still mutate the attributes of that DOM node object.

doorImage1.src = botDoorPath

Starting to make a little more sense?

1 Like

So in addition to having properties and methods, objects can also have attributes such as Id, src, alt and class?

is this correct?

Not quite… :slight_smile: I wish a little more explanation will come.

In broadest terms, properties are attributes and vice versa. Methods are either one, in kind. HTML elements are anything but plain objects, though. They are very complex DOM objects, and have a gazillion properties and methods. The attributes we use in markup are just a smidgen. Add to that the style sheet. Further, add the event listeners. Then add all the other internal stuff.

I’m still not clear on why src was attached to a variable rather than doing a normal variable-to-variable assignment.

In JavaScript, object attributes are called properties.

object.property

That is dot notation that references the property attribute of object.

doorImage1

is an object, not a string. We would not assign a string directly to it, else we lose the object, as described earlier. The assignment goes to the property that is set out for that purpose, the src attribute.

doorImage1.src = "..."

After that statement has executed, we can inspect the id="door1" element and see that the URL has indeed changed to the one we just set it to, via the DOM.

1 Like

Okay! This is beginning to make a little sense.

So this is like saying;

doorImage1 = {   // this an object
  src: "somethig"    // this is the property of the object
}

Then finally we decide to reassign the property of the object to another thing (URL)?

doorImage1.src = "URL" ? // we have reassigned the src property of the object to “URL”

Now, how can we quickly recognize an object (especially one that is not explicitly declared as an object, as in my example above) when we see one, to know what kind of properties or attributes are available to them?

We are the ones defining the objects. There is nothing to recognize. Put yourself in the driver’s seat.


It is important to note that the object doorImage1 refers to is very complex. It has a huge collection of attributes our program will likely never use but that are used behind the scenes.

A bit mysterious, I must say.

So, these huge collection of attributes that are behind the scene, are they equality available to ordinary variable?

They are many and varied, but yes, some of them are assignable to a working variable. Animation uses screen position, screen dimensions, mouse and keyboard events, and so on. They all get a lot of their information from the DOM node where said event takes place.

My .onclick code was working when the doorImage.src’s were set to the path variables, but when I reset them to the openDoor variable, the code stopped working. I’ve combed through everything, even restarted the project to see where I went wrong and watched the video walkthrough. My code is practically identical up until this step(45) but my code isn’t working.

What am I missing??

let doorImage1 = document.getElementById('door1');
let doorImage2 = document.getElementById('door2');
let doorImage3 = document.getElementById('door3');
let closedDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/closed_door.svg";
let botDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/robot.svg";
let beachDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/beach.svg";
let spaceDoorPath = "https://s3.amazonaws.com/codecademy-content/projects/chore-door/images/space.svg";
let numClosedDoors = 3;
let openDoor1;
let openDoor2;
let openDoor3;

const randomChoreDoorGenerator = () => {
  const choreDoor = Math.floor(Math.random() * numClosedDoors);
  if (choreDoor === 0){
    openDoor1 = botDoorPath;
    openDoor2 = beachDoorPath;
    openDoor3 = spaceDoorPath;
  }; else if (choreDoor === 1){
    openDoor2 = botDoorPath;
    openDoor3 = beachDoorPath;
    openDoor1 = spaceDoorPath;
  }; else {
    openDoor3 = botDoorPath;
    openDoor1 = beachDoorPath;
    openDoor2 = spaceDoorPath;
  };
};

doorImage1.onclick = () => {
  if(!isClicked(doorImage1)) {
    doorImage1.src=openDoor1;
    playDoor();
  };
};

doorImage2.onclick = () => {
  if(!isClicked(doorImage2)){
    doorImage2.src=openDoor2;
    playDoor();
  };
};

doorImage3.onclick = () => {
  if(!isClicked(doorImage3)){
    doorImage3.src=openDoor3;
    playDoor();
  };
};

The semi-colons are breaking the if statement.