implement copuing QRCode URL in form creator

This commit is contained in:
Aljaz S
2021-11-25 17:50:04 +01:00
parent 432367d91b
commit c6c42e8f87
3 changed files with 105 additions and 30 deletions

View File

@@ -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;
} }
@@ -130,3 +137,13 @@ button:active {
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;
}

View File

@@ -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)
} }

View File

@@ -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">&#128279;</a> API</h1> <h1 id="api"><a href="#api">&#128279;</a> API</h1>
<h4 id="api-qrcode"><a href="#api-qrcode">&#128279;</a> <code>GET /api/qrcode</code></h4> <h4 id="api-qrcode"><a href="#api-qrcode">&#128279;</a> <code>GET /api/qrcode</code></h4>