mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-07-27 05:29:41 +02:00
fix(ui): multiple ComboMarkdownEditors on one page interfere (#8417)
When there are multiple combo-markdown-editors, then only the first will get changes from the toolbar buttons. Fixes: #6742 Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8417 Reviewed-by: Beowulf <beowulf@beocode.eu> Co-authored-by: zokki <zokki.softwareschmiede@gmail.com> Co-committed-by: zokki <zokki.softwareschmiede@gmail.com>
This commit is contained in:
parent
81e59014da
commit
1937fcf476
3 changed files with 91 additions and 17 deletions
|
@ -11,8 +11,6 @@ import {initTextExpander} from './TextExpander.js';
|
|||
import {showErrorToast, showHintToast} from '../../modules/toast.js';
|
||||
import {POST} from '../../modules/fetch.js';
|
||||
|
||||
let elementIdCounter = 0;
|
||||
|
||||
/**
|
||||
* validate if the given textarea is non-empty.
|
||||
* @param {HTMLElement} textarea - The textarea element to be validated.
|
||||
|
@ -39,10 +37,13 @@ export function validateTextareaNonEmpty(textarea) {
|
|||
const listPrefixRegex = /^\s*((\d+)[.)]\s|[-*+]\s{1,4}\[[ x]\]\s?|[-*+]\s|(>\s?)+)?/;
|
||||
|
||||
class ComboMarkdownEditor {
|
||||
static idSuffixCounter = 0;
|
||||
|
||||
constructor(container, options = {}) {
|
||||
container._giteaComboMarkdownEditor = this;
|
||||
this.options = options;
|
||||
this.container = container;
|
||||
this.elementIdSuffix = ComboMarkdownEditor.idSuffixCounter++;
|
||||
}
|
||||
|
||||
async init() {
|
||||
|
@ -55,8 +56,6 @@ class ComboMarkdownEditor {
|
|||
this.setupLinkInserter();
|
||||
|
||||
await this.switchToUserPreference();
|
||||
|
||||
elementIdCounter++;
|
||||
}
|
||||
|
||||
applyEditorHeights(el, heights) {
|
||||
|
@ -74,7 +73,7 @@ class ComboMarkdownEditor {
|
|||
setupTextarea() {
|
||||
this.textarea = this.container.querySelector('.markdown-text-editor');
|
||||
this.textarea._giteaComboMarkdownEditor = this;
|
||||
this.textarea.id = `_combo_markdown_editor_${elementIdCounter}`;
|
||||
this.textarea.id = `_combo_markdown_editor_${this.elementIdSuffix}`;
|
||||
this.textarea.addEventListener('input', (e) => this.options?.onContentChanged?.(this, e));
|
||||
this.applyEditorHeights(this.textarea, this.options.editorHeights);
|
||||
|
||||
|
@ -96,8 +95,8 @@ class ComboMarkdownEditor {
|
|||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="unindent"]')?.addEventListener('click', () => {
|
||||
this.indentSelection(true, false);
|
||||
});
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${elementIdCounter}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${elementIdCounter}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-table"]')?.setAttribute('data-modal', `div[data-markdown-table-modal-id="${this.elementIdSuffix}"]`);
|
||||
this.textareaMarkdownToolbar.querySelector('button[data-md-action="new-link"]')?.setAttribute('data-modal', `div[data-markdown-link-modal-id="${this.elementIdSuffix}"]`);
|
||||
|
||||
// Track whether any actual input or pointer action was made after focusing, and only intercept Tab presses after that.
|
||||
this.tabEnabled = false;
|
||||
|
@ -195,7 +194,7 @@ class ComboMarkdownEditor {
|
|||
setupDropzone() {
|
||||
const dropzoneParentContainer = this.container.getAttribute('data-dropzone-parent-container');
|
||||
if (dropzoneParentContainer) {
|
||||
this.dropzone = this.container.closest(this.container.getAttribute('data-dropzone-parent-container'))?.querySelector('.dropzone');
|
||||
this.dropzone = this.container.closest(dropzoneParentContainer)?.querySelector('.dropzone');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,13 +206,13 @@ class ComboMarkdownEditor {
|
|||
// So here it uses our defined "data-tab-for" and "data-tab-panel" to generate the "data-tab" attribute for Fomantic.
|
||||
const tabEditor = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-writer');
|
||||
const tabPreviewer = Array.from(tabs).find((tab) => tab.getAttribute('data-tab-for') === 'markdown-previewer');
|
||||
tabEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
|
||||
tabPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
|
||||
tabEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
|
||||
tabPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
|
||||
const toolbar = $container[0].querySelector('markdown-toolbar');
|
||||
const panelEditor = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-writer"]');
|
||||
const panelPreviewer = $container[0].querySelector('.ui.tab[data-tab-panel="markdown-previewer"]');
|
||||
panelEditor.setAttribute('data-tab', `markdown-writer-${elementIdCounter}`);
|
||||
panelPreviewer.setAttribute('data-tab', `markdown-previewer-${elementIdCounter}`);
|
||||
panelEditor.setAttribute('data-tab', `markdown-writer-${this.elementIdSuffix}`);
|
||||
panelPreviewer.setAttribute('data-tab', `markdown-previewer-${this.elementIdSuffix}`);
|
||||
|
||||
tabEditor.addEventListener('click', () => {
|
||||
toolbar.classList.remove('markdown-toolbar-hidden');
|
||||
|
@ -276,10 +275,10 @@ class ComboMarkdownEditor {
|
|||
|
||||
setupTableInserter() {
|
||||
const newTableModal = this.container.querySelector('div[data-modal-name="new-markdown-table"]');
|
||||
newTableModal.setAttribute('data-markdown-table-modal-id', elementIdCounter);
|
||||
newTableModal.setAttribute('data-markdown-table-modal-id', this.elementIdSuffix);
|
||||
|
||||
const button = newTableModal.querySelector('button[data-selector-name="ok-button"]');
|
||||
button.setAttribute('data-element-id', elementIdCounter);
|
||||
button.setAttribute('data-element-id', this.elementIdSuffix);
|
||||
button.addEventListener('click', this.addNewTable);
|
||||
}
|
||||
|
||||
|
@ -311,8 +310,8 @@ class ComboMarkdownEditor {
|
|||
|
||||
setupLinkInserter() {
|
||||
const newLinkModal = this.container.querySelector('div[data-modal-name="new-markdown-link"]');
|
||||
newLinkModal.setAttribute('data-markdown-link-modal-id', elementIdCounter);
|
||||
const textarea = document.getElementById(`_combo_markdown_editor_${elementIdCounter}`);
|
||||
newLinkModal.setAttribute('data-markdown-link-modal-id', this.elementIdSuffix);
|
||||
const textarea = document.getElementById(`_combo_markdown_editor_${this.elementIdSuffix}`);
|
||||
|
||||
$(newLinkModal).modal({
|
||||
// Pre-fill the description field from the selection to create behavior similar
|
||||
|
@ -331,7 +330,7 @@ class ComboMarkdownEditor {
|
|||
});
|
||||
|
||||
const button = newLinkModal.querySelector('button[data-selector-name="ok-button"]');
|
||||
button.setAttribute('data-element-id', elementIdCounter);
|
||||
button.setAttribute('data-element-id', this.elementIdSuffix);
|
||||
button.addEventListener('click', this.addNewLink);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue