Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

406
Views
¿Cómo agregar botones de opción, casillas de verificación y seleccionar un campo en un formulario javascript de varios pasos?

Tengo el siguiente fragmento donde acepto los detalles a través de un formulario de varios pasos. El problema es que actualmente solo acepta los campos de entrada de texto. Como puede ver, la matriz de preguntas contiene el tipo de preguntas donde:

  1. La pregunta n. ° 1 está bien como entrada de texto, ya que aceptaría el nombre.
  2. La pregunta n.º 2 debería ser un botón de opción, ya que aceptaría el género.
  3. La pregunta n.º 3 debe volver a ser un campo de entrada de texto con un selector de fecha para la fecha de nacimiento,
  4. La pregunta n.º 4 debe ser un cuadro de selección para seleccionar un país de la lista y, por último,
  5. La pregunta n.º 5 debe tener el tipo de entrada como casilla de verificación para seleccionar todos aquellos usuarios que estén interesados en ver (hombre, mujer, otro).

Sin embargo, estoy atascado en la implementación de esto ya que soy nuevo en JavaScript. ¿Cómo puedo implementar esto?

La parte interesada del JavaScript es:

 // load the next question function putQuestion() { inputLabel.innerHTML = questions[position].question inputField.type = questions[position].type || 'text' inputField.value = questions[position].answer || '' inputField.focus() // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() }

