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

Toggle the on and off functionality of a button using ajax response for content display

I'm struggling to figure out why the button isn't working for me. I am familiar with how to enable and disable buttons using attr and prop. $(document).on("click", "#btn", function(){ $(this).html("Sending..."); $(this).prop("disabl ...

Is the CSS3 bar chart flipped?

I'm currently developing a responsive bar chart, and everything seems to be going smoothly except for one issue - when viewing it in full screen, the bars appear to be flipped upside down. It's quite puzzling as all other elements such as text an ...

Retrieve all instances of a key-value pair within an object that share the same key

Here is some JSON data: [{"name":"David","text":"Hi"},{"name":"Test_user","text":"test"},{"name":"David","text":"another text"}] I am l ...

Tips for breaking out of the foundation row and aligning with the right edge of the viewport

I have a CodePen example showcasing the Zurb Foundation grid. I am looking for a way to make a div extend to the right edge of the viewport while keeping the left edge in line with the grid as the viewport is resized. <div class="row"> <div cla ...

Angular 2 signal sender

I have a specific class definition for my Project: export class Project { $key: string; file: File; name: string; title: string; cat: string; url: string; progress: number; createdAt: Date = new Date(); constructor(file: File) { th ...

What is the best way to animate the scaling of a CSS property using jQuery?

I need help creating an animation where a circle div with the class of "bubble" grows from nothing to its full size when a button is clicked using jQuery. I am currently facing difficulties in making it work properly. Here's my current code snippet: ...

Ways to conceal components upon clicking a different element

Struggling to make this jQuery function properly. I have a form with all fields contained in a div.form-group. The subscribe button is identified by the id subscribe. I'm aiming to hide the form fields when clicked, but my JavaScript doesn't see ...

Using jQuery to Convert CSV Data into an HTML Table

I've been exploring the incredible jquery.csvtotable.js plugin for converting csv files to html tables. One question that has been on my mind is how can I allow users to select a .csv file using a browse button that isn't a server-side control? ...

Revolutionary CSS and jQuery for an Exceptional Top Navigation Experience

I would like to create a top navigation similar to the one on Facebook, using CSS and jQuery. Here is an example: Additionally: Notice how the arrow in the popbox always remains beneath the selected navigation item, and all popboxes have the same width. ...

Is it feasible to utilize the HTML5 video tag in conjunction with a JSON callback?

Curious about the possibility of a video page layout featuring a main screen and smaller clickable screens below it. When clicking on one of the smaller screens, the main screen would display the selected video, similar to YouTube. We have obtained data f ...

Tips for eliminating empty trailing values and Carriage Returns from a JavaScript array

I needed a way to eliminate empty elements and Carriage Returns from the end of an array. Here's an example of what my array looks like: Input arr: ['', 'Apple', '', 'Banana', '', 'Guava', & ...

Using a jquery function within a Laravel view

I am trying to retrieve a selected item from a dropdown menu using jQuery and then redirect it to a controller function. This function will return some data to be displayed based on the selected item. I could really use some assistance with this. Here is m ...

Iterate through a directory on the local machine and generate elements dynamically

I am looking to create a jQuery-UI tabs menu that includes 54 images on each tab. I have a total of 880 images stored in a folder, and it would be very time-consuming to manually insert an <img> tag for each one. Is there a way to dynamically cycle t ...

Is it necessary to always include all styles for jQuery UI separately in my project?

While reading various articles, I have noticed a common suggestion to explicitly bundle each jQueryUI .css file, such as the answer provided on How to add jQueryUI library in MVC 5 project?. However, upon examining the .css files within the Content/themes/ ...

Tips for Preventing Ant Design from Overriding Existing CSS Styles

Currently, I am working on a ReactJS project. Initially, the entire project was designed using pure CSS. However, I decided to incorporate a small Antd component into my project. Following the provided instructions, I imported the component like this in on ...

working with JSON array information

I have a JSON array retrieved from a database that I need to manipulate. Currently, it consists of 8 separate elements and I would like to condense it down to just 2 elements while nesting the rest. The current structure of my JSON looks like this: { "i ...

Issues with link behavior when using Angular UI-Router

I am just starting to learn AngularJS and I'm trying to figure out how to pass a parameter using anchor tags within the $stateProvider code. I've been attempting to do so, but it doesn't seem to be working. Can someone guide me on the correc ...

Employing jQuery for adding a class to the initial TD in every table row

Currently, I am dealing with a table structured like this: <table width="100%" border="0" cellspacing="0" cellpadding="0" id="tablecontent"> <tr class="tablerow"> <td>This is the td I want to add a class to.</td> <td c ...

encountering a problem with iterating through a JSON array

After making an ajax call and retrieving select options in json format, I implemented the code below to display these new options in place of the existing ones: success: function (data){ var $select = $('#dettaglio'); $select.html(' ...

Is there a way to determine in FireBug the specific JavaScript code being received from the server following an Ajax request?

Within my HTML code, I am transmitting a dollar amount to the server in order to convert its currency within the application. Is there a way for me to use FireBug to track and view the JavaScript that is being received from the server following this Ajax ...