Remove remaining jQuery

This avoids every page on the site parsing 250KB of JavaScript.

supporter-page.js isn't the most elegant code, but at least it's a little more
modular now and no longer user jQuery.
This commit is contained in:
Ben Sturmfels 2024-05-09 22:12:35 +10:00
parent 10dfdb617b
commit 44c0a9db32
Signed by: bsturmfels
GPG key ID: 023C05E2C9C068F0
4 changed files with 50 additions and 9455 deletions

View file

@ -1,12 +1,9 @@
# To-do # To-do
* ensure appropriate caching headers are used * ensure appropriate caching headers are used
* remove jQuery
* consider removing `events` and `worldmap` modules * consider removing `events` and `worldmap` modules
* ask Denver about why so many license files * ask Denver about why so many license files
* serve a 400 in Apache for a hostname we don't explicitly support * serve a 400 in Apache for a hostname we don't explicitly support
* use `<detail>` elements for supporter page hidden sections, rather than
complex jQuery - or consider Alpine.js
* replace `internalNavigate` with inline flexbox layout * replace `internalNavigate` with inline flexbox layout
* add tests for main pages returning 200 * add tests for main pages returning 200
* move `sponsors.py` and `sponsors.html` into `supporters` app * move `sponsors.py` and `sponsors.html` into `supporters` app
@ -14,6 +11,9 @@
# Done # Done
* use `<detail>` elements for supporter page hidden sections, rather than
complex jQuery
* remove jQuery
* split the template/content files out from `conservancy/static` into their own * split the template/content files out from `conservancy/static` into their own
`content` directory (avoid mixing static and non-static content) `content` directory (avoid mixing static and non-static content)
* remove `ForceCanonicalHostnameMiddleware` by ensuring canonical redirect and * remove `ForceCanonicalHostnameMiddleware` by ensuring canonical redirect and

File diff suppressed because it is too large Load diff

View file