Fragmento de trabajo completo.

 var questions = [ {question: "What's your full name?"}, // TEXT INPUT FIELD {question: "What's your gender?"}, // RADIO BUTTONS {male, female, other} {question: "What's your date of birth?"}, // TEXT INPUT FIELD WITH id="datepicker" {question: "What's your country?"}, // SELECT BOX WITH LIST OF COUNTRIES IN IT {question: "Interested in?"} // CHECKBOXES {male, female, other} ] //do something after the questions have been answered var onComplete = function() { var h1 = document.createElement('h1') h1.appendChild(document.createTextNode('Thanks ' + questions[0].answer + ' for checking this pen out!')) setTimeout(function() { register.parentElement.appendChild(h1) setTimeout(function() { h1.style.opacity = 1 }, 50) }, 1000) } ;(function(questions, onComplete) { var tTime = 100 // transition transform time from #register in ms var wTime = 200 // transition width time from #register in ms var eTime = 1000 // transition width time from inputLabel in ms // init if (questions.length == 0) return var position = 0 putQuestion() forwardButton.addEventListener('click', validate) inputField.addEventListener('keyup', function(e) { transform(0, 0) // ie hack to redraw if (e.keyCode == 13) validate() }) previousButton.addEventListener('click', function(e) { if (position === 0) return position -= 1 hideCurrent(putQuestion) }) // load the next question function putQuestion() { inputLabel.innerHTML = questions[position].question inputField.type = questions[position].type || 'text' inputField.value = questions[position].answer || '' inputField.focus() // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() } // when submitting the current question function validate() { var validateCore = function() { return inputField.value.match(questions[position].pattern || /.+/) } if (!questions[position].validate) questions[position].validate = validateCore // check if the pattern matches if (!questions[position].validate()) wrong(inputField.focus.bind(inputField)) else ok(function() { // execute the custom end function or the default value set if (questions[position].done) questions[position].done() else questions[position].answer = inputField.value ++position // if there is a new question, hide current and load next if (questions[position]) hideCurrent(putQuestion) else hideCurrent(function() { // remove the box if there is no next question register.className = 'close' progress.style.width = '100%' onComplete() }) }) } // helper function hideCurrent(callback) { inputContainer.style.opacity = 0 inputLabel.style.marginLeft = 0 inputProgress.style.width = 0 inputProgress.style.transition = 'none' inputContainer.style.border = null setTimeout(callback, wTime) } function showCurrent(callback) { inputContainer.style.opacity = 1 inputProgress.style.transition = '' inputProgress.style.width = '100%' setTimeout(callback, wTime) } function transform(x, y) { register.style.transform = 'translate(' + x + 'px , ' + y + 'px)' } function ok(callback) { register.className = '' setTimeout(transform, tTime * 0, 0, 10) setTimeout(transform, tTime * 1, 0, 0) setTimeout(callback, tTime * 2) } function wrong(callback) { register.className = 'wrong' for (var i = 0; i < 6; i++) // shaking motion setTimeout(transform, tTime * i, (i % 2 * 2 - 1) * 20, 0) setTimeout(transform, tTime * 6, 0, 0) setTimeout(callback, tTime * 7) } }(questions, onComplete))
 @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap'); body { margin: 0; background: #fbc02d; font-family: 'Roboto', sans-serif; overflow-x: hidden; } h1 { position: relative; color: #fff; opacity: 0; transition: .8s ease-in-out; } #progress { position: absolute; background: #c49000; height: 100vh; width: 0; transition: width 0.2s ease-in-out; } .center { height: 100vh; display: flex; justify-content: center; align-items: center; } #register { background: #fff; position: relative; width: 550px; box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.3); transition: transform .1s ease-in-out; } #register.close { width: 0; padding: 0; overflow: hidden; transition: .8s ease-in-out; box-shadow: 0 16px 24px 2px rgba(0,0,0,0); } #forwardButton { position: absolute; right: 20px; bottom: 5px; font-size: 40px; color: #fbc02d; float: right; cursor: pointer; z-index: 20 } #previousButton { position: absolute; font-size: 18px; left: 30px; /* same as padding on container */ top: 12px; z-index: 20; color: #9e9e9e; float: right; cursor: pointer; } #previousButton:hover {color: #c49000} #forwardButton:hover {color: #c49000} .wrong #forwardButton {color: #ff2d26} .close #forwardButton, .close #previousButton {color: #fff} #inputContainer { position: relative; padding: 30px 20px 20px 20px; margin: 10px 60px 10px 10px; opacity: 0; transition: opacity .3s ease-in-out; } #inputContainer input { position: relative; width: 100%; border: none; font-size: 20px; outline: 0; background: transparent; box-shadow: none; } #inputLabel { position: absolute; pointer-events: none; top: 32px; /* same as container padding + margin */ left: 20px; /* same as container padding */ font-size: 20px; transition: .2s ease-in-out; } #inputContainer input:valid + #inputLabel { top: 6px; left: 42px; /* space for previous arrow */ margin-left: 0!important; font-size: 11px; font-weight: normal; color: #9e9e9e; } #inputProgress { border-bottom: 3px solid #fbc02d; width: 0; transition: width .6s ease-in-out; } .wrong #inputProgress { border-color: #ff2d26; } @media (max-width: 420px) { #forwardButton {right: 10px} #previousButton {left: 10px} #inputLabel {left: 0} #inputContainer {padding-left: 0; margin-right:20px} }
 <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <div id="progress"></div> <div class="center"> <div id="register"> <i id="previousButton" class="ion-android-arrow-back"></i> <i id="forwardButton" class="ion-android-arrow-forward"></i> <div id="inputContainer"> <input id="inputField" required multiple /> <label id="inputLabel"></label> <div id="inputProgress"></div> </div> </div> </div>

Sé que necesito dar un ejemplo reproducible mínimo con un código limitado, pero pensé que crear un fragmento funcional daría una buena idea de este microproyecto. Cualquier ayuda sería apreciada. Gracias por adelantado :)

over 4 years ago · Santiago Trujillo
3 answers
Answer question

0

Parece que no está definiendo el tipo en la matriz de preguntas. Esta línea tiene como valor predeterminado todos los campos de entrada en texto porque no pudo encontrar el tipo.

