Last active
May 19, 2022 23:35
-
-
Save noahub/b8c6d63abb50048d42ee721c900450df to your computer and use it in GitHub Desktop.
Turn a regular form into a multi-step form
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
<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> |
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 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 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!
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
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!