1

I have a menu of buttons and am trying to record which buttons a user selects. The user can select multiple buttons before they submit their answer by clicking on the done button. They can change their mind by unclicking selections, but their final answer should be submitted upon clicking the done button.

Currently, I'm able to record multiple button selections by pushing to an array upon each click. However, if a user unclicks a button, I have not been able to figure out how to update my array. For example, if a user clicks A, B, A. It will unselect A, but the array still records ["A", "B"] when it should instead record ["B"]. Does anyone what I am doing wrong?

It's unclear to me whether selections are recorded based on clicks or buttons have the class 'selected' from (let syms = document.querySelectorAll('.selected'). Many thanks in advance!

<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <style media="screen">
    .buttons {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }

    #buttonGallery {
      margin: 10px;
      padding: 10px;
      border: solid 2px black;
      width: 155px;
    }

    #done {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }
  </style>
</head>

<body>
  <div id="buttonGallery">
    <div id="done">
      <p>done</p>
    </div>
  </div>
  <script type="text/javascript">
    let $buttonGallery = $("#buttonGallery");
    let myList = ["A", "B", "C", "D"];
    let myColors = ["red", "green", "blue", "red"];
    let clicked = [];

    myList.map(function(letter, index) {
      let clicked = [];
      let $button = $("<div></div>")
        .addClass("buttons")
        .attr("id", "button_" + letter)
        .html("<p>" + letter + "</p>")
        .on("mouseenter", function() {
          $(this).css("background", myColors[index]);
        })
        .on("mouseleave", function() {
          if (!$(this).hasClass('selected')) {
            $(this).css("background", "transparent");
          }
        })
        .on("click", function() {
          $(this).css("background", myColors[index]);
          $(this).toggleClass('selected');

          // push clicked variables to array
          let syms = document.querySelectorAll('.selected');

          for (let n = 0; n < syms.length; n++) {
            if (!clicked.includes(syms[n].textContent)) {
              clicked.push(syms[n].textContent);
            }
          };

          // send data to server
          console.log('clicked array', clicked);
        })
      $("#done").before($button);
    });

    $("#done").on("click", clearColor);

    function clearColor() {

      $(".buttons").css({
        backgroundColor: 'transparent'
      });
      $(".buttons").removeClass('selected');

      // reset clicked list
      clicked = [];
    }
  </script>
</body>
</script>

</html>

3
  • 2
    Inside button.on('click', function(){......}) add a line clicked = []; before "// push clicked variables to array" and try... Commented Jul 9, 2020 at 1:06
  • @AlwaysaBeginner That worked perfectly! I'm happy it turned out to be a quick fix. Thank you! Commented Jul 9, 2020 at 1:12
  • Good to know it helped.... However, you understand you can simplify your code to add or remove the clicked button from array right? Instead of looping through all the items with selected class and adding them to the array, you can simply add or remove the clicked button. Check the answer from @CHANist Commented Jul 9, 2020 at 1:58

2 Answers 2

1

The problem seems to be in the onClick logic, you only push data into the array, but not removing any out.

<html lang="en" dir="ltr">

<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <style media="screen">
    .buttons {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }

    #buttonGallery {
      margin: 10px;
      padding: 10px;
      border: solid 2px black;
      width: 155px;
    }

    #done {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }
  </style>
</head>

<body>
  <div id="buttonGallery">
    <div id="done">
      <p>done</p>
    </div>
  </div>
  <script type="text/javascript">
    let $buttonGallery = $("#buttonGallery");
    let myList = ["A", "B", "C", "D"];
    let myColors = ["red", "green", "blue", "red"];
    let clicked = [];

    myList.map(function(letter, index) {
      let $button = $("<div></div>")
        .addClass("buttons")
        .attr("id", "button_" + letter)
        .html("<p>" + letter + "</p>")
        .on("mouseenter", function() {
          $(this).css("background", myColors[index]);
        })
        .on("mouseleave", function() {
          if (!$(this).hasClass('selected')) {
            $(this).css("background", "transparent");
          }
        })
        .on("click", function() {
          $(this).css("background", myColors[index]);
          $(this).toggleClass('selected');

          // push clicked variables to array
          var isSelected = $(this).hasClass('selected');
          var value = $(this).text(); 
          console.log('isSelected', isSelected);
          console.log('value', value); 
          if (isSelected) {
              clicked.push(value)
          }
          else {
              clicked = clicked.filter(item => {
                  return item !== value;
              });
          }

          // send data to server
          console.log('clicked array', clicked);
        })
      $("#done").before($button);
    });

    $("#done").on("click", clearColor);

    function clearColor() {

      $(".buttons").css({
        backgroundColor: 'transparent'
      });
      $(".buttons").removeClass('selected');

      // reset clicked list
      clicked = [];
    }
  </script>
</body>
</script>

</html>

Sign up to request clarification or add additional context in comments.

Comments

0

You can make this:

<head>
  <meta charset="utf-8">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <style media="screen">
    .buttons {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }

    #buttonGallery {
      margin: 10px;
      padding: 10px;
      border: solid 2px black;
      width: 155px;
    }

    #done {
      width: 150px;
      height: 50px;
      border: solid 2px black;
      text-align: center;
      color: black;
      cursor: pointer;
      background-color: white;
      margin: 2px;
    }
  </style>
</head>

<body>
  <div id="buttonGallery">
    <div id="done">
      <p>done</p>
    </div>
  </div>
  <script type="text/javascript">
    let $buttonGallery = $("#buttonGallery");
    let myList = ["A", "B", "C", "D"];
    let myColors = ["red", "green", "blue", "red"];
    let clicked = [];

    myList.map(function(letter, index) {
      let $button = $("<div></div>")
        .addClass("buttons")
        .attr("id", "button_" + letter)
        .data({
          letter: letter
        })
        .html("<p>" + letter + "</p>")
        .on("mouseenter", function() {
          $(this).css("background", myColors[index]);
        })
        .on("mouseleave", function() {
          if (!$(this).hasClass('selected')) {
            $(this).css("background", "transparent");
          }
        })
        .on("click", function() {
          $(this).css("background", myColors[index]);
          $(this).toggleClass('selected');

          const selectedLetter = $(this).data().letter;
            if (!clicked.includes(selectedLetter)) {
              clicked.push(selectedLetter);
            } else {
              clicked = clicked.filter((item) => item != selectedLetter);
            }

          // send data to server
          console.log('clicked array', clicked);
        })
      $("#done").before($button);
    });

    $("#done").on("click", clearColor);

    function clearColor() {

      $(".buttons").css({
        backgroundColor: 'transparent'
      });
      $(".buttons").removeClass('selected');

      // reset clicked list
      clicked = [];
    }
  </script>
</body>
</script>

</html>

With .data() jQuery function I set to every button a letter. Then, when I click one of those they have a constant letter. So you can add or remove that letter from the array

And I removed this

let clicked = [];

Because you are declaring in the incorrect scope. With the global variable is good enough

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.