Shaun
Shaun

Reputation: 811

Only show button when .active class is not first child

I'm creating a multi step form using jQuery and I'm trying to only show the #prev button when the active class isn't on the first child. By default I have added display:none to #prev to hide it on load but I'm struggling to display it when the .active class is added onto the other sections.

When targeting this in a if statement using the is(":not(:first-child)) it works but only shows when the active class is added onto #step3.

Can anyone tell me how to ensure the button is only visible when the class .active is on every section except #step1?

if(active.is(":not(:first-child)")) {
    $('#prev').show();
  }

HTML

<div class="multi-step-wrapper" id="multi-step">
            <div id="progressbar">
                <span></span>
            </div>
            <div class="steps-inner">
                <div class="multi-step-section active" id="step1"></div>
                <div class="multi-step-section" id="step2"></div>
                <div class="multi-step-section" id="step3"></div>
                <div class="multi-step-section" id="step4"></div>
                <div class="multi-step-section" id="step5"></div>
                <div class="multi-step-section" id="step6"></div>
                <div class="multi-form-actions">
                    <button id="prev" type="button">Back</button>
                    <button id="next" type="button">Next</button>
                </div>
            </div>
        </div>

CSS

#prev {
  display: none;
}

Jquery

$('.multi-form-actions button').on('click', function() {

  var el = $(this).attr('id');
  var active = $('.multi-step-section.active');

  if(active.is(":not(:first-child)")) {
    $('#prev').show();
  }

  active.removeClass('active');

  if(el == 'prev') {
      active.prev('.multi-step-section').addClass('active');
  }
  else if(el = 'next') {
      active.next('.multi-step-section').addClass('active');
  }

});

Upvotes: 0

Views: 609

Answers (3)

Sarah Gro&#223;
Sarah Gro&#223;

Reputation: 10879

There are a few things you need to do in order to make this work:

  1. Hide all steps that are not active (I assume you're doing this already and left it out for the sake of a shorter example code)
  2. Remove the active state from all the sibling step containers actually, that's not necessary and was a fallacy on my side
  3. Update the element held in the collection of the active variable with the next/previous step accordingly
  4. move the button status check after that
  5. hide the button when the active step is the first one

You'll also have to handle the case when all steps are through, but that's out of the scope of this question.

I also simplified the code to get rid of some redundance.

$('.multi-form-actions button').on('click', function() {
  var el = $(this).attr('id');
  var active = $('.multi-step-section.active');

  // also remove active class from siblings
  active.removeClass('active');

  if(el === 'prev' || el === 'next') { // in case you have any other buttons
    active = active[el]('.multi-step-section').addClass('active');;
  }
  
  // show or hide prev button depending on condition
  $('#prev')[active.is(":not(:first-child)") ? 'show' : 'hide']();
});
#prev,
.multi-step-section {
  display: none;
}

.multi-step-section.active {
  display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  	
<div class="multi-step-wrapper" id="multi-step">
  <div id="progressbar">
    <span></span>
  </div>
  <div class="steps-inner">
    <div class="multi-step-section active" id="step1">step1</div>
    <div class="multi-step-section" id="step2">step2</div>
    <div class="multi-step-section" id="step3">step3</div>
    <div class="multi-step-section" id="step4">step4</div>
    <div class="multi-step-section" id="step5">step5</div>
    <div class="multi-step-section" id="step6">step6</div>
    <div class="multi-form-actions">
      <button id="prev" type="button">Back</button>
      <button id="next" type="button">Next</button>
    </div>
  </div>
</div>

Upvotes: 1

sourkrause
sourkrause

Reputation: 178

Try something like this which will also make sure there is a next active step to activate.

$('.multi-form-actions button').on('click', function() {

  var el = $(this).attr('id');
  var active = $('.multi-step-section.active');
  var nextActive; 

  if(el == 'prev') {
    nextActive = active.prev('.multi-step-section');
  }
  else if(el = 'next') {
    nextActive = active.next('.multi-step-section');
  }

  if (nextActive.length > 0) {
    active.removeClass('active');

    if(nextActive.is(":first-child")) {
      $('#prev').hide();
    }
    else {
      $('#prev').show();
    }

    nextActive.addClass('active');  
  }
});
#prev {
  display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="multi-step-wrapper" id="multi-step">
    <div id="progressbar">
        <span></span>
    </div>
    <div class="steps-inner">
        <div class="multi-step-section active" id="step1"></div>
        <div class="multi-step-section" id="step2"></div>
        <div class="multi-step-section" id="step3"></div>
        <div class="multi-step-section" id="step4"></div>
        <div class="multi-step-section" id="step5"></div>
        <div class="multi-step-section" id="step6"></div>
        <div class="multi-form-actions">
            <button id="prev" type="button">Back</button>
            <button id="next" type="button">Next</button>
        </div>
    </div>
</div>

Upvotes: 0

Taplar
Taplar

Reputation: 24965

So a few fixes to your logic.

  1. Fixed the typo of = on the else if.
  2. Set the active to the new active once it's adjusted.
  3. Check if the active is the first element after it has been adjusted, not before, so it is accurate.
  4. As a bonus, also added the hiding of the prev if it is changed back to the first element.

$('.multi-form-actions button').on('click', function() {
  var el = $(this).attr('id');
  var active = $('.multi-step-section.active');

  active.removeClass('active');

  if (el == 'prev') {
    active = active.prev('.multi-step-section').addClass('active');
  } else if (el == 'next') {
    active = active.next('.multi-step-section').addClass('active');
  }

  if (active.is(":not(:first-child)")) {
    $('#prev').show();
  } else {
    $('#prev').hide();
  }
});
#prev {
  display: none;
}

.active { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="multi-step-wrapper" id="multi-step">
  <div id="progressbar">
    <span></span>
  </div>
  <div class="steps-inner">
    <div class="multi-step-section active" id="step1">a</div>
    <div class="multi-step-section" id="step2">b</div>
    <div class="multi-step-section" id="step3">c</div>
    <div class="multi-step-section" id="step4">d</div>
    <div class="multi-step-section" id="step5">e</div>
    <div class="multi-step-section" id="step6">f</div>
    <div class="multi-form-actions">
      <button id="prev" type="button">Back</button>
      <button id="next" type="button">Next</button>
    </div>
  </div>
</div>

Upvotes: 1

Related Questions