From 5283d45c364f0b4b8d005616687c1a3c157a1cdd Mon Sep 17 00:00:00 2001 From: Eragon Date: Sat, 9 Mar 2024 13:38:43 +0100 Subject: [PATCH] Two editors on one page works, but hotkeys no longer work --- app/routes/account/account.py | 2 + app/static/css/editor.css | 4 +- app/static/scripts/editor.js | 216 +++++++++++++++-------------- app/templates/account/account.html | 3 + app/templates/widgets/editor.html | 28 ++-- 5 files changed, 138 insertions(+), 115 deletions(-) diff --git a/app/routes/account/account.py b/app/routes/account/account.py index bc245c3..ff55f0e 100644 --- a/app/routes/account/account.py +++ b/app/routes/account/account.py @@ -59,6 +59,8 @@ def edit_account(): form.signature.data = current_user.signature form.biography.data = current_user.bio + form.signature.data = current_user.signature + form.biography.data = current_user.bio return render('account/account.html', scripts=["+scripts/entropy.js"], form=form) diff --git a/app/static/css/editor.css b/app/static/css/editor.css index efb5ab9..72f962a 100644 --- a/app/static/css/editor.css +++ b/app/static/css/editor.css @@ -4,7 +4,7 @@ flex-wrap: wrap; align-items: center; } -.editor .btn-group #filler { +.editor .btn-group .filler { flex-grow: 1; } .editor .btn-group button { @@ -85,4 +85,4 @@ transform: translateX(-50%); top: 50vh; } -} \ No newline at end of file +} diff --git a/app/static/scripts/editor.js b/app/static/scripts/editor.js index 5dc3016..225badb 100644 --- a/app/static/scripts/editor.js +++ b/app/static/scripts/editor.js @@ -10,7 +10,7 @@ function editor_event_source(event) /* Grab the button and the parent editor block. The onclick event itself usually reports the SVG in the button as the source */ - let node = event.target || event.srcElement; + let node = event.currentTarget || event.srcElement; while (node != document.body) { if (node.tagName == "BUTTON" && !button) { button = node; @@ -35,9 +35,9 @@ function editor_event_source(event) interval [start:end) (ie. the range where the contents are now located). */ function editor_replace_range(textarea, start, end, contents) { - ta.value = ta.value.substring(0, start) - + contents - + ta.value.substring(end); + textarea.value = textarea.value.substring(0, start) + + contents + + textarea.value.substring(end); return [start, start + contents.length]; } @@ -67,7 +67,7 @@ function editor_insert_around(event, before="", after=null) ta.selectionStart = ta.selectionEnd = start + before.length; } - preview(); + preview(editor); } /* Event handler that modifies each line within the selection through a @@ -102,27 +102,28 @@ function editor_act_on_lines(event, fn) ta.selectionStart = start; ta.selectionEnd = end; - preview(); + preview(editor); } function editor_clear_modals(event, close = true) { // Stop the propagation of the event event.stopPropagation() + const [editor, button, ta] = editor_event_source(event); // Reset all modal inputs - document.getElementById('media-alt-input').value = ''; - document.getElementById('media-link-input').value = ''; - document.getElementById('link-desc-input').value = ''; - document.getElementById('link-link-input').value = ''; - const media_type = document.getElementsByName("media-type"); + editor.getElementsByClassName('media-alt-input')[0].value = ''; + editor.getElementsByClassName('media-link-input')[0].value = ''; + editor.getElementsByClassName('link-desc-input')[0].value = ''; + editor.getElementsByClassName('link-link-input')[0].value = ''; + const media_type = editor.getElementsByClassName("media-type")[0]; for(i = 0; i < media_type.length; i++) { media_type[i].checked = false; } // Close all modal if requested if (!close) { return } - const modals = document.getElementsByClassName('modal'); + const modals = editor.getElementsByClassName('modal'); for (const i of modals) {i.style.display = 'none'}; } @@ -143,7 +144,8 @@ function editor_inline(event, type, enable_preview = true) } if (enable_preview) { - preview(); + const [editor, button, ta] = editor_event_source(event); + preview(editor); } } @@ -172,11 +174,11 @@ function editor_insert_link(event, link_id, text_id, media = false) let indexStart = ta.selectionStart; let indexEnd = ta.selectionEnd; - const link = document.getElementById(link_id).value; - const text = document.getElementById(text_id).value; + const link = editor.getElementsByClassName(link_id)[0].value; + const text = editor.getElementsByClassName(text_id)[0].value; let media_type = ""; - const media_selector = document.getElementsByName("media-type"); + const media_selector = editor.getElementsByClassName("media-type")[0]; for(i = 0; i < media_selector.length; i++) { if (media_selector[i].checked) { media_type = `{type=${media_selector[i].value}}`; @@ -197,7 +199,7 @@ function editor_insert_link(event, link_id, text_id, media = false) ta.selectionStart = ta.selectionEnd = start + 1; } - preview(); + preview(editor); } function editor_title(event, level, diff) @@ -293,6 +295,8 @@ const DISABLE_PREVIEW_ICON = ' item.trim().startsWith("auto-preview="))) { auto_preview = document.cookie.split(";").some((item) => item.includes("auto-preview=true")); @@ -301,25 +305,24 @@ function toggle_auto_preview() { } document.cookie = `auto-preview=${!auto_preview}; max-age=31536000; SameSite=Strict; Secure` if (!auto_preview) { - document.getElementById("toggle_preview").title = "Désactiver la prévisualisation"; - document.getElementById("toggle_preview").innerHTML = DISABLE_PREVIEW_ICON; - document.getElementById("manual_preview").style = "display: none"; + editor.getElementsByClassName("toggle_preview")[0].title = "Désactiver la prévisualisation"; + editor.getElementsByClassName("toggle_preview")[0].innerHTML = DISABLE_PREVIEW_ICON; + editor.getElementsByClassName("manual_preview")[0].style = "display: none"; } else { - document.getElementById("toggle_preview").title = "Activer la prévisualisation"; - document.getElementById("toggle_preview").innerHTML = ENABLE_PREVIEW_ICON; - document.getElementById("manual_preview").style = "display: block"; + editor.getElementsByClassName("toggle_preview")[0].title = "Activer la prévisualisation"; + editor.getElementsByClassName("toggle_preview")[0].innerHTML = ENABLE_PREVIEW_ICON; + editor.getElementsByClassName("manual_preview")[0].style = "display: block"; } } /* This request the server to get a complete render of the current text in the textarea */ -function preview(manual=false) { +function preview(editor, manual=false) { // If auto-preview is disabled and the preview is not manually requested by the user if (document.cookie.split(";").some((item) => item.includes("auto-preview=false")) && !manual) { return; } - const previewArea = document.querySelector("#editor_content_preview"); - - const textarea = document.querySelector(".editor textarea"); + const previewArea = editor.querySelector(".editor_content_preview"); + const ta = editor.querySelector("textarea"); const payload = {text: ta.value}; const headers = new Headers(); @@ -341,86 +344,95 @@ function preview(manual=false) { }); } -if (document.cookie.split(";").some((item) => item.trim().startsWith("auto-preview="))) { - if (document.cookie.split(";").some((item) => item.includes("auto-preview=false"))) { - document.getElementById("toggle_preview").title = "Activer la prévisualisation"; - document.getElementById("toggle_preview").innerHTML = ENABLE_PREVIEW_ICON; - document.getElementById("manual_preview").style = "display: block"; - } +/* Wrapper for user-requested preview refresh */ +function manual_preview(editor_id) { + const editor = document.getElementById("editor_" + editor_id); + preview(editor, manual = true); } -let previewTimeout = null; -let ta = document.querySelector(".editor textarea"); -ta.addEventListener('keydown', function(e) { - // Tab insert some spaces - let keyCode = e.keyCode || e.which; - if (keyCode == 9) { - // TODO Add one tab to selected text without replacing it - e.preventDefault(); +/* Add the event listener for the textarea hotkeys and auto-preview */ +function editor_setup(editor_id) { + const editor = document.getElementById("editor_" + editor_id); - let start = e.target.selectionStart; - let end = e.target.selectionEnd; - // set textarea value to: text before caret + tab + text after caret - e.target.value = e.target.value.substring(0, start) + "\t" + e.target.value.substring(end); - e.target.selectionEnd = start + 1; - } - - /* - * Keybindings for buttons. The default action of the keybinding is prevented. - * Ctrl+B adds bold - * Ctrl+I adds italic - * Ctrl+U adds underline - * Ctrl+S adds strikethrough - * Ctrl+H adds Header +1 - * Ctrl+Enter send the form - */ - if (e.ctrlKey) { - switch (keyCode) { - case 13: - let t = e.target; - while(! (t instanceof HTMLFormElement)) { - t = t.parentNode; - } - try { - t.submit(); - } catch(exception) { - t.submit.click(); - } - e.preventDefault(); - break; - case 66: // B - editor_inline(e, "bold", false); - e.preventDefault(); - break; - case 72: // H - editor_title(e, 0, +1); - e.preventDefault(); - break; - case 73: // I - editor_inline(e, "italic", false); - e.preventDefault(); - break; - case 83: // S - editor_inline(e, "strike", false); - e.preventDefault(); - break; - case 85: // U - editor_inline(e, "underline", false); - e.preventDefault(); - break; + if (document.cookie.split(";").some((item) => item.trim().startsWith("auto-preview="))) { + if (document.cookie.split(";").some((item) => item.includes("auto-preview=false"))) { + editor.getElementsByClassName("toggle_preview")[0].title = "Activer la prévisualisation"; + editor.getElementsByClassName("toggle_preview")[0].innerHTML = ENABLE_PREVIEW_ICON; + editor.getElementsByClassName("manual_preview")[0].style = "display: block"; } } - // Set a timeout for refreshing the preview - if (previewTimeout != null) { + let previewTimeout = null; + let ta = editor.querySelector(".editor textarea"); + ta.addEventListener('keydown', function(e) { + // Tab insert some spaces + let keyCode = e.keyCode || e.which; + if (keyCode == 9) { + // TODO Add one tab to selected text without replacing it + e.preventDefault(); + + let start = e.target.selectionStart; + let end = e.target.selectionEnd; + // set textarea value to: text before caret + tab + text after caret + e.target.value = e.target.value.substring(0, start) + "\t" + e.target.value.substring(end); + e.target.selectionEnd = start + 1; + } + + /* + * Keybindings for buttons. The default action of the keybinding is prevented. + * Ctrl+B adds bold + * Ctrl+I adds italic + * Ctrl+U adds underline + * Ctrl+S adds strikethrough + * Ctrl+H adds Header +1 + * Ctrl+Enter send the form + */ + if (e.ctrlKey) { + switch (keyCode) { + case 13: + let t = e.target; + while(! (t instanceof HTMLFormElement)) { + t = t.parentNode; + } + try { + t.submit(); + } catch(exception) { + t.submit.click(); + } + e.preventDefault(); + break; + case 66: // B + editor_inline(e, "bold", false); + e.preventDefault(); + break; + case 72: // H + editor_title(e, 0, +1); + e.preventDefault(); + break; + case 73: // I + editor_inline(e, "italic", false); + e.preventDefault(); + break; + case 83: // S + editor_inline(e, "strike", false); + e.preventDefault(); + break; + case 85: // U + editor_inline(e, "underline", false); + e.preventDefault(); + break; + } + } + + // Set a timeout for refreshing the preview clearTimeout(previewTimeout); - } - previewTimeout = setTimeout(preview, 3000); -}); + previewTimeout = setTimeout(() => { preview(editor) }, 3000); + }); -document.querySelector('emoji-picker').addEventListener('emoji-click', event => { - editor_clear_modals(event); - editor_insert_around(event, "", event.detail.unicode) - - preview(); -}); + editor.querySelector('emoji-picker').addEventListener('emoji-click', event => { + editor_clear_modals(event); + editor_insert_around(event, "", event.detail.unicode) + + preview(editor); + }); +} diff --git a/app/templates/account/account.html b/app/templates/account/account.html index 898ce5f..5b490fa 100644 --- a/app/templates/account/account.html +++ b/app/templates/account/account.html @@ -73,6 +73,9 @@
{{ widget_editor.text_editor(form.biography) }} + {% for error in form.signature.errors %} + {{ error }} + {% endfor %}

Préférences

diff --git a/app/templates/widgets/editor.html b/app/templates/widgets/editor.html index 13750cb..8278596 100644 --- a/app/templates/widgets/editor.html +++ b/app/templates/widgets/editor.html @@ -1,5 +1,5 @@ {% macro text_editor(field, label=True, autofocus=false) %} -
+
{{ field.label if label }} @@ -113,9 +113,9 @@