Home > Software design >  Javascript button event should undo all other button events
Javascript button event should undo all other button events

Time:08-10

thank you in advance for your help. I’m currently learning Javascript. Although I’m getting the hang of it, I’m still at the stage where I’m probably doing things in not the most efficient way.

I’m trying to create a simple multiple-choice activity on a language-learning site. Here is the HTML of a sample question:

<div >
  <p>1. Question …</p>
  <button onclick=“A.play()">A</button>
  <button onclick=“B.play()">B</button>
  <button onclick=“C.play()">C</button>
  <button onclick=“D.play()">D</button>
</div>

I’d like for every button to have two effects: Firstly, to play an audio that recites the selection out loud, which I already did. Secondly, to darken the button’s background color (i.e. so that it looks “selected”) on click; crucially, it should become un-selected either on clicking again or on clicking another button.

I know how to change the styling of an element with Javascript, but as far as I know I would have to use “toggleClass” here instead, because otherwise you wouldn’t be un-selecting on the second click since the styling is definitively applied rather than toggled. But the main issue that I’m having is that I don’t know how to efficiently make the buttons be in a mutually-exclusive relation with each other; that is, that when you click on another button in the same “activity-mc” element all effects from the other buttons (i.e. any other selection) is negated / deselected. Essentially I want the behavior of a radio button, but with my own custom buttons.

I had a similar issue in another section of the website, and the only way I could figure out to do this was by sort of hard-coding the behavior I was going for. But I don’t want to have to do this every single time I want this type of behavior, so I'm wondering if there's a more efficient way. Here’s what I came up with:

function tab1() {
  $('.tab1').addClass('active');
  $('.tab2').removeClass('active');
  $('.tab3').removeClass('active');
  $('.tab4').removeClass('active');

  $('#tab1').addClass('show');
  $('#tab2').removeClass('show');
  $('#tab3').removeClass('show');
  $('#tab4').removeClass('show');
}

function tab2() {
  $('.tab2').addClass('active');
  $('.tab1').removeClass('active');
  $('.tab3').removeClass('active');
  $('.tab4').removeClass('active');

  $('#tab2').addClass('show');
  $('#tab1').removeClass('show');
  $('#tab3').removeClass('show');
  $('#tab4').removeClass('show');
}

function tab3() {
  $('.tab3').addClass('active');
  $('.tab1').removeClass('active');
  $('.tab2').removeClass('active');
  $('.tab4').removeClass('active');

  $('#tab3').addClass('show');
  $('#tab1').removeClass('show');
  $('#tab2').removeClass('show');
  $('#tab4').removeClass('show');
}

function tab4() {
  $('.tab4').addClass('active');
  $('.tab1').removeClass('active');
  $('.tab2').removeClass('active');
  $('.tab3').removeClass('active');

  $('#tab4').addClass('show');
  $('#tab1').removeClass('show');
  $('#tab2').removeClass('show');
  $('#tab3').removeClass('show');
}

Any advice is appreciated. Thank you!

CodePudding user response:

This would be a slight example of what I understood that you need.

$('body').on('click', '.activity-mc button', function(){
$(this).closest('.activity-mc').find('button').removeClass('show').removeClass('active').css('opacity', '.5');
$(this).addClass('show').addClass('active').css('opacity', '1');

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <p>1. Question …</p>
  <button id="tab1" onclick="A.play()">A</button>
  <button id="tab2" onclick="B.play()">B</button>
  <button id="tab3" onclick="C.play()">C</button>
  <button id="tab4" onclick="D.play()">D</button>
</div>

<div >
  <p>2. Question …</p>
  <button id="tab1" onclick="A.play()">A</button>
  <button id="tab2" onclick="B.play()">B</button>
  <button id="tab3" onclick="C.play()">C</button>
  <button id="tab4" onclick="D.play()">D</button>
</div>

<div >
  <p>3. Question …</p>
  <button id="tab1" onclick="A.play()">A</button>
  <button id="tab2" onclick="B.play()">B</button>
  <button id="tab3" onclick="C.play()">C</button>
  <button id="tab4" onclick="D.play()">D</button>
</div>

CodePudding user response:

I would try a simpler aproach, instead of select every element by id you can provide the function called by a onclick the element clicked.

This example do without dependencies what I think you need

<head>
<style>
...
</style>
<script>
function playButton(button){
    const parent=button.parentNode;
    const buttons=parent.querySelectorAll("button");
    buttons.forEach(b => {
        b.classList.remove('active');
    });
    button.classList.add('active');
}

</script>
</head>

<body>
    <div>
        <p>1. Question …</p>
        <button onclick='playButton(this)'>A</button>
        <button onclick='playButton(this)'>B</button>
        <button onclick='playButton(this)'>C</button>
        <button onclick='playButton(this)'>D</button>
    </div>
    <div>
        <p>2. Question …</p>
        <button onclick='playButton(this)'>A</button>
        <button onclick='playButton(this)'>B</button>
        <button onclick='playButton(this)'>C</button>
        <button onclick='playButton(this)'>D</button>
    </div>
</body>

Hope this helps =)

  • Related