1

I'm trying to change a div's attribute class. I have three defined classes and want to cycle through the classes when a user initiates a click event. The first click event works as expected, but the second doesn't show any results.

I've went through a few iterations of trying to get this to work, but have not had any success. I think what's going on is that the DOM tree isn't being updated with the click event, so when the second click event is fired it sees the card-green class, adds the card-yellow class and then exits the branching logic.

$(document).ready(function() {
  $('body').on('click', function(event) {
    var cardColors = ['card-green', 'card-yellow', 'card-red'];
    if ($(event.target.nodeName).attr('class') == 'card-green') {
      $(event.target.nodeName).removeClass(event.target.nodeName.className).addClass(cardColors[1]);
    } else if ($(this).attr('class') == 'card-yellow') {
      $(event.target.nodeName).removeClass(event.target.nodeName.className).addClass(cardColors[2]);
    } else {
      $(event.target.nodeName).removeClass(event.target.nodeName.className).addClass(cardColors[0]);
    }
  })
});
Jade Cowan
  • 2,543
  • 1
  • 18
  • 32
  • In first click its shwoing yellow color second click red and third is green. is the proper that you want? – Avinash Raut Mar 24 '17 at 19:46
  • Yes. HTML will load with a `card-green` as the default class. First click will change it to yellow, second click will change it to red, third will change it to green, so it can start all over. – Jade Cowan Mar 24 '17 at 19:48
  • code u wrote that is right! just check modified code below – Avinash Raut Mar 24 '17 at 20:34

4 Answers4

1

This changes the color in order of the cards array when elements within the document body are clicked:

(Very similar to @gyre's answer, only includes the event.target within the code logic, rather than just the body).

var cards = ['card-green', 'card-yellow', 'card-red'];

$('body').on('click', function() {

  var elem = event.target,
    curClass = $(elem).attr('class'),
    i = cards.indexOf($(elem).attr('class'));

  $(elem)
    .removeClass(curClass)
    .addClass(cards[i = (i + 1) % cards.length]);
});
div {
  height: 100px;
  width: 100px;
  display: inline-block;
}

.card-green {
  background-color: green;
}

.card-yellow {
  background-color: yellow;
}

.card-red {
  background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="foo" class="card-green"></div>
<div id="bar" class="card-yellow"></div>
<div id="baz" class="card-red"></div>
wahwahwah
  • 3,254
  • 1
  • 21
  • 40
1

Use a switch and toggleClass(). Details are commented in Snippet. No need for an array if you are using a limited number of options. When using $(this) you don't need to keep track of what you clicked (much like event.target except $(this) isn't concerned about events as it is concerned with owner of function.)

SNIPPET

$(document).ready(function() {
  $(document).on('click', 'div', function(event) {
    /* Determine $(this) class
    || Pass class through the switch
    */
    var color = $(this).attr('class');
    /* Each part of the switch is a if/else 
    || conditional. If the condition isn't 
    || met, then it will kick you
    || down to the next conditional and
    || so on, until you reach default or
    || meet a condition in which case the
    || break will kick you out of switch.
    || Each condition has a toggleClass()
    || method to switch colors according
    || to the present class of div
    */
    switch (color) {
      case 'green':
        $(this).toggleClass('green yellow');
        break;
      case 'yellow':
        $(this).toggleClass('yellow red');
        break;
      case 'red':
        $(this).toggleClass('red green');
        break;
      default:
        break;
    }

  });
});
div {
  height: 30px;
  width: 50px;
  border: 1px solid black;
  cursor: pointer;
}

.green {
  background: green
}

.red {
  background: red;
}

.yellow {
  background: yellow
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>



<div class='green'></div>
<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>

<div class='green'></div>
Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68
0

Use an additional index variable to keep track of the position in the array:

Demo Snippet:

$(document).ready(function() {

  var cardColors = ['card-green', 'card-yellow', 'card-red']

  var i = 0

  $('body').on('click', function() {
    
    $(this)
      .removeClass(cardColors[i])
      .addClass(cardColors[i = (i + 1) % cardColors.length])
  })
})
body {
  width: 100vw;
  height: 100vh;
  margin: 0;
  padding: 0;
}

.card-green { background-color: green; }

.card-yellow { background-color: yellow; }

.card-red { background-color: red; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
gyre
  • 16,369
  • 3
  • 37
  • 47
0

The same code is workable just remove nodeName from removeClass(event.target.nodeName.className) instead of this use removeClass(event.target.className). Try this, Its working for me.

$(document).ready(function() {
  $('body').on('click', function(event) {
    var cardColors = ['card-green', 'card-yellow', 'card-red'];
    alert(event.target.className)
    if ($(event.target.nodeName).attr('class') == 'card-green') {
      $(event.target.nodeName).removeClass(event.target.className).addClass(cardColors[1]);
    } else if ($(this).attr('class') == 'card-yellow') {
      $(event.target.nodeName).removeClass(event.target.className).addClass(cardColors[2]);
    } else {
      $(event.target.nodeName).removeClass(event.target.className).addClass(cardColors[0]);
    }
  })
});
Avinash Raut
  • 1,872
  • 20
  • 26
  • It almost works. The only thing that needs to be changed is the condition in the `else if` statement. Instead of `$(this).attr('class') == 'card-yellow'`, it needs to be `$(event.target.nodeName).attr('class') == 'card-yellow`. – Jade Cowan Mar 24 '17 at 21:18