From 4bde535cdde3c66b4525a3ea03a08d94fc9c365c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A0nh=20Nh=C3=A2n?= <60387689+NhanAZ@users.noreply.github.com> Date: Mon, 15 Jul 2024 22:16:10 +0700 Subject: [PATCH] Update interface --- index.html | 535 ++++++++++------------------------------------------- script.js | 154 +++++++++++++++ styles.css | 201 ++++++++++++++++++++ 3 files changed, 452 insertions(+), 438 deletions(-) create mode 100644 script.js create mode 100644 styles.css diff --git a/index.html b/index.html index 7c878da..8816256 100644 --- a/index.html +++ b/index.html @@ -2,447 +2,106 @@ - - - Glyph Tools - - - + + + Glyph Tools + + + -
- - - -
-
-
-
-

Glyph Generator

-
-
-
- - -
- -
-
-
-
-
-
-
-

Hex <-> Emoji Converter

-
-
-

Convert between hexadecimal values and emojis/symbols.

-
- -
-
- 0x - - -
-
- - -
-
-
-
-
-
-
-
-
-
-
-

Generated Glyph

-
-
-
-
-
-
-
-
- - - - +
+
+

Glyph Tools

+

Generate glyphs and convert between hex and emoji

+
+ +
+
+
+
+

Glyph Generator

+
+
+
+ +
+ + +
+
+ + + +
+
+
+ +
+
+
+

Hex ↔ Emoji Converter

+
+
+

Convert between hexadecimal values and emojis/symbols.

+
+ +
+
+ 0x + + +
+
+ + +
+ + +
+
+
+
+ +
+
+
+
+

Generated Glyph

