Preserve card edit scroll position
This commit is contained in:
1 parent
ec6364b32b
commit
01fa2bc2b6
2 files changed
+57
-2
No files matched your search
@@ -965,7 +965,7 @@ function render_auth_home_page(array $user, array $otcProducts = [], array $otcM
|
|||||||
echo '</div>';
|
echo '</div>';
|
||||||
echo '</section>';
|
echo '</section>';
|
||||||
echo '<script src="/scripts/help-icon-overlays.js"></script>';
|
echo '<script src="/scripts/help-icon-overlays.js"></script>';
|
||||||
echo '<script src="/scripts/shared-editable-action-card.js?v=20260920-2"></script>';
|
echo '<script src="/scripts/shared-editable-action-card.js?v=20260930-1"></script>';
|
||||||
echo '<script src="/scripts/shared-mobile-detail.js?v=20260925-1"></script>';
|
echo '<script src="/scripts/shared-mobile-detail.js?v=20260925-1"></script>';
|
||||||
echo '<script src="/scripts/large-table-column-resize.js?v=' . filemtime(__DIR__ . '/../../../../public/scripts/large-table-column-resize.js') . '"></script>';
|
echo '<script src="/scripts/large-table-column-resize.js?v=' . filemtime(__DIR__ . '/../../../../public/scripts/large-table-column-resize.js') . '"></script>';
|
||||||
echo '<script>';
|
echo '<script>';
|
||||||
|
|||||||
@@ -2,9 +2,53 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const cardSelector = '[data-shared-editable-action-card]';
|
const cardSelector = '[data-shared-editable-action-card]';
|
||||||
|
const scrollRestoreStates = new WeakMap();
|
||||||
|
|
||||||
const getCard = (element) => element.closest(cardSelector);
|
const getCard = (element) => element.closest(cardSelector);
|
||||||
|
|
||||||
|
const getScrollContainer = (element) => {
|
||||||
|
let candidate = element?.parentElement || null;
|
||||||
|
|
||||||
|
while (candidate && candidate !== document.body) {
|
||||||
|
const style = window.getComputedStyle(candidate);
|
||||||
|
const scrollable = /(auto|scroll|overlay)/.test(style.overflowY);
|
||||||
|
if (scrollable && candidate.scrollHeight > candidate.clientHeight) {
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
candidate = candidate.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return document.scrollingElement || document.documentElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
const captureScrollPosition = (root, card) => {
|
||||||
|
const container = getScrollContainer(card);
|
||||||
|
scrollRestoreStates.set(root, {
|
||||||
|
card,
|
||||||
|
container,
|
||||||
|
top: container.scrollTop,
|
||||||
|
left: container.scrollLeft,
|
||||||
|
scheduled: false,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const restoreScrollPosition = (root) => {
|
||||||
|
const state = scrollRestoreStates.get(root);
|
||||||
|
if (!state || state.scheduled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.scheduled = true;
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
requestAnimationFrame(() => {
|
||||||
|
if (state.container?.isConnected) {
|
||||||
|
state.container.scrollTo({ top: state.top, left: state.left, behavior: 'auto' });
|
||||||
|
}
|
||||||
|
scrollRestoreStates.delete(root);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const getDirectDeleteElement = (card, selector) => Array.from(card?.children || [])
|
const getDirectDeleteElement = (card, selector) => Array.from(card?.children || [])
|
||||||
.find((child) => child.matches(selector)) || null;
|
.find((child) => child.matches(selector)) || null;
|
||||||
|
|
||||||
@@ -93,7 +137,9 @@
|
|||||||
root.addEventListener('click', (event) => {
|
root.addEventListener('click', (event) => {
|
||||||
const edit = event.target.closest('[data-shared-editable-card-edit]');
|
const edit = event.target.closest('[data-shared-editable-card-edit]');
|
||||||
if (edit && root.contains(edit)) {
|
if (edit && root.contains(edit)) {
|
||||||
setEditMode(getCard(edit), true);
|
const card = getCard(edit);
|
||||||
|
captureScrollPosition(root, card);
|
||||||
|
setEditMode(card, true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +148,7 @@
|
|||||||
const card = getCard(cancel);
|
const card = getCard(cancel);
|
||||||
resetDeleteConfirmation(card);
|
resetDeleteConfirmation(card);
|
||||||
setEditMode(card, false);
|
setEditMode(card, false);
|
||||||
|
scrollRestoreStates.delete(root);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,6 +164,14 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const scrollObserver = new MutationObserver(() => {
|
||||||
|
const state = scrollRestoreStates.get(root);
|
||||||
|
if (state && !root.contains(state.card)) {
|
||||||
|
restoreScrollPosition(root);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
scrollObserver.observe(root, { childList: true, subtree: true });
|
||||||
|
|
||||||
root.addEventListener('input', (event) => {
|
root.addEventListener('input', (event) => {
|
||||||
const input = event.target.closest('[data-shared-editable-card-delete-input]');
|
const input = event.target.closest('[data-shared-editable-card-delete-input]');
|
||||||
if (input && root.contains(input)) {
|
if (input && root.contains(input)) {
|
||||||
|
|||||||
Reference in new issue
Block a user