From c37a104b3b8bf72f9eefedd786e3c0124cbe2ec1 Mon Sep 17 00:00:00 2001 From: Glitchii Date: Mon, 28 Jun 2021 13:17:57 +0100 Subject: [PATCH] Update index.js, index.css --- assets/css/index.css | 14 +- assets/js/index.js | 409 ++++++++++++++++++++++--------------------- 2 files changed, 218 insertions(+), 205 deletions(-) diff --git a/assets/css/index.css b/assets/css/index.css index 4a07a89..46e898a 100644 --- a/assets/css/index.css +++ b/assets/css/index.css @@ -773,8 +773,6 @@ u { .notification .inline { width: auto; height: auto; - padding: .2em; - margin: -.2em 0; border-radius: 3px; font-size: 85%; font-family: Consolas, Andale Mono WT, Andale Mono, Lucida Console, Lucida Sans Typewriter, DejaVu Sans Mono, Bitstream Vera Sans Mono, Liberation Mono, Nimbus Mono L, Monaco, Courier New, Courier, monospace; @@ -782,11 +780,12 @@ u { border: none; overflow: hidden; white-space: pre-wrap; - background-color: #4a3535; color: white; color: inherit; - background-color: inherit; - border: 1px dashed; + /* border: 1px dashed; */ + padding: .3em 0em; + border-radius: 2px; + margin: -.2em 5px; } @keyframes notifAn { @@ -1253,7 +1252,7 @@ textarea { .browse.error>p::after { color: #ee9191; - content: "Request failed. (Check dev-tools)"; + content: "Request failed. (Check console)"; } .linkName { @@ -1651,8 +1650,9 @@ body { height: 100%; } .notification .inline { - display: block; margin-top: 5px; + background-color: #20222500; + border: none; } .bottom .colrs { bottom: 40px; diff --git a/assets/js/index.js b/assets/js/index.js index e18ed05..6f72352 100644 --- a/assets/js/index.js +++ b/assets/js/index.js @@ -99,11 +99,24 @@ window.onload = () => { .onfinish = () => notif.style.removeProperty('display'), time); return false; }, allGood = e => { - let re = /"((icon_)?url")(: *)("(?!https?:\/\/).+?")/g.exec(editor.getValue()); - if (re) return error(`URL should start with https:// or http:// on this line ${makeShort(re[0], 30, 600)}`); + let str = JSON.stringify(e, null, 4), re = /("(?:icon_)?url": *")((?!\w+?:\/\/).+)"/g.exec(str); if (e.timestamp && new Date(e.timestamp).toString() === "Invalid Date") return error('Timestamp is invalid'); + if (re) { // If a URL is found without a protocol + if (!/\w+:|\/\/|^\//g.exec(re[2]) && re[2].includes('.')) { + let activeInput = document.querySelector('input[class$="link" i]:focus') + if (activeInput) { + lastPos = activeInput.selectionStart + 7; + authorLink.value = `http://${re[2]}`; + update(JSON.parse(str.replace(re[0], `${re[1]}http://${re[2]}"`))); + activeInput.setSelectionRange(lastPos, lastPos) + return true; + } + } + return error(`URL should have a protocol. Did you mean http://${makeShort(re[2], 30, 600).replace(' ', '')}?`); + } return true; - }, markup = (txt, opts) => { + }, + markup = (txt, opts) => { txt = txt .replace(/\<:[^:]+:(\d+)\>/g, '') .replace(/\<a:[^:]+:(\d+)\>/g, '') @@ -145,9 +158,9 @@ window.onload = () => { el.style.display = displayType || "unset"; }, hide = el => el.style.removeProperty('display'), imgSrc = (elm, src, remove) => remove ? elm.style.removeProperty('content') : elm.style.content = `url(${src})`, - toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)); - buildGui = (object, opts) => { - gui.innerHTML = ` + toObj = jsonString => JSON.parse(jsonString.replace(/\\"|"(?:\\"|[^"])*"|(\/\/.*|\/\*[\s\S]*?\*\/)/g, (x, y) => y ? "" : x)), + buildGui = (object, opts) => { + gui.innerHTML = `

Message content

@@ -319,206 +332,206 @@ window.onload = () => {
`; - let fieldsEditor = gui.querySelector('.fields ~ .edit'), addField = ` -
-

New Field

- + let fieldsEditor = gui.querySelector('.fields ~ .edit'), addField = ` +
+

New Field

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
`; + if (object.embed?.fields) fieldsEditor.innerHTML = object.embed.fields.filter(f => f && typeof f === 'object').map(f => ` +
+
+
+
+ +
+
+ +
+
+
+ +
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - + -
`; - if (object.embed?.fields) fieldsEditor.innerHTML = object.embed.fields.filter(f => f && typeof f === 'object').map(f => ` -
-
-
-
- -
-
- -
-
-
- -
-
- - - - - - Remove -
-
`).join('\n') + addField; - else fieldsEditor.innerHTML = addField; + Remove +
+
`).join('\n') + addField; + else fieldsEditor.innerHTML = addField; - gui.querySelectorAll('.removeBtn').forEach(e => { - e.addEventListener('click', el => { - fields = gui.querySelector('.fields ~ .edit'); - let field = el.target.closest('.field'); + gui.querySelectorAll('.removeBtn').forEach(e => { + e.addEventListener('click', el => { + fields = gui.querySelector('.fields ~ .edit'); + let field = el.target.closest('.field'); + if (field) { + let i = Array.from(fields.children).indexOf(field), jsonField = object.embed.fields[i]; + if (jsonField) { + object.embed.fields.splice(i, 1); + field.remove(); + update(object); + } + } + }) + }) + + document.querySelectorAll('.gui > .item').forEach(e => { + e.addEventListener('click', el => { + let elm = (el.target.closest('.top>.gui>.item') || el.target); + if (elm.classList.contains('active')) window.getSelection().anchorNode !== elm && elm.classList.remove('active'); + else { + let inlineField = elm.closest('.inlineField'), + input = elm.nextElementSibling.querySelector('input[type="text"]'), + txt = elm.nextElementSibling.querySelector('textarea'); + elm.classList.add('active'); + if (inlineField) inlineField.querySelector('.ttle~input').focus(); + else if (input) { + input.focus(); + input.selectionStart = input.selectionEnd = input.value.length; + } else if (txt) txt.focus(); + elm.classList.contains('fields') && elm.scrollIntoView({ behavior: "smooth", block: "center" }); + } + }) + }) + + content = gui.querySelector('.editContent'); + title = gui.querySelector('.editTitle'); + authorName = gui.querySelector('.editAuthorName'); + authorLink = gui.querySelector('.editAuthorLink'); + desc = gui.querySelector('.editDescription'); + thumbLink = gui.querySelector('.editThumbnailLink'); + imgLink = gui.querySelector('.editImageLink'); + footerText = gui.querySelector('.editFooterText'); + footerLink = gui.querySelector('.editFooterLink'); + fields = gui.querySelector('.fields ~ .edit'); + + document.querySelector('.addField').addEventListener('click', () => { + !json.embed && (json.embed = {}); + let arr = json.embed.fields || []; + if (arr.length >= 25) return error('Cannot have more than 25 fields', 5000); + arr.push({ name: "Field name", value: "Field value", inline: false }); + json.embed.fields = arr; + update(json); + buildGui(json, { newField: true, activate: document.querySelectorAll('.gui > .item.active') }); + }) + + gui.querySelectorAll('textarea, input').forEach(e => e.addEventListener('input', el => { + let value = el.target.value, field = el.target.closest('.field'); if (field) { - let i = Array.from(fields.children).indexOf(field), jsonField = object.embed.fields[i]; + let jsonField = json.embed.fields[Array.from(fields.children).indexOf(field)]; if (jsonField) { - object.embed.fields.splice(i, 1); - field.remove(); - update(object); + if (el.target.type === 'text') jsonField.name = value; + else if (el.target.type === 'textarea') jsonField.value = value; + else jsonField.inline = el.target.checked; + } else { + let obj = {} + if (el.target.type === 'text') obj.name = value; + else if (el.target.type === 'textarea') obj.value = value; + else obj.inline = el.target.checked; + json.embed.fields.push(obj); } - } - }) - }) - - document.querySelectorAll('.gui > .item').forEach(e => { - e.addEventListener('click', el => { - let elm = (el.target.closest('.top>.gui>.item') || el.target); - if (elm.classList.contains('active')) window.getSelection().anchorNode !== elm && elm.classList.remove('active'); - else { - let inlineField = elm.closest('.inlineField'), - input = elm.nextElementSibling.querySelector('input[type="text"]'), - txt = elm.nextElementSibling.querySelector('textarea'); - elm.classList.add('active'); - if (inlineField) inlineField.querySelector('.ttle~input').focus(); - else if (input) { - input.focus(); - input.selectionStart = input.selectionEnd = input.value.length; - } else if (txt) txt.focus(); - elm.classList.contains('fields') && elm.scrollIntoView({ behavior: "smooth", block: "center" }); - } - }) - }) - - content = gui.querySelector('.editContent'); - title = gui.querySelector('.editTitle'); - authorName = gui.querySelector('.editAuthorName'); - authorLink = gui.querySelector('.editAuthorLink'); - desc = gui.querySelector('.editDescription'); - thumbLink = gui.querySelector('.editThumbnailLink'); - imgLink = gui.querySelector('.editImageLink'); - footerText = gui.querySelector('.editFooterText'); - footerLink = gui.querySelector('.editFooterLink'); - fields = gui.querySelector('.fields ~ .edit'); - - document.querySelector('.addField').addEventListener('click', () => { - !json.embed && (json.embed = {}); - let arr = json.embed.fields || []; - if (arr.length >= 25) return error('Cannot have more than 25 fields', 5000); - arr.push({ name: "Field name", value: "Field value", inline: false }); - json.embed.fields = arr; - update(json); - buildGui(json, { newField: true, activate: document.querySelectorAll('.gui > .item.active') }); - }) - - gui.querySelectorAll('textarea, input').forEach(e => e.addEventListener('input', el => { - let v = el.target.value, field = el.target.closest('.field'); - if (field) { - let jsonField = json.embed.fields[Array.from(fields.children).indexOf(field)]; - if (jsonField) { - if (el.target.type === 'text') jsonField.name = v; - else if (el.target.type === 'textarea') jsonField.value = v; - else jsonField.inline = el.target.checked; } else { - let obj = {} - if (el.target.type === 'text') obj.name = v; - else if (el.target.type === 'textarea') obj.value = v; - else obj.inline = el.target.checked; - json.embed.fields.push(obj); - } - } else { - json.embed ??= {}; - switch (el.target) { - case content: json.content = v; break; - case title: json.embed.title = v; break; - case authorName: json.embed.author ??= {}, json.embed.author.name = v; break; - case authorLink: json.embed.author ??= {}, json.embed.author.icon_url = v, imgSrc(el.target.previousElementSibling, v); break; - case desc: json.embed.description = v; break; - case thumbLink: json.embed.thumbnail ??= {}, json.embed.thumbnail.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break; - case imgLink: json.embed.image ??= {}, json.embed.image.url = v, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), v); break; - case footerText: json.embed.footer ??= {}, json.embed.footer.text = v; break; - case footerLink: json.embed.footer ??= {}, json.embed.footer.icon_url = v, imgSrc(el.target.previousElementSibling, v); break; - } - } - update(json); - })) - - if (opts?.activate) { - let elements = opts.activate; - Array.from(elements).map(el => el.className).map(clss => '.' + clss.split(' ').slice(0, 2).join('.')) - .forEach(clss => document.querySelectorAll(clss) - .forEach(e => e.classList.add('active'))) - } else['.item.author', '.item.description'].forEach(clss => document.querySelector(clss).classList.add('active')); - - if (opts?.newField) { - let last = fields.children[fields.childElementCount - 2], el = last.querySelector('.designerFieldName > input'); - el.setSelectionRange(el.value.length, el.value.length); el.focus(); - last.scrollIntoView({ behavior: "smooth", block: "center" }); - } - - let files = document.querySelectorAll('input[type="file"]'); - files.forEach(f => f.addEventListener('change', e => { - if (f.files) { - e.target.nextElementSibling.click(); - e.target.closest('.edit').querySelector('.browse').classList.add('loading'); - } - })) - - document.querySelectorAll('form').forEach(form => form.addEventListener('submit', e => { - e.preventDefault(); - let formData = new FormData(e.target); - formData.append('file', files.files); - formData.append('datetime', '10m'); - fetch('https://tempfile.site/api/files', { - method: 'POST', - body: formData, - }) - .then(res => res.json()) - .then(res => { - let browse = e.target.closest('.edit').querySelector('.browse'); - browse.classList.remove('loading'); - if (!res.ok) { - console.log(res.error); - browse.classList.add('error'); - return setTimeout(() => browse.classList.remove('error'), 5000) + json.embed ??= {}; + switch (el.target) { + case content: json.content = value; break; + case title: json.embed.title = value; break; + case authorName: json.embed.author ??= {}, json.embed.author.name = value; break; + case authorLink: json.embed.author ??= {}, json.embed.author.icon_url = value, imgSrc(el.target.previousElementSibling, value); break; + case desc: json.embed.description = value; break; + case thumbLink: json.embed.thumbnail ??= {}, json.embed.thumbnail.url = value, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), value); break; + case imgLink: json.embed.image ??= {}, json.embed.image.url = value, imgSrc(el.target.closest('.editIcon').querySelector('.imgParent'), value); break; + case footerText: json.embed.footer ??= {}, json.embed.footer.text = value; break; + case footerLink: json.embed.footer ??= {}, json.embed.footer.icon_url = value, imgSrc(el.target.previousElementSibling, value); break; } - imgSrc(e.target.previousElementSibling.querySelector('.editIcon > .imgParent') || e.target.closest('.editIcon').querySelector('.imgParent'), res.link); - let input = e.target.previousElementSibling.querySelector('.editIcon > input') || e.target.previousElementSibling; - input.value = res.link; - if (input === authorLink) json.embed.author.icon_url = res.link; - else if (input === thumbLink) json.embed.thumbnail.url = res.link; - else if (input === imgLink) json.embed.image.url = res.link; - else json.embed.footer.icon_url = res.link; - update(json); - console.info(`Image (${res.link}) will be deleted in 5 minutes. To delete it now got to ${res.link.replace('/files', '/del')} and enter this code: ${res.authkey}`); - }).catch(err => `Request to tempfile.site failed with error: ${err}`) - })) - } + } + update(json); + })) + + if (opts?.activate) { + let elements = opts.activate; + Array.from(elements).map(el => el.className).map(clss => '.' + clss.split(' ').slice(0, 2).join('.')) + .forEach(clss => document.querySelectorAll(clss) + .forEach(e => e.classList.add('active'))) + } else['.item.author', '.item.description'].forEach(clss => document.querySelector(clss).classList.add('active')); + + if (opts?.newField) { + let last = fields.children[fields.childElementCount - 2], el = last.querySelector('.designerFieldName > input'); + el.setSelectionRange(el.value.length, el.value.length); el.focus(); + last.scrollIntoView({ behavior: "smooth", block: "center" }); + } + + let files = document.querySelectorAll('input[type="file"]'); + files.forEach(f => f.addEventListener('change', e => { + if (f.files) { + e.target.nextElementSibling.click(); + e.target.closest('.edit').querySelector('.browse').classList.add('loading'); + } + })) + + document.querySelectorAll('form').forEach(form => form.addEventListener('submit', e => { + e.preventDefault(); + let formData = new FormData(e.target); + formData.append('file', files.files); + formData.append('datetime', '10m'); + fetch('https://tempfile.site/api/files', { + method: 'POST', + body: formData, + }) + .then(res => res.json()) + .then(res => { + let browse = e.target.closest('.edit').querySelector('.browse'); + browse.classList.remove('loading'); + if (!res.ok) { + console.log(res.error); + browse.classList.add('error'); + return setTimeout(() => browse.classList.remove('error'), 5000) + } + imgSrc(e.target.previousElementSibling.querySelector('.editIcon > .imgParent') || e.target.closest('.editIcon').querySelector('.imgParent'), res.link); + let input = e.target.previousElementSibling.querySelector('.editIcon > input') || e.target.previousElementSibling; + input.value = res.link; + if (input === authorLink) ((json.embed ??= {}).author ??= {}).icon_url = res.link; + else if (input === thumbLink) ((json.embed ??= {}).thumbnail ??= {}).url = res.link; + else if (input === imgLink) ((json.embed ??= {}).image ??= {}).url = res.link; + else ((json.embed ??= {}).footer ??= {}).url = res.link; + update(json); + console.info(`Image (${res.link}) will be deleted in 10 minutes. To delete it now, go to ${res.link.replace('/files', '/del')} and enter this code: ${res.authkey}`); + }).catch(err => error(`Request to tempfile.site failed with error: ${err}`, 5000)) + })) + } buildGui(json); fields = gui.querySelector('.fields ~ .edit'); @@ -649,7 +662,7 @@ window.onload = () => { }) document.querySelector('.clear').addEventListener('click', () => { - json = { }; + json = {}; embed.style.removeProperty('border-color'); picker.source.style.removeProperty('background'); update(json); buildGui(json); editor.setValue(JSON.stringify(json, null, 4));