Search code examples
javascripthtmljquerywizard

Trying to get the next div with a specific class name but I keep getting the last one


I have a wizard and I'm trying to create a progress bar. The step that the user is on should be purple and should continue as the user progresses through the form. When I try to go to the next step, the progress bar shows that im on the last step instead of the step i'm currently on.

Here is my markup:

<div class="wizard-step">
            <div class="row">
                <div class="card shadow mb-4 w-100">
                    <div class="card-header py-3">
                        <h6 class="m-0 font-weight-bold text-primary">Payment</h6>
                    </div>
                    <div class="card-body">
                        <row>
                            <div class="form-group">
                                <label for="plan" class="control-label">Select a Plan</label><br />
                                @Html.DropDownListFor(model => model.planid, Model.subscriptionTypes, "None", new { @id = "plan", @class = "form-control" })
                                @Html.ValidationMessageFor(model => model.planid, "", new { @class = "text-danger" })
                            </div>

                            <div class="form-group">
                                <label for="card-number">
                                    Credit or debit card
                                </label>
                                <div id="card-number">
                                    <!-- A Stripe Element will be inserted here. -->
                                </div>
                            </div>

                            <div class="form-group">
                                <div class="row">
                                    <div class="col-md-6">
                                        <label for="card-vc">
                                            CVC
                                        </label>
                                        <div id="card-cvc">
                                            <!-- A Stripe Element will be inserted here. -->
                                        </div>
                                    </div>
                                    <div class="col-md-6">
                                        <label for="card-expiration">
                                            Exp
                                        </label>
                                        <div id="card-expiration">
                                            <!-- A Stripe Element will be inserted here. -->
                                        </div>
                                    </div>
                                </div>
                            </div>
                            <!-- Used to display form errors. -->
                            <div id="card-errors" role="alert"></div>
                    </div>
                </div>
            </div>
        </div>

Here is my Javascript:

 $(function () {



        $(".wizard-step:first").fadeIn(); // show first step


        // attach backStep button handler
        // hide on first step
        $("#back-step").hide().click(function () {
            var $step = $(".wizard-step:visible"); // get current step
            if ($step.prev().hasClass("wizard-step")) { // is there any previous step?
                $step.hide().prev().fadeIn();  // show it and hide current step

                // disable backstep button?
                if (!$step.prev().prev().hasClass("wizard-step")) {
                    $("#back-step").hide();
                }
            }
        });


        // attach nextStep button handler
        $("#next-step").click(function () {

            var $step = $(".wizard-step:visible"); // get current step

            var validator = $("form").validate(); // obtain validator
            var anyError = false;
            $step.find("input").each(function () {
                if (!validator.element(this)) { // validate every input element inside this step
                    anyError = true;
                }
                next_fs = $(this).parent().next().find(".wizard-step");
                $("#progressbar li").eq($(".wizard-step").index(next_fs)).addClass("active");
            });

            if (anyError)
                return false; // exit if any error found




            if ($step.next().hasClass("confirm")) { // is it confirmation?
                // show confirmation asynchronously
                $.post("/wizard/confirm", $("form").serialize(), function (r) {
                    // inject response in confirmation step
                    $(".wizard-step.confirm").html(r);
                });

            }

            if ($step.next().hasClass("wizard-step")) { // is there any next step?
                $step.hide().next().fadeIn();  // show it and hide current step
                $("#back-step").show();   // recall to show backStep button
            }

            else { // this is last step, submit form
                $("form").submit();
            }


        });

    });

I'm trying to find the next step by doing this var next_fs = $(this).parent().next().find(".wizard-step"); $("#progressbar li").eq($(".wizard-step").index(next_fs)).addClass("active");

This keeps making the progress bar show me that I'm on the last step. How can I get it to recognize the next step?

Here is a picture showing the problem. The first two steps should be lit up (set to active) but instead it just sets the first and last one active Problem


