Helper snippets

Some useful snippets working with the Form-API.

General error message

If there are errors after submitting the form, you should show a general error message near the submit-button. The validation is done via Ajax and the errors are rendered on the page without a reload, so perhaps there is an error outside of the viewport.

📘

Automation: generalErrorElement option

We recommend to use the "generalErrorElement" constructor option to automate this.

<input type="submit" value="Jetzt spenden" />
<p id="errorMsg" style="display: none;">
  Es sind leider Fehler aufgetreten, bitte überprüfen Sie Ihre Angaben.
</p>
<script>
  ...
  myForm.on("fundraisingBox:updateSession", function() {
    // show only current field errors on session update
    if(myForm.getErrors().current_fields)
    {
      $("#errorMsg").show();
    }
    else
    {
      $("#errorMsg").hide();
    }
  });
  myForm.on("fundraisingBox:payment", function() {
    if(myForm.getErrors())
    {
      $("#errorMsg").show();
    }
    else
    {
      $("#errorMsg").hide();
    }
  });
</script>

Show a loading-overlay until the form is initialized

The form is initialized asynchronously after your page is loaded, so there might be a short duration until everything is done. For example adding form fields, items or rendering values. We recommend to show such a loading-overlay until everything is done.

📘

Special Case: Apple Pay and Google Pay

If Apple Pay or Google Pay are active in your form, you should also consider an event listener for the fundraisingBox:walletPayReady event. See more details on our separate page for wallet payments.

<div class="loading"></div>
<p class="replace_vars">Thank you for your {{interval}} {{amount}} €</p>
<form id="form">
  ...
  <div id="emailField"></div>
</div>
<script>
  ...
  // show absolute positioned overlay, e.g. with a rotation hourglass
  $(".loading").show();
  // init form
  myForm = $("#form").fundraisingBoxForm({
    hash: "{your_form_hash}" // replace {your_form_hash} with your hash without {}-brackets
  });
  myForm.on("fundraisingBox:init", function() {
    // e.g. append some fields
    myForm.appendFieldRowsTo("#emailField", ["email"]);
    // perhaps call fillValues again if there is dynamic content
    myForm.fillValues();
    // everything is done, hide loading div
    $(".loading").hide();
  });
</script>

Prevent user to submit or navigate to fast

You have to wait for the init-event so the form works properly. If you don't use an overlay we recommend to deactivate the submit button and also the navigation, if you have one and you want to add the session hash to the navigation.

<ul class="nav">
  <li><a href="1.html">1.Step</a></li>
  ...
</ul>
<form id="form">
  ...
</form>
<script>
  ...
  // deactivate form and navigation
  $("#form").on("submit.init", function() { return false; });
	$(".nav a").on("click.init", function() { return false; });
  // init form
  myForm = $("#form").fundraisingBoxForm({
    hash: "{your_form_hash}", // replace {your_form_hash} with your hash without {}-brackets
    addSessionHashTo: ".nav a"
  });
  // reactivate form and navigation after init
  myForm.on("fundraisingBox:init", function() {
    $("#form").off("submit.init");
    $(".nav a").off("click.init");
  });
</script>

Payment method handling

You can visualize the payment methods like you want, e.g. as radio buttons with nice logos. Consider the ability to handle recurring payments of the single methods.

<script>
  ...
  // add payment methods
  $.each(myForm.getPaymentMethods(), function(key, method) {
    $("#paymentMethods").append($('<div class="radio '+(method.recurring ? "" : "notRecurring")+'"><label><input type="radio" name="payment[payment_method]" value="'+key+'">'+method.label+'</label></div>'));
  });
  // hide not recurring methods if recurring donation
  $("#payment_interval").change(function() {
    if($(this).val() == 0)
    {
      $("#paymentMethods .radio").show();
    }
    else
    {
      $("#paymentMethods .notRecurring").hide();
      $("#paymentMethods .notRecurring input").prop("checked", false);
    }
  });
