From 90f25ec2203530218ecdae791cf92915af6bd5ad Mon Sep 17 00:00:00 2001 From: Lukas Schulte Pelkum Date: Sun, 20 Jun 2021 15:58:36 +0200 Subject: [PATCH] Improve the web frontend (#9) * Fix line flowing out of div * Revert line highlighting * Fix tab key behaviour * Move links and version information to a footer * Fix footer hiding last code line * Calculate line number offset based on line overflow * Refactor some code --- web/assets/css/style.css | 107 ++++++++++++++++++++++--------- web/assets/css/style.css.map | 2 +- web/assets/css/style.scss | 87 +++++++++++++++++++------ web/assets/js/autoload.js | 114 ++++++++++++++++++--------------- web/assets/js/buttons.js | 22 +++---- web/assets/js/notifications.js | 4 +- web/index.html | 57 +++++++++-------- 7 files changed, 249 insertions(+), 144 deletions(-) diff --git a/web/assets/css/style.css b/web/assets/css/style.css index 3ca37f4..e18d6bc 100644 --- a/web/assets/css/style.css +++ b/web/assets/css/style.css @@ -101,26 +101,6 @@ html, body { color: initial; } -.navigation .meta { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: horizontal; - -webkit-box-direction: normal; - -ms-flex-direction: row; - flex-direction: row; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; -} - -.navigation .meta #version { - margin-right: 40px; - padding: 5px 10px; - background-color: #000000; - border-radius: 10px; -} - .container { margin-top: 60px; display: -webkit-box; @@ -143,13 +123,12 @@ html, body { .container #linenos span { display: block; width: 100%; + height: 20px; text-align: center; } -.container #linenos span:hover, .container #linenos span.highlight { - background-color: #92b300; - color: #ffffff; - cursor: pointer; +.container #linenos span:last-child { + margin-bottom: 25px; } .container #content { @@ -158,13 +137,8 @@ html, body { } .container #content #code { - white-space: pre; -} - -.container #content #code .highlight { - background-color: #92b30071; - display: inline-block; - min-width: 100%; + word-break: break-all; + white-space: pre-wrap; } .container #content #input { @@ -196,6 +170,57 @@ html, body { background-color: #389b38; } +#footer { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + background-color: #222222; +} + +#footer #flex { + display: -webkit-box; + display: -ms-flexbox; + display: flex; + -webkit-box-orient: horizontal; + -webkit-box-direction: normal; + -ms-flex-direction: row; + flex-direction: row; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: justify; + -ms-flex-pack: justify; + justify-content: space-between; + margin: 0 80px 0 60px; +} + +#footer div { + display: inline-block; +} + +#footer a { + display: inline-block; + text-decoration: none; + color: #ffffff; + padding: 5px 20px; + height: 100%; + -webkit-transition: all 200ms; + transition: all 200ms; +} + +#footer a:hover { + background-color: #333333; + color: #2daa57; +} + +#footer #version { + display: inline-block; + margin-left: 10px; + padding: 5px 30px; + background-color: #111111; +} + @media only screen and (max-width: 650px) { .navigation { padding: 0 20px; @@ -211,5 +236,25 @@ html, body { .navigation .meta #version { display: none; } + #footer #flex { + margin: 0 0 0 25px; + } + #footer .version-container span { + display: none; + } + #footer a { + padding: 5px 15px; + } +} + +@media only screen and (max-width: 500px) { + #footer #flex { + margin: 0; + -ms-flex-pack: distribute; + justify-content: space-around; + } + #footer .version-container { + display: none; + } } /*# sourceMappingURL=style.css.map */ \ No newline at end of file diff --git a/web/assets/css/style.css.map b/web/assets/css/style.css.map index c760aea..3d15a40 100644 --- a/web/assets/css/style.css.map +++ b/web/assets/css/style.css.map @@ -1,6 +1,6 @@ { "version": 3, - "mappings": "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", + "mappings": "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", "sources": [ "style.scss" ], diff --git a/web/assets/css/style.scss b/web/assets/css/style.scss index eb45e1f..0717bb3 100644 --- a/web/assets/css/style.scss +++ b/web/assets/css/style.scss @@ -83,17 +83,6 @@ html, body { } } } - & .meta { - display: flex; - flex-direction: row; - align-items: center; - & #version { - margin-right: 40px; - padding: 5px 10px; - background-color: #000000; - border-radius: 10px; - } - } } .container { @@ -109,11 +98,10 @@ html, body { & span { display: block; width: 100%; + height: 20px; text-align: center; - &:hover, &.highlight { - background-color: #92b300; - color: #ffffff; - cursor: pointer; + &:last-child { + margin-bottom: 25px; } } } @@ -121,12 +109,8 @@ html, body { padding: 20px; width: calc(100vw - 50px); & #code { - white-space: pre; - & .highlight { - background-color: #92b30071; - display: inline-block; - min-width: 100%; - } + word-break: break-all; + white-space: pre-wrap; } & #input { height: 100%; @@ -155,6 +139,42 @@ html, body { } } +#footer { + position: fixed; + bottom: 0; + left: 0; + width: 100%; + background-color: #222222; + & #flex { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin: 0 80px 0 60px; + } + & div { + display: inline-block; + } + & a { + display: inline-block; + text-decoration: none; + color: #ffffff; + padding: 5px 20px; + height: 100%; + transition: all 200ms; + &:hover { + background-color: #333333; + color: #2daa57; + } + } + & #version { + display: inline-block; + margin-left: 10px; + padding: 5px 30px; + background-color: #111111; + } +} + @media only screen and (max-width: 650px) { .navigation { padding: 0 20px; @@ -170,4 +190,29 @@ html, body { display: none; } } + + + #footer { + & #flex { + margin: 0 0 0 25px; + } + & .version-container span { + display: none; + } + & a { + padding: 5px 15px; + } + } +} + +@media only screen and (max-width: 500px) { + #footer { + & #flex { + margin: 0; + justify-content: space-around; + } + & .version-container { + display: none; + } + } } \ No newline at end of file diff --git a/web/assets/js/autoload.js b/web/assets/js/autoload.js index 770d57f..2266cbb 100644 --- a/web/assets/js/autoload.js +++ b/web/assets/js/autoload.js @@ -8,6 +8,12 @@ import * as notifications from "./notifications.js"; buttons.setupButtons(); buttons.setupKeybinds(); +// Define element handles +const versionElement = document.getElementById("version"); +const lineNOsElement = document.getElementById("linenos"); +const codeElement = document.getElementById("code"); +const inputElement = document.getElementById("input"); + // Load the API information async function loadAPIInformation() { const response = await api.getAPIInformation(); @@ -17,87 +23,91 @@ async function loadAPIInformation() { return; } const data = await response.json(); - document.getElementById("version").innerText = data.version; + versionElement.innerText = data.version; } loadAPIInformation(); // Try to load a paste if one exists export let PASTE_ID; +let CODE; async function loadPaste() { if (location.pathname !== "/") { // Define the paste ID and language const split = location.pathname.replace("/", "").split("."); const pasteID = split[0]; const language = split[1]; - + // Retrieve the paste from the API and redirect the user to the main page if it could not be found const response = await api.getPaste(pasteID); if (!response.ok) { location.replace(location.protocol + "//" + location.host); return; } - const data = await response.json(); - + CODE = (await response.json()).content; + // Adjust the button states document.getElementById("btn_save").setAttribute("disabled", true); document.getElementById("btn_delete").removeAttribute("disabled"); document.getElementById("btn_copy").removeAttribute("disabled"); - + // Set the paste content to the DOM - const code = document.getElementById("code"); - code.innerHTML = language - ? hljs.highlight(language, data.content).value - : hljs.highlightAuto(data.content).value; - + codeElement.innerHTML = language + ? hljs.highlight(language, CODE).value + : hljs.highlightAuto(CODE).value; + // Display the line numbers - const lineNOs = document.getElementById("linenos"); - lineNOs.innerHTML = data.content.split(/\n/).map((_, index) => `${index + 1}`).join(''); + renderLineNumbers(); + window.addEventListener("resize", renderLineNumbers); - const sharedLine = parseInt(window.location.hash.toLowerCase().replace("#l", ""), 10); - if (sharedLine) { - lineNOs.innerHTML = data.content.split(/\n/).map((_, index) => { - return index + 1 === sharedLine - ? `${index + 1}` - : `${index + 1}`; - }).join(''); - - let html = code.innerHTML.split(/\n/); - html[sharedLine-1] = `${html[sharedLine-1]}`; - code.innerHTML = html.join("\n"); - } - - // TODO: Update this shitty construct - lineNOs.childNodes.forEach(node => { - node.addEventListener("click", function(_) { - const address = location.protocol + "//" + location.host + location.pathname + "#L" + node.innerText; - location.replace(address); - location.reload(); - }); - node.addEventListener("mouseover", function(_) { - let html = code.innerHTML.split(/\n/); - const index = parseInt(node.innerText, 10) - 1; - html[index] = `${html[index]}`; - code.innerHTML = html.join("\n"); - }); - node.addEventListener("mouseout", function(_) { - let html = code.innerHTML.split(/\n/); - const index = parseInt(node.innerText, 10) - 1; - html[index] = html[index].substring(24, html[index].length - 7); - code.innerHTML = html.join("\n"); - }); - }); - // Set the PASTE_ID variable PASTE_ID = pasteID; } else { - const input = document.getElementById("input"); - input.classList.remove("hidden"); - input.focus(); - window.addEventListener("keydown", function(event) { + inputElement.classList.remove("hidden"); + inputElement.focus(); + window.addEventListener("keydown", function (event) { if (event.keyCode != 9) return; event.preventDefault(); - input.value += " "; + + insertTextAtCursor(inputElement, " "); }); } } -spinner.surround(loadPaste); \ No newline at end of file +spinner.surround(loadPaste); + +function renderLineNumbers() { + lineNOsElement.innerHTML = CODE.split(/\n/).map((line, index) => { + let lineWidth = getTextWidth(line, "16px Source Code Pro"); + let linesSpace = Math.ceil(lineWidth / codeElement.offsetWidth); + + let result = `${index+1}`; + if (linesSpace > 1) { + result += "".repeat(linesSpace - 1); + } + return result; + }).join(""); +} + +// 1:1 skid from https://stackoverflow.com/questions/7404366/how-do-i-insert-some-text-where-the-cursor-is +function insertTextAtCursor(element, text) { + let value = element.value, endIndex, range, doc = element.ownerDocument; + if (typeof element.selectionStart == "number" + && typeof element.selectionEnd == "number") { + endIndex = element.selectionEnd; + element.value = value.slice(0, endIndex) + text + value.slice(endIndex); + element.selectionStart = element.selectionEnd = endIndex + text.length; + } else if (doc.selection != "undefined" && doc.selection.createRange) { + element.focus(); + range = doc.selection.createRange(); + range.collapse(false); + range.text = text; + range.select(); + } +} + +// Also a kind of skid +function getTextWidth(text, font) { + let canvas = getTextWidth.canvas || (getTextWidth.canvas = document.createElement("canvas")); + let context = canvas.getContext("2d"); + context.font = font; + return context.measureText(text).width; +} \ No newline at end of file diff --git a/web/assets/js/buttons.js b/web/assets/js/buttons.js index 682da61..b246c81 100644 --- a/web/assets/js/buttons.js +++ b/web/assets/js/buttons.js @@ -6,10 +6,10 @@ import * as notifications from "./notifications.js"; // setupKeybinds initializes the keybinds for the buttons export function setupKeybinds() { - window.addEventListener("keydown", function(event) { + window.addEventListener("keydown", function (event) { // Return if the CTRL key was not pressed if (!event.ctrlKey) return; - + // Define the DOM element of the pressed button let element = null; switch (event.keyCode) { @@ -30,7 +30,7 @@ export function setupKeybinds() { break; } } - + // Call the onClick function of the button if (element) { if (element.hasAttribute("disabled")) return; @@ -43,13 +43,13 @@ export function setupKeybinds() { // setupButtons configures the click listeners of the buttons export function setupButtons() { // Define the behavior of the 'new' button - document.getElementById("btn_new").addEventListener("click", function() { + document.getElementById("btn_new").addEventListener("click", function () { location.replace(location.protocol + "//" + location.host); }); // Define the behavior of the 'save' button - document.getElementById("btn_save").addEventListener("click", function() { - spinner.surround(async function() { + document.getElementById("btn_save").addEventListener("click", function () { + spinner.surround(async function () { // Return if the text area is empty const input = document.getElementById("input"); if (!input.value) return; @@ -75,8 +75,8 @@ export function setupButtons() { }); // Define the behavior of the 'delete' button - document.getElementById("btn_delete").addEventListener("click", function() { - spinner.surround(async function() { + document.getElementById("btn_delete").addEventListener("click", function () { + spinner.surround(async function () { // Ask the user for the deletion token const deletionToken = prompt("Deletion Token:"); if (!deletionToken) return; @@ -95,11 +95,11 @@ export function setupButtons() { }); // Define the behavior of the 'copy' button - document.getElementById("btn_copy").addEventListener("click", function() { - spinner.surround(async function() { + document.getElementById("btn_copy").addEventListener("click", function () { + spinner.surround(async function () { // Ask for the clipboard permissions askClipboardPermissions(); - + // Copy the code await navigator.clipboard.writeText(document.getElementById("code").innerText); notifications.success("Copied the code!"); diff --git a/web/assets/js/notifications.js b/web/assets/js/notifications.js index 888741c..cdbd2df 100644 --- a/web/assets/js/notifications.js +++ b/web/assets/js/notifications.js @@ -18,7 +18,5 @@ function create(type, message, duration) { node.innerHTML = message; element.appendChild(node); - setTimeout(function() { - element.removeChild(node); - }, duration); + setTimeout(() => element.removeChild(node), duration); } \ No newline at end of file diff --git a/web/index.html b/web/index.html index a9fc50b..e2a7c06 100644 --- a/web/index.html +++ b/web/index.html @@ -1,5 +1,6 @@ + @@ -7,29 +8,36 @@ +
@@ -71,7 +64,21 @@
+ + \ No newline at end of file