+
+
+
+
+
+
+
+ + +
+ + + \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..bbdb410 --- /dev/null +++ b/script.js @@ -0,0 +1,154 @@ +const GRID = 16; + +function Glyph(glyph = "E0") { + const filename = `glyph_${glyph}`; + const startChar = parseInt(filename.split("_").pop() + "00", 16); + let markdownContent = ``; + + for (let i = 0; i < GRID * GRID; i++) { + const row = Math.floor(i / GRID) + 1; + const col = (i % GRID) + 1; + const charCode = startChar + i; + const char = String.fromCodePoint(charCode); + const hexCode = charCode.toString(16).toUpperCase().padStart(4, '0'); + markdownContent += `
+ Position: (${col};${row}) - Hex: 0x${hexCode}${char} + Copied +
`; + } + + document.getElementById('glyph-output').innerHTML = markdownContent; + + document.querySelectorAll('#glyph-output div').forEach(div => { + div.addEventListener('click', function () { + const hexCode = this.getAttribute('data-hex'); + const char = this.getAttribute('data-char'); + navigator.clipboard.writeText(char).then(() => { + showCopyNotification(this); + }); + }); + }); +} + +function showCopyNotification(element) { + const notification = element.querySelector('.copy-notification'); + notification.style.opacity = '1'; + setTimeout(() => { + notification.style.opacity = '0'; + }, 1000); +} + +function initializeGlyph() { + const glyphOutput = document.getElementById('glyph-output'); + if (glyphOutput.innerHTML.trim() === '') { + Glyph("E0"); + } +} + +window.onload = () => { + initializeGlyph(); +}; + +document.getElementById('glyph-input').addEventListener('input', function () { + const glyphInput = this.value.trim(); + const glyphSuccessMsg = document.getElementById('glyphSuccessMsg'); + const glyphErrorMsg = document.getElementById('glyphErrorMsg'); + + if (/^[A-Fa-f0-9]{1,2}$/.test(glyphInput)) { + Glyph(glyphInput || "E0"); + glyphSuccessMsg.textContent = 'Glyph generated successfully!'; + glyphSuccessMsg.classList.remove('d-none'); + glyphErrorMsg.classList.add('d-none'); + } else { + glyphErrorMsg.textContent = 'Please enter a valid hex value (1-2 hex digits).'; + glyphErrorMsg.classList.remove('d-none'); + glyphSuccessMsg.classList.add('d-none'); + } +}); + +let isHexToEmoji = true; + +document.getElementById('conversionModeButton').addEventListener('click', function () { + isHexToEmoji = !isHexToEmoji; + this.textContent = isHexToEmoji ? "Hex to Emoji" : "Emoji to Hex"; + document.getElementById('inputPrefix').style.display = isHexToEmoji ? "inline-block" : "none"; + document.getElementById('converterInput').placeholder = isHexToEmoji ? "Enter hex value" : "Enter emoji/symbol"; + document.getElementById('converterOutput').value = ''; + updateCopyButtonState(); +}); + +function convert() { + const input = document.getElementById('converterInput').value.trim(); + const errorMsg = document.getElementById('errorMsg'); + const successMsg = document.getElementById('successMsg'); + const output = document.getElementById('converterOutput'); + errorMsg.classList.add('d-none'); + successMsg.classList.add('d-none'); + output.value = ''; + + if (isHexToEmoji) { + convertHexToEmoji(input); + } else { + convertEmojiToHex(input); + } + updateCopyButtonState(); +} + +function convertHexToEmoji(input) { + if (/^[0-9A-Fa-f]{1,6}$/.test(input)) { + try { + const codePoint = parseInt(input, 16); + document.getElementById('converterOutput').value = String.fromCodePoint(codePoint); + document.getElementById('successMsg').textContent = 'Converted successfully!'; + document.getElementById('successMsg').classList.remove('d-none'); + } catch (error) { + document.getElementById('errorMsg').textContent = 'Invalid Unicode code point.'; + document.getElementById('errorMsg').classList.remove('d-none'); + } + } else { + document.getElementById('errorMsg').textContent = 'Please enter a valid hex value (1-6 hex digits).'; + document.getElementById('errorMsg').classList.remove('d-none'); + } +} + +function convertEmojiToHex(input) { + if (input.length === 1) { + const hexValue = input.codePointAt(0).toString(16).toUpperCase().padStart(4, '0'); + document.getElementById('converterOutput').value = `0x${hexValue}`; + document.getElementById('successMsg').textContent = 'Converted successfully!'; + document.getElementById('successMsg').classList.remove('d-none'); + } else { + document.getElementById('errorMsg').textContent = 'Please enter a single emoji or symbol.'; + document.getElementById('errorMsg').classList.remove('d-none'); + } +} + +function copyOutput() { + const output = document.getElementById('converterOutput'); + const copyButton = document.getElementById('copyButton'); + + if (output.value.trim() === '') { + return; + } + + navigator.clipboard.writeText(output.value).then(() => { + const originalText = copyButton.innerHTML; + copyButton.innerHTML = 'Copied'; + copyButton.disabled = true; + + setTimeout(() => { + copyButton.innerHTML = originalText; + copyButton.disabled = false; + }, 2000); + }); +} + +function updateCopyButtonState() { + const output = document.getElementById('converterOutput'); + const copyButton = document.getElementById('copyButton'); + copyButton.disabled = output.value.trim() === ''; +} + +document.getElementById('convertButton').addEventListener('click', convert); +document.getElementById('copyButton').addEventListener('click', copyOutput); +document.getElementById('converterInput').addEventListener('input', convert); \ No newline at end of file diff --git a/styles.css b/styles.css new file mode 100644 index 0000000..1361bbf --- /dev/null +++ b/styles.css @@ -0,0 +1,201 @@ +body { + background-color: #f8f9fa; +} + +.container { + max-width: 1200px; +} + +.card { + border: none; + border-radius: 15px; + transition: all 0.3s ease; +} + +.card:hover { + transform: translateY(-5px); + box-shadow: 0 10px 20px rgba(0, 0, 0, 0.1); +} + +.card-header { + border-radius: 15px 15px 0 0 !important; + border-bottom: none; +} + +.btn-primary { + background-color: #4a89dc; + border-color: #4a89dc; +} + +.btn-primary:hover { + background-color: #3b78cc; + border-color: #3b78cc; +} + +.btn-outline-primary { + color: #4a89dc; + border-color: #4a89dc; +} + +.btn-outline-primary:hover { + background-color: #4a89dc; + color: white; +} + +#glyph-output { + display: grid; + grid-template-columns: repeat(16, minmax(30px, 1fr)); + grid-template-rows: repeat(16, 1fr); + gap: 2px; + font-size: 1.2em; + overflow-x: auto; + padding-bottom: 10px; +} + +#glyph-output div { + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + background-color: #ffffff; + border-radius: 8px; + transition: all 0.2s ease; + cursor: pointer; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); + position: relative; +} + +#glyph-output div:hover { + background-color: #f1f3f5; + transform: scale(1.1); + z-index: 1; + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); +} + +.tooltip { + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + background-color: #333; + color: #fff; + padding: 5px 8px; + border-radius: 4px; + font-size: 0.75em; + opacity: 0; + transition: opacity 0.2s, transform 0.2s; + pointer-events: none; + white-space: nowrap; +} + +#glyph-output div:hover .tooltip { + opacity: 1; + transform: translateX(-50%) translateY(-5px); +} + +.copy-notification { + position: absolute; + background-color: rgba(0, 0, 0, 0.7); + color: white; + padding: 5px 10px; + border-radius: 4px; + font-size: 0.8em; + opacity: 0; + transition: opacity 0.3s; +} + +.success-msg { + animation: fadeInOut 2s ease-in-out; +} + +@keyframes fadeInOut { + + 0%, + 100% { + opacity: 0; + } + + 10%, + 90% { + opacity: 1; + } +} + +#conversionModeButton { + transition: all 0.3s ease; +} + +@media (max-width: 767.98px) { + #glyph-output { + font-size: 0.8em; + } + + #convertButton { + width: 100%; + margin-top: 10px; + } +} + +@media (min-width: 768px) { + #glyph-output { + overflow-x: visible; + } +} + +@media (max-width: 767.98px) { + #glyph-output { + font-size: 0.8em; + } + + .input-group { + flex-wrap: wrap; + } + + #convertButton { + width: 100%; + margin-top: 10px; + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; + } + + #converterInput { + border-bottom-right-radius: 0.25rem !important; + } +} + +@media (min-width: 768px) { + #glyph-output { + overflow-x: visible; + } +} + +@media (max-width: 767.98px) { + #generate-glyph { + width: 100%; + margin-top: 10px; + border-top-left-radius: 0.25rem !important; + border-top-right-radius: 0.25rem !important; + } + + #glyph-input { + border-bottom-right-radius: 0.25rem !important; + } +} + +@media (min-width: 768px) { + .converter-input-group { + display: flex; + } + + .converter-input-group .form-control { + flex: 1; + } + + .converter-input-group .btn { + width: 120px; /* Điều chỉnh chiều rộng này nếu cần */ + } + + #inputPrefix { + width: auto; + } +} \ No newline at end of file