Merge pull request #404 from koloml/undo-upload-submit-disabling-from-back-forward-cache

Upload Form: Undo submit button disabling from back/forward cache
This commit is contained in:
liamwhite 2025-02-03 18:26:41 -05:00 committed by GitHub
commit bba88626f6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 96 additions and 4 deletions

View file

@ -6,6 +6,7 @@ import { assertNotNull } from './utils/assert';
import { fetchJson, handleError } from './utils/requests';
import { $, $$, clearEl, hideEl, makeEl, showEl } from './utils/dom';
import { addTag } from './tagsinput';
import { oncePersistedPageShown } from './utils/events';
const MATROSKA_MAGIC = 0x1a45dfa3;
@ -64,17 +65,21 @@ function setupImageUpload() {
imgPreviews.appendChild(label);
});
}
function showError() {
clearEl(imgPreviews);
showEl(scraperError);
enableFetch();
}
function hideError() {
hideEl(scraperError);
}
function disableFetch() {
fetchButton.setAttribute('disabled', '');
}
function enableFetch() {
fetchButton.removeAttribute('disabled');
}
@ -231,13 +236,30 @@ function setupImageUpload() {
function disableUploadButton() {
const submitButton = $('.button.input--separate-top');
if (submitButton !== null) {
submitButton.disabled = true;
submitButton.innerText = 'Please wait...';
if (!submitButton) {
return;
}
const originalButtonText = submitButton.innerText;
submitButton.disabled = true;
submitButton.innerText = 'Please wait...';
// delay is needed because Safari stops the submit if the button is immediately disabled
requestAnimationFrame(() => submitButton.setAttribute('disabled', 'disabled'));
// Rolling back the disabled state when user navigated back to the form.
oncePersistedPageShown(() => {
if (!submitButton.disabled) {
return;
}
submitButton.disabled = false;
submitButton.innerText = originalButtonText;
submitButton.removeAttribute('disabled');
});
}
function submitHandler(event) {

View file

@ -1,4 +1,12 @@
import { delegate, fire, mouseMoveThenOver, leftClick, on, PhilomenaAvailableEventsMap } from '../events';
import {
delegate,
fire,
mouseMoveThenOver,
leftClick,
on,
PhilomenaAvailableEventsMap,
oncePersistedPageShown,
} from '../events';
import { getRandomArrayItem } from '../../../test/randomness';
import { fireEvent } from '@testing-library/dom';
@ -129,6 +137,51 @@ describe('Event utils', () => {
});
});
describe('oncePersistedPageShown', () => {
it('should NOT fire on usual page show', () => {
const mockHandler = vi.fn();
oncePersistedPageShown(mockHandler);
fireEvent.pageShow(window, { persisted: false });
expect(mockHandler).toHaveBeenCalledTimes(0);
});
it('should fire on persisted pageshow', () => {
const mockHandler = vi.fn();
oncePersistedPageShown(mockHandler);
fireEvent.pageShow(window, { persisted: true });
expect(mockHandler).toHaveBeenCalledTimes(1);
});
it('should keep waiting until the first persistent page shown fired', () => {
const mockHandler = vi.fn();
oncePersistedPageShown(mockHandler);
fireEvent.pageShow(window, { persisted: false });
fireEvent.pageShow(window, { persisted: false });
fireEvent.pageShow(window, { persisted: true });
expect(mockHandler).toHaveBeenCalledTimes(1);
});
it('should NOT fire more than once', () => {
const mockHandler = vi.fn();
oncePersistedPageShown(mockHandler);
fireEvent.pageShow(window, { persisted: true });
fireEvent.pageShow(window, { persisted: true });
expect(mockHandler).toHaveBeenCalledTimes(1);
});
});
describe('delegate', () => {
it('should call the native addEventListener method on the element', () => {
const mockElement = document.createElement('div');

View file

@ -54,6 +54,23 @@ export function mouseMoveThenOver<El extends HTMLElement>(element: El, func: (e:
);
}
export function oncePersistedPageShown(func: (e: PageTransitionEvent) => void) {
const controller = new AbortController();
window.addEventListener(
'pageshow',
(e: PageTransitionEvent) => {
if (!e.persisted) {
return;
}
controller.abort();
func(e);
},
{ signal: controller.signal },
);
}
export function delegate<K extends keyof PhilomenaAvailableEventsMap, Target extends Element>(
node: PhilomenaEventElement,
event: K,