What is the best way to arrange images in a 3 by 3 grid, beginning at position 0, using JavaScript to control navigation through button clicks?

When I click on button 1, it starts at image 1 because the counter is set to 0. Clicking on button 2 takes me to image 4 with a counter value of 3, while clicking on button 3 leads to image 7 with a counter value of 6.

The process should also work in reverse - starting from image 7 when button 3 is clicked, moving to image 4 when button 2 is clicked, and then back to image 1 when button 1 is clicked.

I have three buttons that correspond to different positions: 0 for button 1, 1 for button 2, and 2 for button 3. The counter increments by 3 each time a higher-positioned button is clicked.

My goal is to ensure that clicking on button 1 sets the counter to 0, clicking on button 2 sets it to 3, and clicking on button 3 sets it to 6. The counter increases by three for higher-positioned buttons and decreases by three for lower-positioned ones.

I am using variables i for button position and img for the current image number comparison. Here's an example using conditional statements:

let counter = 0;

if(i == 0){
    // setting counter to 0
    img[counter].style.background = "#acc2fa";
}else if(i == 1){
    counter = 3;
    img[counter].style.background = "#084cf6";
}else if(i == 2){
    counter = 6;
    img[counter].style.background = "#031a53";
}

I attempted to simplify the code but encountered issues when the condition is equal to 0. Here's what I tried:

if(i != 0 || (img % 3) == 0){
    counter = counter + 3;
}

If you have any suggestions on how I could address this problem, please let me know. Thank you!

Answer №1

const images = document.querySelectorAll(".image");


const onClick = (ev) => {

  // Resetting the background for all images 
  // No need to save counter or previously selected image
  [...images].forEach(img => img.style.background = "none")

  const value = ev.target.dataset.index;

  const index = (+value)*3 - 3;

  images[index].style.background = "#acc2fa";

}
.image-wrapper {
  display: flex;
  gap: 10px;
  padding-block: 10px;
}

.image {
  border: 1px solid black;
  text-align: center;
  width: 20px;
  height: 20px;
}
<div class="image-wrapper">
  
  <div class="image">1</div>
  <div class="image">2</div>
  <div class="image">3</div>
  <div class="image">4</div>
  <div class="image">5</div>
  <div class="image">6</div>
  <div class="image">7</div>
  <div class="image">8</div>
  <div class="image">9</div>
  
</div>


<button data-index="1" onclick="onClick(event)">1</button>
<button data-index="2" onclick="onClick(event)">2</button>
<button data-index="3" onclick="onClick(event)">3</button>

The concept here involves having three buttons where each triggers a different function for click event listeners like "onButton1Click", "onButton2Click", and so on. However, this approach is not scalable when needing to add more buttons in the future. Instead, we can utilize HTML5 data-* attributes to pass button values directly to the click handler.

We can bypass using these attributes by passing the button value inline:

<button onclick="onClick(1)">1</button>
<button onclick="onClick(2)">2</button>
<button onclick="onClick(3)">3</button>

This change also alters the onClick handler:

const onClick = (value) => {

  [...images].forEach(img => img.style.background = "none")

  const index = value * 3 - 3;

  images[index].style.background = "#acc2fa";

}

Regarding this line of code:

const index = (+value)*3 - 3;

The unary plus operator (+value) converts the string to a number. For example, +"3" equals 3. This conversion was necessary since the data-* attribute returned a string value that needed to be treated as a number.

The formula value * 3 - 3 follows a specific pattern based on the example provided:

Value = 1 => 1 * 3 - 3 = 0 (zero index represents the first image)

Value = 2 => 2 * 3 - 3 = 3 (index 3 corresponds to the fourth image)

Value = 3 => 3 * 3 - 3 = 6 (index 6 corresponds to the seventh image)

Answer №2

The code snippet provided above demonstrates how to reset the background of an image that has been clicked. To achieve this, initialize a counter variable by adding let counter = 0; in the application code, within the scope of the click handler but not inside it. Then, within the click handler, clear the background of the current image based on the value of i:

img[counter].style.background = "revert"; // Clear image background

if(i == 0){
    counter = 0; // Resetting `counter` to zero here
    img[counter].style.background = "#acc2fa";
}else if(i == 1){
    counter = 3;
    img[counter].style.background = "#084cf6";
}else if(i == 2){
    counter = 6;
    img[counter].style.background = "#031a53";
}

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

Whenever I try to execute the command `electron .` in the electron-quickstart project, I immediately encounter an error within the

Upon successfully installing Electron, I attempted to run it using "electron" or "electron -v" commands. Unfortunately, I encountered an error while running it on Windows 10. C:\Windows\System32\electron-quick-start>electron -v modu ...

The useEffect hook is able to fetch data even when the state stored in the dependency array remains constant

