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

Transferring API information into a nested array and displaying the outcome

Currently, I am utilizing an API to fetch an array of users from which I sort them and collect those with a personalTrainerId matching my userId into an array. The ultimate goal is to render these users as cards on the interface. The desired format for th ...

React callbacks involve the interaction between three different components

Currently, I am working with 3 distinct components: -The friendsPage component contains a list of friends and invitations to friends -The friendComponent displays detailed information about a friend along with possible actions (which are handled in the t ...

Struggling to pass two objects as props and have them be equated to one another

I have a scenario where I am passing a worker object as a prop to the view.vue field. In the mounted method of the component, I am trying to assign this worker object to the manager object. However, when I use the assignment `this.manager = this.worker`, i ...

Utilizing a function that changes a UNIX timestamp to a month/day/year layout

I have been working with ExpressJS and am facing a challenge in converting the UNIX format date to mm/dd/yyyy format when retrieving the date value. I attempted to create a function for this conversion, but encountered an issue where my methods cannot be c ...

Visibility of text compromised when placing transparent button inside input field

After adding a clear button inside the input box in Angular, I am facing an issue where the text in the input box is being overlapped and not fully visible. Below you will find detailed information on this problem. HTML Code <ng-template pTemplate=&quo ...

A guide on transferring documents between collections using Mongoose and MongoDB

I have a list of tasks that includes both completed and incomplete items. Additionally, I have two buttons - one for deleting an item (which is functional) and the other for marking an item as done or not. I am struggling with creating a function to move ...

Is there a way to transform individual data into a collective group dataset?

Here is the input data provided: data = [ { name: "John Cena", groupName: "WWE" }, { name: "Nandini", groupName: null }, { name: "Rock", groupName: "WWE" }, { name: "Vinay", groupName: null }, { name: "Rey Mesterio", groupName: "WWE" ...

Unlocking the Chrome performance tool summary using SeleniumDiscovering the Chrome performance tool

I'm looking to utilize the Chrome performance tool for analyzing my website and then extract a summary of the results using Selenium WebDriver in Java. Despite extensive searching, I haven't been able to find a suitable solution yet. To give you ...

Error: npx is unable to locate the module named 'webpack'

I'm currently experimenting with a customized Webpack setup. I recently came across the suggestion to use npx webpack instead of node ./node_modules/webpack/bin/webpack.js. However, I am encountering some difficulties getting it to function as expecte ...

Error: The javascript function is unable to execute because undefined is not recognized as a function

I've been struggling with an error in my "bubble sort" function that I wrote to organize a list of images. Whenever I run the function, I keep getting the message "Uncaught TypeError: undefined is not a function". Can anyone provide some guidance? $j ...

Using Vue.js to increment a value in an array every time a new row is added

In Vue.js, I am attempting to increment an array value when adding a new row. However, I encounter the following error message: You may have an infinite update loop in a component render function. The JavaScript logic looks like this: new Vue({ el: ...

JS Nav Dots are not activating the Active Class

I have been utilizing a code snippet from this source to incorporate a vertical dot navigation feature into a single-page website. The navigation smoothly scrolls to different sections when a link is clicked, with an active highlight on the current section ...

"Want to extend the current date (Y-m-d) by a few days? Here

On my form, there is a date input that I want to automatically set to the date that is 14 days from today. I know how to set the value to today's date, but how can I add 14 days to it? <p>Term:<br> <input type="date" name="term" i ...

I am curious if there is a feature in intro.js that allows for the highlighting of text or images to

I am having trouble getting intro.js to work with Ionic 4 as the highlighted text is not showing up view image here This is how I implemented the code in Angular 7: intro() { let intro = introJs.introJs(); intro.setOptions({ exitOnOverlayClick: false, ...

Is there a way to position the search bar on a new line within the navigation bar when the screen size is at its maximum width for mobile

I have a search bar on my navigation bar, but I am looking to move it to the next line within a maximum width if the screen display is extra small (xs) or for mobile devices. Below is the code snippet: <nav class="navbar navbar-expand-md fixed-top ...

Guidelines for implementing a seamless translation effect with CSS3

CSS: .horizon { position: absolute; top: 380px; width: 1800px; height: 50px; background: url(images/road.png) repeat-x; -webkit-animation-name: prop-600; -webkit-animation-duration: 20s; -webkit-animation-iteration-count: i ...

Tips on removing the red border from a text box within an HTML form with the help of AngularJS

My form has the following appearance: https://i.stack.imgur.com/T3NQW.png Upon clicking the submit button, the textbox fields display a red border due to the required attribute. Afterwards, I aim to click the reset button in order to remove the red bord ...

Creating custom modals for individual elements using PHP

Currently, I am working on a project that involves allowing users to select an item from a list retrieved from a MySQL database. The goal is to have buttons generated based on the selected item, shown below: Here is a trimmed version of my code thus far: ...

An issue occurred with the session being undefined in Node.js Express4

I'm encountering an issue where my session is undefined in new layers even after setting the value within an "if" statement. /*******************************************/ /**/ var express = require('express'), /**/ cookieParse ...

Tips for customizing the appearance of a Link component while it is the active page in Next.js

I'm seeking advice on how to style an anchor component differently when it is active on a page. Here's the code I have so far: import Link from 'next/link'; import styled from 'styled-components'; const NavStyle = styled.nav` ...