简体   繁体   中英

javascript change colors conditionally

Lets say you have three elements, all white or no color applied at all. if any element clicked/selected it turns red, If any two elements clicked/selected they're red & green. If all three elements clicked/selected they're red, green, blue. Now when any element is clicked a second time it will turn back to white, but no matter what they still need to follow theses rules.

1 element = red

2 element = red, green

3 element = red, green, blue

With help I have so far came up with this code but cannot figure out how to make the event react based on the conditions needed. For example if all three are clicked and we click to remove the green color, then the blue will need to be green. jsFiddle with classes example

css

.container {
background-color: #ffffff;
border: 1px solid blue;
border-radius: 10px;
width: 100px;
height: 50px;
}
.red { background-color: #ff0000; }
.green { background-color: #00ff00; }
.blue { background-color: #0000ff; }

elements

<div class='container' id='1' style='margin: 150px 0 0 75px; float: left;'></div>
<div class='container' id='2' style='margin: 150px 0 0 175px; float: left;'></div>
<div class='container' id='3' style='margin: 150px 0 0 220px; float: left;'></div>

Javascript

window.onload=function () {
      // set color classes into an array
      var classes = ["red", "green", "blue"];
      var nextClass = 0;
      var element = document.querySelectorAll( ".container" );

      // loop through container class elements one at a time onclick run changeClass
      for ( var i = 0; i < element.length; i++ )
      {
          element[i].addEventListener( "click", changeClass );
      }

      function changeClass ( eventListener )  
      {
         var element = eventListener.currentTarget;
         var currentClass = hasClass( element, classes );

              if ( currentClass )
              {
                  element.classList.remove( currentClass )
              }
              else
              {
                  element.classList.add( classes[nextClass] );
                  nextClass = (nextClass + 1 ) % classes.length;
              }

      }//end function

      function hasClass( element, classes )
      {
          // loop through classes array
          for ( var i = 0; i < classes.length; i++ )
          {
              // onclick if all classes applied return currentClass
              if ( element.classList.contains( classes[i] ) )
              {
                  return classes[i];
              }
          }

      }// end function

}//end onload

Is there a way to load these classes based on the conditions needed?

Could also load the colors inline using element.style.backgroundColor , but still doesn't help me. The last person that helped me was very talented and I'm hoping for the same help :)... Have learned a lot so far but still stuck, close but just can't get it right.

Here is the code I came up with: See it in action My updated code jsFiddle

    window.onload=function () {
      var classes = ["red", "green", "blue"];
      var nextClass = 0;
      var element = document.querySelectorAll( ".container" );

      for ( var i = 0; i < element.length; i++ )
      {
          element[i].addEventListener( "click", changeClass );
      }

      function changeClass ( eventListener )  
      {
         var elementG = document.querySelector( '.green' );
         var elementB = document.querySelector( '.blue' );
         var elementR = document.querySelector( '.red' );
         var element = eventListener.currentTarget;
         var currentClass = hasClass( element, classes );
         var red = removeRed( element, classes );
         var green = removeGreen( element, classes );

        if ( currentClass )
        {
            element.classList.remove( currentClass )
            nextClass--;
          if (nextClass < 0) 
          {
              nextClass += classes.length;
          }
        }
        else
        {
            element.classList.add( classes[nextClass] );
            nextClass = (nextClass + 1 ) % classes.length;
        }

        if ( red && elementB != null )
        {
            elementB.classList.add( 'red' );
            elementB.classList.remove( 'blue' );
        }
        else if ( red && elementB == null && elementG != null)
        {
            elementG.classList.add( 'red' );
            elementG.classList.remove( 'green' )
        }
        if ( green && elementB != null )
        {
            elementB.classList.add( 'green' );
            elementB.classList.remove( 'blue' );
        }             

      }//end function

      function hasClass( element, classes )
      {
          // loop through classes array
          for ( var i = 0; i < classes.length; i++ )
          {
              // if all three classes
              if ( element.classList.contains( classes[i] ) )
              {
                  return classes[i];
              }
          }

      }// end function

      function removeRed( element, classes )
      {
          if ( element.classList.contains( classes[0] ) )
          {
              return classes[0];
          }
      }// end function
      function removeGreen( element, classes )
      {
          if ( element.classList.contains( classes[1] ) )
          {
              return classes[1]
          }
      }
}//end onload

I think you need to also keep track of the order the elements were clicked. I would suggest you do this by keeping an object that will act as a sort of key/value pair, where the key is the "id" of the element clicking/unclicking, and the value is the number it was clicked (ie 1 = red, 2 = green, etc.).

Then, in changeClass(), when adding the class, you can also add to the object the number it was clicked at. When removing the class, you can unset the key in the object and iterate over the items in the object and decrement anything that had a higher value. This decrement will allow you to adjust the color/number of anything that was clicked after that button that was just "unclicked" (eg a blue button should turn green if you "unclick" the green button).

Might look something like this:

Initialize with this:

var state = {};

Do this when clicking (before incrementing nextclass):

state[element.id] = nextClass;

Do this when unclicking:

var removedNum = state[element.id];
delete state[element.id];
nextClass--;
if (nextClass < 0) { nextClass += classes.length; }
var i;
var keys = Object.keys(state);
for (i = 0; i < keys.length; i++) {
    if (state[keys[i]] >= removedNum) {
        // decrement only things after the button unclicked
        var checkElement = document.getElementById(keys[i]);
        state[keys[i]]--;
        var checkClass = hasClass(checkElement, classes);
        if (checkClass) {
            // remove its existing class
            checkElement.classList.remove(checkClass);
        }
        // add the one it should now have
        checkElement.classList.add( classes[state[keys[i]]] );
    }
}

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