Current File : /home/kelaby89/public_html/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';
    }
}

Page not found – Hello World !