mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-02-08 15:16:43 +01:00
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:
commit
bba88626f6
3 changed files with 96 additions and 4 deletions
|
@ -6,6 +6,7 @@ import { assertNotNull } from './utils/assert';
|
||||||
import { fetchJson, handleError } from './utils/requests';
|
import { fetchJson, handleError } from './utils/requests';
|
||||||
import { $, $$, clearEl, hideEl, makeEl, showEl } from './utils/dom';
|
import { $, $$, clearEl, hideEl, makeEl, showEl } from './utils/dom';
|
||||||
import { addTag } from './tagsinput';
|
import { addTag } from './tagsinput';
|
||||||
|
import { oncePersistedPageShown } from './utils/events';
|
||||||
|
|
||||||
const MATROSKA_MAGIC = 0x1a45dfa3;
|
const MATROSKA_MAGIC = 0x1a45dfa3;
|
||||||
|
|
||||||
|
@ -64,17 +65,21 @@ function setupImageUpload() {
|
||||||
imgPreviews.appendChild(label);
|
imgPreviews.appendChild(label);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError() {
|
function showError() {
|
||||||
clearEl(imgPreviews);
|
clearEl(imgPreviews);
|
||||||
showEl(scraperError);
|
showEl(scraperError);
|
||||||
enableFetch();
|
enableFetch();
|
||||||
}
|
}
|
||||||
|
|
||||||
function hideError() {
|
function hideError() {
|
||||||
hideEl(scraperError);
|
hideEl(scraperError);
|
||||||
}
|
}
|
||||||
|
|
||||||
function disableFetch() {
|
function disableFetch() {
|
||||||
fetchButton.setAttribute('disabled', '');
|
fetchButton.setAttribute('disabled', '');
|
||||||
}
|
}
|
||||||
|
|
||||||
function enableFetch() {
|
function enableFetch() {
|
||||||
fetchButton.removeAttribute('disabled');
|
fetchButton.removeAttribute('disabled');
|
||||||
}
|
}
|
||||||
|
@ -231,13 +236,30 @@ function setupImageUpload() {
|
||||||
|
|
||||||
function disableUploadButton() {
|
function disableUploadButton() {
|
||||||
const submitButton = $('.button.input--separate-top');
|
const submitButton = $('.button.input--separate-top');
|
||||||
if (submitButton !== null) {
|
|
||||||
submitButton.disabled = true;
|
if (!submitButton) {
|
||||||
submitButton.innerText = 'Please wait...';
|
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
|
// delay is needed because Safari stops the submit if the button is immediately disabled
|
||||||
requestAnimationFrame(() => submitButton.setAttribute('disabled', '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) {
|
function submitHandler(event) {
|
||||||
|
|
|
@ -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 { getRandomArrayItem } from '../../../test/randomness';
|
||||||
import { fireEvent } from '@testing-library/dom';
|
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', () => {
|
describe('delegate', () => {
|
||||||
it('should call the native addEventListener method on the element', () => {
|
it('should call the native addEventListener method on the element', () => {
|
||||||
const mockElement = document.createElement('div');
|
const mockElement = document.createElement('div');
|
||||||
|
|
|
@ -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>(
|
export function delegate<K extends keyof PhilomenaAvailableEventsMap, Target extends Element>(
|
||||||
node: PhilomenaEventElement,
|
node: PhilomenaEventElement,
|
||||||
event: K,
|
event: K,
|
||||||
|
|
Loading…
Reference in a new issue