vibecoded page and function change in ino
This commit is contained in:
@@ -71,7 +71,7 @@ void drawTextNodes(bool reset_cursor = true)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void scrollAllScrollableTexts()
|
void scrollAllScrollableTexts(split_scroll_mode = false)
|
||||||
{
|
{
|
||||||
for (unsigned char i = 0; i < MAX_TEXT_NODES_COUNT; i++)
|
for (unsigned char i = 0; i < MAX_TEXT_NODES_COUNT; i++)
|
||||||
{
|
{
|
||||||
@@ -81,10 +81,8 @@ void scrollAllScrollableTexts()
|
|||||||
short y1 = text_nodes[i].pos_y;
|
short y1 = text_nodes[i].pos_y;
|
||||||
short x2 = text_nodes[i].pos_x + text_nodes[i].characterSize.width * text_nodes[i].character_count + text_nodes[i].character_count - 1;
|
short x2 = text_nodes[i].pos_x + text_nodes[i].characterSize.width * text_nodes[i].character_count + text_nodes[i].character_count - 1;
|
||||||
short y2 = text_nodes[i].pos_y + text_nodes[i].characterSize.height - 1;
|
short y2 = text_nodes[i].pos_y + text_nodes[i].characterSize.height - 1;
|
||||||
// If the text is scrolling on the upper part of the screen, scroll it to the left.
|
if (split_scroll_mode || text_nodes[i].pos_y < 7)
|
||||||
if (text_nodes[i].pos_y < 7)
|
|
||||||
{
|
{
|
||||||
// If the text is completely out of the screen, mark it as deleted.
|
|
||||||
if (x2 < 0)
|
if (x2 < 0)
|
||||||
{
|
{
|
||||||
text_nodes[i].is_deleted = true;
|
text_nodes[i].is_deleted = true;
|
||||||
@@ -93,10 +91,8 @@ void scrollAllScrollableTexts()
|
|||||||
shiftGivenRectangleLeft(x1, y1, x2, y2, text_nodes[i].scroll_slowness);
|
shiftGivenRectangleLeft(x1, y1, x2, y2, text_nodes[i].scroll_slowness);
|
||||||
text_nodes[i].pos_x -= text_nodes[i].scroll_slowness;
|
text_nodes[i].pos_x -= text_nodes[i].scroll_slowness;
|
||||||
}
|
}
|
||||||
// If the text is scrolling on the lower part of the screen, scroll it to the right.
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the text is completely out of the screen, mark it as deleted.
|
|
||||||
if (x1 > PANEL_MAX_X)
|
if (x1 > PANEL_MAX_X)
|
||||||
{
|
{
|
||||||
text_nodes[i].is_deleted = true;
|
text_nodes[i].is_deleted = true;
|
||||||
|
|||||||
+457
-86
@@ -5,31 +5,124 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
max-width: 800px;
|
max-width: 1200px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
|
background-color: #0d1117;
|
||||||
|
color: #c9d1d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: #333;
|
color: #c9d1d9;
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid-container {
|
.size-controls {
|
||||||
display: inline-grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(5, 25px);
|
justify-content: center;
|
||||||
gap: 5px;
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #161b22;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-input-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-input-group label {
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
color: #c9d1d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-input-group input[type="number"] {
|
||||||
|
width: 80px;
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 16px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #0d1117;
|
||||||
|
color: #c9d1d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-input-group input[type="number"]:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: #58a6ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-controls {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
padding: 15px;
|
||||||
|
background-color: #161b22;
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 10px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker-group label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #c9d1d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-picker-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background-color: #0d1117;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="color"] {
|
||||||
|
width: 50px;
|
||||||
|
height: 35px;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.color-value {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #c9d1d9;
|
||||||
|
min-width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas-container {
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background-color: #f5f5f5;
|
background-color: #161b22;
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox-cell {
|
#gridCanvas {
|
||||||
width: 25px;
|
cursor: crosshair;
|
||||||
height: 25px;
|
display: block;
|
||||||
cursor: pointer;
|
background-color: #000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.controls {
|
.controls {
|
||||||
@@ -41,129 +134,378 @@
|
|||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: #0969da;
|
background-color: transparent;
|
||||||
color: white;
|
color: #c9d1d9;
|
||||||
border: none;
|
border: 1px solid #c9d1d9;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
margin: 0 5px;
|
margin: 0 5px;
|
||||||
|
transition: all 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
button:hover {
|
button:hover {
|
||||||
background-color: #0860ca;
|
background-color: rgba(201, 209, 217, 0.1);
|
||||||
|
border-color: #ffffff;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.json-output {
|
.export-section {
|
||||||
margin-top: 20px;
|
margin: 20px 0;
|
||||||
padding: 15px;
|
padding: 20px;
|
||||||
background-color: #f6f8fa;
|
background-color: #161b22;
|
||||||
border: 1px solid #d0d7de;
|
border-radius: 8px;
|
||||||
|
border: 1px solid #30363d;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-section h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #c9d1d9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.export-options {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 15px;
|
||||||
|
margin: 15px 0;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
background-color: #0d1117;
|
||||||
|
border: 1px solid #30363d;
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
font-family: 'Courier New', monospace;
|
cursor: pointer;
|
||||||
font-size: 12px;
|
transition: all 0.2s;
|
||||||
white-space: pre-wrap;
|
user-select: none;
|
||||||
word-wrap: break-word;
|
|
||||||
max-height: 400px;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.hidden {
|
.radio-group:hover {
|
||||||
display: none;
|
border-color: #58a6ff;
|
||||||
|
background-color: rgba(88, 166, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button {
|
.radio-group input[type="radio"] {
|
||||||
background-color: #2da44e;
|
cursor: pointer;
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group label {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #c9d1d9;
|
||||||
|
margin: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.radio-group.selected {
|
||||||
|
border-color: #58a6ff;
|
||||||
|
background-color: rgba(88, 166, 255, 0.15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.format-description {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #8b949e;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copy-button:hover {
|
.generate-button {
|
||||||
background-color: #2c974b;
|
margin-top: 15px;
|
||||||
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copied-message {
|
.copied-message {
|
||||||
color: #2da44e;
|
color: #3fb950;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
display: inline-block;
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.3s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copied-message.show {
|
||||||
|
opacity: 1;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="grid-container" id="checkboxGrid"></div>
|
<h1>Grid Color Generator</h1>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="size-controls">
|
||||||
<button onclick="generateJSON()">Generate JSON</button>
|
<div class="size-input-group">
|
||||||
|
<label for="rowsInput">Rows:</label>
|
||||||
|
<input type="number" id="rowsInput" min="1" max="50" value="16">
|
||||||
|
</div>
|
||||||
|
<div class="size-input-group">
|
||||||
|
<label for="colsInput">Columns:</label>
|
||||||
|
<input type="number" id="colsInput" min="1" max="50" value="43">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="color-controls">
|
||||||
|
<div class="color-picker-group">
|
||||||
|
<label for="colorPicker">Draw Color:</label>
|
||||||
|
<div class="color-picker-wrapper">
|
||||||
|
<input type="color" id="colorPicker" value="#ffffff">
|
||||||
|
<span class="color-value" id="colorValue">#ffffff</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="canvas-container">
|
||||||
|
<canvas id="gridCanvas"></canvas>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
<button onclick="clearGrid()">Clear All</button>
|
<button onclick="clearGrid()">Clear All</button>
|
||||||
<button onclick="checkAll()">Check All</button>
|
<button onclick="fillAll()">Fill All</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="jsonOutputContainer" class="hidden">
|
<div class="export-section">
|
||||||
<h3>JSON Output:</h3>
|
<h3>Export Format</h3>
|
||||||
<div class="json-output" id="jsonOutput"></div>
|
<div class="export-options">
|
||||||
<button class="copy-button" onclick="copyToClipboard()">Copy to Clipboard</button>
|
<div class="radio-group selected" onclick="selectFormat('boolean')">
|
||||||
<span id="copiedMessage" class="copied-message hidden">✓ Copied!</span>
|
<input type="radio" id="formatBoolean" name="exportFormat" value="boolean" checked>
|
||||||
|
<label for="formatBoolean">Boolean (true/false)</label>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="radio-group" onclick="selectFormat('color')">
|
||||||
|
<input type="radio" id="formatColor" name="exportFormat" value="color">
|
||||||
|
<label for="formatColor">Color (hex codes)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="format-description">
|
||||||
|
<strong>Boolean:</strong> Exports filled cells as true, empty as false<br>
|
||||||
|
<strong>Color:</strong> Exports actual hex color values, empty cells as null
|
||||||
|
</div>
|
||||||
|
<div class="generate-button">
|
||||||
|
<button onclick="generateAndCopy()">Generate & Copy to Clipboard</button>
|
||||||
|
<span id="copiedMessage" class="copied-message">✓ Copied!</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Initialize the 7x5 grid (7 rows, 5 columns)
|
const canvas = document.getElementById('gridCanvas');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
let currentRows = 16;
|
||||||
|
let currentCols = 43;
|
||||||
|
let cellSize = 25;
|
||||||
|
let gridState = []; // Stores color values or null
|
||||||
|
let isDrawing = false;
|
||||||
|
let drawMode = null; // 'fill' or 'erase'
|
||||||
|
let currentColor = '#ffffff';
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
const colors = {
|
||||||
|
background: '#000000',
|
||||||
|
border: '#30363d',
|
||||||
|
borderHover: '#58a6ff'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Select format radio button
|
||||||
|
function selectFormat(format) {
|
||||||
|
// Update radio buttons
|
||||||
|
const booleanRadio = document.getElementById('formatBoolean');
|
||||||
|
const colorRadio = document.getElementById('formatColor');
|
||||||
|
|
||||||
|
if (format === 'boolean') {
|
||||||
|
booleanRadio.checked = true;
|
||||||
|
colorRadio.checked = false;
|
||||||
|
} else {
|
||||||
|
booleanRadio.checked = false;
|
||||||
|
colorRadio.checked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update visual selection
|
||||||
|
const radioGroups = document.querySelectorAll('.radio-group');
|
||||||
|
radioGroups.forEach(group => group.classList.remove('selected'));
|
||||||
|
event.currentTarget.classList.add('selected');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize grid state
|
||||||
function initializeGrid() {
|
function initializeGrid() {
|
||||||
const grid = document.getElementById('checkboxGrid');
|
gridState = [];
|
||||||
grid.innerHTML = '';
|
for (let i = 0; i < currentRows; i++) {
|
||||||
|
gridState[i] = [];
|
||||||
|
for (let j = 0; j < currentCols; j++) {
|
||||||
|
gridState[i][j] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (let i = 0; i < 7; i++) {
|
// Resize canvas
|
||||||
for (let j = 0; j < 5; j++) {
|
canvas.width = currentCols * cellSize;
|
||||||
const checkbox = document.createElement('input');
|
canvas.height = currentRows * cellSize;
|
||||||
checkbox.type = 'checkbox';
|
|
||||||
checkbox.className = 'checkbox-cell';
|
drawGrid();
|
||||||
checkbox.dataset.row = i;
|
}
|
||||||
checkbox.dataset.col = j;
|
|
||||||
grid.appendChild(checkbox);
|
// Draw the grid
|
||||||
|
function drawGrid() {
|
||||||
|
// Clear canvas with black background
|
||||||
|
ctx.fillStyle = colors.background;
|
||||||
|
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
|
||||||
|
// Draw cells
|
||||||
|
for (let i = 0; i < currentRows; i++) {
|
||||||
|
for (let j = 0; j < currentCols; j++) {
|
||||||
|
drawCell(i, j, gridState[i][j]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate JSON from checkbox states
|
// Draw individual cell
|
||||||
function generateJSON() {
|
function drawCell(row, col, colorValue) {
|
||||||
const checkboxes = document.querySelectorAll('.checkbox-cell');
|
const x = col * cellSize;
|
||||||
const grid = [];
|
const y = row * cellSize;
|
||||||
|
|
||||||
// Create 2D array (7 rows x 5 columns)
|
// Draw cell background (black)
|
||||||
for (let i = 0; i < 7; i++) {
|
ctx.fillStyle = colors.background;
|
||||||
grid[i] = [];
|
ctx.fillRect(x, y, cellSize, cellSize);
|
||||||
for (let j = 0; j < 5; j++) {
|
|
||||||
const checkbox = document.querySelector(`[data-row="${i}"][data-col="${j}"]`);
|
// Draw cell border
|
||||||
grid[i][j] = checkbox.checked;
|
ctx.strokeStyle = colors.border;
|
||||||
|
ctx.lineWidth = 1;
|
||||||
|
ctx.strokeRect(x + 0.5, y + 0.5, cellSize - 1, cellSize - 1);
|
||||||
|
|
||||||
|
// Draw filled state with color
|
||||||
|
if (colorValue !== null) {
|
||||||
|
ctx.fillStyle = colorValue;
|
||||||
|
const padding = 3;
|
||||||
|
ctx.fillRect(
|
||||||
|
x + padding,
|
||||||
|
y + padding,
|
||||||
|
cellSize - padding * 2,
|
||||||
|
cellSize - padding * 2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display JSON
|
// Get cell coordinates from mouse position
|
||||||
const jsonOutput = document.getElementById('jsonOutput');
|
function getCellFromMouse(e) {
|
||||||
const jsonOutputContainer = document.getElementById('jsonOutputContainer');
|
const rect = canvas.getBoundingClientRect();
|
||||||
jsonOutput.textContent = JSON.stringify(grid, null, 2);
|
const mouseX = e.clientX - rect.left;
|
||||||
jsonOutputContainer.classList.remove('hidden');
|
const mouseY = e.clientY - rect.top;
|
||||||
|
|
||||||
// Hide copied message
|
const col = Math.floor(mouseX / cellSize);
|
||||||
document.getElementById('copiedMessage').classList.add('hidden');
|
const row = Math.floor(mouseY / cellSize);
|
||||||
|
|
||||||
|
if (row >= 0 && row < currentRows && col >= 0 && col < currentCols) {
|
||||||
|
return { row, col };
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear all checkboxes
|
// Mouse down event
|
||||||
function clearGrid() {
|
canvas.addEventListener('mousedown', function(e) {
|
||||||
const checkboxes = document.querySelectorAll('.checkbox-cell');
|
e.preventDefault();
|
||||||
checkboxes.forEach(cb => cb.checked = false);
|
isDrawing = true;
|
||||||
|
|
||||||
|
const cell = getCellFromMouse(e);
|
||||||
|
if (cell) {
|
||||||
|
if (e.button === 0) { // Left click
|
||||||
|
drawMode = 'fill';
|
||||||
|
gridState[cell.row][cell.col] = currentColor;
|
||||||
|
} else if (e.button === 2) { // Right click
|
||||||
|
drawMode = 'erase';
|
||||||
|
gridState[cell.row][cell.col] = null;
|
||||||
|
}
|
||||||
|
drawCell(cell.row, cell.col, gridState[cell.row][cell.col]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mouse move event
|
||||||
|
canvas.addEventListener('mousemove', function(e) {
|
||||||
|
if (!isDrawing) return;
|
||||||
|
|
||||||
|
const cell = getCellFromMouse(e);
|
||||||
|
if (cell) {
|
||||||
|
if (drawMode === 'fill') {
|
||||||
|
gridState[cell.row][cell.col] = currentColor;
|
||||||
|
} else if (drawMode === 'erase') {
|
||||||
|
gridState[cell.row][cell.col] = null;
|
||||||
|
}
|
||||||
|
drawCell(cell.row, cell.col, gridState[cell.row][cell.col]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mouse up event
|
||||||
|
canvas.addEventListener('mouseup', function(e) {
|
||||||
|
isDrawing = false;
|
||||||
|
drawMode = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Mouse leave event
|
||||||
|
canvas.addEventListener('mouseleave', function(e) {
|
||||||
|
isDrawing = false;
|
||||||
|
drawMode = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prevent context menu
|
||||||
|
canvas.addEventListener('contextmenu', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Color picker change
|
||||||
|
document.getElementById('colorPicker').addEventListener('input', function(e) {
|
||||||
|
currentColor = e.target.value;
|
||||||
|
document.getElementById('colorValue').textContent = currentColor;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update grid size
|
||||||
|
function updateGridSize() {
|
||||||
|
const rowsInput = document.getElementById('rowsInput');
|
||||||
|
const colsInput = document.getElementById('colsInput');
|
||||||
|
|
||||||
|
currentRows = parseInt(rowsInput.value) || 1;
|
||||||
|
currentCols = parseInt(colsInput.value) || 1;
|
||||||
|
|
||||||
|
if (currentRows < 1) currentRows = 1;
|
||||||
|
if (currentCols < 1) currentCols = 1;
|
||||||
|
|
||||||
|
initializeGrid();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check all checkboxes
|
// Generate JSON and copy to clipboard
|
||||||
function checkAll() {
|
function generateAndCopy() {
|
||||||
const checkboxes = document.querySelectorAll('.checkbox-cell');
|
const formatRadios = document.getElementsByName('exportFormat');
|
||||||
checkboxes.forEach(cb => cb.checked = true);
|
let selectedFormat = 'boolean';
|
||||||
|
|
||||||
|
for (const radio of formatRadios) {
|
||||||
|
if (radio.checked) {
|
||||||
|
selectedFormat = radio.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy JSON to clipboard
|
let outputData = [];
|
||||||
function copyToClipboard() {
|
|
||||||
const jsonText = document.getElementById('jsonOutput').textContent;
|
if (selectedFormat === 'boolean') {
|
||||||
|
// Convert to boolean: filled = true, empty = false
|
||||||
|
for (let i = 0; i < currentRows; i++) {
|
||||||
|
outputData[i] = [];
|
||||||
|
for (let j = 0; j < currentCols; j++) {
|
||||||
|
outputData[i][j] = gridState[i][j] !== null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Keep color values: hex codes or null
|
||||||
|
outputData = JSON.parse(JSON.stringify(gridState)); // Deep copy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate JSON string
|
||||||
|
const jsonText = JSON.stringify(outputData, null, 2);
|
||||||
|
|
||||||
|
// Copy to clipboard
|
||||||
navigator.clipboard.writeText(jsonText).then(() => {
|
navigator.clipboard.writeText(jsonText).then(() => {
|
||||||
const message = document.getElementById('copiedMessage');
|
const message = document.getElementById('copiedMessage');
|
||||||
message.classList.remove('hidden');
|
message.classList.add('show');
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
message.classList.add('hidden');
|
message.classList.remove('show');
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
alert('Failed to copy to clipboard');
|
alert('Failed to copy to clipboard');
|
||||||
@@ -171,8 +513,37 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear all cells
|
||||||
|
function clearGrid() {
|
||||||
|
for (let i = 0; i < currentRows; i++) {
|
||||||
|
for (let j = 0; j < currentCols; j++) {
|
||||||
|
gridState[i][j] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fill all cells
|
||||||
|
function fillAll() {
|
||||||
|
for (let i = 0; i < currentRows; i++) {
|
||||||
|
for (let j = 0; j < currentCols; j++) {
|
||||||
|
gridState[i][j] = currentColor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawGrid();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add event listeners to inputs
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const rowsInput = document.getElementById('rowsInput');
|
||||||
|
const colsInput = document.getElementById('colsInput');
|
||||||
|
|
||||||
|
rowsInput.addEventListener('input', updateGridSize);
|
||||||
|
colsInput.addEventListener('input', updateGridSize);
|
||||||
|
|
||||||
// Initialize grid on page load
|
// Initialize grid on page load
|
||||||
initializeGrid();
|
initializeGrid();
|
||||||
</script>
|
});
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
Reference in New Issue
Block a user