diff options
author | KN4CK3R <KN4CK3R@users.noreply.github.com> | 2021-05-23 16:14:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-23 17:14:03 +0300 |
commit | 6021fbfe7a4e73c209eeea514a929fcb5598d63e (patch) | |
tree | 0058ceeaa2df9d20655aae7ad78c82f3e0f7623e /web_src/js/markup | |
parent | b4d10598c9be1ba8008c5a47ef1cd3612e99331a (diff) | |
download | gitea-6021fbfe7a4e73c209eeea514a929fcb5598d63e.tar.gz gitea-6021fbfe7a4e73c209eeea514a929fcb5598d63e.zip |
Make tasklist checkboxes clickable (#15791)
Co-authored-by: silverwind <me@silverwind.io>
Co-authored-by: Lauris BH <lauris@nix.lv>
Diffstat (limited to 'web_src/js/markup')
-rw-r--r-- | web_src/js/markup/content.js | 9 | ||||
-rw-r--r-- | web_src/js/markup/tasklist.js | 62 |
2 files changed, 70 insertions, 1 deletions
diff --git a/web_src/js/markup/content.js b/web_src/js/markup/content.js index f06c9908f2..19b749aaab 100644 --- a/web_src/js/markup/content.js +++ b/web_src/js/markup/content.js @@ -1,5 +1,12 @@ import {renderMermaid} from './mermaid.js'; +import {initMarkupTasklist} from './tasklist.js'; -export async function renderMarkupContent() { +// code that runs for all markup content +export async function initMarkupContent() { await renderMermaid(document.querySelectorAll('code.language-mermaid')); } + +// code that only runs for comments +export function initCommentContent() { + initMarkupTasklist(); +} diff --git a/web_src/js/markup/tasklist.js b/web_src/js/markup/tasklist.js new file mode 100644 index 0000000000..5a7291b4d0 --- /dev/null +++ b/web_src/js/markup/tasklist.js @@ -0,0 +1,62 @@ +/** + * Attaches `input` handlers to markdown rendered tasklist checkboxes in comments. + * + * When a checkbox value changes, the corresponding [ ] or [x] in the markdown string + * is set accordingly and sent to the server. On success it updates the raw-content on + * error it resets the checkbox to its original value. + */ + +const preventListener = (e) => e.preventDefault(); + +export function initMarkupTasklist() { + for (const el of document.querySelectorAll(`.markup[data-can-edit=true]`) || []) { + const container = el.parentNode; + const checkboxes = el.querySelectorAll(`.task-list-item input[type=checkbox]`); + + for (const checkbox of checkboxes) { + if (checkbox.dataset.editable) return; + checkbox.dataset.editable = 'true'; + checkbox.addEventListener('input', async () => { + const checkboxCharacter = checkbox.checked ? 'x' : ' '; + const position = parseInt(checkbox.dataset.sourcePosition) + 1; + + const rawContent = container.querySelector('.raw-content'); + const oldContent = rawContent.textContent; + const newContent = oldContent.substring(0, position) + checkboxCharacter + oldContent.substring(position + 1); + if (newContent === oldContent) return; + + // Prevent further inputs until the request is done. This does not use the + // `disabled` attribute because it causes the border to flash on click. + for (const checkbox of checkboxes) { + checkbox.addEventListener('click', preventListener); + } + + try { + const editContentZone = container.querySelector('.edit-content-zone'); + const {updateUrl, context} = editContentZone.dataset; + + await $.post(updateUrl, { + _csrf: window.config.csrf, + content: newContent, + context, + }); + + rawContent.textContent = newContent; + } catch (err) { + checkbox.checked = !checkbox.checked; + console.error(err); + } + + // Enable input on checkboxes again + for (const checkbox of checkboxes) { + checkbox.removeEventListener('click', preventListener); + } + }); + } + + // Enable the checkboxes as they are initially disabled by the markdown renderer + for (const checkbox of checkboxes) { + checkbox.disabled = false; + } + } +} |