@ -7,8 +7,6 @@
"use strict"; "use strict";
var NEW_AMOUNT_EVENT = 'conservancy:newamount';
var flipClass = function(elem, byeClass, hiClass) { var flipClass = function(elem, byeClass, hiClass) {
var classList = elem.classList; var classList = elem.classList;
classList.remove(byeClass); classList.remove(byeClass);
@ -26,10 +24,6 @@ var buildAmountData = function(amountInput) {
return amountData; return amountData;
} }
var supportTypeSelector = function(supportTypeHash) {
return $(supportTypeHash + "Selector");
};
/* We've sometimes published links that say #renew instead of #renewal. /* We've sometimes published links that say #renew instead of #renewal.
Rewrite that to work as intended. */ Rewrite that to work as intended. */
if (window.location.hash === "#renew") { if (window.location.hash === "#renew") {
@ -38,6 +32,24 @@ if (window.location.hash === "#renew") {
var formCorrectionNeeded = qs('#form-correction-needed'); 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 () { function init_sustainer_form_validation () {
// Forms start in "invalid" form, with the errors shown, so that // Forms start in "invalid" form, with the errors shown, so that
// non-Javascript users see the errors by default and know what they must // non-Javascript users see the errors by default and know what they must
@ -45,39 +57,23 @@ function init_sustainer_form_validation () {
formCorrectionNeeded.classList.add('hidden'); formCorrectionNeeded.classList.add('hidden');
qsa('form.supporter-form').forEach(function(form) { qsa('form.supporter-form').forEach(function(form) {
var $amountInput = $('input[type=number]', form).first(); var amountInput = qs('input[type=number]', form);
var amountError = qs('.supporter-form-input .form-error', form); var amountError = qs('.supporter-form-input .form-error', form);
var $amountError = $('.form-error', $amountInput.parents('.supporter-form-input'));
$amountError.on(NEW_AMOUNT_EVENT, function(event, amountData) { function amount_change_handler () {
var isValid = amountData.newAmount >= amountData.minAmount;
if (amountData.oldAmount === undefined) {
if (isValid) {
amountError.classList.add('hidden');
} else {
flipClass($amountInput[0], 'valid', 'invalid');
amountError.classList.remove('hidden');
}
} else if (isValid) {
flipClass($amountInput[0], 'invalid', 'valid');
hide(amountError);
} else if (amountData.oldAmount >= amountData.minAmount) {
flipClass($amountInput[0], 'valid', 'invalid');
show(amountError);
}
});
$amountInput.on('input', function(event) {
event.target.classList.remove('invalid');
}).on('focusout', function(event) {
var amountInput = event.target;
var amountData = buildAmountData(amountInput); var amountData = buildAmountData(amountInput);
$amountError.trigger(NEW_AMOUNT_EVENT, amountData); new_amount(amountData, amountInput, amountError);
amountInput.dataset.oldAmount = amountData.newAmount; amountInput.dataset.oldAmount = amountData.newAmount;
}).trigger('focusout'); }
amountInput.addEventListener('input', function() {
amountInput.classList.remove('invalid');
})
amountInput.addEventListener('focusout', amount_change_handler);
amount_change_handler();
form.addEventListener('submit', function(event) { form.addEventListener('submit', function(event) {
var amountData = buildAmountData($amountInput[0]); var amountData = buildAmountData(amountInput);
if (amountData.newAmount >= amountData.minAmount) { if (amountData.newAmount >= amountData.minAmount) {
formCorrectionNeeded.classList.add('hidden'); formCorrectionNeeded.classList.add('hidden');
} else { } else {
@ -90,24 +86,28 @@ function init_sustainer_form_validation () {
} }
function init_sustainer_type_switching () { function init_sustainer_type_switching () {
var selectSupportType = function(event) { function selectSupportType(selectedLink) {
var $selectedLink = $(event.target); qsa(".supporter-type-selector a").forEach(function(el) {
$(".supporter-type-selector a").removeClass("supporter-type-selector-selected"); el.classList.remove("supporter-type-selector-selected");
$selectedLink.addClass("supporter-type-selector-selected"); });
$(".supporter-type-selection").hide(); selectedLink.classList.add("supporter-type-selector-selected");
$(event.target.hash).show(); 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'); formCorrectionNeeded.classList.add('hidden');
return false; return false;
}; };
$(".supporter-type-selector a").bind("click", selectSupportType); qsa(".supporter-type-selector a").forEach(function(el) {
el.addEventListener("click", () => selectSupportType(el));
});
var selectSupportTypeFromHash = function() { let el = qs(window.location.hash !== '' ? window.location.hash + 'Selector' : '#annualSelector');
return supportTypeSelector(window.location.hash).click(); selectSupportType(el);
};
$(window).bind("hashchange", selectSupportTypeFromHash); window.addEventListener("hashchange", function () {
if (selectSupportTypeFromHash().length === 0) { let el = qs(window.location.hash !== '' ? window.location.hash + 'Selector' : '#annualSelector');
supportTypeSelector("#annual").click(); selectSupportType(el);
} });
}; };
function init_expanders () { function init_expanders () {

View file

@ -15,7 +15,6 @@
<link rel="stylesheet" type="text/css" href="{% static 'css/tachyons.css' %}"/> <link rel="stylesheet" type="text/css" href="{% static 'css/tachyons.css' %}"/>
<link rel="stylesheet" type="text/css" media="screen" href="{% static 'css/conservancy.css' %}" /> <link rel="stylesheet" type="text/css" media="screen" href="{% static 'css/conservancy.css' %}" />
<link rel="stylesheet" type="text/css" media="(min-width: 67em)" href="{% static 'css/conservancy-bigscreen.css' %}" /> <link rel="stylesheet" type="text/css" media="(min-width: 67em)" href="{% static 'css/conservancy-bigscreen.css' %}" />
<script type="text/javascript" src="{% static 'js/jquery-1.7.2.js' %}" defer></script>
<script type="text/javascript" src="{% static 'js/conservancy.js' %}" defer></script> <script type="text/javascript" src="{% static 'js/conservancy.js' %}" defer></script>
{% block head %}{% endblock %} {% block head %}{% endblock %}
</head> </head>