Home > Enterprise >  addClass based on attribute for/id relationships
addClass based on attribute for/id relationships

Time:09-03

I got this script half-working but need help finishing it off. My jQuery skills are weak at best.

I'm basically creating an interactive flow chart using jQuery to add an expand class. But I went in search of a solution that would be more elegant than 1000 individual addClass scripts.

HTML (I removed excessive stuff):

<div >
  <div >Question</div>
  <button for="question-1-yes-action" >Yes</button>
  <button for="question-1-no-action" >No</button>
</div>
<div >
  <div id="question-1-yes-action" >
    <div >Answer Yes</div>
  </div>
  <div id="question-1-no-action" >
    <div >Answer No</div>
  </div>
</div>

jQuery:

$(function() {
    var currentFlow = $("button").attr("for");
    $("button").click(function() {
        $( "div[ id="   currentFlow   "]").addClass( "expand" );
    });
});

The idea was to identify the container that needed the "expand" class added to it based on the for/ID relationship. At first, I thought it worked! If I click "Yes" the "Answer Yes" will get the "expand" class added to it. However... if I click "No," the "Answer Yes" also gets the "expand" class added to it. So clearly I did something wrong. I just don't know what it is or if my logic will even succeed.

Any advice would be appreciated.

CodePudding user response:

Your code is nearly there, the issue you have is that you only set currentFlow once, when the page loads. It instead needs to be set when the click event happens, and it needs to read the for from the button which was clicked.

In addition, it's not good practice to create non-standard attributes in your HTML. In this case, for. If you want to store custom metadata in your HTML, use a data attribute instead.

Lastly, if you're going to select an element by its id, use an id selector, not an attribute selector.

Here's a working example with all these amendments incorporated:

jQuery($ => {
  $('.action-button').on('click', e => {
    e.preventDefault();
    $('.expand').removeClass('expand');
    let currentFlow = $(e.target).data("for");
    $(currentFlow).addClass('expand');
  });
});
.answer { display: none; }
.answer.expand { display: block; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div >
  <div >Question</div>
  <button type="button" data-for="#question-1-yes-action" >Yes</button>
  <button type="button" data-for="#question-1-no-action" >No</button>
</div>
<div >
  <div id="question-1-yes-action" >
    <div>Answer Yes</div>
  </div>
  <div id="question-1-no-action" >
    <div>Answer No</div>
  </div>
</div>

Note that I also replaced all your x classes with more meaningful names.

CodePudding user response:

You will have to fetch the for attribute on click of the button. So that the script fetches the attribute of the clicked button.

In your case, by default the attribute of the first button is retrieved. I have modified the code as shown below:

$(function() {
    $("button").click(function() {
        var currentFlow = $(this).attr("for");
        $( "div[ id="   currentFlow   "]").addClass( "expand" );
    });
});

CodePudding user response:

$(function() {
  $('button[for*="-action"]').click(function() {
    var id = $(this).attr('for');
    $('div[id*="-action"]').removeClass('expand');
    $('div[id="'   id   '"]').addClass('expand');
  });
});
.expand {
  background-color: red;
  padding-bottom: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div >
  <div >Question</div>
  <button for="yes-action" >Yes</button>
  <button for="no-action" >No</button>
</div>

<div >
  <div id="yes-action" >
    <div >Answer Yes</div>
  </div>
  <div id="no-action" >
    <div >Answer No</div>
  </div>
</div>

  • Related