</script>

Adding sorted choices dynamically

Some choices (interval, wants_receipt, fb_item_id, payment_method) can be managed and sorted in your FundraisingBox form settings. If this should also apply to your form, you have to add the options via javascript.

<select id="intervals"></select>
...
<script>
  ...
  myForm.on("fundraisingBox:init", function () {
				// append available intervals dynamically
				$.each(myForm.getFormFields().interval.options, function (index, option) {
					$("#intervals").append($("<label class='radio-inline'><input type='radio' name='payment[interval]' value='" + option.key + "'>" + option.value + "</label>"));
				});
				myForm.fillValues(); // call fill values manually again because of dynamic intervals append
			});
</script>

Update Checkbox Label for Fee Coverage

To dynamically reflect the covered fee and the amount inclusive of the fee in the checkbox label for fee coverage, follow these steps. This script updates the label when there is a change in the payment[amount] or payment[interval] fields.
If you use payment[amount] as hidden field and set the value programmatically, trigger the change on the hidden input $('input[name="payment[amount]"]').trigger('change');

<script>
function updateCoveredFeeCheckboxWording() { 
  const coverTheFeeResult = myForm.getCoverTheFeeResult();  
  /* set your currency and country code */
  const euroFormatter = new Intl.NumberFormat('de-DE', { 
    style: 'currency',
    currency: 'EUR', 
  }); 
  /* wording for the label if no amount is given */
  let wording = 'Cover fees with an additional contribution.';   
  if (coverTheFeeResult.covered_fee > 0) {
    /* wording with selected interval for the checkbox label if an amount is given */
    const intervalFormatted = getIntervalText();
    wording = `Cover fees with an additional contribution of ${euroFormatter.format(coverTheFeeResult.covered_fee)} and increase ${intervalFormatted} donation to ${euroFormatter.format(coverTheFeeResult.amount_inclusive_fee)}.`;
 }
  $('label[for="payment_donor_covers_the_fee"]').text(wording); 
}
/* get selected interval */
function getInterval() {
    return $('select[name="payment[interval]"]') ? parseInt($('select[name="payment[interval]"]').val(),10) : null;
}
/* get interval text from selected option */
function getIntervalText() {
    const interval = getInterval();
    const intervalField = $('select[name="payment[interval]"]');
    if (!intervalField) return 'one-time';
    return intervalField.find(`option[value="${interval}"]`).text();
}
myForm.on("change", 'input[name="payment[amount]"], select[name="payment[interval]"]', function() { 
  updateCoveredFeeCheckboxWording();
});
</script>

Set checksum amount to hidden inputField payment[covered_fee_checksum_amount]

To set the checksum amount for fee coverage, follow these steps. This script sets the value for the hidden input field payment[covered_fee_checksum_amount] and includes change events for payment[amount] and payment[donor_covers_the_fee] to dynamically update the calculated covered_fee_checksum_amount.
If you use payment[amount] as hidden field and set the value programmatically, trigger the change on the hidden input $('input[name="payment[amount]"]').trigger('change');

<script>
function setCheckSumAmount() {
   /* get CoverTheFeeResult */
  const coverTheFeeResult = myForm.getCoverTheFeeResult();
  /* check if checkbox is selected*/
  const donorCoversTheFee = myForm.getDonorCoversTheFee();
  /*  hidden input field for covered_fee_checksum_amount*/
  const $checkSum = $('input[name="payment[covered_fee_checksum_amount]');
  /* update value */
  const checkSumAmount = donorCoversTheFee ? coverTheFeeResult.amount_inclusive_fee : coverTheFeeResult.amount;
  $checkSum.val(checkSumAmount);   
}
myForm.on("change", 'input[name="payment[amount]"], input[name="payment[donor_covers_the_fee]"]', function() {
  setCheckSumAmount();
});
</script>