How can I use an hCaptcha callback with Getform and Ajax form submission?

353 views Asked by At

I'm using Getform https://getform.io/ for a Javascript contact form, along with hCaptcha hcaptcha.com. GetForm fully supports hCaptcha https://docs.getform.io/features/spam-filtering/hcaptcha/ . But neither Getform or hCaptcha offer support at the code level, hence, I'm asking here.

I'm using the Getform Ajax form, which keeps the user on the same page after a form submission. It's very basic and is from Getform's cut-and-paste example. I'm using "required" attributes for each field, and Getform automatically validates those and won't allow a form button submit click until all fields validate. The form and the required fields work and the form submits when not integrating hCaptcha.

But what I want to do is integrate hCaptcha and automatically bind the hCaptcha challenge to the submit button, so hCaptcha only appears after the submit button is clicked.

For that I need a callback, as outlined here https://docs.hcaptcha.com/invisible#programmatically-invoke-the-challenge and the callback is basically this:

function onSubmit(token) {
    document.getElementById('ajaxForm').submit();
  }

But that callback I added doesn't work with the Ajax function. With the code below, hCaptcha appears when the form submit button is clicked, and when solved, the form submits. The Getform log shows that the hCaptcha was solved, and the message is received at Getform, but because form field validation doesn't take place before form submission, required form fields can empty in the message if they were left empty on submit.

Question: how do I use either function onSubmit(token) (or a different function) in the jQuery Ajax function below so the sequence is this: submit can't be clicked without the required form fields, and when they are filled out and submit is clicked, then hCaptcha is shown, and if the hCaptcha is successfully solved, the form is finally submitted via post.

HTML:

<div class="form-container">

<form  id="ajaxForm" accept-charset="UTF-8"  action="https://getform.io/f/form-id" method="POST">

<label for="email" required="required">Your Email</label><br>
<input type="email" name="email" class="form-control" id="email"  aria-describedby="emailHelp" placeholder="Enter email" required="required">

<label for="name">Your Name</label><br>
<input type="text" name="name" class="form-control" id="name" placeholder="Enter name" required="required">

<label for="name">Your Message</label>
<textarea cols="50" rows="5" name="message" class="form-control" id="message" placeholder="Enter Message" required="required" minlength="20" maxlength="500"></textarea>

<button class="h-captcha" data-sitekey="site-key" data-callback="onSubmit" type="submit">Submit</button>

</form>

<div class="success">Message sent OK!</div>

</div>

Javascript:

jQuery('.success').removeClass('is-active');  // Hide div on page load

jQuery("#ajaxForm").submit(function(e){
  e.preventDefault();
  var action = jQuery(this).attr("action");
  jQuery.ajax({
    type: "POST",
    url: action,
    crossDomain: true,
    data: new FormData(this),
    dataType: "json",
    contentType: "multipart/form-data",
    processData: false,
    contentType: false,
    headers: {
      "Accept": "application/json"
    }

  }).done(function() {
    jQuery('.success').addClass('is-active');  // Shows sucess div
    jQuery("button[type='submit']").prop('disabled',true); //Disabled button to prevent multiple submits
    $("#ajaxForm :input").val('');          //clears form fields after submit

  }).fail(function() {
     alert('Something broke - you should try again');
  });
});

function onSubmit(token) {
    document.getElementById('ajaxForm').submit();   // Callback as required by Hcaptcha, which doesn't work
  }
1

There are 1 answers

5
Patrick Hume On

Updated:

Sorry my bad, the key was to use data-callback instead, this works but your need to fix your jQuery.ajax call as I do not know if new FormData($("#ajaxForm")) will work just like that think you need to see Send FormData and String Data Together Through JQuery AJAX?

function onLoad() {
    var element = document.getElementById("submit");
    element.onclick = validate;
}
$("#ajaxForm").submit(function (event) {
    event.preventDefault();
    const response = grecaptcha.getResponse();
    // can add in js vaildation here if you wanted to
    if (!document.getElementById("exampleInputName").value) {
        alert("You must add text to the required field");
        return false;
    }
    // Check capture has been completed
    if (response.length === 0) {
        alert("Please complete recaptha");
        return false;
    }
    // could manually tigger capture promt with: hcaptcha.execute();
    // instead of the respone length check
});

function onSubmit(token) {
    alert("thanks " + document.getElementById("exampleInputName").value);
    const action = $("#ajaxForm").attr("action");
    //TODO FIX FORM DATA SEE: https://stackoverflow.com/questions/21060247/send-formdata-and-string-data-together-through-jquery-ajax
    /*
    $.ajax({
        type: "POST",
        url: action,
        crossDomain: true,
        data: new FormData($("#ajaxForm")),
        dataType: "json",
        contentType: "multipart/form-data",
        processData: false,
        contentType: false,
        headers: {
            "Accept": "application/json"
        }
    }).done(function () {
        $('.success').addClass('is-active');
    }).fail(function () {
        alert('An error occurred please try again later.')
    })
    */
}
h1 {
  font-size: 20px;
  margin-top: 24px;
  margin-bottom: 24px;
}

img {
height: 60px;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://js.hcaptcha.com/1/api.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="col-md-6 offset-md-3 mt-5">
  <a target="_blank" href="https://getform.io?ref=codepenHTML">
    <img src='https://i.imgur.com/O1cKLCn.png'>
  </a>
  <br>
  <a target="_blank" href="https://getform.io?ref=codepenHTML" class="mt-3 d-flex">Getform.io | Get your free endpoint now</a>
  <h1>Getform.io hCaptcha HTML Form Example with File Upload</h1>
  <form accept-charset="UTF-8" action="https://getform.io/f/d709b72b-d30b-4316-9cc1-4d1d33778a8b" method="POST" enctype="multipart/form-data" target="_blank" id="ajaxForm">
    <div class="form-group">
      <label for="exampleInputName">Full Name</label>
      <input type="text" name="fullname" class="form-control" id="exampleInputName" placeholder="Enter your name and surname" required="required">
    </div>

    <div class="form-group">
      <label for="exampleInputEmail1" required="required">Email address</label>
      <input type="email" name="email" class="form-control" id="exampleInputEmail1" aria-describedby="emailHelp" placeholder="Enter email">
    </div>
    <div class="form-group">
      <label for="exampleFormControlSelect1">Favourite Platform</label>
      <select class="form-control" id="exampleFormControlSelect1" name="platform" required="required">
        <option>Github</option>
        <option>Gitlab</option>
        <option>Bitbucket</option>
      </select>
    </div>
    <hr>
    <div class="form-group mt-3">
      <label class="mr-2">Upload your CV:</label>
      <input type="file" name="file">
    </div>
    <hr>
    <div class="h-captcha" id="hcaptcha" data-sitekey="194e8efb-f32d-4d44-8ffb-b54694c2f321"  data-callback="onSubmit"></div>
    <button id="submit" class="btn btn-primary">Submit</button>
  </form>
</div>