commit e894d2e9d2a42aa68de9d5a72302b970f29ebcd9
parent a359904e447cf39e8cf765009ccfc5be7172d527
Author: Hunter
Date:   Mon, 20 Oct 2025 12:32:28 -0400

duplicate image on cmd+click

Diffstat:
Mscript.js | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 63 insertions(+), 1 deletion(-)

diff --git a/script.js b/script.js @@ -185,6 +185,8 @@ function addImage(src, xCell, yCell, widthCells, heightCells) { grid.appendChild(container); setupImageHandlers(imageData); + + return imageData; } function calculatePanBounds(imageData) { @@ -259,7 +261,7 @@ function setupImageHandlers(imageData) { bringToFront(container); }); - // Moving / Deleting + // Moving / Deleting / Duplicating container.addEventListener('mousedown', (e) => { if (e.target.classList.contains('resize-handle')) return; @@ -275,6 +277,66 @@ function setupImageHandlers(imageData) { return; } + // Cmd-click (or Ctrl-click on Windows/Linux) to duplicate + if (e.metaKey || e.ctrlKey) { + // Calculate target position (2 cells to the right if there's room) + let newXCell = imageData.xCell + 2; + let newYCell = imageData.yCell; + + // If there's not enough room to the right, try to place appropriately + if (newXCell + imageData.widthCells > GRID_COLS) { + // Try wrapping to next row + newXCell = 0; + newYCell = imageData.yCell + imageData.heightCells; + + // If that goes off the bottom, place at origin + if (newYCell + imageData.heightCells > GRID_ROWS) { + newXCell = 0; + newYCell = 0; + } + } + + // Create duplicate with the same image source and dimensions + const imgElement = container.querySelector('img'); + const newImageData = addImage( + imgElement.src, + newXCell, + newYCell, + imageData.widthCells, + imageData.heightCells + ); + + // Copy pan and zoom settings from original + // Store the original settings to apply after image loads + const originalPanX = imageData.panX; + const originalPanY = imageData.panY; + const originalUserScale = imageData.userScale; + + // Override the onload to copy settings + const newImg = newImageData.container.querySelector('img'); + const originalOnload = newImg.onload; + newImg.onload = () => { + // Run the original onload first + if (originalOnload) originalOnload.call(newImg); + + // Then apply the copied settings + newImageData.panX = originalPanX; + newImageData.panY = originalPanY; + newImageData.userScale = originalUserScale; + updateImagePosition(newImageData); + }; + + // If image is already loaded (cached), trigger the settings copy + if (newImg.complete && newImageData.naturalWidth > 0) { + newImageData.panX = originalPanX; + newImageData.panY = originalPanY; + newImageData.userScale = originalUserScale; + updateImagePosition(newImageData); + } + + return; + } + // Lock cursor to move during drag operation document.body.style.cursor = 'move'; document.body.classList.add('dragging');