Update the picture and assign a class for the currently selected menu or button

I am currently working on creating interactive buttons that change an image when hovered over and clicked. The active button should have a specific class applied to it, which will be removed once another button is clicked.

However, I have encountered some issues with the implementation.

jQuery(document).ready(function($) {
  $('.button-one').on('click mouseover', function() {
    $('#change-image').attr('src', '/image-1.png');
    $('.button-one').removeClass('btn-active');
    $(this).addClass('btn-active');
  });
  
  $('.button-two').on('click mouseover', function() {
    $('#change-image').attr('src', '/image-2.png');
    $('.button-one').removeClass('btn-active');
    $(this).addClass('btn-active');
  });
  
  $('.button-three').on('click mouseover', function() {
    $('#change-image').attr('src', '/image-3.png');
    $('.button-one').removeClass('btn-active');
    $(this).addClass('btn-active');
  });
});
.button-container ul {
  display: flex;
}

.btn li a {
  padding: 9px 18px;
  margin-right: 1em;
  background: #8a8c8e;
  color: #ffffff;
  font-weight: bold;
  font-size: 18px;
  border: none;
  display: block;
}

.btn li a:hover {
  background: #ee2e24;
  color: #ffffff;
  display: block;
}

.btn li a.btn-active {
  background: #ee2e24;
  color: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="image-container"><img id="change-image" src="/image-1.png" alt="Image 1" /></div>
<div class="button-container">
  <ul class="btn">
    <li><a class="button-one">Image 1</a></li>
    <li><a class="button-two">Image 2</a></li>
    <li><a class="button-three">Image 3</a></li>
  </ul>
</div>

Answer №1

The issue arises from the fact that you are not removing the btn-active class from all elements in every repeated hover/click function.

To address this issue and enhance the code, you can assign a common class to the button elements to categorize them based on their behavior. By doing so, you can utilize a single event handler to update the img source depending on the triggering element. To store the image path information, you can utilize a data attribute on the buttons.

Adopting this approach ensures that the JavaScript will handle an unlimited number of buttons without necessitating the creation of numerous new functions or event handlers.

jQuery($ => {
  $('.button').on('click mouseover', e => {
    let $btn = $(e.target);
    $('#change-image').attr('src', $btn.data('imgsrc'));
    $('.button').removeClass('btn-active');
    $btn.addClass('btn-active');
  });
});
.button-container ul {
  display: flex;
}

.btn li a {
  padding: 9px 18px;
  margin-right: 1em;
  background: #8a8c8e;
  color: #ffffff;
  font-weight: bold;
  font-size: 18px;
  border: none;
  display: block;
}

.btn li a:hover {
  background: #ee2e24;
  color: #ffffff;
  display: block;
}

.btn li a.btn-active {
  background: #ee2e24;
  color: #ffffff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="image-container"><img id="change-image" src="https://via.placeholder.com/100x100.png?text=Image 1" alt="Image" /></div>
<div class="button-container">
  <ul class="btn">
    <li><a class="button btn-active" data-imgsrc="https://via.placeholder.com/100x100.png?text=Image 1">Image 1</a></li>
    <li><a class="button" data-imgsrc="https://via.placeholder.com/100x100.png?text=Image 2">Image 2</a></li>
    <li><a class="button" data-imgsrc="https://via.placeholder.com/100x100.png?text=Image 3">Image 3</a></li>
  </ul>
</div>

Answer №2

Attempting to achieve this using vanilla JavaScript. I implemented onclick events on each button that send the class name as an argument, which is then compared to add or remove the "btn-active" class accordingly.

const toggleActive = (className) => {
    let buttons = [];
    buttons[0] = document.querySelector(".button-one"); 
    buttons[1] = document.querySelector(".button-two");
    buttons[2] = document.querySelector(".button-three");

    for(let i=0; i<buttons.length; i++){
        if(buttons[i].classList.contains(className)){
            buttons[i].classList.add('btn-active');
        }else{
            buttons[i].classList.remove('btn-active');
        }
    }
}
.button-container ul {
    display: flex;
}
.btn li a {
    padding: 9px 18px;
    margin-right: 1em;
    background: #8a8c8e;
    color: #ffffff;
    font-weight: bold;
    font-size: 18px;
    border: none;
    display: block;
}
.btn li a:hover {
    background: #ee2e24;
    color: #ffffff;
    display: block;
}

.btn li a.btn-active {
    background: #ee2e24;
    color: #ffffff;
}
<div class="button-container">
    <ul class="btn">
    <li><a class="button-one" onclick="toggleActive(this.getAttribute('class'))">Image 1</a></li>
    <li><a class="button-two" onclick="toggleActive(this.getAttribute('class'))">Image 2</a></li>
    <li><a class="button-three" onclick="toggleActive(this.getAttribute('class'))">Image 3</a></li>
    </ul>
</div>

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

What can be done to stop the event handler from executing?

My goal is to verify a user's authentication every time they click on a button. If the user happens to be logged out and tries to click on a button, they should be redirected back to the home page. The issue I'm facing is that the code after the ...

One creative method for iterating through an array of objects and making modifications

Is there a more efficient way to achieve the same outcome? Brief Description: routes = [ { name: 'vehicle', activated: true}, { name: 'userassignment', activated: true}, { name: 'relations', activated: true}, { name: &apos ...

Using Jquery to Retrieve the Attribute Value from an HTML Element

I am currently developing an interactive online quiz application that is organized by chapters, with each chapter having its own quiz. Users can navigate through the chapters via a menu and start quizzes by clicking on a button after loading the chapter co ...

Sending a POST request from AngularJS to the SLIM Framework appears to be causing issues

Greetings! I am facing an issue with my AngularJS http.post() request to the Slim PHP framework. 'use strict'; soup.factory('loginService',function($http){ return { login:function(user){ console ...

Overlap and cover additional elements within a DIV

I am looking to create a versatile function that can effortlessly overlay various elements such as selects, textfields, inputs, divs, tables, and more with a partially transparent div matching their exact height and width. I have managed to obtain the pos ...

Requesting identification results in no response

I am facing an issue with my contact form validation script, which uses Bootstrap 3.2 and the securimage captcha add-on. The IDs of my input and textarea elements are returning as 'undefined', making it impossible to display error messages when n ...

Restrict the quantity of items retrieved from an AJAX response

An AJAX call has returned a response consisting of a list of <a> elements: <a href="/1/">One</a> <a href="/2/">Two</a> <a href="/3/">Three</a> I am looking to select only the first n a elements from this response ...

Using CSS to target specific attributes on standalone elements

Ever since I stumbled upon AMCSS, I have been utilizing standalone attribute selectors. Recently, I made the switch from Compass to cssnext, only to discover that syntax highlighting appears to be malfunctioning in Atom and other platforms where I tested i ...

Is there a way to dynamically load a file on scroll using JavaScript specifically on the element <ngx-monaco-diff-editor>?

I've been attempting this task for over a week now in Angular without success. Would someone be able to provide guidance? The onContainerScroll() function isn't being triggered, and I'm considering using JavaScript instead. How can I achiev ...

Tips on how to properly display the date in v-Calendar

I'm struggling to format the date output from the v-calendar. Currently, it appears like: Fri Jul 31 2020 00:00:00 GMT+0200 (utc summertime) However, I would like it to display as 2020-07-28. I have searched through the documentation but couldn' ...

My Schema contains a Sub Schema that I need to make specific updates to

This is the structure of my schema: const mongoose = require('mongoose') const MaterialListSchema = new mongoose.Schema({ nomenclature:{ type: String, required: true }, national: { type: String, requir ...

Issue with retrieving data from MySQL database using PHP in Chart.js

I am currently facing an issue while trying to populate a chart using the ChartJS plugin with data from my MySQL database. I keep encountering the error message: mysqli_fetch_assoc(): Couldn't fetch mysqli_result in ... Despite using json_encode, ...

Ensure that the child div with a background color extends all the way to the bottom of its parent div

Having trouble getting two divs inside another one to stretch to the bottom without cutting off content? The goal is for both divs to adjust in height based on whichever one is longer, filling the outer div completely. When the left div (menu) is longer t ...

Create a left-aligned div that spans the entire width of the screen, adjusting its width based on the screen size and positioning it slightly

I have a parent container with two child elements inside. I want the first child to align to the left side and the second child to align to the right side, but not starting from the exact center point. They should be positioned slightly off-center by -100p ...

Increase the space around the text while zooming out to create a larger surrounding area

When zooming out, I would like the black area surrounding my text to expand instead of a white area appearing to the right. I attempted setting width:auto; on both div elements, but the black part disappeared completely. Below is my HTML code: <!DOCTYP ...

Removing a Button from a Form Using JavaScript

Here is a snippet of my HTML code: <form id="form"> <input id="deleteNumber" name="del" type="hidden" /> <input id="addAddress" name="addAddress" type="hidden" /> ... ... ... <a href="javascript:deleteAddress();" class="deleteItem" ...

Can a Jquery *compiler* be developed?

Upon encountering this informative question, the idea of creating a jQuery compiler crossed my mind. The concept was to design a tool that could translate jQuery code into raw JavaScript code for execution. In my imagination, the process of executing a bl ...

WordPress site experiencing issues with sub-menus disappearing following recent upgrade

I'm currently investigating a problem on a WordPress website where sub-menus are not showing up after upgrading to WP 3.9.1. The website, which can be found here, is using the Zeus theme (v. 1.1.0) and it seems that the behavior of the sub-menus is co ...

Limiting the options available in dropdown menus

In my HTML code, I have two drop-down lists that look like this: <select name="from" id="abs-from-1"> <option value="1">One</option> <option value="2">Two</option> <option value="3">Three</option> ...

Modify the custom attribute value assigned to an image

I am facing an issue with a document containing two thumbnail images (front and rear, like a bank check). I have successfully implemented zoom functionality on the front image by displaying a square part of the original large image. However, when I click o ...