1
0
mirror of https://github.com/koloml/philomena-tagging-assistant.git synced 2026-05-09 07:12:19 +00:00

Extracted CLS compensation logic into separate method

This commit is contained in:
2026-04-05 19:46:34 +04:00
parent 7d41524b4a
commit 4f52906123

View File

@@ -9,8 +9,8 @@ import { EVENT_PRESET_TAG_CHANGE_APPLIED, type PresetTagChange } from "$content/
export class TagsForm extends BaseComponent {
#togglePresetsButton: HTMLButtonElement = document.createElement('button');
#presetsList = EditorPresetsBlock.create();
#plainEditorTextarea: HTMLTextAreaElement|null = null;
#fancyEditorInput: HTMLInputElement|null = null;
#plainEditorTextarea: HTMLTextAreaElement | null = null;
#fancyEditorInput: HTMLInputElement | null = null;
#tagsSet: Set<string> = new Set();
protected build() {
@@ -173,7 +173,7 @@ export class TagsForm extends BaseComponent {
#onTagChangeRequested(event: CustomEvent<PresetTagChange>) {
const targetElement = event.target instanceof HTMLElement ? event.target : null;
const { addedTags = null, removedTags = null } = event.detail;
const {addedTags = null, removedTags = null} = event.detail;
let tagChangeList: string[] = [];
if (addedTags) {
@@ -188,31 +188,33 @@ export class TagsForm extends BaseComponent {
);
}
const containerOffset = this.#presetsList.container.offsetTop;
const presetOffset = targetElement?.offsetTop || 0;
this.#applyTagChangesWithFancyTagEditor(
tagChangeList.join(',')
this.#executeAndCompensateForLayoutShift(
() => this.#applyTagChangesWithFancyTagEditor(tagChangeList.join(',')),
[this.#presetsList.container, targetElement],
);
}
const containerOffsetDifference = this.#presetsList.container.offsetTop - containerOffset;
let presetOffsetDifference = (targetElement?.offsetTop || 0) - presetOffset;
#executeAndCompensateForLayoutShift(executeOperation: () => void, elements: (HTMLElement | null)[]) {
const offsetsListBefore = TagsForm.#gatherOffsetsFromElements(elements);
executeOperation();
const offsetsListAfter = TagsForm.#gatherOffsetsFromElements(elements);
// If target element is no longer visible, then there is no need to apply scrolling fix, otherwise it will shift
// user up. Invisible elements are always report 0 offset.
if (targetElement?.checkVisibility() === false) {
presetOffsetDifference = 0;
const resultDifference = offsetsListAfter
.map((offsetAfter, index) =>
offsetAfter !== null && offsetsListBefore[index] !== null
? offsetAfter - offsetsListBefore[index]
: null)
.filter(difference => difference !== null)
.reduce((summary, difference) => summary + difference, 0);
if (resultDifference === 0) {
return;
}
// Compensating for the layout shift: when user clicks on a tag (or on "add/remove all tags"), tag editor might
// overflow the current line and wrap tags around to the next line, causing presets section to shift. We need to
// avoid that for better UX.
if (containerOffsetDifference !== 0 || presetOffsetDifference !== 0) {
window.scrollTo({
top: window.scrollY + containerOffsetDifference + presetOffsetDifference,
behavior: 'instant',
});
}
window.scrollTo({
top: scrollY + resultDifference,
behavior: 'instant',
})
}
#applyTagChangesWithFancyTagEditor(tagsListWithChanges: string): void {
@@ -241,7 +243,7 @@ export class TagsForm extends BaseComponent {
this.refreshTagColors();
}
#onPlainEditorReloadRequested(event: CustomEvent<ReloadCustomOptions|null>) {
#onPlainEditorReloadRequested(event: CustomEvent<ReloadCustomOptions | null>) {
if (!event.detail?.skipTagColorRefresh) {
this.refreshTagColors();
}
@@ -251,6 +253,14 @@ export class TagsForm extends BaseComponent {
}
}
static #gatherOffsetsFromElements(elements: (HTMLElement | null)[]): (number | null)[] {
return elements.map(
maybeElement => maybeElement?.checkVisibility()
? maybeElement?.offsetTop
: null
);
}
static watchForEditors() {
document.body.addEventListener('click', event => {
const targetElement = event.target;