Skip to content
This repository has been archived by the owner on Jun 25, 2021. It is now read-only.

Commit

Permalink
Improve/fix new force recurring js
Browse files Browse the repository at this point in the history
  • Loading branch information
Rich Lott / Artful Robot committed Feb 24, 2021
1 parent afba98b commit 496f5b4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 16 deletions.
9 changes: 7 additions & 2 deletions docs/howto/membership.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ handle memberships.

If you use Price Sets and you have the "Auto renew option, not required"
selected then the user will not be shown the tick-box allowing them to select
Auto Renew, and this will break things. So better to use the straight forward
auto renew option rather than give an option that will break things.
Auto Renew, and this will break things. So better to use the straight
forward *require auto renew* option rather than give an option that will
break things.

If you want to offer a choice of processors, and some of them do support
non-recurring memberships, then please see the
[Force Recurring setting](../reference/settings.md)

Technical people might like to know that without this, CiviCRM creates a single
contribution and a membership record, but no `contribution_recur` record. This
Expand Down
13 changes: 10 additions & 3 deletions docs/reference/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@
- JSON key: `forceRecurring`

CiviContribute's Contribution Pages allow you to *offer* recurring
payments. But for GoCardless we always want payments to be recurring.
payments. And if using the Membership sections then they may give a choice
on auto-renew. **But GoCardless requires payments to be recurring.**

Enabling this setting will add Javascript to Contribution Pages that
ensures the recurring checkbox is checked whenever a GoCardless payment
processor is selected.
ensures the recurring/renew checkbox is checked whenever a GoCardless
payment processor is selected.

**If you do not have another solution in place, you should enable this
setting to prevent failed mandates and frustrated supporters.** You may
enable it anyway, but you should test that it works with whatever other
custom Javascript you have running on your page.

!!! warning
If you offer GoCardless with a membership that doesn't support auto-renew
you’re in trouble: if you use this option then it will become
auto-renewing; if you don't use this option, well then it’s going to crash
because this GoCardless integration only offers recurring.

## Send receipts for payments set up by custom code

- Default setting: `never`
Expand Down
4 changes: 2 additions & 2 deletions info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
<url desc="Support">https://github.com/artfulrobot/uk.artfulrobot.civicrm.gocardless</url>
<url desc="Licensing">http://www.gnu.org/licenses/agpl-3.0.html</url>
</urls>
<releaseDate>2020-11-19</releaseDate>
<version>1.10.0</version>
<releaseDate>2021-02-24</releaseDate>
<version>1.10.1</version>
<develStage>stable</develStage>
<compatibility>
<ver>5.35</ver>
Expand Down
39 changes: 30 additions & 9 deletions js/gcform.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,25 @@
//
// - Contribution forms with a choice of PPs use radio buttons.
//
// Bug: When only Other amount is selected or before a radio amount is chosen, there's no PP stuff until an amount is entered.
//
document.addEventListener('DOMContentLoaded', function () {
// var debug = console.log;
var debug = function() {};
debug("GoCardless loaded");

// This next line gets swapped out by PHP
var goCardlessProcessorIDs = [];

// CiviCRM uses isRecur for non-membership payments, and autoRenew for memberships.
// Nb. autoRenew may not be there e.g. if autoRenew is not allowed, or is not optional.
var isRecurInput = document.getElementById('is_recur');
// Note: the auto renew input might be a checkbox OR a hidden element.
var autoRenewInput = document.getElementById('auto_renew');
// If Civi offers a choice of payment processors by radio, they'll be found like this:
var ppRadios = document.querySelectorAll('input[type="radio"][name="payment_processor_id"]');
var goCardlessProcessorSelected;
var selectedProcessorName;
// Boolean: whether the currently selected payment processor is a GoCardless one.
var goCardlessProcessorSelected = false;
// The name of the selected GoCardless processor, or is empty.
var selectedProcessorName = null;

// Note: templates/CRM/common/paymentBlock.tpl includes JS which
// un-checks the .checked property on all payment processor radios when that
Expand All @@ -38,6 +41,7 @@ document.addEventListener('DOMContentLoaded', function () {
if (isRecurInput) {
isRecurInput.addEventListener('change', function(e) {
if (!isRecurInput.checked && goCardlessProcessorSelected) {
// They tried to un-check it, but GoCardless is selected.
e.preventDefault();
e.stopPropagation();
forceRecurring(true);
Expand All @@ -46,8 +50,8 @@ document.addEventListener('DOMContentLoaded', function () {
debug("Added event listener to isRecurInput", isRecurInput);
}

// Listen for when the user changes/tries to change the autoRenewInput
if (autoRenewInput) {
// Listen for when the user changes/tries to change the autoRenewInput checkbox
if (autoRenewInput && autoRenewInput.getAttribute('type') === 'checkbox') {
autoRenewInput.addEventListener('change', function(e) {
if (!autoRenewInput.checked && goCardlessProcessorSelected) {
e.preventDefault();
Expand Down Expand Up @@ -90,14 +94,15 @@ document.addEventListener('DOMContentLoaded', function () {
// set goCardlessProcessorSelected and if found, forceRecurring
function gcFixRecurFromRadios() {
var ppID;
selectedProcessorName = null;
[].forEach.call(ppRadios, function(r) {
if (r.checked) {
ppID = parseInt(r.value);
var label = document.querySelector('label[for="' + r.id + '"]');
selectedProcessorName = label ? label.textContent : 'Direct Debit';
}
});
goCardlessProcessorSelected = (goCardlessProcessorIDs.indexOf(ppID) > -1);
goCardlessProcessorSelected = (typeof ppID === 'number') && (goCardlessProcessorIDs.indexOf(ppID) > -1);

if (goCardlessProcessorSelected && !gcWasPreviouslySelected) {
forceRecurring();
Expand All @@ -116,10 +121,11 @@ document.addEventListener('DOMContentLoaded', function () {
});

gcFixRecurFromRadios();
// Look out for when it changes.
window.setInterval(gcFixRecurFromRadios, 500);
// Look out for when it changes in a way we can't detect.
window.setInterval(gcFixRecurFromRadios, 300);
}
else {
// The processor type is fixed.
var ppInput = document.querySelectorAll('input[type="hidden"][name="payment_processor_id"]');
if (ppInput.length === 1) {
// We have a single payment processor involved that won't be changing.
Expand All @@ -134,4 +140,19 @@ document.addEventListener('DOMContentLoaded', function () {
}
}

if ('showHideAutoRenew' in window) {
// This function is defined in templates/CRM/Contribute/Form/Contribution/MembershipBlock.tpl
// and called by Civi in various places, including in onclick HTML attributes, defined in:
// - CRM/Contribute/Form/ContributionBase.php
// - CRM/Price/BAO/PriceField.php
// Wrap this function to ensure we still forceRecurring if GC is selected.
var origShowHideAutoRenew = window.showHideAutoRenew;
window.showHideAutoRenew = function(memTypeId) {
origShowHideAutoRenew(memTypeId);
if (goCardlessProcessorSelected) {
forceRecurring();
}
};
}

});

0 comments on commit 496f5b4

Please sign in to comment.