简体   繁体   中英

Can't remove of add class from HTML element

I have three coloured buttons. When I pick a button, I want it to be selected, and the other two to be deselected. red, blue and yellow are objects with the property isSelected set to true or false. I can select one button once, setting isSelected to true for that button. However, I can't seem to select a new button and deselect the current one.

(I know I can do this with jQuery easily... but I'm trying to learn how to use Javascript objects here...)

The code below doesn't run, it's the bits I think are relevant to the problem without the HTML and CSS. The app is on CodePen: http://codepen.io/isachenx/pen/LxEOOR

My idea is to set isSelected to true or false for each of the selectors. If isSelected is true, I add the class .selected to the html string, if it's false, the string does not include the class. I then re-render (at least that's what I think I'm doing) the string every time the li element is clicked...

  //create constructor function Selector(colour){ this.colour = colour this.isSelected = false } //set method to select and deselect the list items Selector.prototype.selectColour = function(){ this.isSelected = true } Selector.prototype.deselectColour = function(){ this.isSelected = false } //render the string for the list item to HTML Selector.prototype.toHTML = function(){ let htmlString = "" htmlString += '<li id="' + this.colour + '" class="' + this.colour if (this.isSelected){ htmlString += ' selected' } htmlString += '"></li>' return htmlString } //Constructor to render every list item to html 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.selectColour() blue.deselectColour() yellow.deselectColour() controls.renderInElement(controlElement) } let blueButton = document.getElementById('blue') blueButton.onclick = function(){ blue.selectColour() red.deselectColour() yellow.deselectColour() controls.renderInElement(controlElement) } let yellowButton = document.getElementById('yellow') yellowButton.onclick = function(){ yellow.selectColour() red.deselectColour() blue.deselectColour() controls.renderInElement(controlElement) } 

Setting isSelected to true or false doesn't change the class on the DOM element. To add/remove a class:

var colourObj = document.querySelector(colour);
colourObj.classList.add('selected');
//or to remove a class
colourObj.classList.remove('selected');

By your code, a second click on either button does not work. The reason is that onclick is set only for the first time.

Your toHTML function clears the existing buttons (line 33: list.innerHTML = '' ), as a result clears their onclick events. You have to set them again inside toHTML .

Like so:

Selector.prototype.toHTML = function(){

  // set the on click function to the desired color
  let onclickStr = 'setOnClick(\'' + this.colour + '\')';

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

  // Note the following change
  htmlString += '" onclick="' + onclickStr + '"></li>'
  return htmlString
}

Then, wrap your xxxbutton.onclick functions with:

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)
}

JSFIDDLE DEMO

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM