使用 JavaScript 多步骤表单进行联系表单验证

Posted

技术标签:

【中文标题】使用 JavaScript 多步骤表单进行联系表单验证【英文标题】:contact form Validation with JavaScript multi step form 【发布时间】:2021-01-14 03:18:18 【问题描述】:

我目前有一个使用 javascript 进行下一步的多步骤联系表单,但我需要添加输入验证,以便在进入下一步之前检查输入是否被选中或填写,它继续下一步,不检查是否已填写。

//jQuery time
var current_fs, next_fs, previous_fs; //fieldsets
var left, opacity, scale; //fieldset properties which we will animate
var animating; //flag to prevent quick multi-click glitches

$(".next").click(function() 
  if (animating) return false;
  animating = true;

  current_fs = $(this).parent();
  next_fs = $(this).parent().next();

  //activate next step on progressbar using the index of next_fs
  $("#progressbar li").eq($("fieldset").index(next_fs)).addClass("active");

  //show the next fieldset
  next_fs.show();
  //hide the current fieldset with style
  current_fs.animate(
    opacity: 0
  , 
    step: function(now, mx) 
      //as the opacity of current_fs reduces to 0 - stored in "now"
      //1. scale current_fs down to 80%
      scale = 1 - (1 - now) * 0.2;
      //2. bring next_fs from the right(50%)
      left = (now * 50) + "%";
      //3. increase opacity of next_fs to 1 as it moves in
      opacity = 1 - now;
      current_fs.css(
        'transform': 'scale(' + scale + ')',
        'position': 'absolute'
      );
      next_fs.css(
        'left': left,
        'opacity': opacity
      );
    ,
    duration: 800,
    complete: function() 
      current_fs.hide();
      animating = false;
    ,
    //this comes from the custom easing plugin
    easing: 'easeInOutBack'
  );
);

$(".previous").click(function() 
  if (animating) return false;
  animating = true;

  current_fs = $(this).parent();
  previous_fs = $(this).parent().prev();

  //de-activate current step on progressbar
  $("#progressbar li").eq($("fieldset").index(current_fs)).removeClass("active");

  //show the previous fieldset
  previous_fs.show();
  //hide the current fieldset with style
  current_fs.animate(
    opacity: 0
  , 
    step: function(now, mx) 
      //as the opacity of current_fs reduces to 0 - stored in "now"
      //1. scale previous_fs from 80% to 100%
      scale = 0.8 + (1 - now) * 0.2;
      //2. take current_fs to the right(50%) - from 0%
      left = ((1 - now) * 50) + "%";
      //3. increase opacity of previous_fs to 1 as it moves in
      opacity = 1 - now;
      current_fs.css(
        'left': left
      );
      previous_fs.css(
        'transform': 'scale(' + scale + ')',
        'opacity': opacity
      );
    ,
    duration: 800,
    complete: function() 
      current_fs.hide();
      animating = false;
    ,
    //this comes from the custom easing plugin
    easing: 'easeInOutBack'
  );
);

$(".submit").click(function() 
  return false;
)
#msform 
  max-width: 400px;
  margin: 50px auto;
  text-align: center;
  position: relative;


#msform fieldset 
  background: white;
  border: 0 none;
  border-radius: 3px;
  box-shadow: 0 0 15px 1px rgba(0, 0, 0, 0.4);
  padding: 20px 30px;
  box-sizing: border-box;
  width: 100%;
  margin: 0 auto;
  /*stacking fieldsets above each other*/
  position: relative;



/*Hide all except the first fieldset*/

#msform fieldset:not(:first-of-type) 
  display: none;



/*inputs*/

#msform input,
#msform textarea 
  padding: 15px;
  border: 1px solid #ccc;
  border-radius: 3px;
  margin-bottom: 10px;
  width: 100%;
  box-sizing: border-box;
  font-family: montserrat;
  color: #2C3E50;
  font-size: 13px;


.field 
  text-align: left;
  width: auto !important;
  border: 1px solid #81e2ff;
  border-top: none;
  padding: 10px;
  #radio-select 
    width: auto;
  



/*buttons*/

#msform .action-button 
  width: 100px;
  background: #27AE60;
  font-weight: bold;
  color: white;
  border: 0 none;
  border-radius: 1px;
  cursor: pointer;
  padding: 10px 5px;
  margin: 10px 5px;


#msform .action-button:hover,
#msform .action-button:focus 
  box-shadow: 0 0 0 2px white, 0 0 0 3px #27AE60;



/*headings*/

.fs-title 
  font-size: 15px;
  text-transform: uppercase;
  color: #2C3E50;
  margin-bottom: 10px;


.fs-subtitle 
  font-weight: normal;
  font-size: 13px;
  color: #666;
  margin-bottom: 20px;



/*progressbar*/

