From 9e91e96783146b97c8a096cf368ee6283c1a4372 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 7 Nov 2025 19:33:00 -0800 Subject: [PATCH] [Tools] Add QR code generator --- resources/tools/qr-generator.css | 19 ++++++ resources/tools/qr-generator.js | 102 +++++++++++++++++++++++++++++++ src/Pages/ToolPage.php | 1 + tests/data/tools-index.html | 2 +- tests/data/tools-missing.html | 2 +- 5 files changed, 124 insertions(+), 2 deletions(-) create mode 100644 resources/tools/qr-generator.css create mode 100644 resources/tools/qr-generator.js diff --git a/resources/tools/qr-generator.css b/resources/tools/qr-generator.css new file mode 100644 index 0000000..feb2c6a --- /dev/null +++ b/resources/tools/qr-generator.css @@ -0,0 +1,19 @@ +#qr-generator-controls { + width: fit-content; +} + +#qr-generator--btn { + display: block; + margin: auto; + margin-top: 20px; +} + +#qr-generator--target { + margin-left: 20px; + width: 500px; + padding: 5px; +} + +#qr-generator-output { + margin-top: 20px; +} diff --git a/resources/tools/qr-generator.js b/resources/tools/qr-generator.js new file mode 100644 index 0000000..2dbc573 --- /dev/null +++ b/resources/tools/qr-generator.js @@ -0,0 +1,102 @@ +const makeQRImg = ( data ) => { + const img = document.createElement( 'img' ); + // Figure out size + let size = '250x250'; + if ( data.length > 400 ) { + size = '500x500'; + } else if ( data.length > 200 ) { + size = '300x300'; + } + img.setAttribute( + 'src', + 'https://api.qrserver.com/v1/create-qr-code/?size=' + size + '&data=' + encodeURIComponent( data ) + ); + return img; +} + +/** + * Return the overall
that holds the elements + */ +const makeControls = () => { + const wrapper = document.createElement( 'div' ); + wrapper.setAttribute( 'id', 'qr-generator-controls' ); + + const targetLabel = document.createElement( 'label' ); + targetLabel.setAttribute( 'for', 'qr-generator--target' ); + targetLabel.innerText = 'Target URL:'; + wrapper.append( targetLabel ); + + const targetElem = document.createElement( 'input' ); + targetElem.setAttribute( 'type', 'text' ); + targetElem.setAttribute( 'id', 'qr-generator--target' ); + + wrapper.append( targetElem ); + + const generateBtn = document.createElement( 'button' ); + generateBtn.setAttribute( 'id', 'qr-generator--btn' ); + generateBtn.innerText = 'Generate'; + + const emitGeneration = () => { + const newEvent = new CustomEvent( + 'do-generate', + { + detail: { + url: targetElem.value + } + } + ); + wrapper.dispatchEvent( newEvent ); + }; + + generateBtn.addEventListener( 'click', emitGeneration ); + + // Listen to the enter key + targetElem.addEventListener( + 'keypress' , + ( e ) => { + if ( e.key === 'Enter' ) { + emitGeneration(); + } + } + ); + + wrapper.append( generateBtn ); + + return wrapper; +}; + +const onLoad = () => { + // Popup to avoid accidental reloads + window.onbeforeunload = () => false; + + const target = document.getElementById( 'tool-target' ); + + const controls = makeControls(); + target.append( controls ); + + const outputElem = document.createElement( 'div' ); + outputElem.setAttribute( 'id', 'qr-generator-output' ); + target.append( outputElem ); + + const downloadNote = document.createElement( 'p' ); + downloadNote.innerText = 'To download, right click on the image and save the image.'; + downloadNote.innerText += 'You can submit a new URL to generate a new QR code.' + + const downloadNoteHolder = document.createElement( 'div' ); + target.append( downloadNoteHolder ); + + controls.addEventListener( + 'do-generate', + ( e ) => { + // console.log( e ); + // So that a new URL clears the existing image while waiting + outputElem.replaceChildren(); + outputElem.replaceChildren( makeQRImg( e.detail.url ) ) + if ( downloadNoteHolder.children.length === 0 ) { + downloadNoteHolder.append( downloadNote ); + } + } + ); +}; + +document.addEventListener( 'DOMContentLoaded', onLoad ); diff --git a/src/Pages/ToolPage.php b/src/Pages/ToolPage.php index 19f2e3f..61a2c05 100644 --- a/src/Pages/ToolPage.php +++ b/src/Pages/ToolPage.php @@ -12,6 +12,7 @@ class ToolPage extends BasePage { private const TOOL_MAPPING = [ 'countdown' => true, 'dvorak' => true, + 'qr-generator' => true, ]; public function __construct( array $params ) { diff --git a/tests/data/tools-index.html b/tests/data/tools-index.html index 10a841a..2cc3bf1 100644 --- a/tests/data/tools-index.html +++ b/tests/data/tools-index.html @@ -1,3 +1,3 @@ -Tools

Known tools

These are just some JavaScript utilities for Daniel, though anyone who wants to +Tools

Known tools

These are just some JavaScript utilities for Daniel, though anyone who wants to is obviously free to use them.

\ No newline at end of file diff --git a/tests/data/tools-missing.html b/tests/data/tools-missing.html index 0e63ce3..8470a54 100644 --- a/tests/data/tools-missing.html +++ b/tests/data/tools-missing.html @@ -1,3 +1,3 @@ -Tools

Error

The requested tool `missing` is not recognized

Known tools

These are just some JavaScript utilities for Daniel, though anyone who wants to +Tools

Error

The requested tool `missing` is not recognized

Known tools

These are just some JavaScript utilities for Daniel, though anyone who wants to is obviously free to use them.

\ No newline at end of file