skip to Main Content

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 class="activity-mc">
  <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!

2

Answers


  1. 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 class="activity-mc">
      <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 class="activity-mc">
      <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 class="activity-mc">
      <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>
    Login or Signup to reply.
  2. 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 =)

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search