PDF UX: auto-reorder on drag, visual delete animation, remove apply button
- Reorder: drag-drop auto-saves after 800ms, no button needed - Delete: selected pages fade out + shrink on delete click - Delete button shows Удаление... state - Reorder hint shows Сохранение.../Порядок сохранён - Better drop positioning (left/right of target)
This commit is contained in:
parent
78c181aa6c
commit
93952d0844
@ -769,8 +769,7 @@
|
||||
<span class="option-label">Перетаскивайте страницы мышкой для нового порядка</span>
|
||||
<div class="page-grid" id="reorderPageGrid"></div>
|
||||
<div class="grid-action-bar">
|
||||
<button class="grid-action-btn primary" id="btnReorderApply" onclick="executeReorderPages()">Применить порядок</button>
|
||||
<span class="page-grid-hint" id="reorderHint"></span>
|
||||
<span class="page-grid-hint" id="reorderHint">Перетащите и отпустите — порядок сохранится автоматически</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1746,19 +1745,20 @@
|
||||
const fromPage = e.dataTransfer.getData('text/plain');
|
||||
const fromEl = grid.querySelector('[data-page="' + fromPage + '"]');
|
||||
if (fromEl && fromEl !== thumb) {
|
||||
// Swap positions in DOM
|
||||
const parent = thumb.parentNode;
|
||||
const thumbNext = thumb.nextSibling;
|
||||
if (fromEl.nextSibling === thumb) {
|
||||
parent.insertBefore(thumb, fromEl);
|
||||
// Insert dragged element before or after drop target
|
||||
const rect = thumb.getBoundingClientRect();
|
||||
const midX = rect.left + rect.width / 2;
|
||||
if (e.clientX < midX) {
|
||||
grid.insertBefore(fromEl, thumb);
|
||||
} else {
|
||||
parent.insertBefore(fromEl, thumb);
|
||||
parent.insertBefore(thumb, thumbNext);
|
||||
grid.insertBefore(fromEl, thumb.nextSibling);
|
||||
}
|
||||
// Update visual numbers
|
||||
// Update visual order numbers
|
||||
Array.from(grid.children).forEach((el, idx) => {
|
||||
el.querySelector('.page-thumb-num').textContent = idx + 1;
|
||||
});
|
||||
// Auto-save reorder
|
||||
autoSaveReorder();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1798,12 +1798,25 @@
|
||||
const fileId = state.selectedFileId;
|
||||
if (!fileId) { showError('Выберите файл'); return; }
|
||||
clearError();
|
||||
// Hide deleted pages visually
|
||||
const grid = document.getElementById('deletePageGrid');
|
||||
if (grid) {
|
||||
grid.querySelectorAll('.page-thumb.selected').forEach(el => {
|
||||
el.style.transition = 'opacity .3s, transform .3s';
|
||||
el.style.opacity = '0';
|
||||
el.style.transform = 'scale(0.8)';
|
||||
setTimeout(() => el.remove(), 300);
|
||||
});
|
||||
}
|
||||
document.getElementById('btnDeleteSelected').disabled = true;
|
||||
document.getElementById('btnDeleteSelected').textContent = 'Удаление...';
|
||||
try {
|
||||
const res = await fetch('/pdf/delete', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ fileId, pages: pages.join(',') }) });
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error);
|
||||
showResult(data);
|
||||
} catch(e) { showError(e.message); }
|
||||
document.getElementById('btnDeleteSelected').textContent = 'Удалить выбранные (0)';
|
||||
};
|
||||
|
||||
window.executeRotatePages = async function() {
|
||||
@ -1847,6 +1860,31 @@
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Auto-save reorder on drop
|
||||
let _reorderTimeout = null;
|
||||
function autoSaveReorder() {
|
||||
clearTimeout(_reorderTimeout);
|
||||
const hint = document.getElementById('reorderHint');
|
||||
if (hint) hint.textContent = 'Сохранение...';
|
||||
_reorderTimeout = setTimeout(async () => {
|
||||
const grid = document.getElementById('reorderPageGrid');
|
||||
if (!grid) return;
|
||||
const order = Array.from(grid.querySelectorAll('.page-thumb')).map(t => parseInt(t.dataset.page));
|
||||
const fileId = state.selectedFileId;
|
||||
if (!fileId) return;
|
||||
try {
|
||||
const res = await fetch('/pdf/reorder', { method: 'POST', headers: {'Content-Type':'application/json'}, body: JSON.stringify({ fileId, order }) });
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.error);
|
||||
if (hint) hint.textContent = 'Порядок сохранён';
|
||||
showResult(data);
|
||||
} catch(e) {
|
||||
if (hint) hint.textContent = 'Ошибка: ' + e.message;
|
||||
}
|
||||
}, 800);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
</script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user