tweaking series order tools
This commit is contained in:
@@ -7,7 +7,8 @@
|
|||||||
|
|
||||||
const state = {
|
const state = {
|
||||||
isSelectMode: false,
|
isSelectMode: false,
|
||||||
selectedIds: new Set()
|
selectedIds: new Set(),
|
||||||
|
selectionOrder: [] // Array to track order of selection
|
||||||
};
|
};
|
||||||
|
|
||||||
// DOM elements (populated on init)
|
// DOM elements (populated on init)
|
||||||
@@ -28,6 +29,8 @@
|
|||||||
dom.tagInput = document.getElementById('bulkTagInput');
|
dom.tagInput = document.getElementById('bulkTagInput');
|
||||||
dom.autocomplete = document.getElementById('bulkTagAutocomplete');
|
dom.autocomplete = document.getElementById('bulkTagAutocomplete');
|
||||||
dom.commonTags = document.getElementById('commonTagsList');
|
dom.commonTags = document.getElementById('commonTagsList');
|
||||||
|
dom.floatingPreview = document.getElementById('floatingPreview');
|
||||||
|
dom.floatingPreviewImage = document.getElementById('floatingPreviewImage');
|
||||||
|
|
||||||
if (!dom.selectBtn || !dom.panel) return;
|
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() {
|
function toggleSelectMode() {
|
||||||
@@ -104,12 +131,18 @@
|
|||||||
|
|
||||||
if (state.selectedIds.has(id)) {
|
if (state.selectedIds.has(id)) {
|
||||||
state.selectedIds.delete(id);
|
state.selectedIds.delete(id);
|
||||||
|
state.selectionOrder = state.selectionOrder.filter(x => x !== id);
|
||||||
item.classList.remove('selected');
|
item.classList.remove('selected');
|
||||||
|
removeOrderBadge(item);
|
||||||
} else {
|
} else {
|
||||||
state.selectedIds.add(id);
|
state.selectedIds.add(id);
|
||||||
|
state.selectionOrder.push(id);
|
||||||
item.classList.add('selected');
|
item.classList.add('selected');
|
||||||
|
addOrderBadge(item, state.selectionOrder.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update all badges to reflect current order
|
||||||
|
updateAllOrderBadges();
|
||||||
updateCount();
|
updateCount();
|
||||||
loadCommonTags();
|
loadCommonTags();
|
||||||
dispatchSelectionChanged();
|
dispatchSelectionChanged();
|
||||||
@@ -117,8 +150,10 @@
|
|||||||
|
|
||||||
function clearSelection() {
|
function clearSelection() {
|
||||||
state.selectedIds.clear();
|
state.selectedIds.clear();
|
||||||
|
state.selectionOrder = [];
|
||||||
document.querySelectorAll('.img-clickable.selected').forEach(el => {
|
document.querySelectorAll('.img-clickable.selected').forEach(el => {
|
||||||
el.classList.remove('selected');
|
el.classList.remove('selected');
|
||||||
|
removeOrderBadge(el);
|
||||||
});
|
});
|
||||||
updateCount();
|
updateCount();
|
||||||
updateCommonTagsDisplay();
|
updateCommonTagsDisplay();
|
||||||
@@ -133,7 +168,10 @@
|
|||||||
|
|
||||||
function dispatchSelectionChanged() {
|
function dispatchSelectionChanged() {
|
||||||
document.dispatchEvent(new CustomEvent('selectionChanged', {
|
document.dispatchEvent(new CustomEvent('selectionChanged', {
|
||||||
detail: { count: state.selectedIds.size }
|
detail: {
|
||||||
|
count: state.selectedIds.size,
|
||||||
|
orderedIds: [...state.selectionOrder]
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,11 +203,43 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateSelectionUI() {
|
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 => {
|
document.querySelectorAll('.img-clickable').forEach(item => {
|
||||||
const id = parseInt(item.dataset.id);
|
const id = parseInt(item.dataset.id);
|
||||||
if (state.selectedIds.has(id)) {
|
if (state.selectedIds.has(id)) {
|
||||||
item.classList.add('selected');
|
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)
|
// Expose global API for other scripts (like series editor)
|
||||||
window.selectedImages = state.selectedIds;
|
window.selectedImages = state.selectedIds;
|
||||||
|
window.selectionOrder = state.selectionOrder; // Ordered array of selected IDs
|
||||||
window.clearSelection = clearSelection;
|
window.clearSelection = clearSelection;
|
||||||
window.enableSelectMode = enableSelectMode;
|
window.enableSelectMode = enableSelectMode;
|
||||||
window.disableSelectMode = disableSelectMode;
|
window.disableSelectMode = disableSelectMode;
|
||||||
|
|||||||
@@ -2036,6 +2036,55 @@ body.select-mode .gallery-infinite-container {
|
|||||||
font-size: 0.85rem;
|
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 */
|
/* Mobile: full-width panel from bottom */
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
.bulk-editor-panel {
|
.bulk-editor-panel {
|
||||||
|
|||||||
@@ -120,6 +120,11 @@
|
|||||||
<!-- Modal -->
|
<!-- Modal -->
|
||||||
{% include '_gallery_modal.html' %}
|
{% 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 -->
|
<!-- Bulk Editor Panel -->
|
||||||
<aside id="bulkEditorPanel" class="bulk-editor-panel">
|
<aside id="bulkEditorPanel" class="bulk-editor-panel">
|
||||||
<div class="bulk-editor-header">
|
<div class="bulk-editor-header">
|
||||||
@@ -204,7 +209,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
addToSeriesBtn.addEventListener('click', async () => {
|
addToSeriesBtn.addEventListener('click', async () => {
|
||||||
if (!window.selectedImages || window.selectedImages.size === 0) return;
|
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;
|
const startPage = parseInt(startPageInput.value) || 1;
|
||||||
|
|
||||||
addToSeriesBtn.disabled = true;
|
addToSeriesBtn.disabled = true;
|
||||||
|
|||||||
Reference in New Issue
Block a user