/* 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 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; } /* 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"; } var formCorrectionNeeded = qs('#form-correction-needed'); function new_amount(amountData, amountInput, amountError) { var isValid = amountData.newAmount >= amountData.minAmount; if (amountData.oldAmount === undefined) { if (isValid) { hide(amountError); } else { flipClass(amountInput, 'valid', 'invalid'); show(amountError); } } else if (isValid) { flipClass(amountInput, 'invalid', 'valid'); hide(amountError); } else if (amountData.oldAmount >= amountData.minAmount) { flipClass(amountInput, 'valid', 'invalid'); show(amountError); } } 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: formCorrectionNeeded.classList.add('hidden'); qsa('form.supporter-form').forEach(function(form) { var amountInput = qs('input[type=number]', form); var amountError = qs('.supporter-form-input .form-error', form); function amount_change_handler () { var amountData = buildAmountData(amountInput); new_amount(amountData, amountInput, amountError); amountInput.dataset.oldAmount = amountData.newAmount; } amountInput.addEventListener('input', function() { amountInput.classList.remove('invalid'); }) amountInput.addEventListener('focusout', amount_change_handler); amount_change_handler(); form.addEventListener('submit', function(event) { var amountData = buildAmountData(amountInput); if (amountData.newAmount >= amountData.minAmount) { formCorrectionNeeded.classList.add('hidden'); } else { formCorrectionNeeded.classList.remove('hidden') .css("font-weight", "bold").css("font-size", "150%"); event.preventDefault(); } }); }); } function init_sustainer_type_switching () { function selectSupportType(selectedLink) { qsa(".supporter-type-selector a").forEach(function(el) { el.classList.remove("supporter-type-selector-selected"); }); selectedLink.classList.add("supporter-type-selector-selected"); qsa(".supporter-type-selection").forEach(function(el) { hide(el); }); let hash = window.location.hash !== '' ? window.location.hash : '#annual'; show(qs(hash)); formCorrectionNeeded.classList.add('hidden'); return false; }; qsa(".supporter-type-selector a").forEach(function(el) { el.addEventListener("click", () => selectSupportType(el)); }); let el = qs(window.location.hash !== '' ? window.location.hash + 'Selector' : '#annualSelector'); selectSupportType(el); window.addEventListener("hashchange", function () { let el = qs(window.location.hash !== '' ? window.location.hash + 'Selector' : '#annualSelector'); selectSupportType(el); }); }; function init_expanders () { // To avoid hitting visitors with a wall of text, we initially hide the // "Year in Review" and similar text inside expandable
// 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();