The unpredictable number is malfunctioning and is only showing up on the initial element

I'm facing an issue with my code. The scenario is, upon clicking the first door, an image opens based on a random number condition; for example, 1 equals an empty door and 2 equals finding a person behind it.

Now, when I click on the second or third door, the previously opened door should revert to its original image, but currently, only the first door is functioning as expected.

To address this problem, I believe adding ".is-selected" might be necessary, but I am unsure about its implementation.

Instead of utilizing HTML, I aim to accomplish this using JavaScript.

const doorTarget = document.querySelector(".door-track");
const doorClick = Array.from(doorTarget.children);

const door = true;

doorClick.forEach(function (test) {
  test.addEventListener("click", function () {
    if (door) {
      const doorRandom = Math.floor(Math.random() * 3) + 1;
  
      console.log(doorRandom);

      if (doorRandom === 1) {
        document.querySelector(".test1").src = "images/friends.png";
      } else {
        document.querySelector(".test1").src = "images/empty-room.png";

      }
    }
  })
})
<div class="door-wrapper">
    <div class=" door-track-container">
      <ul class="door-track">
        <li class="door-number">
          <a href="#"><img class="test1 is-selected" src="images/door.png"></a>
        </li>
        <li class="door-number">
          <a href="#"><img class="test1" src="images/door.png"></a>
        </li>
        <li class="door-number">
          <a href="#"><img class="test1" src="images/door.png"></a>
        </li>
      </ul>
    </div>

  </div>

Answer №1

Mastering Event Delegation

