Having trouble removing or adding a class to an HTML element?

I have a collection of three colored buttons. My goal is to allow users to select one button at a time, triggering it to be highlighted while the others are unselected. Each button corresponds to an object with a property called isSelected that can be set to true or false. While I am aware that achieving this functionality with jQuery would be straightforward, I am committed to mastering JavaScript objects.

The snippet below contains what I believe to be the pertinent code segments for troubleshooting, excluding any HTML and CSS components. You can access the complete application on CodePen: http://codepen.io/isachenx/pen/LxEOOR

My approach involves toggling the isSelected property between true and false for each button instance. If the value is true, a css class named .selected should be applied in the generated HTML string; otherwise, the class shouldn't be included. On every click event for a list item element, I aim to re-render the respective part of the string...

// Define a constructor function
function Selector(color) {
  this.color = color;
  this.isSelected = false;
}

// Methods for selecting/deselecting list items
Selector.prototype.selectColor = function() {
  this.isSelected = true;
}

Selector.prototype.deselectColor = function() {
  this.isSelected = false;
}

// Render list item as HTML string
Selector.prototype.toHTML = function() {
  let htmlString = "";
  htmlString += '<li id="' + this.color + '" class="' + this.color;
  if (this.isSelected) {
    htmlString += ' selected';
  }
  htmlString += '"></li>';
  return htmlString;
}

// Constructor for rendering all list items
function Controls() {
  this.selectors = [];
}

Controls.prototype.add = function(selector) {
  this.selectors.push(selector);
}

Controls.prototype.renderInElement = function(list) {
  list.innerHTML = '';
  for (let i = 0; i < this.selectors.length; i++) {
    list.innerHTML += this.selectors[i].toHTML();
  }
}

let controls = new Controls();

let red = new Selector('red');
let blue = new Selector('blue');
let yellow = new Selector('yellow');

controls.add(red);
controls.add(blue);
controls.add(yellow);

let controlElement = document.getElementById('controlButtons');
controls.renderInElement(controlElement);

let redButton = document.getElementById('red');
redButton.onclick = function() {
  red.selectColor();
  blue.deselectColor();
  yellow.deselectColor();
  controls.renderInElement(controlElement);
};

let blueButton = document.getElementById('blue');
blueButton.onclick = function() {
  blue.selectColor();
  red.deselectColor();
  yellow.deselectColor();
  controls.renderInElement(controlElement);
};

let yellowButton = document.getElementById('yellow');
yellowButton.onclick = function() {
  yellow.selectColor();
  red.deselectColor();
  blue.deselectColor();
  controls.renderInElement(controlElement);
};

Answer №1

When looking at your code, it seems that a second click on either button is not functioning properly. This issue arises because the onclick event is only set for the first click.

In your toHTML function, you are clearing the existing buttons (specifically on line 33: list.innerHTML = ''), which consequently clears their onclick events as well. You need to re-set them within the toHTML function.

To address this problem, make the following modifications:

Selector.prototype.toHTML = function(){

  // Set the onclick function for color selection
  let onclickStr = 'setOnClick(\'' + this.colour + '\')';

  let htmlString = ""
  htmlString += '<li id="' + this.colour + '" class="' + this.colour
  if (this.isSelected){
    htmlString += ' selected'
  }

  // Make sure to include the update below
  htmlString += '" onclick="' + onclickStr + '"></li>'
  return htmlString
}

Then, enclose your xxxbutton.onclick functions with the following:

function setOnClick(color) {
  let redButton = document.getElementById('red')
  let blueButton = document.getElementById('blue')
  let yellowButton = document.getElementById('yellow')
  if(color==='red'){    
    red.selectColour()
    blue.deselectColour()
    yellow.deselectColour()
  }else if(color==='blue'){
    blue.selectColour()
    red.deselectColour()
    yellow.deselectColour()
  }else{
    yellow.selectColour()
    red.deselectColour()
    blue.deselectColour()
  }
  controls.renderInElement(controlElement)
}

View JSFIDDLE DEMO

Answer №2

Modifying the isSelected property to either true or false does not result in any alterations to the class of the DOM element. If you wish to include or exclude a class:

let item = document.querySelector(itemClass);
item.classList.add('active');
//or to remove a class
item.classList.remove('active');

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

Guide on integrating next-images with rewrite in next.config.js

I'm currently facing a dilemma with my next.config.js file. I've successfully added a proxy to my requests using rewrite, but now I want to incorporate next-images to load svg files as well. However, I'm unsure of how to combine both functio ...

Out of the blue synchronization issues arising from utilizing the nodejs events module

