Current File : /home/kelaby89/www/software/gram-grid-planner/script.js |
document.getElementById('imageUpload').addEventListener('change', handleImageUpload);
document.getElementById('gridSizeSlider').addEventListener('input', handleGridSizeChange);
document.getElementById('gridSizeButton').addEventListener('click', resetGridSize);
document.getElementById('helpButton').addEventListener('click', showHelp);
document.getElementById('closeHelpButton').addEventListener('click', closeHelp);
document.getElementById('saveGridButton').addEventListener('click', saveGridState);
document.getElementById('loadGridButton').addEventListener('click', () => document.getElementById('loadGridInput').click());
document.getElementById('loadGridInput').addEventListener('change', handleLoadGrid);
document.getElementById('removeSelectedButton').addEventListener('click', removeSelectedImages);
document.getElementById('themeToggleButton').addEventListener('click', toggleTheme);
document.getElementById('aboutButton').addEventListener('click', showAbout);
document.getElementById('closeAboutButton').addEventListener('click', closeAbout);
let selectedElements = [];
let draggedElement = null;
let singleDrag = false;
function updateImageCounter() {
const imageCounter = document.getElementById('imageCount');
const gridContainer = document.getElementById('gridContainer');
imageCounter.textContent = `${gridContainer.children.length}`;
}
function handleImageUpload(event) {
const files = event.target.files;
const gridContainer = document.getElementById('gridContainer');
// Loop through selected files
Array.from(files).forEach((file, index) => {
const reader = new FileReader();
reader.onload = function(e) {
// Create a div element with the class 'grid-item'
const gridItem = document.createElement('div');
gridItem.classList.add('grid-item');
gridItem.draggable = true;
gridItem.dataset.index = gridContainer.children.length;
// Create an image element
const img = document.createElement('img');
img.src = e.target.result;
// Append the image to the grid-item
gridItem.appendChild(img);
// Add event listeners for selection and drag-and-drop
gridItem.addEventListener('click', handleSelect);
gridItem.addEventListener('dragstart', handleDragStart);
gridItem.addEventListener('dragover', handleDragOver);
gridItem.addEventListener('drop', handleDrop);
gridItem.addEventListener('dragend', handleDragEnd);
// Add touch event listeners for drag-and-drop on touchscreens
gridItem.addEventListener('touchstart', handleTouchStart, { passive: true });
gridItem.addEventListener('touchmove', handleTouchMove, { passive: true });
gridItem.addEventListener('touchend', handleTouchEnd);
// Append the grid-item to the grid container
gridContainer.appendChild(gridItem);
// Update the size of the new grid item
updateGridItemSize(gridItem);
// Update the image counter
updateImageCounter();
};
// Read the file as a data URL
reader.readAsDataURL(file);
});
}
function handleGridSizeChange(event) {
const size = event.target.value + 'px';
document.documentElement.style.setProperty('--grid-item-size', size);
document.querySelectorAll('.grid-item').forEach(item => {
item.style.width = size;
item.style.height = size;
});
}
function resetGridSize() {
const defaultSize = 250;
const slider = document.getElementById('gridSizeSlider');
slider.value = defaultSize;
handleGridSizeChange({ target: slider });
}
function updateGridItemSize(gridItem) {
const size = getComputedStyle(document.documentElement).getPropertyValue('--grid-item-size');
gridItem.style.width = size;
gridItem.style.height = size;
}
function handleSelect(event) {
const gridItem = event.currentTarget;
if (event.ctrlKey || event.metaKey) {
gridItem.classList.toggle('selected');
if (gridItem.classList.contains('selected')) {
selectedElements.push(gridItem);
} else {
selectedElements = selectedElements.filter(item => item !== gridItem);
}
} else {
selectedElements.forEach(item => item.classList.remove('selected'));
selectedElements = [gridItem];
gridItem.classList.add('selected');
}
}
function handleDragStart(event) {
const gridItem = event.target.closest('.grid-item');
singleDrag = !gridItem.classList.contains('selected');
draggedElement = singleDrag ? [gridItem] : selectedElements.length > 0 ? selectedElements : [gridItem];
draggedElement.forEach(item => item.classList.add('draggable'));
event.dataTransfer.effectAllowed = 'move';
}
function handleDragOver(event) {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}
function handleDrop(event) {
event.preventDefault();
const targetElement = event.target.closest('.grid-item');
if (draggedElement.includes(targetElement)) return;
const gridContainer = document.getElementById('gridContainer');
const targetIndex = Array.from(gridContainer.children).indexOf(targetElement);
// Remove dragged elements from their current position
draggedElement.forEach(item => gridContainer.removeChild(item));
// Insert dragged elements next to each other starting at the target index
draggedElement.forEach((item, index) => {
const insertBeforeElement = gridContainer.children[targetIndex + index];
if (insertBeforeElement) {
gridContainer.insertBefore(item, insertBeforeElement);
} else {
gridContainer.appendChild(item);
}
});
}
function handleDragEnd(event) {
draggedElement.forEach(item => item.classList.remove('draggable'));
draggedElement = null;
singleDrag = false;
}
// Touch event handlers
function handleTouchStart(event) {
const touch = event.touches[0];
const gridItem = event.target.closest('.grid-item');
singleDrag = !gridItem.classList.contains('selected');
draggedElement = singleDrag ? [gridItem] : selectedElements.length > 0 ? selectedElements : [gridItem];
draggedElement.forEach(item => item.classList.add('draggable'));
// Create a simulated drag event
const simulatedEvent = new MouseEvent('dragstart', {
bubbles: true,
cancelable: true,
view: window,
clientX: touch.clientX,
clientY: touch.clientY
});
gridItem.dispatchEvent(simulatedEvent);
}
function handleTouchMove(event) {
const touch = event.touches[0];
const gridItem = document.elementFromPoint(touch.clientX, touch.clientY).closest('.grid-item');
if (gridItem && draggedElement.includes(gridItem)) return;
const simulatedEvent = new MouseEvent('dragover', {
bubbles: true,
cancelable: true,
view: window,
clientX: touch.clientX,
clientY: touch.clientY
});
if (gridItem) {
gridItem.dispatchEvent(simulatedEvent);
}
}
function handleTouchEnd(event) {
const touch = event.changedTouches[0];
const gridItem = document.elementFromPoint(touch.clientX, touch.clientY).closest('.grid-item');
const simulatedEvent = new MouseEvent('drop', {
bubbles: true,
cancelable: true,
view: window,
clientX: touch.clientX,
clientY: touch.clientY
});
if (gridItem) {
gridItem.dispatchEvent(simulatedEvent);
}
draggedElement.forEach(item => item.classList.remove('draggable'));
draggedElement = null;
singleDrag = false;
}
function saveGridState() {
const gridItems = document.querySelectorAll('.grid-item');
const gridState = Array.from(gridItems).map(item => ({
src: item.querySelector('img').src,
index: item.dataset.index
}));
const blob = new Blob([JSON.stringify(gridState)], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'grid-state.json';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function handleLoadGrid(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function(e) {
const gridState = JSON.parse(e.target.result);
restoreGridState(gridState);
};
reader.readAsText(file);
}
function restoreGridState(gridState) {
const gridContainer = document.getElementById('gridContainer');
gridContainer.innerHTML = '';
gridState.forEach(item => {
const gridItem = document.createElement('div');
gridItem.classList.add('grid-item');
gridItem.draggable = true;
gridItem.dataset.index = item.index;
const img = document.createElement('img');
img.src = item.src;
gridItem.appendChild(img);
gridItem.addEventListener('click', handleSelect);
gridItem.addEventListener('dragstart', handleDragStart);
gridItem.addEventListener('dragover', handleDragOver);
gridItem.addEventListener('drop', handleDrop);
gridItem.addEventListener('dragend', handleDragEnd);
// Add touch event listeners for drag-and-drop on touchscreens
gridItem.addEventListener('touchstart', handleTouchStart, { passive: true });
gridItem.addEventListener('touchmove', handleTouchMove, { passive: true });
gridItem.addEventListener('touchend', handleTouchEnd);
gridContainer.appendChild(gridItem);
updateGridItemSize(gridItem);
});
// Update the image counter
updateImageCounter();
}
function removeSelectedImages() {
selectedElements.forEach(item => item.remove());
selectedElements = [];
updateImageCounter(); // Update the image counter
}
function showHelp() {
document.getElementById('helpModal').classList.add('active');
}
function closeHelp() {
document.getElementById('helpModal').classList.remove('active');
}
function showAbout() {
document.getElementById('aboutModal').classList.add('active');
}
function closeAbout() {
document.getElementById('aboutModal').classList.remove('active');
}
function toggleTheme() {
const themeButton = document.getElementById('themeToggleButton');
if (document.body.classList.toggle('light-mode')) {
themeButton.textContent = 'Dark Mode';
} else {
themeButton.textContent = 'Light Mode';
}
}