Implement an eventListener() on the parent list element (<ol>, <ul>, etc.) and set conditions so that only specific child elements like <img>s can respond to the defined event (e.g. click, mouseover, etc). Utilize the Event Object by accessing:

  • event.target always refers to the triggering element of the event (e.g. clicked <img>, mouseover <div>, etc.)

  • event.currentTarget represents the element with the attached eventListener().

 <ol id='list'>...</ol>
 document.querySelector('#list').addEventListener('click', function(event) {...

If using <a> tags as buttons and wanting to prevent their default behavior, adjust the markup as follows:

  <a href="#/"></a>

Adding a forward slash should resolve this: /

Demo

The demo contains detailed explanations in the comments.

// This will be event.currentTarget
const doorTarget = document.querySelector(".door-track");
// Gather all img.test1 into a NodeList
const doors = document.querySelectorAll('.test1');

// Remember to always pass the event object
doorTarget.addEventListener("click", function(event) {
  // Set all img.src to default
  doors.forEach(function(door) {
    door.src = "https://placeimg.com/160/90/nature";
  });

  // Check if the clicked element is NOT the list itself... 
  if (event.target !== event.currentTarget) {
    // Verify that the clicked element's class is .test1
    if (event.target.className === "test1") {
      // Generate a random number between 1 and 3
      const doorRandom = Math.floor(Math.random() * 3) + 1;
      // If the number is 1...
      if (doorRandom === 1) {
        // Modify the src of the clicked image to a person image
        event.target.src = "https://placeimg.com/160/90/people";
      } else {
        // Otherwise change the clicked image to a tech image
        event.target.src = "https://placeimg.com/160/90/tech";
      }
    }
  }
});
ul {
  display: flex;
  list-style: none;
}
<div class="door-wrapper">
  <div class=" door-track-container">
    <ul class="door-track">
      <li class="door-number">
        <a href="#/"><img class="test1" src="https://placeimg.com/160/90/nature"></a>
      </li>
      <li class="door-number">
        <a href="#/"><img class="test1" src="https://placeimg.com/160/90/nature"></a>
      </li>
      <li class="door-number">
        <a href="#/"><img class="test1" src="https://placeimg.com/160/90/nature"></a>
      </li>
    </ul>
  </div>

</div>

Answer №2

Here is the code formatted as per your request, please review the instructions

const doorTarget = document.querySelector(".door-track");
const doorClick = Array.from(doorTarget.children);

const door = true;

doorClick.forEach(function (test) {
  let t= test;
  test.addEventListener("click", function () {
    // reset all selected classes, remove this if not needed I am unsure if you want it
    doorClick.forEach((item)=> item.querySelector("img").classList.remove("is-selected")) 
    
    if (door) {
      const doorRandom = Math.floor(Math.random() * 3) + 1;
      
      var img = t.querySelector("img");
      
      console.log(doorRandom);
      // add class selected to the image
      img.classList.add("is-selected")
      // change the src or whatever of the image
      if (doorRandom === 1) {
        img.src = "images/friends.png";
      } else {
        img.src = "images/empty-room.png";

     }
      
   }
 })
})
.is-selected{
border:1px solid red;
}
<div class="door-wrapper">
    <div class=" door-track-container">
      <ul class="door-track">
        <li class="door-number">
          <a href="#"><img class="test1" src="images/door.png"></a>
        </li>
        <li class="door-number">
          <a href="#"><img class="test1" src="images/door.png"></a>
        </li>
        <li class="door-number">
          <a href="#"><img class="test1" src="images/door.png"></a>
        </li>
      </ul>
    </div>

  </div>

Answer №3

If you want to toggle a class, you can do so by using the following JavaScript:

document.querySelector(".test1").classList.toggle("is-selected");

This will add the class if it's not already present, and remove it if it is.

Additionally, to remove a class specifically, you can use:

document.querySelector(".test1").classList.remove("is-selected");

Don't forget that in order to target multiple elements, you should utilize querySelectorAll() and iterate through the HTML Collection accordingly.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Allowing input fields to accept decimal numbers

I am currently facing an issue with an input field that is set to type=number, which does not allow for decimal numbers. However, I need to enable users to input decimal numbers but haven't been able to make it work. Would using regex be a possible so ...

Developing a digital sound system using JavaScript

I am currently in the process of developing a music player. Below is my HTML code: <div id="main"> <div id="list" draggable="true"> </div> <div id="player"> <div id="buttons"> < ...

Sharing Data via JSON for a Pop-Up Display

section of a website, there is a button that, when clicked, triggers a small pop-up. The data being posted appears to be in JSON format as seen in HttpFox. Personally, I have little knowledge of javascript and AJAX. When the specific button is clicked, i ...

Reasons for storing `https.get()` inside a request constant in Node.js

When using simple javascript, any content written to the console is displayed on the console itself. An example would be as follows: const name = "david"; This will display david in the console. However, in Node.js, if I store a request in a const varia ...

What is the method to extract a single user instead of a group of users?

I am attempting to transition from a list of users to displaying the profile of a single user on a separate page. My goal is to achieve this using routerLink and passing the specific user's id to the next page. Although the routing is functioning co ...

What are the steps to create a connect4 board featuring rounded corners and curved sides?

How can I create a Connect4 board with the exact styles and properties shown in the image? I want to achieve the curved sides effect as displayed. Can this be done using only HTML elements, or is there an easy SVG solution available? Here is my current co ...

Advancing through time with progress

How can I display a progress indicator for events in fullcalendar based on the current time by changing their color dynamically in HTML? Thank you for your help! ...

What method does AngularJS use to distinguish between these two properties?

I grasp the concept that ng-model generates a property that corresponds to the {{name}}. How does AngularJS distinguish between the {{name}} derived from the ng-model and the {{name}} originating from the ng-repeat/ng-init? <section class="section"> ...

Struggling to differentiate between the various CSS elements on a webpage and pinpointing the correct CSS for use

I have been attempting to replicate the "card-deck" layout that showcases eight cards on a specific webpage. After successfully copying the HTML structure by inspecting the card-deck class, I am now facing the challenge of locating the corresponding CSS ...

Select the even-numbered occurrences of a specific class in CSS using the nth-child()

I am encountering an issue with my table layout. The structure is similar to the following: <tbody> <tr class="row">...</tr> <tr class="row--expanded">...</tr> <tr class="row">...</ ...

Insert a percentage sign into a right-aligned text box

I am trying to figure out how to permanently display a % symbol at the far right side of a textbox that shows a percentage. Can anyone help me with this? ...

Issue with Webpack: file-loader failing to load SVG files dynamically in HTML

Configuration in package.json: { "name": "webpackTutorial", ... "devDependencies": { "bootstrap": "^4.3.1", ... "webpack-merge": "^4.2.2" } } Webpack Configuration in webpack.common.js: var HtmlWebpackPlugin = ...

Automatically generate the first user on the Parse Server system

Is it feasible to programmatically create a User on Parse server without the need for sign up? More information can be found at https://github.com/parse-community/parse-server We attempted this using cloud code. var user = Parse.User(); user.setUserna ...

Is your jQuery search scope correctly restricted?

Upon coming across this code snippet, I can't help but wonder if it's merely limiting the scope or selecting both elements simultaneously. container = jQuery("#test", parent.document); jQuery("param[name=scale]", another.object) Would anyone b ...

Using JSON.parse on the output of BsonDocument.ToJson results in an error

When fetching information from MongoDB and sending it to the client, I encountered a dilemma: var retrievedBsonDocument = ... retrieve data from database ... var dtoObject = new Dto { MyBson = retrievedBsonDocument.ToJson() }; While trying to parse the M ...

Using JQuery to make a GET request and receive a JSON response, then selecting particular objects

I am in the process of developing a straightforward web application. The concept involves users inputting a license plate number, which will then connect to an OpenData API based on Socrata that houses information about all registered vehicles in my countr ...

Encountering OAuthCallbackError while using Next.js Auth

I am currently working on developing an app for analyzing Spotify data. However, I am encountering an error related to authorization. Below is the content of my auth file: Here is the code snippet: import NextAuth from "next-auth"; import Spotif ...

Refreshing a webpage post initial loading using Next.js

Having trouble with my checkout route ""./checkout"" that displays embedded elements from Xola. The issue arises when using client-side routing as the checkout page requires a manual refresh to load correctly and show the Xola elements on the DOM ...

Controlling Javascript events

Currently, I am working on implementing an in-place editor using jQuery. The functionality is such that when you click on the text you wish to edit, it will replace the content with an input field, specifically a select tag. Everything seems to be functio ...

How to visually deactivate a flat button ( <input type="button"> ) programmatically with JavaScript

I am facing an issue with my buttons. I have one regular button and another flat button created using input elements. After every click, I want to disable the buttons for 5 seconds. The disable function is working properly for the normal button, but for th ...