inputField.type = preguntas[posición].tipo || 'texto'

 var questions = [ {question: "What's your full name?"}, // TEXT INPUT FIELD {question: "What's your gender?", type:"radio"}, // RADIO BUTTONS {male, female, other} {question: "What's your date of birth?"}, // TEXT INPUT FIELD WITH id="datepicker" {question: "What's your country?"}, // SELECT BOX WITH LIST OF COUNTRIES IN IT {question: "Interest in?"} // CHECKBOXES {male, female, other} ] //do something after the questions have been answered var onComplete = function() { var h1 = document.createElement('h1') h1.appendChild(document.createTextNode('Thanks ' + questions[0].answer + ' for checking this pen out!')) setTimeout(function() { register.parentElement.appendChild(h1) setTimeout(function() { h1.style.opacity = 1 }, 50) }, 1000) } ;(function(questions, onComplete) { var tTime = 100 // transition transform time from #register in ms var wTime = 200 // transition width time from #register in ms var eTime = 1000 // transition width time from inputLabel in ms // init if (questions.length == 0) return var position = 0 putQuestion() forwardButton.addEventListener('click', validate) inputField.addEventListener('keyup', function(e) { transform(0, 0) // ie hack to redraw if (e.keyCode == 13) validate() }) previousButton.addEventListener('click', function(e) { if (position === 0) return position -= 1 hideCurrent(putQuestion) }) // load the next question function putQuestion() { inputLabel.innerHTML = questions[position].question inputField.type = questions[position].type || 'text' inputField.value = questions[position].answer || '' inputField.focus() // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() } // when submitting the current question function validate() { var validateCore = function() { return inputField.value.match(questions[position].pattern || /.+/) } if (!questions[position].validate) questions[position].validate = validateCore // check if the pattern matches if (!questions[position].validate()) wrong(inputField.focus.bind(inputField)) else ok(function() { // execute the custom end function or the default value set if (questions[position].done) questions[position].done() else questions[position].answer = inputField.value ++position // if there is a new question, hide current and load next if (questions[position]) hideCurrent(putQuestion) else hideCurrent(function() { // remove the box if there is no next question register.className = 'close' progress.style.width = '100%' onComplete() }) }) } // helper function hideCurrent(callback) { inputContainer.style.opacity = 0 inputLabel.style.marginLeft = 0 inputProgress.style.width = 0 inputProgress.style.transition = 'none' inputContainer.style.border = null setTimeout(callback, wTime) } function showCurrent(callback) { inputContainer.style.opacity = 1 inputProgress.style.transition = '' inputProgress.style.width = '100%' setTimeout(callback, wTime) } function transform(x, y) { register.style.transform = 'translate(' + x + 'px , ' + y + 'px)' } function ok(callback) { register.className = '' setTimeout(transform, tTime * 0, 0, 10) setTimeout(transform, tTime * 1, 0, 0) setTimeout(callback, tTime * 2) } function wrong(callback) { register.className = 'wrong' for (var i = 0; i < 6; i++) // shaking motion setTimeout(transform, tTime * i, (i % 2 * 2 - 1) * 20, 0) setTimeout(transform, tTime * 6, 0, 0) setTimeout(callback, tTime * 7) } }(questions, onComplete))
 @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap'); body { margin: 0; background: #fbc02d; font-family: 'Roboto', sans-serif; overflow-x: hidden; } h1 { position: relative; color: #fff; opacity: 0; transition: .8s ease-in-out; } #progress { position: absolute; background: #c49000; height: 100vh; width: 0; transition: width 0.2s ease-in-out; } .center { height: 100vh; display: flex; justify-content: center; align-items: center; } #register { background: #fff; position: relative; width: 550px; box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.3); transition: transform .1s ease-in-out; } #register.close { width: 0; padding: 0; overflow: hidden; transition: .8s ease-in-out; box-shadow: 0 16px 24px 2px rgba(0,0,0,0); } #forwardButton { position: absolute; right: 20px; bottom: 5px; font-size: 40px; color: #fbc02d; float: right; cursor: pointer; z-index: 20 } #previousButton { position: absolute; font-size: 18px; left: 30px; /* same as padding on container */ top: 12px; z-index: 20; color: #9e9e9e; float: right; cursor: pointer; } #previousButton:hover {color: #c49000} #forwardButton:hover {color: #c49000} .wrong #forwardButton {color: #ff2d26} .close #forwardButton, .close #previousButton {color: #fff} #inputContainer { position: relative; padding: 30px 20px 20px 20px; margin: 10px 60px 10px 10px; opacity: 0; transition: opacity .3s ease-in-out; } #inputContainer input { position: relative; width: 100%; border: none; font-size: 20px; outline: 0; background: transparent; box-shadow: none; } #inputLabel { position: absolute; pointer-events: none; top: 32px; /* same as container padding + margin */ left: 20px; /* same as container padding */ font-size: 20px; transition: .2s ease-in-out; } #inputContainer input:valid + #inputLabel { top: 6px; left: 42px; /* space for previous arrow */ margin-left: 0!important; font-size: 11px; font-weight: normal; color: #9e9e9e; } #inputProgress { border-bottom: 3px solid #fbc02d; width: 0; transition: width .6s ease-in-out; } .wrong #inputProgress { border-color: #ff2d26; } @media (max-width: 420px) { #forwardButton {right: 10px} #previousButton {left: 10px} #inputLabel {left: 0} #inputContainer {padding-left: 0; margin-right:20px} }
 <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <div id="progress"></div> <div class="center"> <div id="register"> <i id="previousButton" class="ion-android-arrow-back"></i> <i id="forwardButton" class="ion-android-arrow-forward"></i> <div id="inputContainer"> <input id="inputField" required multiple /> <label id="inputLabel"></label> <div id="inputProgress"></div> </div> </div> </div>

over 4 years ago · Santiago Trujillo Report

0

Bien, primero, debe modificar su objeto de preguntas para que contenga las propiedades necesarias para crear sus elementos.

Luego, modifique un poco su html para que contenga otro contenedor dentro del contenedor de entrada donde pueda agregar campos de entrada adicionales (radio, casilla de verificación, seleccionar)

No estoy seguro si esto es lo que quieres, pero puedes referirte a esto:

 var questions = [{ question: "What's your full name?", type: 'text', name: 'fullname' }, // TEXT INPUT FIELD { question: "What's your gender?", type: 'radio', name: 'gender', values: ['male', 'female', 'other'] }, // RADIO BUTTONS {male, female, other} { question: "What's your date of birth?", type: 'text', name: 'dob' }, // TEXT INPUT FIELD WITH id="datepicker" { question: "What's your country?", type: 'select', name: 'country', values: ['Canada', 'US', 'Other'] }, // SELECT BOX WITH LIST OF COUNTRIES IN IT { question: "Interest in?", type: 'checkbox', name: 'interest', values: ['male', 'female', 'other'] } // CHECKBOXES {male, female, other} ] //do something after the questions have been answered var onComplete = function() { var h1 = document.createElement('h1') h1.appendChild(document.createTextNode('Thanks ' + questions[0].answer + ' for checking this pen out!')) setTimeout(function() { register.parentElement.appendChild(h1) setTimeout(function() { h1.style.opacity = 1 }, 50) }, 1000) } ; (function(questions, onComplete) { var tTime = 100 // transition transform time from #register in ms var wTime = 200 // transition width time from #register in ms var eTime = 1000 // transition width time from inputLabel in ms // init if (questions.length == 0) return var position = 0 putQuestion() forwardButton.addEventListener('click', validate) inputField.addEventListener('keyup', function(e) { transform(0, 0) // ie hack to redraw if (e.keyCode == 13) validate() }) previousButton.addEventListener('click', function(e) { if (position === 0) return position -= 1 hideCurrent(putQuestion) }) // load the next question function putQuestion() { //hide the elements that you create so they don't show up when you proceed to next steps const hideExtraElems = document.querySelectorAll('#inputWrapper span, #inputWrapper select'); hideExtraElems.forEach(elem => { elem.style.display = 'none'; }); inputLabel.innerHTML = questions[position].question inputField.type = questions[position].type || 'text' //add a name attribute so that radio buttons can work inputField.name = questions[position].name if (questions[position].type == 'radio' || questions[position].type == 'checkbox') { //validation for type radio and checkbox //hide the main input field inputField.style.visibility = 'hidden'; //loop through each value for questions[position].values.forEach(item => { //create a span that will contain your new input fields let innerWrapper = document.createElement("span"); //style a bit innerWrapper.style.display = 'flex'; innerWrapper.style. justifyContent = 'space-between'; //add value name inside the span before adding the element itself let textNode = document.createTextNode(item.toUpperCase()); //append the value name to the span element innerWrapper.appendChild(textNode); //create a new input either using createElement or clone your inputField let newInput = document.getElementById('inputField').cloneNode(true); //assign attributes accordingly newInput.type = questions[position].type; newInput.value = item; newInput.id = newInput.id + '-' + item; newInput.style.visibility = 'visible'; newInput.style.width = 'auto'; //append the input field inside the span innerWrapper.appendChild(newInput); //append the span inside the wrapper inputWrapper.appendChild(innerWrapper); }); } else if (questions[position].type == 'select') { //validation for select field //hide the main input field inputField.style.visibility = 'hidden'; //create the main select box outside the loop let newSelect = document.createElement("select"); //loop through the options questions[position].values.forEach(item => { //create an option element and assign the attributes let newOption = document.createElement("option"); let textNode = document.createTextNode(item.toUpperCase()); newOption.value = item; newOption.appendChild(textNode); //append the final option inside the select newSelect.appendChild(newOption); }); //append the select inside the inputWrapper inputWrapper.appendChild(newSelect); } else { //show the inputField inputField.style.visibility = 'visible'; inputField.value = questions[position].values || '' inputField.focus(); } // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() } // when submitting the current question function validate() { var validateCore = function() { return inputField.value.match(questions[position].pattern || /.+/) } if (!questions[position].validate) questions[position].validate = validateCore // check if the pattern matches if (!questions[position].validate()) wrong(inputField.focus.bind(inputField)) else ok(function() { // execute the custom end function or the default value set if (questions[position].done) questions[position].done() else questions[position].answer = inputField.value ++position // if there is a new question, hide current and load next if (questions[position]) hideCurrent(putQuestion) else hideCurrent(function() { // remove the box if there is no next question register.className = 'close' progress.style.width = '100%' onComplete() }) }) } // helper function hideCurrent(callback) { inputContainer.style.opacity = 0 inputLabel.style.marginLeft = 0 inputProgress.style.width = 0 inputProgress.style.transition = 'none' inputContainer.style.border = null setTimeout(callback, wTime) } function showCurrent(callback) { inputContainer.style.opacity = 1 inputProgress.style.transition = '' inputProgress.style.width = '100%' setTimeout(callback, wTime) } function transform(x, y) { register.style.transform = 'translate(' + x + 'px , ' + y + 'px)' } function ok(callback) { register.className = '' setTimeout(transform, tTime * 0, 0, 10) setTimeout(transform, tTime * 1, 0, 0) setTimeout(callback, tTime * 2) } function wrong(callback) { register.className = 'wrong' for (var i = 0; i < 6; i++) // shaking motion setTimeout(transform, tTime * i, (i % 2 * 2 - 1) * 20, 0) setTimeout(transform, tTime * 6, 0, 0) setTimeout(callback, tTime * 7) } }(questions, onComplete))
 @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap'); body { margin: 0; background: #fbc02d; font-family: 'Roboto', sans-serif; overflow-x: hidden; } h1 { position: relative; color: #fff; opacity: 0; transition: .8s ease-in-out; } #progress { position: absolute; background: #c49000; height: 100vh; width: 0; transition: width 0.2s ease-in-out; } select{ width: 100%; border: 0; outline: none; padding: 1rem 0; } .center { height: 100vh; display: flex; justify-content: center; align-items: center; } #register { background: #fff; position: relative; width: 550px; box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.3); transition: transform .1s ease-in-out; } #register.close { width: 0; padding: 0; overflow: hidden; transition: .8s ease-in-out; box-shadow: 0 16px 24px 2px rgba(0,0,0,0); } #forwardButton { position: absolute; right: 20px; bottom: 5px; font-size: 40px; color: #fbc02d; float: right; cursor: pointer; z-index: 20 } #previousButton { position: absolute; font-size: 18px; left: 30px; /* same as padding on container */ top: 12px; z-index: 20; color: #9e9e9e; float: right; cursor: pointer; } #previousButton:hover {color: #c49000} #forwardButton:hover {color: #c49000} .wrong #forwardButton {color: #ff2d26} .close #forwardButton, .close #previousButton {color: #fff} #inputContainer { position: relative; padding: 30px 20px 20px 20px; margin: 10px 60px 10px 10px; opacity: 0; transition: opacity .3s ease-in-out; } #inputContainer input { position: relative; width: 100%; border: none; font-size: 20px; outline: 0; background: transparent; box-shadow: none; } #inputLabel { position: absolute; pointer-events: none; top: 32px; /* same as container padding + margin */ left: 20px; /* same as container padding */ font-size: 20px; transition: .2s ease-in-out; } #inputContainer input:valid + #inputLabel { top: 6px; left: 42px; /* space for previous arrow */ margin-left: 0!important; font-size: 11px; font-weight: normal; color: #9e9e9e; } #inputProgress { border-bottom: 3px solid #fbc02d; width: 0; transition: width .6s ease-in-out; } .wrong #inputProgress { border-color: #ff2d26; } @media (max-width: 420px) { #forwardButton {right: 10px} #previousButton {left: 10px} #inputLabel {left: 0} #inputContainer {padding-left: 0; margin-right:20px} }
 <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <div id="progress"></div> <div class="center"> <div id="register"> <i id="previousButton" class="ion-android-arrow-back"></i> <i id="forwardButton" class="ion-android-arrow-forward"></i> <div id="inputContainer"> <div id="inputWrapper"> <input id="inputField" required multiple /> <label id="inputLabel"></label> </div> <div id="inputProgress"></div> </div> </div> </div>

over 4 years ago · Santiago Trujillo Report

0

Hice lo mejor que pude para hacer lo que me pediste, verás que agregué 3 divs para incluir tus diferentes solicitudes

También modifico tu condición de validación.

Esperando que pueda ayudarte

 var questions = [ { question: "What's your full name?", type: "text" }, // TEXT INPUT FIELD { question: "What's your gender?", type: "radio", response: ['male','female','other'] }, // RADIO BUTTONS {male, female, other} { question: "What's your date of birth?", type: "date" }, // TEXT INPUT FIELD WITH id="datepicker" { question: "What's your country?", type: "select", response: ['UK','FR','DE'] }, // SELECT BOX WITH LIST OF COUNTRIES IN IT { question: "Interest in?", type: "checkbox", response: ['male','female','other'] } // CHECKBOXES {male, female, other} ] //do something after the questions have been answered var onComplete = function() { var h1 = document.createElement('h1') h1.appendChild(document.createTextNode('Thanks ' + questions[0].answer + ' for checking this pen out!')) setTimeout(function() { register.parentElement.appendChild(h1) setTimeout(function() { h1.style.opacity = 1 }, 50) }, 1000) } ;(function(questions, onComplete) { var tTime = 100 // transition transform time from #register in ms var wTime = 200 // transition width time from #register in ms var eTime = 1000 // transition width time from inputLabel in ms // init if (questions.length == 0) return var position = 0 putQuestion() forwardButton.addEventListener('click', validate) inputField.addEventListener('keyup', function(e) { transform(0, 0) // ie hack to redraw if (e.keyCode == 13) validate() }) previousButton.addEventListener('click', function(e) { if (position === 0) return position -= 1 hideCurrent(putQuestion) $('#gender').hide(); $('#country').hide(); $('#interest').hide(); }) // load the next question function putQuestion() { $('#gender').hide(); $('#country').hide(); $('#interest').hide(); $(inputField).attr('readonly',false); $(inputField).attr('required',false); inputLabel.innerHTML = questions[position].question; inputField.type = 'text'; switch(questions[position].type){ case "text": $(inputField).attr('required',true) inputField.value = questions[position].answer || ''; break; case "radio": $(inputField).attr('readonly',true) inputField.value = ''; let nbrGender = questions[position].response; if( $('#gender').children().length > 0 ){ $('#gender').children().remove() } $('#gender').show(); for( var $i = 0; $i < nbrGender.length; ++$i ){ let checkedGender = questions[position].answer == questions[position].response[$i] ? 'checked' : ''; $('#gender').append( '<input type="radio" name="onlyone" value="'+questions[position].response[$i]+'" '+checkedGender+'>'+ '<label id="text'+$i+'">'+questions[position].response[$i]+'</label>' ); } break; case "date": inputField.type = 'date'; inputField.value = questions[position].answer; break; case "select": $(inputField).attr('readonly',true) inputField.value = ''; var nbrCountry = questions[position].response; if( $('#country').children().length > 0 ){ $('#country').children().remove() } $('#country').show(); var optionCountry; for( var $i = 0; $i < nbrCountry.length; ++$i ){ let selectedCountry = questions[position].answer == questions[position].response[$i] ? 'selected' : ''; optionCountry += '<option value="'+questions[position].response[$i]+'" '+selectedCountry+'>'+questions[position].response[$i]+'</option>' } $('#country').append(' <select name="gender" id="countryList">'+optionCountry+'</select>') break; case "checkbox": $(inputField).attr('readonly',true) inputField.value = ''; let nbrInterest = questions[position].response; if( $('#interest').children().length > 0 ){ $('#interest').children().remove() } $('#interest').show(); for( var $i = 0; $i < nbrInterest.length; ++$i ){ let checkedInterest = questions[position].answer == questions[position].response[$i] ? 'checked' : ''; $('#interest').append( '<input type="checkbox" name="onlyone" value="'+questions[position].response[$i]+'" '+checkedInterest+'>'+ '<label id="text'+$i+'">'+questions[position].response[$i]+'</label>' ); } break; default: inputField.type = 'text'; inputField.value = questions[position].answer || ''; break; } inputField.focus() // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() } // when submitting the current question function validate() { var validateCore = function() { if(inputField.type == "date" && inputField.value ){ questions[position].answer =inputField.value; return true; }else if ( inputField.type != "date" ){ if(inputField.value.match(questions[position].pattern || /.+/) ){ questions[position].answer =inputField.value; return true; } else if( $('#countryList').is(':visible') && $('#countryList').find(':selected').length > 0 ){ questions[position].answer = $('#country').find(':selected')[0].value return true; } else if( $('#gender').is(':visible') && $('#gender').find(':checked').length > 0 ){ questions[position].answer = $('#gender').find(':checked')[0].value return true; }else if( $('#interest').is(':visible') && $('#interest').find(':checked').length > 0 ){ let responseInterest = []; $('#interest').find(':checked').each(function(){ responseInterest.push($(this).val()); }); questions[position].answer = responseInterest; return true; } else{ return false; } }else{ return false } } if (!questions[position].validate) questions[position].validate = validateCore // check if the pattern matches if (!questions[position].validate()) wrong(inputField.focus.bind(inputField)) else ok(function() { // execute the custom end function or the default value set if (questions[position].done) questions[position].done() ++position // if there is a new question, hide current and load next if (questions[position]) hideCurrent(putQuestion) else hideCurrent(function() { // remove the box if there is no next question register.className = 'close' progress.style.width = '100%' onComplete() }) }) } // helper function hideCurrent(callback) { inputContainer.style.opacity = 0 inputLabel.style.marginLeft = 0 inputProgress.style.width = 0 inputProgress.style.transition = 'none' inputContainer.style.border = null setTimeout(callback, wTime) } function showCurrent(callback) { inputContainer.style.opacity = 1 inputProgress.style.transition = '' inputProgress.style.width = '100%' setTimeout(callback, wTime) } function transform(x, y) { register.style.transform = 'translate(' + x + 'px , ' + y + 'px)' } function ok(callback) { register.className = '' setTimeout(transform, tTime * 0, 0, 10) setTimeout(transform, tTime * 1, 0, 0) setTimeout(callback, tTime * 2) } function wrong(callback) { register.className = 'wrong' for (var i = 0; i < 6; i++) // shaking motion setTimeout(transform, tTime * i, (i % 2 * 2 - 1) * 20, 0) setTimeout(transform, tTime * 6, 0, 0) setTimeout(callback, tTime * 7) } }(questions, onComplete)) // load the next question function putQuestion() { inputLabel.innerHTML = questions[position].question inputField.type = questions[position].type || 'text' inputField.value = questions[position].answer || '' inputField.focus() // set the progress of the background progress.style.width = position * 100 / questions.length + '%' previousButton.className = position ? 'ion-android-arrow-back' : 'ion-person' showCurrent() }
 @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@100&display=swap'); body { margin: 0; background: #fbc02d; font-family: 'Roboto', sans-serif; overflow-x: hidden; } h1 { position: relative; color: #fff; opacity: 0; transition: .8s ease-in-out; } #progress { position: absolute; background: #c49000; height: 100vh; width: 0; transition: width 0.2s ease-in-out; } .center { height: 100vh; display: flex; justify-content: center; align-items: center; } #register { background: #fff; position: relative; width: 550px; box-shadow: 0 16px 24px 2px rgba(0,0,0,0.14), 0 6px 30px 5px rgba(0,0,0,0.12), 0 8px 10px -5px rgba(0,0,0,0.3); transition: transform .1s ease-in-out; } #register.close { width: 0; padding: 0; overflow: hidden; transition: .8s ease-in-out; box-shadow: 0 16px 24px 2px rgba(0,0,0,0); } #forwardButton { position: absolute; right: 20px; bottom: 5px; font-size: 40px; color: #fbc02d; float: right; cursor: pointer; z-index: 20 } #previousButton { position: absolute; font-size: 18px; left: 30px; /* same as padding on container */ top: 12px; z-index: 20; color: #9e9e9e; float: right; cursor: pointer; } #previousButton:hover {color: #c49000} #forwardButton:hover {color: #c49000} .wrong #forwardButton {color: #ff2d26} .close #forwardButton, .close #previousButton {color: #fff} #inputContainer { position: relative; padding: 30px 20px 20px 20px; margin: 10px 60px 10px 10px; opacity: 0; transition: opacity .3s ease-in-out; } #inputContainer input { position: relative; width: 100%; border: none; font-size: 20px; outline: 0; background: transparent; box-shadow: none; } #inputLabel { position: absolute; pointer-events: none; top: 32px; /* same as container padding + margin */ left: 20px; /* same as container padding */ font-size: 20px; transition: .2s ease-in-out; } #inputContainer input:valid + #inputLabel { top: 6px; left: 42px; /* space for previous arrow */ margin-left: 0!important; font-size: 11px; font-weight: normal; color: #9e9e9e; } #inputProgress { border-bottom: 3px solid #fbc02d; width: 0; transition: width .6s ease-in-out; } .wrong #inputProgress { border-color: #ff2d26; } @media (max-width: 420px) { #forwardButton {right: 10px} #previousButton {left: 10px} #inputLabel {left: 0} #inputContainer {padding-left: 0; margin-right:20px} }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <link rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css"> <div id="progress"></div> <div class="center"> <div id="register"> <i id="previousButton" class="ion-android-arrow-back"></i> <i id="forwardButton" class="ion-android-arrow-forward"></i> <div id="inputContainer"> <input id="inputField" /> <label id="inputLabel"></label> <div id="inputProgress"></div> <div id="gender"></div> <div id="country"></div> <div id="interest"></div> </div> </div> </div>

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!