supporter: Refactor amount-checking JavaScript.

* Separate out amount-parsing and reacting into separate events.  This sets
  the stage for other elements to react to the custom
  'conservancy:newamount' event.
* Set up events in the context of each supporter form, with closures.  This
  lets us avoid weird CSS selector gymnastics in the event, and instead
  drill down from the form to find the elements we need.

There are no functional changes in this code, barring bugs.
This commit is contained in:
Brett Smith 2017-01-08 18:23:51 -05:00
parent 5f9a4395f3
commit cb5b5ec23f

View file

@ -5,19 +5,23 @@
** Find a copy of GPL at https://sfconservancy.org/GPLv3
*/
var NEW_AMOUNT_EVENT = 'conservancy:newamount';
var flipClass = function(elem, byeClass, hiClass) {
var classList = elem.classList;
classList.remove(byeClass);
classList.add(hiClass);
}
var checkAmountValid = function(amountInput) {
var value = parseFloat(amountInput.value);
var min = parseFloat(amountInput.min);
/* Is the value is a valid float, it will stringify back to itself. */
var isValid = (String(value) === amountInput.value) && (value >= min);
amountInput.dataset.valid = isValid ? '1' : '0';
return isValid;
var buildAmountData = function(amountInput) {
var amountData = {
minAmount: parseFloat(amountInput.min),
newAmount: parseFloat(amountInput.value),
}
if (amountInput.dataset.oldAmount !== undefined) {
amountData.oldAmount = parseFloat(amountInput.dataset.oldAmount);
}
return amountData;
}
var supportTypeSelector = function(supportTypeHash) {
@ -45,32 +49,40 @@ $(document).ready(function() {
var $formCorrectionNeeded = $('#form-correction-needed');
$formCorrectionNeeded.addClass('hidden');
$('form.supporter-form input[type=number]').on('input', function(event) {
event.target.classList.remove('invalid');
}).on('focusout', function(event) {
var amountInput = event.target;
var wasValid = amountInput.dataset.valid === '1';
var isValid = checkAmountValid(amountInput);
$('form.supporter-form').each(function(index, form) {
var $amountInput = $('input[type=number]', form).first();
var $amountError = $('.form-error', $amountInput[0].parentNode);
$amountError.on(NEW_AMOUNT_EVENT, function(event, amountData) {
var isValid = amountData.newAmount >= amountData.minAmount;
if (amountData.oldAmount === undefined) {
if (isValid) {
flipClass(amountInput, 'invalid', 'valid');
if (!wasValid) {
$('.form-error', amountInput.parentNode).fadeOut();
}
} else if (wasValid) {
flipClass(amountInput, 'valid', 'invalid');
$('.form-error', amountInput.parentNode).fadeIn();
}
}).each(function(index, elem) {
if (checkAmountValid(elem)) {
$('.form-error', elem.parentNode).addClass('hidden');
$amountError.addClass('hidden');
} else {
elem.classList.add('invalid');
$('.form-error', elem.parentNode).removeClass('hidden');
flipClass($amountInput[0], 'valid', 'invalid');
$amountError.removeClass('hidden');
}
} else if (isValid) {
flipClass($amountInput[0], 'invalid', 'valid');
$amountError.fadeOut();
} else if (amountData.oldAmount >= amountData.minAmount) {
flipClass($amountInput[0], 'valid', 'invalid');
$amountError.fadeIn();
}
});
$('form.supporter-form').on('submit', function(event) {
if (checkAmountValid($('input[name=amount]', event.target)[0])) {
$amountInput.on('input', function(event) {
event.target.classList.remove('invalid');
}).on('focusout', function(event) {
var amountInput = event.target;
var amountData = buildAmountData(amountInput);
$amountError.trigger(NEW_AMOUNT_EVENT, amountData);
amountInput.dataset.oldAmount = amountData.newAmount;
}).trigger('focusout');
$(form).on('submit', function(event) {
var amountData = buildAmountData($amountInput[0]);
if (amountData.newAmount >= amountData.minAmount) {
$formCorrectionNeeded.addClass('hidden');
} else {
$formCorrectionNeeded.removeClass('hidden')
@ -78,6 +90,7 @@ $(document).ready(function() {
event.preventDefault();
}
});
});
var selectSupportType = function(event) {
var $selectedLink = $(event.target);