grid.js (5.4 KB)
1 // Paper dimensions in mm 2 const LETTER_WIDTH_MM = 215.9; // 8.5 inches 3 const LETTER_HEIGHT_MM = 279.4; // 11 inches 4 const A4_WIDTH_MM = 210; 5 const A4_HEIGHT_MM = 297; 6 const MARGIN_MM = 6.35; // 0.25 inches 7 8 // Calculate maximum grid dimensions that fit both Letter and A4 with margins 9 function calculateGridDimensions(cellSize) { 10 // Available printable area (limiting factor is the smaller of Letter/A4 for each dimension) 11 const availableWidth = Math.min(LETTER_WIDTH_MM, A4_WIDTH_MM) - (2 * MARGIN_MM); 12 const availableHeight = Math.min(LETTER_HEIGHT_MM, A4_HEIGHT_MM) - (2 * MARGIN_MM); 13 14 // Calculate how many cells fit 15 const cols = Math.floor(availableWidth / cellSize); 16 const rows = Math.floor(availableHeight / cellSize); 17 18 return { cols, rows }; 19 } 20 21 // Calculate grid dimensions as percentage of Letter paper (used for screen layout) 22 function calculateGridPercentages(cellSize, cols, rows) { 23 const gridWidthMM = cols * cellSize; 24 const gridHeightMM = rows * cellSize; 25 return { 26 widthPercent: (gridWidthMM / LETTER_WIDTH_MM) * 100, 27 heightPercent: (gridHeightMM / LETTER_HEIGHT_MM) * 100 28 }; 29 } 30 31 // Cell size bounds (in mm) 32 const MIN_CELL_SIZE_MM = 2; 33 const MAX_CELL_SIZE_MM = 10; 34 35 let GRID_COLS = 49; 36 let GRID_ROWS = 66; 37 let CELL_SIZE_MM = 4; // Physical size of each cell when printed (can be overridden by URL parameter) 38 39 const grid = document.getElementById('grid'); 40 41 // Parse URL parameters for custom cell size 42 function parseCellSizeFromURL() { 43 const urlParams = new URLSearchParams(window.location.search); 44 const gridSizeParam = urlParams.get('grid-size'); 45 46 if (gridSizeParam) { 47 // Remove 'mm' suffix if present 48 const sizeStr = gridSizeParam.toLowerCase().replace('mm', '').trim(); 49 const size = parseFloat(sizeStr); 50 51 // Check if size is valid 52 if (isNaN(size)) { 53 showPopup('Invalid grid size. Using default 4mm.', 3000); 54 return 4; 55 } 56 57 // Check if size is within reasonable bounds 58 if (size < MIN_CELL_SIZE_MM || size > MAX_CELL_SIZE_MM) { 59 showPopup(`Grid size must be between ${MIN_CELL_SIZE_MM}mm and ${MAX_CELL_SIZE_MM}mm. Using default 4mm.`, 3500); 60 return 4; 61 } 62 63 showPopup(`Grid set to ${size}mm`); 64 return size; 65 } 66 67 return 4; // Default 68 } 69 70 // Initialize cell size from URL 71 CELL_SIZE_MM = parseCellSizeFromURL(); 72 73 // Calculate grid dimensions based on cell size 74 const gridDimensions = calculateGridDimensions(CELL_SIZE_MM); 75 GRID_COLS = gridDimensions.cols; 76 GRID_ROWS = gridDimensions.rows; 77 78 // Calculate grid percentages for screen layout 79 const gridPercentages = calculateGridPercentages(CELL_SIZE_MM, GRID_COLS, GRID_ROWS); 80 81 // Update CSS variables for both screen and print 82 document.documentElement.style.setProperty('--cell-size-mm', `${CELL_SIZE_MM}mm`); 83 document.documentElement.style.setProperty('--grid-cols', GRID_COLS); 84 document.documentElement.style.setProperty('--grid-rows', GRID_ROWS); 85 document.documentElement.style.setProperty('--grid-width-percent', `${gridPercentages.widthPercent}%`); 86 document.documentElement.style.setProperty('--grid-height-percent', `${gridPercentages.heightPercent}%`); 87 88 // Calculate cell size dynamically based on actual grid dimensions 89 function getCellSize() { 90 const gridRect = grid.getBoundingClientRect(); 91 return { 92 width: gridRect.width / GRID_COLS, 93 height: gridRect.height / GRID_ROWS, 94 totalWidth: gridRect.width, 95 totalHeight: gridRect.height 96 }; 97 } 98 99 // Calculate pixel-perfect position for a cell range 100 function getPixelPerfectBounds(cellX, cellY, cellWidth, cellHeight) { 101 // Get all grid cells and measure their actual positions 102 const gridCells = grid.querySelectorAll('.grid-cell'); 103 104 // Calculate the index of the top-left cell 105 const startCellIndex = cellY * GRID_COLS + cellX; 106 const startCell = gridCells[startCellIndex]; 107 108 if (!startCell) { 109 // Fallback if cell doesn't exist 110 const cellSize = getCellSize(); 111 return { 112 left: cellX * cellSize.width, 113 top: cellY * cellSize.height, 114 width: cellWidth * cellSize.width, 115 height: cellHeight * cellSize.height 116 }; 117 } 118 119 // Get the actual position of the start cell relative to the grid 120 const gridRect = grid.getBoundingClientRect(); 121 const startCellRect = startCell.getBoundingClientRect(); 122 123 const left = startCellRect.left - gridRect.left; 124 const top = startCellRect.top - gridRect.top; 125 126 // Calculate end position by finding the bottom-right cell 127 const endCellIndex = (cellY + cellHeight - 1) * GRID_COLS + (cellX + cellWidth - 1); 128 const endCell = gridCells[endCellIndex]; 129 130 if (!endCell) { 131 // Fallback if end cell doesn't exist 132 const cellSize = getCellSize(); 133 return { 134 left: left, 135 top: top, 136 width: cellWidth * cellSize.width, 137 height: cellHeight * cellSize.height 138 }; 139 } 140 141 const endCellRect = endCell.getBoundingClientRect(); 142 const right = endCellRect.right - gridRect.left; 143 const bottom = endCellRect.bottom - gridRect.top; 144 145 return { 146 left: left, 147 top: top, 148 width: right - left, 149 height: bottom - top 150 }; 151 } 152 153 // Create grid cells 154 for (let i = 0; i < GRID_COLS * GRID_ROWS; i++) { 155 const cell = document.createElement('div'); 156 cell.className = 'grid-cell'; 157 158 // Add right border to rightmost column 159 const col = i % GRID_COLS; 160 if (col === GRID_COLS - 1) { 161 cell.classList.add('right-edge'); 162 } 163 164 // Add bottom border to bottom row 165 const row = Math.floor(i / GRID_COLS); 166 if (row === GRID_ROWS - 1) { 167 cell.classList.add('bottom-edge'); 168 } 169 170 grid.appendChild(cell); 171 } 172 173 // Apply solid border style for grids 3.56mm or smaller 174 if (CELL_SIZE_MM <= 3.56) { 175 document.documentElement.classList.add('solid-grid'); 176 }