diff --git a/app/javascript/editor/editor.ts b/app/javascript/editor/editor.ts index b9e1e9f..be1180f 100644 --- a/app/javascript/editor/editor.ts +++ b/app/javascript/editor/editor.ts @@ -1,5 +1,5 @@ import { storeContent, restoreContent, forgetContent } from 'editor/storage' -import { isDirectChild, moveChildren, safeGetSelection, safeGetRangeAt, setAuxiliaryToolbar, parentBlockNames } from 'editor/utils' +import { isDirectChild, moveChildren, safeGetSelection, safeGetRangeAt, setAuxiliaryToolbar, parentBlockNames, clearSelected } from 'editor/utils' import { types, getValidChildren, getType } from 'editor/types' import { setupButtons as setupMarksButtons } from 'editor/types/marks' import { setupButtons as setupBlocksButtons } from 'editor/types/blocks' @@ -252,8 +252,7 @@ function setupEditor (editorEl: HTMLElement): void { const type = getType(target) if (!type || !type.type.onClick) { setAuxiliaryToolbar(editor, null) - const selectedEl = editor.contentEl.querySelector('[data-editor-selected]') - if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected + clearSelected(editor) return true } type.type.onClick(editor, target) diff --git a/app/javascript/editor/types.ts b/app/javascript/editor/types.ts index 3a178ee..3c215a8 100644 --- a/app/javascript/editor/types.ts +++ b/app/javascript/editor/types.ts @@ -20,6 +20,10 @@ export interface EditorNode { // ej: ul: { handleNothing: li } handleEmpty: 'do-nothing' | 'remove' | EditorBlock, + // esta función puede ser llamada para cosas que no necesariamente sea la + // creación del nodo con el botón; por ejemplo, al intentar recuperar + // el formato. esto es importante por que, por ejemplo, no deberíamos + // cambiar la selección acá. create: (editor: Editor) => HTMLElement, onClick?: (editor: Editor, target: Element) => void, diff --git a/app/javascript/editor/types/blocks.ts b/app/javascript/editor/types/blocks.ts index eb57b55..28f6384 100644 --- a/app/javascript/editor/types/blocks.ts +++ b/app/javascript/editor/types/blocks.ts @@ -79,6 +79,7 @@ export function setupButtons (editor: Editor): void { : type const el = replacementType.create(editor) + replacementType.onClick && replacementType.onClick(editor, el) moveChildren(blockEl, el, null) parentEl.replaceChild(el, blockEl) sel.collapse(el) diff --git a/app/javascript/editor/types/link.ts b/app/javascript/editor/types/link.ts index 1ec0217..40a26e1 100644 --- a/app/javascript/editor/types/link.ts +++ b/app/javascript/editor/types/link.ts @@ -1,6 +1,13 @@ import { Editor } from 'editor/editor' import { EditorNode } from 'editor/types' -import { markNames, setAuxiliaryToolbar } from 'editor/utils' +import { markNames, setAuxiliaryToolbar, clearSelected } from 'editor/utils' + +function select (editor: Editor, el: HTMLAnchorElement): void { + clearSelected(editor) + el.dataset.editorSelected = '' + editor.toolbar.auxiliary.link.urlEl.value = el.href + setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.link.parentEl) +} export const link: EditorNode = { selector: 'a', @@ -10,9 +17,7 @@ export const link: EditorNode = { onClick (editor, el) { if (!(el instanceof HTMLAnchorElement)) throw new Error('oh no') - el.dataset.editorSelected = '' - editor.toolbar.auxiliary.link.urlEl.value = el.href - setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.link.parentEl) + select(editor, el) }, } diff --git a/app/javascript/editor/types/mark.ts b/app/javascript/editor/types/mark.ts index a4be4c4..1e63e36 100644 --- a/app/javascript/editor/types/mark.ts +++ b/app/javascript/editor/types/mark.ts @@ -1,6 +1,6 @@ import { Editor } from 'editor/editor' import { EditorNode } from 'editor/types' -import { markNames, setAuxiliaryToolbar } from 'editor/utils' +import { markNames, setAuxiliaryToolbar, clearSelected } from 'editor/utils' const hex = (x: string) => ("0" + parseInt(x).toString(16)).slice(-2) // https://stackoverflow.com/a/3627747 @@ -11,6 +11,16 @@ function rgbToHex (rgb: string): string { return "#" + hex(matches[1]) + hex(matches[2]) + hex(matches[3]) } +function select (editor: Editor, el: HTMLElement): void { + clearSelected(editor) + el.dataset.editorSelected = '' + editor.toolbar.auxiliary.mark.colorEl.value + = el.style.backgroundColor + ? rgbToHex(el.style.backgroundColor) + : '#f206f9' + setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.mark.parentEl) +} + export const mark: EditorNode = { selector: 'mark', allowedChildren: [...markNames.filter(n => n !== 'mark'), 'text'], @@ -19,12 +29,7 @@ export const mark: EditorNode = { onClick (editor, el) { if (!(el instanceof HTMLElement)) throw new Error('oh no') - el.dataset.editorSelected = '' - editor.toolbar.auxiliary.mark.colorEl.value - = el.style.backgroundColor - ? rgbToHex(el.style.backgroundColor) - : '#f206f9' - setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.mark.parentEl) + select(editor, el) }, } diff --git a/app/javascript/editor/types/marks.ts b/app/javascript/editor/types/marks.ts index b626b59..ac2493a 100644 --- a/app/javascript/editor/types/marks.ts +++ b/app/javascript/editor/types/marks.ts @@ -4,7 +4,6 @@ import { safeGetSelection, safeGetRangeAt, moveChildren, markNames, - setAuxiliaryToolbar, } from 'editor/utils' import { link } from 'editor/types/link' import { mark } from 'editor/types/mark' @@ -82,6 +81,7 @@ export function setupButtons (editor: Editor): void { return console.error("No puedo marcar cosas a través de distintos bloques!") const tagEl = type.create(editor) + type.onClick && type.onClick(editor, tagEl) tagEl.appendChild(range.extractContents()) diff --git a/app/javascript/editor/types/multimedia.ts b/app/javascript/editor/types/multimedia.ts index 16bf696..7fdc0ca 100644 --- a/app/javascript/editor/types/multimedia.ts +++ b/app/javascript/editor/types/multimedia.ts @@ -3,7 +3,7 @@ import { EditorNode, getType } from 'editor/types' import { safeGetSelection, safeGetRangeAt, markNames, parentBlockNames, - setAuxiliaryToolbar, + setAuxiliaryToolbar, clearSelected, } from 'editor/utils' // TODO: tener ActiveStorage como import así no hacemos hacks @@ -59,6 +59,18 @@ function setAlt (multimediaInnerEl: HTMLElement, value: string): void { } } +function select (editor: Editor, el: HTMLElement): void { + clearSelected(editor) + el.dataset.editorSelected = '' + + const innerEl = el.querySelector('[data-multimedia-inner]') + if (!innerEl) throw new Error('No hay multimedia válida') + if (innerEl.tagName !== 'P') + editor.toolbar.auxiliary.multimedia.altEl.value = getAlt(innerEl) || '' + + setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.multimedia.parentEl) +} + export const multimedia: EditorNode = { selector: 'figure[data-multimedia]', allowedChildren: 'ignore-children', @@ -85,14 +97,7 @@ export const multimedia: EditorNode = { onClick (editor, el) { if (!(el instanceof HTMLElement)) throw new Error('oh no') - el.dataset.editorSelected = '' - - const innerEl = el.querySelector('[data-multimedia-inner]') - if (!innerEl) throw new Error('No hay multimedia válida') - if (innerEl.tagName !== 'P') - editor.toolbar.auxiliary.multimedia.altEl.value = getAlt(innerEl) || '' - - setAuxiliaryToolbar(editor, editor.toolbar.auxiliary.multimedia.parentEl) + select(editor, el) }, } function createElementWithFile (url: string, type: string): HTMLElement { @@ -213,6 +218,7 @@ export function setupButtons (editor: Editor): void { if (!parentEl) throw new Error('Inesperado') const el = multimedia.create(editor) + multimedia.onClick!(editor, el) parentEl.insertBefore(el, blockEl.nextElementSibling) return false diff --git a/app/javascript/editor/utils.ts b/app/javascript/editor/utils.ts index fc9e087..fd3b082 100644 --- a/app/javascript/editor/utils.ts +++ b/app/javascript/editor/utils.ts @@ -71,3 +71,7 @@ export function setAuxiliaryToolbar (editor: Editor, bar: HTMLElement | null): v } if (bar) bar.dataset.editorAuxiliaryActive = 'active' } +export function clearSelected (editor: Editor): void { + const selectedEl = editor.contentEl.querySelector('[data-editor-selected]') + if (selectedEl) delete (selectedEl as HTMLElement).dataset.editorSelected +}