Last active
February 5, 2018 14:55
-
-
Save tomsihap/58763d54259cc888b4df377c1ba2cd69 to your computer and use it in GitHub Desktop.
Step by step form with jQuery & Bootstrap -- v0.1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script src="steps.js"></script> | |
<link href="steps.css" rel="stylesheet"> | |
<div class="container container-flex"> | |
<ul id="steps" class="list-inline"> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="1" data-complete="1" data-currentstep="1" class="btn btn-sm">1</label> | |
</li> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="2" data-complete="0" data-currentstep="0" class="btn btn-sm">2</label> | |
</li> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="3" data-complete="0" data-currentstep="0" class="btn btn-sm">3</label> | |
</li> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="4" data-complete="0" data-currentstep="0" class="btn btn-sm">4</label> | |
</li> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="5" data-complete="0" data-currentstep="0" class="btn btn-sm">5</label> | |
</li> | |
<li class="list-inline-item"> | |
<label data-role='change' data-step="6" data-complete="0" data-currentstep="0" class="btn btn-sm">Done !</label> | |
</li> | |
</ul> | |
<div id="stepalert" class="alert alert-danger alert-dismissible fade show" role="alert" style="display:none;"> | |
<strong>Oups !</strong> An alert when you click on a step before completing the previous ones. | |
<button id="closealert" type="button" class="close" aria-label="Close"> <span aria-hidden="true">×</span> </button> | |
</div> | |
<div id="form-steps"> | |
<form id="form"> | |
<!-- STEP 1--> | |
<div data-step="1" class="card step" style="display:none;"> | |
<div class="card-body"> | |
<h5 class="card-title">First step!</h5> | |
<p class="card-text">Nice text to introduce your form.</p> | |
</div> | |
<div class="card-footer"> | |
<a data-step="1" data-role="next" href="#" class="btn btn-primary pull-right">Call to action! <i class="fa fa-arrow-right" aria-hidden="true"></i></a> | |
</div> | |
</div> | |
<!-- STEP 2--> | |
<div data-step="2" class="card step" style="display:none;"> | |
<div class="card-body"> | |
<h5 class="card-title">Nice second step</h5> | |
<label for="short_description">Name</label> | |
<input type="text" class="form-control form-control-sm"> | |
<small class="form-text text-muted">Little explanation on why your name is an important one.</small> | |
<label for="name">Mon nom complet</label> | |
<input type="text" name="name" id="name" class="form-control form-control-sm"> | |
<label for="birthdate">My birthdate</label> | |
<input type="date" class="form-control form-control-sm"> | |
</div> | |
<div class="card-footer"> | |
<a data-step="2" data-role="prev" href="#" class="btn btn-success"><i class="fa fa-arrow-left" aria-hidden="true"></i> Previous page</a> | |
<a data-step="2" data-role="next" href="#" class="btn btn-success pull-right">Next page <i class="fa fa-arrow-right" aria-hidden="true"></i></a> | |
</div> | |
</div> | |
... | |
<!-- LAST STEP --> | |
<div data-step="5" class="card step" style="display:none;"> | |
<div class="card-body"> | |
<h5 class="card-title">Mes documents</h5> | |
<div class="form-check"> | |
<input class="form-check-input" type="checkbox" required> | |
<label class="form-check-label" for=""> | |
I've read the terms & conditions, etc. | |
</label> | |
</div> | |
</div> | |
<div class="card-footer"> | |
<a data-step="5" data-role="prev" href="#" class="btn btn-success"><i class="fa fa-arrow-left" aria-hidden="true"></i> Previous page</a> | |
<button type="submit" class="btn btn-primary pull-right">Done ! <i class="fa fa-arrow-right" aria-hidden="true"></i></button> | |
</div> | |
</div> | |
</form> | |
</div> | |
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@media screen and (min-width: 992px) { | |
.container-flex { | |
max-width: 40%; | |
} | |
} | |
label { | |
margin-top: 8px; | |
margin-bottom: 0px; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$(function () { | |
// Onclick sur next ! | |
$('a[data-role=\'next\']').each(function () { | |
$(this).on('click', function () { | |
nextStepFrom($(this).data('step')); | |
}); | |
}); | |
// Onclick sur prev ! | |
$('a[data-role=\'prev\']').each(function () { | |
$(this).on('click', function () { | |
prevStepFrom($(this).data('step')); | |
}); | |
}); | |
// Onclick sur label de step ! Uniquement si le data-complete = 1 du currentstep ou si data-current = 1 | |
$('label[data-role=\'change\']').each(function () { | |
$(this).on('click', function () { | |
console.log('this data step : ' + $(this).data('step')); | |
// Si data-complete = 1 OU data-current = 1, sinon trigger Error | |
if ($('label[data-step=' + $(this).data('step') + ']').data('complete') == 1 || $('label[data-step=' + (parseInt($(this).data('step') - 1)) + ']').data('complete') == 1) { | |
prevStep($(this).data('step')); | |
} | |
else { alertIncomplete(); } | |
}); | |
}); | |
// Onclick sur nextstepfrom (ou prevstep afin de prévenir une modif après un retour sur un ancien form), on vérifie que tous les autres forms sont complete | |
var checkCompleteBeforeNext = function (requestedStep) { | |
let completes = []; | |
// On teste les labels | |
$('label[data-complete]').each(function () { | |
// On teste uniquement les labels précédents à celui qu'on requête | |
if ($(this).data('step') < requestedStep) { | |
if ($(this).data('complete') == 1) { completes.push(true); } | |
else { completes.push(false); } | |
} | |
}); | |
// S'il y a un false dans l'array c'est qu'un des champ n'est pas complete | |
if ($.inArray(completes, false) > -1) { | |
console.log(completes); | |
alertIncomplete(); | |
return false; | |
} | |
else { | |
return true; | |
} | |
} | |
// click sur suivant | |
var nextStepFrom = function (currentStep) { | |
let current = currentStep; | |
let next = currentStep + 1; | |
checkAndSetComplete(current); | |
if (checkCompleteBeforeNext(next)) { | |
$('label[data-step=' + current + ']').data('currentstep', 0); | |
$('label[data-step=' + next + ']').data('currentstep', 1); | |
checkCompletedForm(); | |
} | |
} | |
// click sur précédent | |
var prevStepFrom = function (currentStep) { | |
let current = currentStep; | |
let prev = currentStep - 1; | |
$('label[data-step=' + current + ']').data('currentstep', 0); | |
$('label[data-step=' + prev + ']').data('currentstep', 1); | |
checkCompletedForm(); | |
} | |
// click sur un label de step | |
var prevStep = function (step) { | |
if (checkCompleteBeforeNext(step)) { | |
$('label[data-step]').each(function () { | |
$(this).data('currentstep', 0); | |
}); | |
$('label[data-step=' + step + ']').data('currentstep', 1); | |
checkCompletedForm(); | |
} | |
} | |
var setDisabled = function (el) { | |
el.attr('disabled', true).removeClass('btn-primary').removeClass('btn-success').addClass('btn-disabled'); | |
} | |
var setCurrent = function (el) { | |
el.attr('disabled', false).removeClass('btn-success').removeClass('btn-disabled').addClass('btn-primary'); | |
} | |
var setComplete = function (el) { | |
el.attr('disabled', false).removeClass('btn-primary').removeClass('btn-disabled').addClass('btn-success'); | |
} | |
// Affichage du step en cours | |
var showCurrentForm = function () { | |
$('div[data-step]').each(function () { | |
// Si c'est le current-step | |
if ($('label[data-step=' + $(this).data('step') + ']').data('currentstep') == 1) { $(this).show(); } | |
else { $(this).hide(); } | |
}) | |
} | |
var checkAndSetComplete = function (stepId) { | |
$('label[data-step=' + stepId + ']').data('complete', 1); | |
} | |
// Vérifie l'état des forms pour affichage des labels - appelé onload et onclick sur prev, next, change | |
var checkCompletedForm = function () { | |
$('label[data-step]').each(function () { | |
// Si c'est le current-step | |
if ($(this).data('currentstep') == 1) { setCurrent($(this)); } | |
// Sinon il est soit avant soit après | |
else { | |
if ($(this).data('complete') == 1) { setComplete($(this)); } | |
// Sinon il est incomplet c'est une nextstep | |
else { setDisabled($(this)); } | |
} | |
}); | |
// On cache l'alerte si elle s'était trigger | |
$('#stepalert').hide(); | |
showCurrentForm(); | |
} | |
// Appelée dans checkCompleteBeforeNext() si suivant erroné, et dans le onclick label change | |
var alertIncomplete = function () { | |
$('#stepalert').show(); | |
$('#closealert').on('click', function () { | |
$('#stepalert').hide(); | |
}); | |
} | |
// On check une première fois tous les forms | |
checkCompletedForm(); | |
}); |
Author
tomsihap
commented
Feb 5, 2018
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment