Files
@ 73e30c30e844
Branch filter:
Location: website/conservancy/static/js/supporter-page.js
73e30c30e844
5.1 KiB
application/javascript
Further split up the supporter JS into functions
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /* Copyright (C) 2012-2013 Denver Gingerich,
** Copyright (C) 2013-2014, 2020 Bradley M. Kuhn,
** Copyright (C) 2016, 2020 Brett Smith.
** License: GPLv3-or-later
** Find a copy of GPL at https://sfconservancy.org/GPLv3
*/
"use strict";
var NEW_AMOUNT_EVENT = 'conservancy:newamount';
var flipClass = function(elem, byeClass, hiClass) {
var classList = elem.classList;
classList.remove(byeClass);
classList.add(hiClass);
}
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) {
return $(supportTypeHash + "Selector");
};
/* We've sometimes published links that say #renew instead of #renewal.
Rewrite that to work as intended. */
if (window.location.hash === "#renew") {
window.location.hash = "#renewal";
}
function init_sustainer_form_validation () {
// Forms start in "invalid" form, with the errors shown, so that
// non-Javascript users see the errors by default and know what they must
// enter. Now we hide those for JavaScript users:
var $formCorrectionNeeded = $('#form-correction-needed');
$formCorrectionNeeded.addClass('hidden');
$('form.supporter-form').each(function(index, form) {
var $amountInput = $('input[type=number]', form).first();
var $amountError = $('.form-error', $amountInput.parents('.supporter-form-input'));
$amountError.on(NEW_AMOUNT_EVENT, function(event, amountData) {
var isValid = amountData.newAmount >= amountData.minAmount;
if (amountData.oldAmount === undefined) {
if (isValid) {
$amountError.addClass('hidden');
} else {
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();
}
});
$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')
.css("font-weight", "bold").css("font-size", "150%");
event.preventDefault();
}
});
});
}
function init_sustainer_type_switching () {
var selectSupportType = function(event) {
var $selectedLink = $(event.target);
$(".supporter-type-selector a").removeClass("supporter-type-selector-selected");
$selectedLink.addClass("supporter-type-selector-selected");
$(".supporter-type-selection").hide();
$(event.target.hash).show();
$formCorrectionNeeded.addClass('hidden');
return false;
};
$(".supporter-type-selector a").bind("click", selectSupportType);
var selectSupportTypeFromHash = function() {
return supportTypeSelector(window.location.hash).click();
};
$(window).bind("hashchange", selectSupportTypeFromHash);
if (selectSupportTypeFromHash().length === 0) {
supportTypeSelector("#annual").click();
}
};
function init_expanders () {
// To avoid hitting visitors with a wall of text, we initially hide the
// "Year in Review" and similar text inside expandable <details>
// sections. If the URL fragment references one of these sections, we open
// that section.
let details = qs('details' + window.location.hash) // eg. #WritingAndSpeaking
if (window.location.hash && details) {
details.open = true;
details.scrollIntoView();
}
// Exable convenient "expand all" link to expand/hide all sections at once.
qsa('.expander').forEach(function(expander) {
expander.innerHTML = expander.dataset['expandLinkText'];
expander.addEventListener('click', function() {
let details_elements = qsa('.expandable-section details');
let some_closed = Array.from(details_elements).some(el => !el.open);
details_elements.forEach(function(el) {
el.open = some_closed;
});
});
});
}
init_sustainer_form_validation();
init_sustainer_type_switching();
init_expanders();
|