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
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>