Skip to content

Instantly share code, notes, and snippets.

@noahub
Last active May 19, 2022 23:35
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save noahub/b8c6d63abb50048d42ee721c900450df to your computer and use it in GitHub Desktop.
Save noahub/b8c6d63abb50048d42ee721c900450df to your computer and use it in GitHub Desktop.
Turn a regular form into a multi-step form
<style>
#container {
margin-top: -45px;
width: 100%;
height: 8px;
position: relative;
}
.lp-form-errors{
display: none !important;
}
.hasError{
border: 1px solid tomato !important;
box-shadow: 0px 0px 5px 1px tomato !important;
}
.hide {
display: none !important;
}
.lp-pom-form-field, .lp-pom-button {
-webkit-animation: KEYFRAME-NAME 2s;
-moz-animation: KEYFRAME-NAME 2s;
-o-animation: KEYFRAME-NAME 2s;
animation: KEYFRAME-NAME 2s;
}
@-webkit-keyframes KEYFRAME-NAME {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-moz-keyframes KEYFRAME-NAME {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-o-keyframes KEYFRAME-NAME {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes KEYFRAME-NAME {
0% { opacity: 0; }
100% { opacity: 1; }
}
</style>
<script type="text/javascript" src="https://rawgit.com/kimmobrunfeldt/progressbar.js/1.0.0/dist/progressbar.js"></script>
<script>
//Update the following IDs with your own button IDs
var backButton = document.getElementById('lp-pom-button-14');
var nextButton = document.getElementById('lp-pom-button-13');
var showProgressBar = false;
/*---------------
Global Vars
---------------*/
var submitButton = document.querySelector(".lp-pom-form .lp-pom-button");
var formContainer = document.querySelector(".lp-element .lp-pom-form");
var currentField = 0;
var allFields = document.getElementsByClassName("lp-pom-form-field");
var errorSpan = document.createElement('span');
/*---------------
Onload
---------------*/
//hide all form fields
for(i=0; i < allFields.length; i++){
allFields[i].classList.add('hide');
allFields[i].style.top = "0px";
}
//hide buttons
backButton.classList.add('hide');
submitButton.classList.add('hide');
//reveal first field
allFields[0].classList.remove('hide');
if (allFields[currentField].querySelector('input') && allFields[0].querySelector('input').type == "text"){
allFields[0].querySelector('input[type="text"]').focus();
}
//add error span
errorSpan.classList.add('hide');
errorSpan.style.color = 'red';
errorSpan.style.position = 'absolute';
var labelHeight;
if(allFields[0].querySelector('label')){
labelHeight = allFields[0].querySelector('label').clientHeight;
}else {
labelHeight = 25;
}
errorSpan.style.top = '-'+labelHeight+'px';
formContainer.appendChild(errorSpan);
//Set up Progress Bar
if(showProgressBar){
//add div
var progressContainer = document.createElement("div");
progressContainer.id = "container";
formContainer.appendChild(progressContainer);
//configure Progress Bar
var bar = new ProgressBar.Line(container, {
strokeWidth: 4,
easing: 'easeInOut',
duration: 1400,
color: '#FFEA82',
trailColor: '#eee',
trailWidth: 1,
svgStyle: {width: '100%', height: '100%'},
from: {color: '#FFEA82'},
to: {color: '#74D16A'},
text: {
style: {
// Text color.
// Default: same as stroke color (options.color)
color: '#fff',
position: 'absolute',
right: '0',
top: '30px',
padding: 0,
margin: 0,
transform: null
},
autoStyleContainer: false
},
step: function(state, bar) {
bar.setText((currentField+1) + ' of '+ allFields.length);
bar.path.setAttribute('stroke', state.color);
}
});
}
/*---------------
Functions
---------------*/
var nextEvent = function(){
//hide current field
allFields[currentField].classList.add('hide');
//reveal next field
currentField +=1;
allFields[currentField].classList.remove('hide');
if (allFields[currentField].querySelector('input') && allFields[currentField].querySelector('input').type == "text"){
allFields[currentField].querySelector('input[type="text"]').focus();
};
//if currentField > 0, show back
if(currentField > 0){
backButton.classList.remove('hide');
}
//if currentField = allFields show submit button
if(currentField == allFields.length-1){
submitButton.classList.remove('hide');
nextButton.classList.add('hide');
}
//progressbar
updateProgress();
};
var backEvent = function(){
//hide current field
allFields[currentField].classList.add('hide');
submitButton.classList.add('hide');
//reveal previous field
currentField -=1;
allFields[currentField].classList.remove('hide');
if (allFields[currentField].querySelector('input') && allFields[currentField].querySelector('input').type == "text"){
allFields[currentField].querySelector('input[type="text"]').focus();
};
//if currentField is 0, hide back button
if(currentField == 0){
backButton.classList.add('hide');
nextButton.classList.remove('hide');
}
if(currentField <= allFields.length-1){
nextButton.classList.remove('hide');
}
//progressbar
updateProgress();
};
var currentFieldInvalid = function(){
var invalid = false;
//run validation event
lp.jQuery('.lp-pom-form form').validate().form();
//get current field id
var currentId;
if(allFields[currentField].querySelector('input')){
currentId = allFields[currentField].querySelector('input').id;
}else{
currentId = allFields[currentField].children[1].id;
}
//get error list array of objects
var errorList = lp.jQuery('.lp-pom-form form').validate().errorList;
//is field id in error list
for(var i=0;i<errorList.length;i++){
if(currentId == errorList[i].element.id){
errorSpan.textContent = errorList[i].message;
invalid = true;
}
}
return invalid;
}
var updateProgress = function(){
if(showProgressBar){
var barSize = (currentField+1) / allFields.length;
bar.animate(barSize); // Number from 0.0 to 1.0
}
};
updateProgress();
/*---------------
Event Listeners
---------------*/
//click next
nextButton.addEventListener("click", function(e){
if(currentFieldInvalid()){
//add hasError to current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.add("hasError");
}else{
allFields[currentField].children[1].classList.add("hasError");
}
errorSpan.classList.remove('hide');
e.preventDefault();
}else{
//remove hasError from current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.remove("hasError");
}else{
allFields[currentField].children[1].classList.remove("hasError");
}
errorSpan.classList.add('hide');
nextEvent();
}
});
//click back
backButton.addEventListener("click", function(){
backEvent();
});
//submit button click
submitButton.addEventListener("click", function(e){
if(currentFieldInvalid()){
//add hasError to current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.add("hasError");
}else{
allFields[currentField].children[1].classList.add("hasError");
}
errorSpan.classList.remove('hide');
e.preventDefault();
}else{
//remove hasError from current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.remove("hasError");
}else{
allFields[currentField].children[1].classList.remove("hasError");
}
errorSpan.classList.add('hide');
}
});
//enter key
document.body.addEventListener('keydown', function(e) {
var keyCode = e.keyCode || e.which;
//enter key
if (keyCode === 13 && currentField < allFields.length-1) {
if(currentFieldInvalid()){
//add hasError to current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.add("hasError");
}else{
allFields[currentField].children[1].classList.add("hasError");
}
errorSpan.classList.remove('hide');
e.preventDefault();
}else{
//remove hasError from current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.remove("hasError");
}else{
allFields[currentField].children[1].classList.remove("hasError");
}
errorSpan.classList.add('hide');
e.preventDefault();
nextEvent();
}
}else if(keyCode === 13 && currentField === allFields.length-1){
if(currentFieldInvalid()){
//add hasError to current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.add("hasError");
}else{
allFields[currentField].children[1].classList.add("hasError");
}
errorSpan.classList.remove('hide');
e.preventDefault();
}else{
//remove hasError from current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.remove("hasError");
}else{
allFields[currentField].children[1].classList.remove("hasError");
}
errorSpan.classList.add('hide');
}
}
//left key
if (keyCode === 37){
if(currentField>0){
backEvent();
}
}
//right key
else if (keyCode === 39){
if(currentField < allFields.length-1){
if(currentFieldInvalid()){
//add hasError to current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.add("hasError");
}else{
allFields[currentField].children[1].classList.add("hasError");
}
errorSpan.classList.remove('hide');
e.preventDefault();
}else{
//remove hasError from current field
if(allFields[currentField].querySelector('input')){
allFields[currentField].querySelector('input').classList.remove("hasError");
}else{
allFields[currentField].children[1].classList.remove("hasError");
}
errorSpan.classList.add('hide');
nextEvent();
}
}
}
});
/**
* Do not remove this section; it allows our team to troubleshoot and track feature adoption.
* TS:0002-03-062
*/
</script>
@dunsterville
Copy link

Hey Noah, Awesome Script! Would there be a way to get multiple fields to show at once instead of one at a time? Would you have to create a separate variable that functions along with current field? Thanks!

@noahub
Copy link
Author

noahub commented Feb 1, 2017

@dunsterville I don't have a solution for this quite yet, it's something I'm look into though!

Keep an eye on community.unbounce.com for the latest!

@franciscoMigliardi24
Copy link

hey!
how can i make this form to look like this?
https://www.webistry.com/#step-1
I mean, to show a 2-3-4 imputs of the form before the "next"
thanks!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment