Add functionality to expand the markdown editor

The editor will now have a default height of 300px but a button will let
the user expand the editor. It will expand it to fit all content (or up
to 400px if the content was not exceeding 300px). In the expanded mode
the editor will keep growing as the user types more content.
This commit is contained in:
Julia Casamitjana
2024-04-15 13:23:00 +02:00
committed by Dominic Sauer
parent f10bcb96a6
commit 749074fec0
5 changed files with 95 additions and 3 deletions

View File

@ -1,7 +1,7 @@
/** /**
* ToastUi editor initializer * ToastUi editor initializer
* *
* This script transforms form textareas created with * This script transforms form textareas created with
* "MarkdownFormBuilder" into ToastUi markdown editors. * "MarkdownFormBuilder" into ToastUi markdown editors.
* *
*/ */
@ -25,7 +25,7 @@ const initializeMarkdownEditors = () => {
target: "_blank", target: "_blank",
}, },
previewHighlight: false, previewHighlight: false,
height: "400px", height: "300px",
autofocus: false, autofocus: false,
usageStatistics: false, usageStatistics: false,
language: I18n.locale, language: I18n.locale,
@ -45,6 +45,8 @@ const initializeMarkdownEditors = () => {
}, },
}); });
setResizeBtn(formInput, toastEditor);
// Prevent user from drag'n'dropping images in the editor // Prevent user from drag'n'dropping images in the editor
toastEditor.removeHook("addImageBlobHook"); toastEditor.removeHook("addImageBlobHook");
@ -82,6 +84,48 @@ const setMarkdownEditorTheme = (theme) => {
}); });
}; };
const hasScrollBar = (el) => el.scrollHeight > el.clientHeight;
const toggleScrollbarModifier = (btn, el) => {
if (el.clientHeight === 0) return;
btn.classList.toggle(
"markdown-editor__resize-btn--with-scrollbar",
hasScrollBar(el)
);
};
const setResizeBtn = (formInput, editor) => {
const resizeBtn = document.querySelector(`#${formInput.id}-resize`);
if (!resizeBtn) return;
const editorTextArea = editor
.getEditorElements()
.mdEditor.querySelector('[contenteditable="true"]');
toggleScrollbarModifier(resizeBtn, editorTextArea);
new MutationObserver(() => {
toggleScrollbarModifier(resizeBtn, editorTextArea);
}).observe(editorTextArea, {
attributes: true,
});
resizeBtn.addEventListener("click", () => {
const height = editor.getHeight();
if (height && height === "300px") {
editor.setHeight("auto");
editor.setMinHeight("400px");
resizeBtn.classList.add("markdown-editor__resize-btn--collapse");
resizeBtn.title = I18n.t("markdown_editor.collapse");
resizeBtn.ariaLabel = I18n.t("markdown_editor.collapse");
} else {
editor.setHeight("300px");
editor.setMinHeight("300px");
resizeBtn.classList.remove("markdown-editor__resize-btn--collapse");
resizeBtn.title = I18n.t("markdown_editor.expand");
resizeBtn.ariaLabel = I18n.t("markdown_editor.expand");
}
});
};
$(document).on("turbolinks:load", function () { $(document).on("turbolinks:load", function () {
initializeMarkdownEditors(); initializeMarkdownEditors();
disableImageUpload(); disableImageUpload();

View File

@ -8,7 +8,7 @@ class MarkdownFormBuilder < ActionView::Helpers::FormBuilder
@template.capture do @template.capture do
@template.concat form_textarea @template.concat form_textarea
@template.concat @template.tag.div(class: 'markdown-editor', data: {behavior: 'markdown-editor-widget', id: label_target}) @template.concat toast_ui_editor
end end
end end
@ -21,6 +21,18 @@ class MarkdownFormBuilder < ActionView::Helpers::FormBuilder
class: 'd-none' class: 'd-none'
end end
def toast_ui_editor
@template.tag.div(class: 'markdown-editor__wrapper') do
@template.concat @template.tag.div(class: 'markdown-editor', data: {behavior: 'markdown-editor-widget', id: label_target})
@template.concat resize_btn
end
end
def resize_btn
@template.tag.button(class: 'markdown-editor__resize-btn fa-solid', type: 'button', id: "#{label_target}-resize",
title: I18n.t(:'markdown_editor.expand'), aria_label: I18n.t(:'markdown_editor.expand'))
end
def base_id def base_id
options[:markdown_id_suffix] || @attribute_name options[:markdown_id_suffix] || @attribute_name
end end

View File

@ -5,6 +5,36 @@
* { * {
box-sizing: content-box; box-sizing: content-box;
} }
&__wrapper {
position: relative;
}
&__resize-btn {
box-sizing: border-box;
position: absolute;
bottom: 30px;
right: 0;
background: transparent;
border: 1px solid transparent;
color: var(--bs-secondary-text-emphasis);
z-index: 100;
&::after {
content: "\f065";
}
&--with-scrollbar {
right: 18px;
}
&--collapse {
right: 0;
&::after {
content: "\f066";
}
}
&:hover {
background: var(--bs-secondary-bg);
}
}
} }
// /*------------------------------------*\ // /*------------------------------------*\

View File

@ -835,6 +835,9 @@ de:
<br> <br>
This mail was automatically sent by CodeOcean. <br> This mail was automatically sent by CodeOcean. <br>
subject: "Eine Aufgabe auf CodeOcean benötigt Ihr Feedback" subject: "Eine Aufgabe auf CodeOcean benötigt Ihr Feedback"
markdown_editor:
expand: Editor aufklappen
collapse: Editor zuklappen
request_for_comments: request_for_comments:
click_here: Zum Kommentieren auf die Seitenleiste klicken! click_here: Zum Kommentieren auf die Seitenleiste klicken!
comments: Kommentare comments: Kommentare

View File

@ -835,6 +835,9 @@ en:
<br> <br>
This mail was automatically sent by CodeOcean. <br> This mail was automatically sent by CodeOcean. <br>
subject: "An exercise on CodeOcean needs your feedback" subject: "An exercise on CodeOcean needs your feedback"
markdown_editor:
expand: Expand editor
collapse: Collapse editor
request_for_comments: request_for_comments:
click_here: Click on this sidebar to comment! click_here: Click on this sidebar to comment!
comments: Comments comments: Comments