tweaking series order tools
This commit is contained in:
@@ -7,7 +7,8 @@
|
||||
|
||||
const state = {
|
||||
isSelectMode: false,
|
||||
selectedIds: new Set()
|
||||
selectedIds: new Set(),
|
||||
selectionOrder: [] // Array to track order of selection
|
||||
};
|
||||
|
||||
// DOM elements (populated on init)
|
||||
@@ -28,6 +29,8 @@
|
||||
dom.tagInput = document.getElementById('bulkTagInput');
|
||||
dom.autocomplete = document.getElementById('bulkTagAutocomplete');
|
||||
dom.commonTags = document.getElementById('commonTagsList');
|
||||
dom.floatingPreview = document.getElementById('floatingPreview');
|
||||
dom.floatingPreviewImage = document.getElementById('floatingPreviewImage');
|
||||
|
||||
if (!dom.selectBtn || !dom.panel) return;
|
||||
|
||||
@@ -63,6 +66,30 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Preview on hover in select mode
|
||||
document.addEventListener('mouseenter', handlePreviewShow, true);
|
||||
document.addEventListener('mouseleave', handlePreviewHide, true);
|
||||
}
|
||||
|
||||
function handlePreviewShow(e) {
|
||||
if (!state.isSelectMode || !dom.floatingPreview) return;
|
||||
const item = e.target.closest('.img-clickable');
|
||||
if (!item) return;
|
||||
|
||||
const fullSrc = item.dataset.full;
|
||||
if (fullSrc && dom.floatingPreviewImage) {
|
||||
dom.floatingPreviewImage.src = fullSrc;
|
||||
dom.floatingPreview.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
function handlePreviewHide(e) {
|
||||
if (!dom.floatingPreview) return;
|
||||
const item = e.target.closest('.img-clickable');
|
||||
if (!item) return;
|
||||
|
||||
dom.floatingPreview.classList.remove('active');
|
||||
}
|
||||
|
||||
function toggleSelectMode() {
|
||||
@@ -104,12 +131,18 @@
|
||||
|
||||
if (state.selectedIds.has(id)) {
|
||||
state.selectedIds.delete(id);
|
||||
state.selectionOrder = state.selectionOrder.filter(x => x !== id);
|
||||
item.classList.remove('selected');
|
||||
removeOrderBadge(item);
|
||||
} else {
|
||||
state.selectedIds.add(id);
|
||||
state.selectionOrder.push(id);
|
||||
item.classList.add('selected');
|
||||
addOrderBadge(item, state.selectionOrder.length);
|
||||
}
|
||||
|
||||
// Update all badges to reflect current order
|
||||
updateAllOrderBadges();
|
||||
updateCount();
|
||||
loadCommonTags();
|
||||
dispatchSelectionChanged();
|
||||
@@ -117,8 +150,10 @@
|
||||
|
||||
function clearSelection() {
|
||||
state.selectedIds.clear();
|
||||
state.selectionOrder = [];
|
||||
document.querySelectorAll('.img-clickable.selected').forEach(el => {
|
||||
el.classList.remove('selected');
|
||||
removeOrderBadge(el);
|
||||
});
|
||||
updateCount();
|
||||
updateCommonTagsDisplay();
|
||||
@@ -133,7 +168,10 @@
|
||||
|
||||
function dispatchSelectionChanged() {
|
||||
document.dispatchEvent(new CustomEvent('selectionChanged', {
|
||||
detail: { count: state.selectedIds.size }
|
||||
detail: {
|
||||
count: state.selectedIds.size,
|
||||
orderedIds: [...state.selectionOrder]
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -165,11 +203,43 @@
|
||||
}
|
||||
|
||||
function updateSelectionUI() {
|
||||
// Re-apply selected class to any newly loaded images that are in selection
|
||||
// Re-apply selected class and order badges to any newly loaded images that are in selection
|
||||
document.querySelectorAll('.img-clickable').forEach(item => {
|
||||
const id = parseInt(item.dataset.id);
|
||||
if (state.selectedIds.has(id)) {
|
||||
item.classList.add('selected');
|
||||
const orderIndex = state.selectionOrder.indexOf(id);
|
||||
if (orderIndex !== -1) {
|
||||
addOrderBadge(item, orderIndex + 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------
|
||||
// Order Badge Helpers
|
||||
// ---------------------------
|
||||
function addOrderBadge(item, orderNumber) {
|
||||
removeOrderBadge(item); // Remove existing badge first
|
||||
const badge = document.createElement('div');
|
||||
badge.className = 'selection-order-badge';
|
||||
badge.textContent = orderNumber;
|
||||
item.appendChild(badge);
|
||||
}
|
||||
|
||||
function removeOrderBadge(item) {
|
||||
const existing = item.querySelector('.selection-order-badge');
|
||||
if (existing) existing.remove();
|
||||
}
|
||||
|
||||
function updateAllOrderBadges() {
|
||||
document.querySelectorAll('.img-clickable').forEach(item => {
|
||||
const id = parseInt(item.dataset.id);
|
||||
const orderIndex = state.selectionOrder.indexOf(id);
|
||||
if (orderIndex !== -1) {
|
||||
addOrderBadge(item, orderIndex + 1);
|
||||
} else {
|
||||
removeOrderBadge(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -474,6 +544,7 @@
|
||||
|
||||
// Expose global API for other scripts (like series editor)
|
||||
window.selectedImages = state.selectedIds;
|
||||
window.selectionOrder = state.selectionOrder; // Ordered array of selected IDs
|
||||
window.clearSelection = clearSelection;
|
||||
window.enableSelectMode = enableSelectMode;
|
||||
window.disableSelectMode = disableSelectMode;
|
||||
|
||||
@@ -2036,6 +2036,55 @@ body.select-mode .gallery-infinite-container {
|
||||
font-size: 0.85rem;
|
||||
}
|
||||
|
||||
/* Floating preview overlay (for select mode hover) */
|
||||
.floating-preview {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1000;
|
||||
width: 600px;
|
||||
height: 500px;
|
||||
background: var(--panel);
|
||||
border: 2px solid var(--accent);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
|
||||
padding: 4px;
|
||||
pointer-events: none;
|
||||
}
|
||||
.floating-preview.active {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.floating-preview img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
object-fit: contain;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
/* Selection order badge on gallery items */
|
||||
.selection-order-badge {
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 0.75rem;
|
||||
font-weight: bold;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
|
||||
z-index: 10;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Mobile: full-width panel from bottom */
|
||||
@media (max-width: 640px) {
|
||||
.bulk-editor-panel {
|
||||
|
||||
@@ -120,6 +120,11 @@
|
||||
<!-- Modal -->
|
||||
{% include '_gallery_modal.html' %}
|
||||
|
||||
<!-- Floating Preview (for select mode hover) -->
|
||||
<div id="floatingPreview" class="floating-preview">
|
||||
<img id="floatingPreviewImage" src="" alt="Preview">
|
||||
</div>
|
||||
|
||||
<!-- Bulk Editor Panel -->
|
||||
<aside id="bulkEditorPanel" class="bulk-editor-panel">
|
||||
<div class="bulk-editor-header">
|
||||
@@ -204,7 +209,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
addToSeriesBtn.addEventListener('click', async () => {
|
||||
if (!window.selectedImages || window.selectedImages.size === 0) return;
|
||||
|
||||
const imageIds = Array.from(window.selectedImages);
|
||||
// Use selectionOrder (click order) for page ordering
|
||||
const imageIds = window.selectionOrder ? [...window.selectionOrder] : Array.from(window.selectedImages);
|
||||
const startPage = parseInt(startPageInput.value) || 1;
|
||||
|
||||
addToSeriesBtn.disabled = true;
|
||||
|
||||
Reference in New Issue
Block a user