Solution

  • You can solve this simply by declaring a variable globally which will have index of current div which is display so whenever next button is clicked just increment its value then , pass same to eq(count) to show next div and same you can do for back button .Also , modify below code according to your requirement.

    Demo Code :

    $(function() {
    
      var index = 0; //delcare this
      $(".wizard-step:first").fadeIn(); // show first step
      $("#back-step").hide().click(function() {
        $("#progressbar li").eq(index).removeClass("active"); //remove active class when backbutton on curent wizard
        index--; //decrement value
        var $step = $(".wizard-step:visible");
        if ($step.prev().hasClass("wizard-step")) {
          $step.hide().prev().fadeIn();
          if (!$step.prev().prev().hasClass("wizard-step")) {
            $("#back-step").hide();
          }
        }
      });
    
    
      // attach nextStep button handler
      $("#next-step").click(function() {
        index++; //increment 
        var $step = $(".wizard-step:visible"); // get current ste
        var anyError = false;
        $step.find("input").each(function() {
          /*if (!validator.element(this)) { // validate every input element inside this step
              anyError = true;
          }*/
    
        });
    
    
        if (anyError)
          return false; // exit if any error found
    
    
    
    
        if ($step.next().hasClass("confirm")) { // is it confirmation?
          // show confirmation asynchronously
          $.post("/wizard/confirm", $("form").serialize(), function(r) {
            // inject response in confirmation step
            $(".wizard-step.confirm").html(r);
          });
    
        }
    
        if ($step.next().hasClass("wizard-step")) { 
          $step.hide().next().fadeIn();
          //add active class to current div
          $("#progressbar li").eq(index).addClass("active");
          $("#back-step").show(); // recall to show backStep button
        } else { // this is last step, submit form
          $("form").submit();
        }
    
    
    
    
      });
    
    });
    .wizard-step {
      display: none;
    }
    
    #progressbar {
      text-align: center;
      position: relative;
      margin-bottom: 30px;
      overflow: hidden;
      color: lightgrey;
      z-index: 0;
    }
    
    #progressbar .active {
      color: #673AB7
    }
    
    #progressbar li {
      list-style-type: none;
      font-size: 15px;
      width: 25%;
      float: left;
      position: relative;
      font-weight: 400
    }
    
    #progressbar #account:before {
      font-family: FontAwesome;
      content: "\f13e"
    }
    
    #progressbar #personal:before {
      font-family: FontAwesome;
      content: "\f007"
    }
    
    #progressbar #payment:before {
      font-family: FontAwesome;
      content: "\f030"
    }
    
    #progressbar #confirm:before {
      font-family: FontAwesome;
      content: "\f00c"
    }
    
    #progressbar li:before {
      width: 50px;
      height: 50px;
      line-height: 45px;
      display: block;
      font-size: 20px;
      color: #ffffff;
      background: lightgray;
      border-radius: 50%;
      margin: 0 auto 10px auto;
      padding: 2px
    }
    
    #progressbar li:after {
      content: '';
      width: 100%;
      height: 2px;
      background: lightgray;
      position: absolute;
      left: 0;
      top: 25px;
      z-index: -1
    }
    
    #progressbar li.active:before,
    #progressbar li.active:after {
      background: #673AB7
    }
    
    .progress {
      height: 20px
    }
    
    .progress-bar {
      background-color: #673AB7
    }
    
    .fit-image {
      width: 100%;
      object-fit: cover
    }
    
    .StripeElement {
      box-sizing: border-box;
      height: 40px;
      padding: 10px 12px;
      border: 1px solid transparent;
      border-radius: 4px;
      background-color: white;
      box-shadow: 0 1px 3px 0 #e6ebf1;
      -webkit-transition: box-shadow 150ms ease;
      transition: box-shadow 150ms ease;
    }
    
    .StripeElement--focus {
      box-shadow: 0 1px 3px 0 #cfd7df;
    }
    
    .StripeElement--invalid {
      border-color: #fa755a;
    }
    
    .StripeElement--webkit-autofill {
      background-color: #fefde5 !important;
    }
    
    .green {
      border: solid green 1px;
    }
    
    .error {
      border: solid red 1px;
    }
    
    .select2-container--default .select2-selection--single {
      border: 1px solid #ccc !important;
      border-radius: 4px !important;
    }
    
    .select2-container--default .select2-selection--single .select2-selection__rendered {
      line-height: 1.428571429 !important;
      padding: 6px 12px !important;
    }
    
    .select2-container .select2-selection--single {
      height: 34px;
    }
    
    .select2-container--default .select2-selection--single .select2-selection__arrow b {
      margin-top: 0;
    }
    
    .validation-summary-valid {
      display: none;
    }
    <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet" />
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>
    
    <h2>Create</h2>
    
    <body>
    
      <form id="payment-form">
    
        <div class="form-horizontal">
          <h4>LoginSecurityQuestionsViewModel</h4>
          <hr />
          <div class="container">
            <!-- progressbar -->
            <ul id="progressbar">
              <li class="active" id="account"><strong>Account</strong></li>
              <li id="personal"><strong>Personal</strong></li>
              <li id="payment"><strong>Image</strong></li>
              <li id="confirm"><strong>Finish</strong></li>
            </ul>
            <div class="progress">
              <div class="progress-bar progress-bar-striped progress-bar-animated" role="progressbar" aria-valuemin="0" aria-valuemax="100"></div>
            </div> <br>
            <!-- fieldsets -->
            <div class="wizard-step">
              <div class="row">
                <div class="card shadow mb-4 w-100">
                  <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-primary">Personal Information</h6>
                  </div>
                  <div class="card-body">
                    <div class="row">
                      <div class="form-group col-md-6">
                        <label class="control-label">First Name</label>
                        <input type="text" class="form-control" name="First Name" id="fName" />
    
                        <div class="form-group col-md-6">
                          <label class="control-label">Last Name</label>
                          <input type="text" class="form-control" name="Last Name" id="lName" />
    
                        </div>
                      </div>
                      <div class="row">
                        <div class="form-group col-md-12">
                          <label class="control-label">Company</label>
                          <input type="text" class="form-control" name="Company" id="company" />
                        </div>
                      </div>
                      <div class="row">
                        <div class="form-group col-md-12">
                          <label class="control-label">E-mail</label>
                          <input type="text" class="form-control" name="Email" id="email" />
                        </div>
                      </div>
    
    
    
                    </div>
    
    
                  </div>
                </div>
              </div>
            </div>
            <div class="wizard-step">
              <div class="row">
                <div class="card shadow mb-4 w-100">
                  <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-primary">Security</h6>
                  </div>
                  <div class="card-body">
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Password</label>
                        <input type="password" class="form-control" name="Password" Name id="password" />
                        <ul class="form-text text-muted">
                          <li>Must be 8-20 characters long</li>
                          <li>Must contain at least 1 number</li>
                          <li>Must contain at least 1 uppercase letter</li>
                          <li>Must contain at least 1 lowercase letter </li>
                          <li>Must contain a special character (e.g. ! ; # * %)</li>
                        </ul>
                      </div>
                    </div>
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Confirm Password</label>
                        <input type="password" class="form-control" name="Confirm Password" id="cnfPassword" />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
    
            <div class="wizard-step">
              <div class="row">
                <div class="card shadow mb-4 w-100">
                  <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-primary">Affiliation</h6>
                  </div>
                  <div class="card-body">
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Church Affiliation 1</label><br />
                        <input type="text" class="form-control" name="Affiliation" Name id="affiliation1" />
                      </div>
                    </div>
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Church Affiliation 2</label><br />
                        <input type="text" class="form-control" name="Affiliation2" Name id="affiliation2" />
                      </div>
                    </div>
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Church Affiliation 3</label><br />
                        <input type="text" class="form-control" name="Affiliation3" Name id="affiliation3" />
                      </div>
                    </div>
                    <div class="row">
                      <div class="form-group col-md-12">
                        <label class="control-label">Church Affiliation 4</label><br />
                        <input type="text" class="form-control" name="Affiliation4" Name id="affiliation4" />
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
    
            <div class="wizard-step">
              <div class="row">
                <div class="card shadow mb-4 w-100">
                  <div class="card-header py-3">
                    <h6 class="m-0 font-weight-bold text-primary">Payment</h6>
                  </div>
                  <div class="card-body">
                    <row>
    
    
                      <div class="form-group">
                        <label for="card-number">
                                        Credit or debit card
                                    </label>
                        <div id="card-number">
                          <!-- A Stripe Element will be inserted here. -->
                        </div>
                      </div>
    
                      <div class="form-group">
                        <div class="row">
                          <div class="col-md-6">
                            <label for="card-vc">
                                                CVC
                                            </label>
                            <div id="card-cvc">
                              <!-- A Stripe Element will be inserted here. -->
                            </div>
                          </div>
                          <div class="col-md-6">
                            <label for="card-expiration">
                                                Exp
                                            </label>
                            <div id="card-expiration">
                              <!-- A Stripe Element will be inserted here. -->
                            </div>
                          </div>
                        </div>
                      </div>
                      <!-- Used to display form errors. -->
                      <div id="card-errors" role="alert"></div>
                  </div>
                </div>
              </div>
            </div>
            <p>
              <input type="button" id="back-step" name="back-step" value="< Back" />
              <input type="button" id="next-step" name="next-step" value="Next >" />
            </p>
          </div>
        </div>