mirror of
https://gitplac.si/aljaxus/upn-qr.git
synced 2025-12-16 19:50:57 +00:00
implement copuing QRCode URL in form creator
This commit is contained in:
@@ -75,7 +75,8 @@ pre {
|
|||||||
pre {
|
pre {
|
||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
input {
|
input,
|
||||||
|
button {
|
||||||
background-color: var(--c-dark);
|
background-color: var(--c-dark);
|
||||||
border-color: var(--c-dark);
|
border-color: var(--c-dark);
|
||||||
color: var(--c-primary);
|
color: var(--c-primary);
|
||||||
@@ -84,12 +85,17 @@ input {
|
|||||||
font-family: monospace;
|
font-family: monospace;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
input:read-only {
|
button {
|
||||||
|
background-color: var(--c-darkish)
|
||||||
|
}
|
||||||
|
input:read-only,
|
||||||
|
button:disabled {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
background-color: var(--c-darkish);
|
background-color: var(--c-darkish);
|
||||||
}
|
}
|
||||||
input:focus:not(:readonly),
|
input:focus:not(:read-only),
|
||||||
input:focus-visible:not(:readonly) {
|
input:focus-visible:not(:read-only),
|
||||||
|
button:focus:not(:disabled) {
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
outline: solid 1px var(--c-accent);
|
outline: solid 1px var(--c-accent);
|
||||||
}
|
}
|
||||||
@@ -100,11 +106,12 @@ input[type=number] {
|
|||||||
|
|
||||||
input[type=submit],
|
input[type=submit],
|
||||||
button {
|
button {
|
||||||
|
--box-shadow-color: var(--c-accent);
|
||||||
border: none;
|
border: none;
|
||||||
outline: solid 1px var(--c-accent);
|
outline: solid 1px var(--c-accent);
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
box-shadow: 4px 4px 1px 1px var(--c-accent);
|
box-shadow: 4px 4px 1px 1px var(--box-shadow-color);
|
||||||
color: var(--c-accent);
|
color: var(--c-accent);
|
||||||
margin: 0 4px 4px 0;
|
margin: 0 4px 4px 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -119,7 +126,7 @@ button:focus-visible,
|
|||||||
button:hover {
|
button:hover {
|
||||||
transition: all ease-in-out .2s;
|
transition: all ease-in-out .2s;
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: 2px 2px 1px 1px var(--c-accent);
|
box-shadow: 2px 2px 1px 1px var(--box-shadow-color);
|
||||||
margin: 2px;
|
margin: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,4 +136,14 @@ button:active {
|
|||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
margin: 4px 0 0 4px;
|
margin: 4px 0 0 4px;
|
||||||
|
}
|
||||||
|
button.success {
|
||||||
|
color: #6cc070;
|
||||||
|
outline-color: #6cc070;
|
||||||
|
--box-shadow-color: #6cc070;
|
||||||
|
}
|
||||||
|
button.error {
|
||||||
|
color: #ff6633;
|
||||||
|
outline-color: #ff6633;
|
||||||
|
--box-shadow-color: #ff6633;
|
||||||
}
|
}
|
||||||
@@ -34,6 +34,12 @@ div {
|
|||||||
row-gap: .5rem;
|
row-gap: .5rem;
|
||||||
column-gap: 1rem;;
|
column-gap: 1rem;;
|
||||||
}
|
}
|
||||||
|
.code {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
grid-template-columns: auto;
|
||||||
|
row-gap: 1rem;
|
||||||
|
}
|
||||||
.code {
|
.code {
|
||||||
background-size: contain;
|
background-size: contain;
|
||||||
background-position: top center;
|
background-position: top center;
|
||||||
@@ -67,7 +73,7 @@ div {
|
|||||||
{ n: "issuer-address", d: "Issuer address", p: "Za deveto smreko 15 k", t: "text" },
|
{ n: "issuer-address", d: "Issuer address", p: "Za deveto smreko 15 k", t: "text" },
|
||||||
{ n: "issuer-city", d: "Issuer city", p: "1000 Ljubljana", t: "text" },
|
{ n: "issuer-city", d: "Issuer city", p: "1000 Ljubljana", t: "text" },
|
||||||
{ n: "iban", d: "IBAN", p: "SI56047500000280672", t: "text" },
|
{ n: "iban", d: "IBAN", p: "SI56047500000280672", t: "text" },
|
||||||
{ n: "amount", d: "Amount", p: "00000001050", t: "number" },
|
{ n: "amount", d: "Amount", p: "35090 (350.90€)", t: "number" },
|
||||||
{ n: "code", d: "Code", p: "OTHR", t: "text" },
|
{ n: "code", d: "Code", p: "OTHR", t: "text" },
|
||||||
{ n: "purpose", d: "Purpose", p: "moutain bike first half", t: "text" },
|
{ n: "purpose", d: "Purpose", p: "moutain bike first half", t: "text" },
|
||||||
{ n: "reference", d: "Reference", p: "SI121234567890120", t: "text" }
|
{ n: "reference", d: "Reference", p: "SI121234567890120", t: "text" }
|
||||||
@@ -91,11 +97,8 @@ div {
|
|||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
<script>
|
<script>
|
||||||
const inputs = document.getElementsByTagName("input")
|
|
||||||
const qrcode = document.getElementById("qrcode")
|
const qrcode = document.getElementById("qrcode")
|
||||||
function val (name) {
|
function val (name) { return document.getElementsByName(name)?.[0]?.value || "" }
|
||||||
return document.getElementsByName(name)?.[0]?.value || ""
|
|
||||||
}
|
|
||||||
let debounce = null
|
let debounce = null
|
||||||
function updateQRdeb () {
|
function updateQRdeb () {
|
||||||
clearTimeout(debounce)
|
clearTimeout(debounce)
|
||||||
@@ -104,23 +107,26 @@ function updateQRdeb () {
|
|||||||
updateQR()
|
updateQR()
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
function getNewUrl () {
|
||||||
|
const qstring = [
|
||||||
|
["client_name", val("client-name")],
|
||||||
|
["client_address", val("client-address")],
|
||||||
|
["client_city", val("client-city")],
|
||||||
|
["amount", val("amount").padStart(11, "0")],
|
||||||
|
["purpose_code", val("code")],
|
||||||
|
["payment_purpose", val("purpose")],
|
||||||
|
["iban", val("iban")],
|
||||||
|
["reference", val("reference")],
|
||||||
|
["issuer_name", val("issuer-name")],
|
||||||
|
["issuer_address", val("issuer-address")],
|
||||||
|
["issuer_city", val("issuer-city")],
|
||||||
|
].map(v => `${v[0]}=${v[1]}`).join("&")
|
||||||
|
return `${window.location.origin}/api/qrcode?${qstring}`
|
||||||
|
}
|
||||||
function updateQR (e) {
|
function updateQR (e) {
|
||||||
try {
|
try {
|
||||||
const qstring = [
|
|
||||||
["client_name", val("client-name")],
|
|
||||||
["client_address", val("client-address")],
|
|
||||||
["client_city", val("client-city")],
|
|
||||||
["amount", val("amount")],
|
|
||||||
["purpose_code", val("code")],
|
|
||||||
["payment_purpose", val("purpose")],
|
|
||||||
["iban", val("iban")],
|
|
||||||
["reference", val("reference")],
|
|
||||||
["issuer_name", val("issuer-name")],
|
|
||||||
["issuer_address", val("issuer-address")],
|
|
||||||
["issuer_city", val("issuer-city")],
|
|
||||||
].map(v => `${v[0]}=${v[1]}`).join("&")
|
|
||||||
const newurl = `/api/qrcode?${qstring}`
|
|
||||||
const preloadImg = new Image();
|
const preloadImg = new Image();
|
||||||
|
const newurl = getNewUrl()
|
||||||
preloadImg.addEventListener("load", () => qrcode.style.setProperty('background-image', `url("${newurl}"), url("/public/invalid-content.png")`))
|
preloadImg.addEventListener("load", () => qrcode.style.setProperty('background-image', `url("${newurl}"), url("/public/invalid-content.png")`))
|
||||||
preloadImg.addEventListener("error", () => qrcode.style.setProperty('background-image', `url("/public/invalid-content.png")`))
|
preloadImg.addEventListener("error", () => qrcode.style.setProperty('background-image', `url("/public/invalid-content.png")`))
|
||||||
preloadImg.src=newurl;
|
preloadImg.src=newurl;
|
||||||
@@ -128,7 +134,9 @@ function updateQR (e) {
|
|||||||
setImgUrl(`url("/public/invalid-content.png")`)
|
setImgUrl(`url("/public/invalid-content.png")`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (el of inputs) {
|
|
||||||
|
// Add input listener to all inputs
|
||||||
|
for (el of document.getElementsByTagName("input")) {
|
||||||
el.addEventListener("input", updateQRdeb)
|
el.addEventListener("input", updateQRdeb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,8 @@ section div {
|
|||||||
row-gap: .5rem;
|
row-gap: .5rem;
|
||||||
column-gap: .5rem;
|
column-gap: .5rem;
|
||||||
}
|
}
|
||||||
.maker > div:last-child {
|
.maker > div:nth-last-child(1) { grid-column-end: -1; }
|
||||||
grid-column-end: -1;
|
.maker > div:nth-last-child(2) { grid-column-end: -2; }
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
<body>
|
<body>
|
||||||
<section>
|
<section>
|
||||||
@@ -64,7 +63,7 @@ section div {
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="amount">Amount</label>
|
<label for="amount">Amount</label>
|
||||||
<input type="number" placeholder="00000001132" name="amount">
|
<input type="number" placeholder="00000001132" min="0" max="99999999999" name="amount">
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label for="code">Purpose code</label>
|
<label for="code">Purpose code</label>
|
||||||
@@ -94,11 +93,62 @@ section div {
|
|||||||
<label for="issuer-city">Issuer city</label>
|
<label for="issuer-city">Issuer city</label>
|
||||||
<input type="text" placeholder="1000 Ljubljana" name="issuer-city">
|
<input type="text" placeholder="1000 Ljubljana" name="issuer-city">
|
||||||
</div>
|
</div>
|
||||||
|
<div>
|
||||||
|
<button id="copyurl" type="button">Copy URL</button>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<input type="submit" value="Create form">
|
<input type="submit" value="Create form">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<script>
|
||||||
|
function val (name) { return document.getElementsByName(name)?.[0]?.value || "" }
|
||||||
|
function getNewUrl () {
|
||||||
|
const qstring = [
|
||||||
|
["client_name", val("client-name")],
|
||||||
|
["client_address", val("client-address")],
|
||||||
|
["client_city", val("client-city")],
|
||||||
|
["amount", val("amount").padStart(11, "0")],
|
||||||
|
["purpose_code", val("code")],
|
||||||
|
["payment_purpose", val("purpose")],
|
||||||
|
["iban", val("iban")],
|
||||||
|
["reference", val("reference")],
|
||||||
|
["issuer_name", val("issuer-name")],
|
||||||
|
["issuer_address", val("issuer-address")],
|
||||||
|
["issuer_city", val("issuer-city")],
|
||||||
|
].map(v => `${v[0]}=${v[1]}`).join("&")
|
||||||
|
return `${window.location.origin}/api/qrcode?${qstring}`
|
||||||
|
}
|
||||||
|
const copyBtn = document.getElementById("copyurl")
|
||||||
|
copyBtn.addEventListener("click", () => copyUrl())
|
||||||
|
function copyUrl () {
|
||||||
|
try {
|
||||||
|
const dummy = document.createElement('input')
|
||||||
|
document.body.appendChild(dummy)
|
||||||
|
dummy.value = getNewUrl()
|
||||||
|
dummy.select()
|
||||||
|
document.execCommand('copy')
|
||||||
|
document.body.removeChild(dummy)
|
||||||
|
|
||||||
|
copyBtn.innerText = "Copied!"
|
||||||
|
copyBtn.classList.add("success")
|
||||||
|
setTimeout(() => {
|
||||||
|
copyBtn.innerText = "Copy URL"
|
||||||
|
copyBtn.classList.remove("success")
|
||||||
|
}, 750)
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
copyBtn.innerText = "Failed!"
|
||||||
|
copyBtn.classList.add("error")
|
||||||
|
setTimeout(() => {
|
||||||
|
copyBtn.innerText = "Copy URL"
|
||||||
|
copyBtn.classList.remove("error")
|
||||||
|
}, 750)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<section>
|
<section>
|
||||||
<h1 id="api"><a href="#api">🔗</a> API</h1>
|
<h1 id="api"><a href="#api">🔗</a> API</h1>
|
||||||
<h4 id="api-qrcode"><a href="#api-qrcode">🔗</a> <code>GET /api/qrcode</code></h4>
|
<h4 id="api-qrcode"><a href="#api-qrcode">🔗</a> <code>GET /api/qrcode</code></h4>
|
||||||
|
|||||||
Reference in New Issue
Block a user