From 7f6dcac1540e7628ec7aa5102cab88aa59d4d723 Mon Sep 17 00:00:00 2001 From: Leon Mika Date: Mon, 26 Jan 2026 11:02:33 +1100 Subject: [PATCH] Added hex colour --- .gitignore | 2 + site/hex-color/index.html | 37 ++++++++++++ site/hex-color/script.js | 116 ++++++++++++++++++++++++++++++++++++++ site/hex-color/style.css | 20 +++++++ site/index.html | 1 + 5 files changed, 176 insertions(+) create mode 100644 site/hex-color/index.html create mode 100644 site/hex-color/script.js create mode 100644 site/hex-color/style.css diff --git a/.gitignore b/.gitignore index 2f7896d..188ebd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ target/ +.vscode/ +.idea/ \ No newline at end of file diff --git a/site/hex-color/index.html b/site/hex-color/index.html new file mode 100644 index 0000000..921b912 --- /dev/null +++ b/site/hex-color/index.html @@ -0,0 +1,37 @@ + + + + + + Hex Color Converter - Tools + + + + + +
+
+

Hex Color Converter

+

Convert hex color values to normalized RGB components

+
+
+
+ + + + + + + + + + + + + + + + +
+ + diff --git a/site/hex-color/script.js b/site/hex-color/script.js new file mode 100644 index 0000000..07852ed --- /dev/null +++ b/site/hex-color/script.js @@ -0,0 +1,116 @@ +async function addHexFromClipboard() { + try { + const text = await navigator.clipboard.readText(); + const hex = text.trim(); + + // Parse hex color + const color = parseHexColor(hex); + if (!color) { + alert('Invalid hex color in clipboard. Expected format: #RRGGBB or #RRGGBBAA'); + return; + } + + // Add row to table + addColorRow(hex, color); + + // Show table if hidden + document.getElementById('colorTable').classList.remove('hidden'); + } catch (err) { + alert('Failed to read from clipboard: ' + err.message); + } +} + +document.getElementById('addHexBtn').addEventListener('click', addHexFromClipboard); + +document.getElementById('showHiddenBtn').addEventListener('click', () => { + const rows = document.querySelectorAll('#colorTableBody tr.hidden'); + rows.forEach(row => row.classList.remove('hidden')); + updateShowHiddenButton(); +}); + +document.addEventListener('keydown', (e) => { + if (e.key === 'p' || e.key === 'P') { + addHexFromClipboard(); + } +}); + +function parseHexColor(hex) { + // Remove leading hash if present + const cleanHex = hex.startsWith('#') ? hex.slice(1) : hex; + + // Validate hex string (6 or 8 characters) + if (!/^[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/.test(cleanHex)) { + return null; + } + + // Parse components + const r = parseInt(cleanHex.slice(0, 2), 16) / 255; + const g = parseInt(cleanHex.slice(2, 4), 16) / 255; + const b = parseInt(cleanHex.slice(4, 6), 16) / 255; + const a = cleanHex.length === 8 ? parseInt(cleanHex.slice(6, 8), 16) / 255 : 1.0; + + return { r, g, b, a, hex: '#' + cleanHex }; +} + +function addColorRow(originalHex, color) { + const tbody = document.getElementById('colorTableBody'); + const row = tbody.insertRow(); + + // Preview cell + const previewCell = row.insertCell(); + const preview = document.createElement('div'); + preview.style.width = '40px'; + preview.style.height = '40px'; + preview.style.backgroundColor = `rgba(${color.r * 255}, ${color.g * 255}, ${color.b * 255}, ${color.a})`; + preview.style.border = '1px solid #ccc'; + preview.style.borderRadius = '4px'; + previewCell.appendChild(preview); + + // Hex cell + const hexCell = row.insertCell(); + hexCell.textContent = color.hex; + + // Normalized components cell + const normalizedCell = row.insertCell(); + const normalizedText = `${color.r.toFixed(1)}, ${color.g.toFixed(1)}, ${color.b.toFixed(1)}, ${color.a.toFixed(1)}`; + normalizedCell.textContent = normalizedText; + + // Action cell with copy and hide buttons + const actionCell = row.insertCell(); + + const copyBtn = document.createElement('button'); + copyBtn.textContent = 'Copy'; + copyBtn.className = 'secondary'; + copyBtn.addEventListener('click', () => { + navigator.clipboard.writeText(normalizedText).then(() => { + const originalText = copyBtn.textContent; + copyBtn.textContent = 'Copied!'; + setTimeout(() => { + copyBtn.textContent = originalText; + }, 1500); + }).catch(err => { + alert('Failed to copy: ' + err.message); + }); + }); + actionCell.appendChild(copyBtn); + + const hideBtn = document.createElement('button'); + hideBtn.textContent = 'Hide'; + hideBtn.className = 'secondary'; + hideBtn.addEventListener('click', () => { + row.classList.add('hidden'); + updateShowHiddenButton(); + }); + actionCell.appendChild(hideBtn); +} + +function updateShowHiddenButton() { + const hiddenRows = document.querySelectorAll('#colorTableBody tr.hidden'); + const showHiddenBtn = document.getElementById('showHiddenBtn'); + + if (hiddenRows.length > 0) { + showHiddenBtn.classList.remove('hidden'); + } else { + showHiddenBtn.classList.add('hidden'); + } +} diff --git a/site/hex-color/style.css b/site/hex-color/style.css new file mode 100644 index 0000000..a5b0997 --- /dev/null +++ b/site/hex-color/style.css @@ -0,0 +1,20 @@ +.hidden { + display: none; +} + +#colorTable { + margin-top: 2rem; +} + +#colorTable button { + margin: 0; + margin-right: 0.5rem; +} + +#colorTable td { + vertical-align: middle; +} + +#showHiddenBtn { + margin-top: 1rem; +} diff --git a/site/index.html b/site/index.html index 55afdd4..23d989a 100644 --- a/site/index.html +++ b/site/index.html @@ -30,6 +30,7 @@
  • Finska Scorecard
  • Mental Arithmatic Game
  • Neon Snake: vibe-coded by Google Gemini
  • +
  • Hex Color Converter