I have been working on developing a quiz page that utilizes the useEffect hook to fetch data. The data retrieved includes the question as well as multiple-choice options. There is a button labeled Check Answer which, when clicked, reveals the user's f ...

Error 500 occurred when attempting to access an external PHP file

I am currently utilizing WP Web Scraper version 3.2. When I place the shortcode or template tag (php code) directly into my page, the plugin functions correctly and displays the values. However, when I attempt to include the template tag in an external php ...

"Utilizing ng-select with ng-model: A Step-by-Step Guide

Currently, I am working on a code that involves using ng-repeat to loop through options. My goal is to utilize ng-select to choose a value based on a specific condition. However, according to the AngularJS documentation: ngSelected does not interact wit ...

I'm having trouble getting my innerHTML command to update anything on the webpage, and the reason is eluding me

Below is the code snippet provided: <div id="js"><button onclick="document.getElementById('js').innerHTML=('<form> <input type=text name=tick1></input> <input type=text name=tick2></input> ...

An elegant approach to converting a JavaScript object containing key-value pairs into an array of objects, each with a single key-value pair

Essentially, I have an enum that represents different statuses status = {1: "new", 2: "working" ... } and my goal is to transform it into something like status = [{1: "new"}, {2: "working"} ...] in a way that is cl ...

What is the best way to ensure my php variable is easily accessed?

Recently, I've been working on implementing a timer and came across the idea in a post on Stack Overflow. <?php if(($_SERVER['REQUEST_METHOD'] === 'POST') && !empty($_POST['username'])) { //secondsDif ...

XML powered jQuery menu

Admittedly, I have not yet used XML with jQuery. Below is a snippet of the XML: <folder title="Home"> <item title="Welcome" /> <folder title="My Photos"> <folder title="Holiday"> <item title="Photo 1" /> ...

Sending AJAX data from VIEW to CONTROLLER in PHP (MVC) using AJAX: A step-by-step guide

I have a page at http://visiting/blog. The Controller contains two methods: action_index and add_index. When Action_index() executes, it returns pages with indexes. On the other hand, Add_index() invokes a model's method called add_data(), which inse ...

What is the best way to manage a custom child event that is triggered using this.$emit in a parent component, specifically within the <script> section of the .vue file?

In our project, we're utilizing vue and typescript, which means that our .vue files are structured very similarly to the layout outlined in this blogpost. One of our child components is emitting a custom event called changeType. I'd like to trig ...

New messages are revealed as the chat box scrolls down

Whenever a user opens the chatbox or types a message, I want the scroll bar to automatically move down to show the most recent messages. I came across a solution that seems like it will do the trick: The issue is that despite implementing the provided cod ...

Translating coordinates into their corresponding location on the chart

I'm currently working with a dataset containing information about an area in Western Europe. I am trying to convert coordinates into values within this table, facing a challenge similar to the one described in this query. However, I lack experience in ...

What solutions are available to resolve the routing problem in React.js?

On my fourth day working with Node and React.js, I am creating a custom offline search function for Docusaurus 2. I've built a JSON index and implemented a search function using elasticlunr. My goal is to redirect to a separate results page, but I&apo ...

Pop-up notification badge using AJAX technology

Is there a way to implement a notification number badge using Ajax, similar to what Facebook does? I can't provide an image here, but most people are probably familiar with the concept. It's like when you sign into Facebook and see a small number ...

Automatically insert content into a div following the execution of an AJAX delete function using jQuery

I've been working on a feature to display an auto-populated message in the results div when a user deletes the last item from their favorites list, indicating that it is empty. However, I've hit a roadblock and can't seem to make it work. H ...

What is the fallback mechanism in Astro js when the cache is unavailable?

When the cache is not accessible in Next.js, the page will be server-side rendered and displayed using either the true or blocking fallback approach. I am curious about the approach taken by Astro.js in this situation. I am planning to develop a dynamic b ...

The concept of CSS "preload" animation

When working with CSS, I encountered an issue with lag while loading 24 different mask images for a transition effect. To address this, I tried using a div called "preload" to cache the images and prevent lag on playback: <div class='trans' s ...

Generating variables dynamically within a React Native component

In my React Native component, I need to create a variable that will be used multiple times. Each instance of this component should have a different variable name for reference. <View ref={view => { shapeView = view; }} onLayout={({ nativeE ...

Utilize jQuery's animate method to scroll to the top after toggling a class in Vue

I am in the process of developing a FAQ page using vue.js Here is what I have implemented so far: <li v-for="i in items | searchFor searchString" v-on:click="toggleCollapse(i)" :class="{ collapsed: i.collapse, expanded: !i.collapse }" > <p> ...

Difficulty encountered in closing div by clicking the background with the help of jquery

I am facing a challenge with properly closing a div container and restoring it to its original state when I click outside of it. Despite trying various solutions from stackoverflow and extensive internet research, I have been unable to find or come up with ...