import { Editor } from 'editor/editor' import { safeGetSelection, safeGetRangeAt, moveChildren, blockNames, parentBlockNames, } from 'editor/utils' import { EditorNode, getType } from 'editor/types' function makeParentBlock (tag: string, create: EditorNode["create"]): EditorNode { return { selector: tag, allowedChildren: [...blockNames, 'multimedia'], handleEmpty: 'remove', create, } } // TODO: añadir blockquote // XXX: si agregás algo acá, probablemente le quieras hacer un botón // en app/views/posts/attributes/_content.haml export const parentBlocks: { [propName: string]: EditorNode } = { left: makeParentBlock('div[data-align=left]', () => { const el = document.createElement('div') el.dataset.align = 'left' return el }), center: makeParentBlock('div[data-align=center]', () => { const el = document.createElement('div') el.dataset.align = 'center' return el }), right: makeParentBlock('div[data-align=right]', () => { const el = document.createElement('div') el.dataset.align = 'right' return el }), } export function setupButtons (editor: Editor): void { for (const [ name, type ] of Object.entries(parentBlocks)) { const buttonEl = editor.toolbarEl.querySelector( `[data-editor-button="parentBlock-${name}"]` ) if (!buttonEl) continue buttonEl.addEventListener("click", event => { event.preventDefault() const sel = safeGetSelection(editor) if (!sel) return const range = safeGetRangeAt(sel) if (!range) return // TODO: Esto solo mueve el bloque en el que está el final de la selección // (anchorNode). quizás lo podemos hacer al revés (iterar desde contentEl // para encontrar los bloques que están seleccionados y moverlos/cambiarles // el parentBlock) let blockEl = sel.anchorNode while (true) { if (!blockEl) throw new Error('WTF') if (!blockEl.parentElement) throw new Error('No pude encontrar contentEl!') let type = getType(blockEl.parentElement) if (!type) throw new Error('La selección está en algo que no es un type!') if (type.typeName === 'contentEl' || parentBlockNames.includes(type.typeName) ) break blockEl = blockEl.parentElement } if (!(blockEl instanceof Element)) throw new Error('La selección no está en un elemento!') const parentEl = blockEl.parentElement if (!parentEl) throw new Error('no') const replacementEl = type.create(editor) if (parentEl == editor.contentEl) { // no está en un parentBlock editor.contentEl.insertBefore(replacementEl, blockEl) replacementEl.appendChild(blockEl) } else { // está en un parentBlock moveChildren(parentEl, replacementEl, null) editor.contentEl.replaceChild(replacementEl, parentEl) } sel.collapse(replacementEl) return false }) } }