| 1 |
/** |
| 2 |
* @since 2.17.0 |
| 3 |
*/ |
| 4 |
window.GiveDonationSummary = { |
| 5 |
init: function () { |
| 6 |
GiveDonationSummary.initAmount(); |
| 7 |
GiveDonationSummary.initFrequency(); |
| 8 |
GiveDonationSummary.initTotal(); |
| 9 |
}, |
| 10 |
|
| 11 |
/** |
| 12 |
* This function returns formated donation amount. |
| 13 |
* |
| 14 |
* @since 2.23.1 |
| 15 |
* @return {string} |
| 16 |
*/ |
| 17 |
getFormattedDonationAmount: function ($form) { |
| 18 |
const unFormattedAmount = Give.fn.unFormatCurrency( |
| 19 |
$form.find('[name="give-amount"]').val(), |
| 20 |
Give.form.fn.getInfo('decimal_separator', $form) |
| 21 |
); |
| 22 |
|
| 23 |
return Give.fn.formatCurrency( |
| 24 |
unFormattedAmount, |
| 25 |
{symbol: Give.form.fn.getInfo('currency_symbol', $form)}, |
| 26 |
$form |
| 27 |
); |
| 28 |
}, |
| 29 |
|
| 30 |
/** |
| 31 |
* @since 2.17.0 |
| 32 |
* |
| 33 |
* @since 2.24.0 add eventlistner for custom input amount changes. |
| 34 |
*/ |
| 35 |
initAmount: function () { |
| 36 |
GiveDonationSummary.observe('[name="give-amount"]', function (targetNode, $form) { |
| 37 |
$form.find('[data-tag="amount"]').html(GiveDonationSummary.getFormattedDonationAmount($form)); |
| 38 |
}); |
| 39 |
|
| 40 |
const targetNode = document.querySelector('[name="give-amount"]'); |
| 41 |
if (targetNode) { |
| 42 |
const $form = jQuery(targetNode.closest('.give-form')); |
| 43 |
|
| 44 |
targetNode.addEventListener('change', function () { |
| 45 |
$form.find('[data-tag="amount"]').html(GiveDonationSummary.getFormattedDonationAmount($form)); |
| 46 |
}); |
| 47 |
} |
| 48 |
}, |
| 49 |
|
| 50 |
/** |
| 51 |
* Recurring frequency |
| 52 |
* |
| 53 |
* @since 2.17.0 |
| 54 |
*/ |
| 55 |
initFrequency: function () { |
| 56 |
// Donor's Choice Recurring |
| 57 |
GiveDonationSummary.observe( |
| 58 |
'[name="give-recurring-period"]', |
| 59 |
GiveDonationSummary.handleDonorsChoiceRecurringFrequency |
| 60 |
); |
| 61 |
|
| 62 |
// Admin Defined Recurring |
| 63 |
GiveDonationSummary.observe('[name="give-price-id"]', GiveDonationSummary.handleAdminDefinedRecurringFrequency); |
| 64 |
|
| 65 |
// Admin Defined Recurring - "Set Donation" |
| 66 |
GiveDonationSummary.observe( |
| 67 |
'[name="_give_is_donation_recurring"]', |
| 68 |
GiveDonationSummary.handleAdminDefinedSetDonationFrequency |
| 69 |
); |
| 70 |
|
| 71 |
// Admin Defined Recurring - "Multi-level" |
| 72 |
GiveDonationSummary.observe('[name="give-price-id"]', GiveDonationSummary.handleAdminDefinedRecurringFrequency); |
| 73 |
}, |
| 74 |
|
| 75 |
/** |
| 76 |
* @since 2.18.0 |
| 77 |
*/ |
| 78 |
handleDonorsChoiceRecurringFrequency: function (targetNode, $form) { |
| 79 |
$form.find('.js-give-donation-summary-frequency-help-text').toggle(!targetNode.checked); |
| 80 |
$form.find('[data-tag="frequency"]').toggle(!targetNode.checked); |
| 81 |
$form.find('[data-tag="recurring"]').toggle(targetNode.checked).html(targetNode.dataset['periodLabel']); |
| 82 |
|
| 83 |
// Donor's Choice Period |
| 84 |
const donorsChoice = document.querySelector('[name="give-recurring-period-donors-choice"]'); |
| 85 |
if (donorsChoice) { |
| 86 |
const donorsChoiceValue = donorsChoice.options[donorsChoice.selectedIndex].value || false; |
| 87 |
if (donorsChoiceValue) { |
| 88 |
$form |
| 89 |
.find('[data-tag="recurring"]') |
| 90 |
.html(GiveDonationSummaryData.recurringLabelLookup[donorsChoiceValue]); |
| 91 |
} |
| 92 |
} |
| 93 |
}, |
| 94 |
|
| 95 |
/** |
| 96 |
* @since 2.18.0 |
| 97 |
*/ |
| 98 |
handleAdminDefinedRecurringFrequency: function (targetNode, $form) { |
| 99 |
const priceID = targetNode.value; |
| 100 |
const recurringDetailsEl = document.querySelector('.give_recurring_donation_details'); |
| 101 |
|
| 102 |
if (!recurringDetailsEl) { |
| 103 |
return; |
| 104 |
} |
| 105 |
|
| 106 |
const recurringDetails = JSON.parse(recurringDetailsEl.value); |
| 107 |
|
| 108 |
if ('undefined' !== typeof recurringDetails['multi']) { |
| 109 |
const isRecurring = 'yes' === recurringDetails['multi'][priceID]['_give_recurring']; |
| 110 |
const periodLabel = recurringDetails['multi'][priceID]['give_recurring_pretty_text']; |
| 111 |
|
| 112 |
$form.find('.js-give-donation-summary-frequency-help-text').toggle(!isRecurring); |
| 113 |
$form.find('[data-tag="frequency"]').toggle(!isRecurring); |
| 114 |
$form.find('[data-tag="recurring"]').toggle(isRecurring).html(periodLabel); |
| 115 |
} |
| 116 |
}, |
| 117 |
|
| 118 |
handleAdminDefinedSetDonationFrequency: function (targetNode, $form) { |
| 119 |
const isRecurring = targetNode.value; |
| 120 |
const adminChoice = document.querySelector('.give-recurring-admin-choice'); |
| 121 |
|
| 122 |
if (isRecurring && adminChoice) { |
| 123 |
$form.find('.js-give-donation-summary-frequency-help-text').toggle(!isRecurring); |
| 124 |
$form.find('[data-tag="frequency"]').toggle(!isRecurring); |
| 125 |
$form.find('[data-tag="recurring"]').html(adminChoice.textContent); |
| 126 |
} |
| 127 |
}, |
| 128 |
|
| 129 |
/** |
| 130 |
* @since 2.23.1 Remove dependency on checkbox. Removed first argument. |
| 131 |
* @since 2.18.0 |
| 132 |
*/ |
| 133 |
handleFees: function ($form) { |
| 134 |
const feeModeEnableElement = $form.find('[name="give-fee-mode-enable"]'); |
| 135 |
|
| 136 |
if (!feeModeEnableElement || 'true' !== $form.find('[name="give-fee-mode-enable"]').val()) { |
| 137 |
$form.find('.js-give-donation-summary-fees').toggle(false); |
| 138 |
return; |
| 139 |
} |
| 140 |
|
| 141 |
$form.find('.js-give-donation-summary-fees').toggle(true); |
| 142 |
|
| 143 |
const feeMessageTemplateParts = $form.find('.give-fee-message-label').attr('data-feemessage').split(' '); |
| 144 |
const feeMessageParts = $form.find('.give-fee-message-label-text').text().split(' '); |
| 145 |
const formattedFeeAmount = feeMessageParts |
| 146 |
.filter((messagePart) => !feeMessageTemplateParts.includes(messagePart)) |
| 147 |
.pop(); |
| 148 |
$form.find('[data-tag="fees"]').html(formattedFeeAmount); |
| 149 |
}, |
| 150 |
|
| 151 |
/** |
| 152 |
* @since 2.17.0 |
| 153 |
*/ |
| 154 |
initTotal: function () { |
| 155 |
GiveDonationSummary.observe('.give-final-total-amount', function (targetNode, $form) { |
| 156 |
$form.find('[data-tag="total"]').html(targetNode.textContent); |
| 157 |
|
| 158 |
GiveDonationSummary.handleFees($form); |
| 159 |
}); |
| 160 |
|
| 161 |
// Force an initial mutation for the Total Amount observer |
| 162 |
const totalAmount = document.querySelector('.give-final-total-amount'); |
| 163 |
if (totalAmount) { |
| 164 |
totalAmount.textContent = totalAmount.textContent; |
| 165 |
} |
| 166 |
}, |
| 167 |
|
| 168 |
/** |
| 169 |
* Placeholder callback, which is only used when the gateway changes. |
| 170 |
*/ |
| 171 |
handleNavigateBack: function () {}, |
| 172 |
|
| 173 |
/** |
| 174 |
* Changing gateways re-renders parts of the form via AJAX. |
| 175 |
*/ |
| 176 |
onGatewayLoadSuccess: function () { |
| 177 |
const inserted = jQuery('#give_purchase_form_wrap .give-donation-summary-section').detach(); |
| 178 |
if (inserted.length) { |
| 179 |
jQuery('.give-donation-summary-section').remove(); |
| 180 |
inserted.appendTo('#donate-fieldset'); |
| 181 |
GiveDonationSummary.initTotal(); |
| 182 |
|
| 183 |
// Overwrite the handler because updating the gateway breaks the original binding. |
| 184 |
GiveDonationSummary.handleNavigateBack = function (e) { |
| 185 |
e.stopPropagation(); |
| 186 |
e.preventDefault(); |
| 187 |
window.formNavigator.back(); |
| 188 |
}; |
| 189 |
} |
| 190 |
}, |
| 191 |
|
| 192 |
/** |
| 193 |
* Observe an element and respond to changes to that element. |
| 194 |
* |
| 195 |
* @since 2.17.0 |
| 196 |
* |
| 197 |
* @param {string} selectors |
| 198 |
* @param {callable} callback |
| 199 |
* @param {boolean} callImmediately |
| 200 |
*/ |
| 201 |
observe: function (selectors, callback, callImmediately = true) { |
| 202 |
const targetNode = document.querySelector(selectors); |
| 203 |
|
| 204 |
if (!targetNode) return; |
| 205 |
|
| 206 |
const $form = jQuery(targetNode.closest('.give-form')); |
| 207 |
|
| 208 |
new MutationObserver(function (mutationsList) { |
| 209 |
for (const mutation of mutationsList) { |
| 210 |
// Use traditional 'for loops' for IE 11 |
| 211 |
if (mutation.type === 'attributes') { |
| 212 |
/** |
| 213 |
* @param targetNode The node matching the element as defined by the specific selectors |
| 214 |
* @param $form The closest `.give-form` node to the targetNode, wrapped in jQuery |
| 215 |
*/ |
| 216 |
callback(mutation.target, $form); |
| 217 |
} |
| 218 |
} |
| 219 |
}).observe(targetNode, {attributes: true}); |
| 220 |
|
| 221 |
if (callImmediately) { |
| 222 |
callback(targetNode, $form); |
| 223 |
} |
| 224 |
}, |
| 225 |
}; |
| 226 |
|
| 227 |
jQuery(document).on('give:postInit', GiveDonationSummary.init); |
| 228 |
jQuery(document).on('Give:onGatewayLoadSuccess', GiveDonationSummary.onGatewayLoadSuccess); |
| 229 |
|