#progressbar 
  margin-bottom: 30px;
  overflow: hidden;
  /*CSS counters to number the steps*/
  counter-reset: step;


#progressbar li 
  list-style-type: none;
  color: white;
  text-transform: uppercase;
  font-size: 9px;
  width: 33.33%;
  float: left;
  position: relative;


#progressbar li:before 
  content: counter(step);
  counter-increment: step;
  width: 20px;
  line-height: 20px;
  display: block;
  font-size: 10px;
  color: #333;
  background: white;
  border-radius: 3px;
  margin: 0 auto 5px auto;



/*progressbar connectors*/

#progressbar li:after 
  content: '';
  width: 100%;
  height: 2px;
  background: white;
  position: absolute;
  left: -50%;
  top: 9px;
  z-index: -1;
  /*put it behind the numbers*/


#progressbar li:first-child:after 
  /*connector not needed before the first step*/
  content: none;



/*marking active/completed steps green*/


/*The number of the step and the connector before it = green*/

#progressbar li.active:before,
#progressbar li.active:after 
  background: #27AE60;
  color: white;

<form name="myform" id="msform" action="formhandler.php" method="POST" onsubmit="return validateForm()" onkeydown="return event.key != 'Enter';">
  <!-- progressbar -->
  <!-- fieldsets -->
  <fieldset>
    <h2 class="fs-title">WHERE DO YOU NEED FENCERS?</h2>
    <input type="text" name="postcode" id="search_term" placeholder="Enter postcode or town/city" Autocomplete="off" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>
  <fieldset>
    <h2 class="fs-title">What type of property is this for?</h2>
    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="property" value="House">
      <label for="Property">House</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="property" value="Flat">
      <label for="Property">Flat</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="property" value="Bungalow">
      <label for="Property">Bungalow</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="property" value="commercial place">
      <label for="Property">commercial place</label><br>
    </div>
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>
  <fieldset>
    <h2 class="fs-title">What does this project invole?</h2>
    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="install a new fence">
      <label for="Project">install a new fence</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="install a new gate">
      <label for="Project">install a new gate</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="Repair an existing fence">
      <label for="Project">Repair an existing fence</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="Repair an existing gate">
      <label for="Project">Repair an existing gate</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="Replace an existing fence">
      <label for="Project">Replace an existing fence</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="project" value="Replace an existing gate">
      <label for="Project">Replace an existing gate</label><br>
    </div>

    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>
  <fieldset>
    <h2 class="fs-title">What material would you like for the project?</h2>
    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="material" value="Wood">
      <label for="material">Wood</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="material" value="Steel">
      <label for="material">steel</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="material" value="Vinyl">
      <label for="material">Vinyl</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="material" value="Not Sure Please Recommend">
      <label for="material">Not Sure Please Recommend</label><br>
    </div>
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>
  <fieldset>
    <h2 class="fs-title">How high should the fence be?</h2>
    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="Under 4 Feet">
      <label for="height">Under 4 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="4 Feet">
      <label for="height">4 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="5 Feet">
      <label for="height">5 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="6 Feet">
      <label for="height">6 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="7 Feet">
      <label for="height">7 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="8 Feet">
      <label for="height">8 Feet</label><br>
    </div>


    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="Over 8 Feet">
      <label for="height">Over 8 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="height" value="As recommended by professional">
      <label for="height">As recommended by professional</label><br>
    </div>


    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>
  <fieldset>
    <h2 class="fs-title">How long will the fence approximately be??</h2>
    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="Under 50 Feet">
      <label for="length">Under 50 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="50-100 Feet">
      <label for="length">50-100 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="100-200 Feet">
      <label for="length">100-200Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="200-300 Feet">
      <label for="length">200-300 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="Over 300 Feet ">
      <label for="length">Over 300 Feet</label><br>
    </div>

    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="I'm not sure">
      <label for="length">I'm not sure</label><br>
    </div>


    <div class="field" id="property-radio">
      <input type="radio" id="radio-select" name="length" value="Other">
      <label for="length">Other</label><br>
    </div>
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>

  <fieldset>
    <h2 class="fs-title">What email address would you like your quote sent to?</h2>
    <input type="email" name="email" placeholder="email address" />
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>

  <fieldset>
    <h2 class="fs-title">What is your phone number?</h2>
    <input type="tel" name="phone" placeholder="Phone Number" />
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <input type="button" name="next" class="next action-button" value="Next" />
  </fieldset>

  <fieldset>
    <h2 class="fs-title">What email address would you like your quote sent to?</h2>
    <input type="text" name="fname" placeholder="email address" />
    <input type="button" name="previous" class="previous action-button" value="Previous" />
    <button type="submit" class="next action-button">Submit</button>
  </fieldset>
</form>

【问题讨论】:

有很多方法可以做到这一点,我使用了一个名为 jQuery Validation 的插件:jqueryvalidation.org 感谢您的回复。这是我第一次使用 javascript,所以我不熟悉它,请您进一步解释如何将建议的验证添加到联系表单中谢谢 【参考方案1】:

我创建了一个working fiddle,它展示了如何将 jQuery Validate 与您的代码一起用于前两个步骤在您的步骤进展中。

这就是我所做的:

加载了 jquery validate 插件:

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-validate/1.19.1/jquery.validate.min.js" integrity="sha512-0QDLUJ0ILnknsQdYYjG7v2j8wERkKufvjBNmng/EdR/s/SE7X8cQ9y0+wMzuQT0lfXQ/NhG+zhmHNOWTUS3kMA==" crossorigin="anonymous"></script>

为您的&lt;fieldset&gt; 元素添加了一个 data-step="#" 属性/值,我们可以使用它来确定单击“下一步”按钮时我们所处的步骤#。

<fieldset data-step="1">

在第 2 步中为所有无线电输入添加了一个名为“property-type”的类名。我们将使用这个类作为第 2 步的验证目标,如下所示。我还将所有 ID 重命名为唯一的! (您需要在其他输入上修复此问题 - 我只在步骤 2 中修复了它们)。例如:

<input type="radio" class="property-type" id="property-type-1" name="property" value="House">

我在您的 JS 代码中添加了一个文档就绪功能,并将您现有的点击事件绑定移到其中。

$(document).ready(function()
   
   // moved your existing click event binding definitions here
);

我定义了一个全局变量 msformValidation,然后在 doc ready 中我实例化了一个新的 jquery 验证对象,该对象存储在这个变量中。

验证规则作为参数传递给插件的实例化函数。需要注意的是,规则是为输入的 NAME 定义的。 (不是输入的类型、id 或类!)

msformValidation = $('#msform').validate(
    submitHandler: function ()  , // prevent traditional form submission
    rules:
        'postcode':  // this is the input name for the first step
            required: true        
         ,
         'property':  // this is the input name of the radio group in the second step
             required: true
         
       
  );

现在剩下要做的就是修改函数处理程序,以便单击下一个按钮:

$(".next").click(function() 
   if (animating) return false;
   animating = true;

   current_fs = $(this).parent();

   // run the validations on the input for the current step    
   var validationPassed = false;
   if(current_fs.data('step') == 1)                  
      validationPassed = $('#search_term').valid();
   else if(current_fs.data('step') == 2)
      validationPassed = $('.property-type').valid();
   

   // check to see if the validator for the specific step we are on passed or not.
   if(validationPassed == false)
     // do not proceed!
     animating = false;
     return;
           
    
   // .. proceed with your code..

请注意,与使用输入名称定义规则的方式不同,检查特定输入是否为 .valid() 是否使用输入 ID,例如:$('#search_term').valid();,但无线电组除外,然后您使用不同的通用类名称分配给同一组中的所有输入,例如:$('.property-type').valid();

另外请注意,我在单选组列表的末尾添加了一个&lt;label&gt; 元素,以专门定位我希望显示任何验证错误消息的位置。如果我没有添加它,那么在这种情况下,消息将始终显示在第一个无线电输入下方。

<label id="property-error" class="error" for="property"></label>

您分配给此标签的 ID 值很重要!这是input NAME-error

一旦您知道何时使用输入名称、ID 和类别,该插件实际上非常容易使用。

【讨论】:

非常感谢您花时间解释并告诉我该怎么做。 .我已按照您提供的所有步骤进行操作,并且它运行良好,在选择选项或填写输入之前阻止表单提交。我面临的唯一问题是填写并提交表单时它没有到达我的像以前一样的表单处理程序,就像它在验证之前所做的那样。选择提交按钮时,联系人表格消失,我留下了背景。如果你能告诉我可能是什么解决方案,我将不胜感激 从验证实例中删除这个:submitHandler: function () , // prevent traditional form submission 嗨 Drew 非常感谢您的解释。我删除了 submitHandler: function () , // 防止传统的表单提交。当我提交它时,它就消失了。如果你可以请告诉我我可能会尝试什么。非常感谢您的支持 听起来像是一个单独的问题,超出了这个问题的范围。请使用此新问题的相关详细信息创建一个新问题。我很乐意在那里看看。 你好。我创建了一个新问题,并尽可能详细地解释了谢谢

以上是关于使用 JavaScript 多步骤表单进行联系表单验证的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swiftmailer 的 PHP 驱动的 HTML 联系表单有多安全?

使用 Jquery Validation 插件的 MultiStep 表单客户端验证

在 Hartl 的教程中添加联系表单

如何验证此多步骤表单

将变量从 PHP 传递到 javascript 并传递到 html 表单

javascript Wordpress - 事件监听器 - 联系表单