Flask-Files/app/static/js/selection.js
2025-03-24 20:34:42 +01:00

182 lines
No EOL
5.4 KiB
JavaScript

document.addEventListener('DOMContentLoaded', function () {
const filesContainer = document.getElementById('files-container');
if (!filesContainer) return;
// Create selection box element
const selectionBox = document.createElement('div');
selectionBox.className = 'selection-box';
selectionBox.style.display = 'none';
document.body.appendChild(selectionBox);
// Selection variables
let isSelecting = false;
let startX, startY;
let selectedItems = [];
// Handle mouse down on container (start selection)
filesContainer.addEventListener('mousedown', function (e) {
// Only start selection if clicking on empty space with left mouse button
if (e.target === filesContainer && e.button === 0) {
isSelecting = true;
startX = e.clientX;
startY = e.clientY;
// Position selection box
selectionBox.style.left = `${startX}px`;
selectionBox.style.top = `${startY}px`;
selectionBox.style.width = '0px';
selectionBox.style.height = '0px';
selectionBox.style.display = 'block';
// Clear existing selection if not holding shift
if (!e.shiftKey) {
clearSelection();
}
// Prevent default behavior
e.preventDefault();
}
});
// Handle mouse move (update selection box)
document.addEventListener('mousemove', function (e) {
if (!isSelecting) return;
// Calculate new dimensions
const width = Math.abs(e.clientX - startX);
const height = Math.abs(e.clientY - startY);
// Calculate top-left corner
const left = e.clientX < startX ? e.clientX : startX;
const top = e.clientY < startY ? e.clientY : startY;
// Update selection box
selectionBox.style.left = `${left}px`;
selectionBox.style.top = `${top}px`;
selectionBox.style.width = `${width}px`;
selectionBox.style.height = `${height}px`;
// Check which items are in the selection
const selectionRect = selectionBox.getBoundingClientRect();
const items = filesContainer.querySelectorAll('.file-item, .folder-item');
items.forEach(item => {
const itemRect = item.getBoundingClientRect();
// Check if item intersects with selection box
const intersects = !(
itemRect.right < selectionRect.left ||
itemRect.left > selectionRect.right ||
itemRect.bottom < selectionRect.top ||
itemRect.top > selectionRect.bottom
);
if (intersects) {
item.classList.add('selected');
if (!selectedItems.includes(item)) {
selectedItems.push(item);
}
} else if (!e.shiftKey && !item.classList.contains('manually-selected')) {
item.classList.remove('selected');
const index = selectedItems.indexOf(item);
if (index > -1) {
selectedItems.splice(index, 1);
}
}
});
});
// Handle mouse up (end selection)
document.addEventListener('mouseup', function () {
if (isSelecting) {
isSelecting = false;
selectionBox.style.display = 'none';
// Mark selected items
selectedItems.forEach(item => {
item.classList.add('manually-selected');
});
// Update selection actions
updateSelectionActions();
}
});
// Handle item click (toggle selection)
filesContainer.addEventListener('click', function (e) {
const item = e.target.closest('.file-item, .folder-item');
if (item) {
// If holding Ctrl or Shift, toggle selection
if (e.ctrlKey || e.shiftKey) {
e.preventDefault();
item.classList.toggle('selected');
item.classList.toggle('manually-selected');
const index = selectedItems.indexOf(item);
if (index > -1) {
selectedItems.splice(index, 1);
} else {
selectedItems.push(item);
}
updateSelectionActions();
} else {
// If not holding Ctrl/Shift, clear selection and select only this item
if (!item.classList.contains('selected')) {
clearSelection();
item.classList.add('selected');
item.classList.add('manually-selected');
selectedItems = [item];
updateSelectionActions();
}
}
} else if (e.target === filesContainer) {
// Clicking on empty space clears selection
clearSelection();
}
});
// Clear selection
function clearSelection() {
const items = filesContainer.querySelectorAll('.file-item, .folder-item');
items.forEach(item => {
item.classList.remove('selected', 'manually-selected');
});
selectedItems = [];
updateSelectionActions();
}
// Update selection actions (e.g., show action bar)
function updateSelectionActions() {
const actionBar = document.getElementById('selection-actions');
if (actionBar) {
if (selectedItems.length > 0) {
actionBar.classList.add('active');
// Update count
const countElement = actionBar.querySelector('.selection-count');
if (countElement) {
countElement.textContent = `${selectedItems.length} item(s) selected`;
}
} else {
actionBar.classList.remove('active');
}
}
}
// Select all items
window.selectAllItems = function () {
const items = filesContainer.querySelectorAll('.file-item, .folder-item');
items.forEach(item => {
item.classList.add('selected', 'manually-selected');
if (!selectedItems.includes(item)) {
selectedItems.push(item);
}
});
updateSelectionActions();
};
});