In my code, I am utilizing the Node Events module to execute a function asynchronously. var events = require('events'); var eventEmitter = new events.EventEmitter(); eventEmitter.on('myEvent', f2); function f1(x, y) { console.log( ...

Secure API Calls with Prismic while Keeping Access Tokens Hidden

As I delve into the world of building a Vue.js web app, I find myself faced with the challenge of making calls to my Prismic repository without exposing my access token. The Rest API approach outlined here seems promising, but I'm at a loss on how to ...

Guide on transforming the best.pt model of YOLOv8s into JavaScript

After successfully training a custom dataset on YOLOv8s model using Google Colab, I now have the best.pt file that I want to integrate into a web app via JavaScript. I've come across mentions of TensorFlow.js as a potential solution, but I'm stil ...

Swapping out bullet points for delicious food icons in an unordered list on an HTML page

I am working with the following code snippet: <div id="instructions"> <h3>Get it done</h3> <ol> <li>In a blender add the eggs, chocolate powder, butter, flour, sugar and milk.</li> <li>Then whisk ...

Is there a way to disable logging for MongoDatabase connections?

After starting up my Node.js web server and connecting to the MongoDB database, I noticed that sensitive information including my password is being displayed in the console. This could be a security risk as the console may be publicly accessible on some ho ...

Having difficulty accessing the 'makeCurrent' property of an undefined object in Angular mobile application

I have followed the steps outlined in the Angular mobile toolkit guide found at https://github.com/angular/mobile-toolkit/blob/master/guides/cli-setup.md My Node version is v4.4.3 NPM version is 2.15.1 The issue arises when I run the command $ ng serve, ...

"Positioning an image at the center with Bootstrap

I've been attempting to center an image on my webpage above the footer, but all my efforts have failed. Here is the HTML code I've been using: <div class="center-block"> <img alt="footer" title="footer" class="image-footer" src="./i ...

Incorporating custom CSS and HTML into the link is essential for enhancing the appearance of KnpMenu

I'm working with the KnpMenuBundle and I need to customize a link that has the route 'uri'=>'#'. How can I achieve this? The desired link should be styled like this: <a href="#" class="js-sub-menu-toggle"> &l ...

Discover the Location and Sign Up for Angular2+ Service

I'm currently using the Google Maps API to retrieve a user's geoLocation data, including latitude and longitude. My goal is to pass this information to a web API service in order to receive JSON output of surrounding addresses. I have implemented ...

use ajax to dynamically load a section of the webpage based on filter criteria

I need to implement a search filter using 3 checkboxes. The search results will be displayed in the div with the id=posts_results <div class="checkbox"> <label><input type="checkbox" id="id1" class="typePost" value="En groupe"> ...

Please enter only numerical values using jQuery

Currently, I am facing a slight issue. My goal is to only run the code when the input characters are numbers. This is the snippet of code I have been working with: $(".jq-sales, .jq-variablecosts, .jq-fixedcosts, .jq-additional-sales, .jq-sales-units, .j ...

"Receiving a 404 error when sending a POST request, but getting

When attempting to send a POST request, I encountered a 404 error response from the server. Strangely, when sending a GET request, I received a 200 response. I have experimented with different methods: $.ajax({ type:"POST", url: "script.php", ...

Unable to reference the namespace 'ThemeDefinition' as a valid type within Vuetify

Looking to develop a unique theme for Vuetify v3.0.0-alpha.10 and I'm working with my vuetify.ts plugin file. import "@mdi/font/css/materialdesignicons.css"; import "vuetify/lib/styles/main.sass"; import { createVuetify, ThemeDefinition } from "v ...

Encountered an issue during the Jest test where the error message states 'Cannot call Class constructor Stack without using the keyword 'new''

I have encountered an issue with my Jest test for an AWS CDK configuration import { expect as expectCDK, matchTemplate, MatchStyle } from '@aws-cdk/assert'; import * as cdk from '@aws-cdk/core'; import { KmsMultiregionPrincipalKey } fro ...

UI binder is having difficulty resolving CSS

After creating a search panel for my application using UI binder, I noticed that the desired behavior is not being achieved. Ui.xml <g:HTMLPanel> <c:SimpleContainer> <c:InfoContainerHeader text="{labels.searchFilter}" /> ...

Inability to load a MySQL table using Ajax on the same webpage

I'm facing an issue where I want to load a table from mySql on the same page without getting redirected to another page. The user selects a date range, and upon pressing submit, it should appear in the designated div id tag. However, the functionality ...

AngularJS flexible route parameter

My AngularJS application has routes that can be either: www.website.com/blog/xyz www.website.com/blog/xyz/title/other-params In the second URL, the title parameter is used for readability purposes only and is not mandatory in the URL. Therefore, I have i ...

Building an HTML Form for Requests

Having some trouble creating an HTML form, particularly with resizing the Fieldset and legend elements. As a novice programmer, I am practicing building HTML forms. My goal is to have the form adjust its size based on the window without displacing the cont ...

What is the process to designate a specific value to a key in an array?

I need assistance in updating the description array within the schema by adding the about and link values, followed by using the .save() function to store it in the database. Any guidance on this issue would be greatly appreciated. Thank you for your help. ...