diff --git a/app/assets/javascripts/01-types.js b/app/assets/javascripts/01-types.js index 62749598..369b650f 100644 --- a/app/assets/javascripts/01-types.js +++ b/app/assets/javascripts/01-types.js @@ -145,13 +145,6 @@ function rgb2hex(rgb) { return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); } -// Encuentra lx primer hijx de `selector` que esté en la selección dentro de `node` -const findInSelection = (selector, node) => { - for (const child of node.querySelectorAll(selector)) { - if (window.getSelection().containsNode(child)) return child - } -} - const getSelected = contentEl => contentEl.querySelector(".selected") const typesWithProperties = { @@ -172,7 +165,7 @@ const typesWithProperties = { setupInput (editorEl, contentEl) { const markColorInputEl = editorEl.querySelector(`*[data-prop="mark-color"]`) markColorInputEl.addEventListener("change", event => { - const markEl = findInSelection(marks.mark.selector, contentEl) + const markEl = contentEl.querySelector(marks.mark.selector + ".selected") if (markEl) markEl.style.backgroundColor = markColorInputEl.value }, false) }, diff --git a/app/assets/javascripts/02-editor.js b/app/assets/javascripts/02-editor.js index 0a839b3f..78938408 100644 --- a/app/assets/javascripts/02-editor.js +++ b/app/assets/javascripts/02-editor.js @@ -324,6 +324,42 @@ function cleanNode (node, contentEl) { } } +/* Generar el clickListener para este editor. + */ +function generateClickListener (editorEl, contentEl) { + /* El event listener para los typesWithProperties. + */ + return function clickListener (event) { + // Borrar todas las selecciones + for (const el of contentEl.querySelectorAll(".selected")) { + el.classList.remove("selected") + } + + setAuxiliaryToolbar(editorEl) + + let selectedType + let selectedEl + + for (const [name, type] of Object.entries(typesWithProperties)) { + type.disableInput(editorEl) + + let el = event.target + while (el && !el.matches(type.selector)) el = el.parentElement + if (el && contentEl.contains(el)) { + selectedType = type + selectedEl = el + } + } + + if (selectedType) { + event.preventDefault() + selectedType.updateInput(selectedEl, editorEl) + event.target.classList.add("selected") + return false + } + } +} + function setupEditor (editorEl) { // XXX: ¡Esto afecta a todo el documento! ¿Quizás usar un iframe para el editor? document.execCommand('defaultParagraphSeparator', false, 'p') @@ -342,46 +378,11 @@ function setupEditor (editorEl) { }) document.addEventListener("selectionchange", event => { cleanContent(contentEl) - - const sel = window.getSelection() - const range = sel.getRangeAt(0) - - let parentEl = range.commonAncestorContainer - if (parentEl.nodeType !== Node.ELEMENT_NODE) parentEl = parentEl.parentElement - - if (!contentEl.contains(parentEl)) return - - // Borrar todas las selecciones - for (const el of contentEl.querySelectorAll(".selected")) { - el.classList.remove("selected") - } - for (const el of contentEl.querySelectorAll(".selected-unactive")) { - el.classList.remove("selected-unactive") - } - - setAuxiliaryToolbar(editorEl) - - for (const [name, type] of Object.entries(typesWithProperties)) { - let i = 0 - const results = parentEl.querySelectorAll(type.selector) - - if (results.length) { - for (const el of results) { - if (!sel.containsNode(el)) continue - if (i === 0) { - type.updateInput(el, editorEl) - el.classList.add("selected") - } else { - el.classList.add("selected-unactive") - } - i++ - } - } else { - type.disableInput(editorEl) - } - } }) + const clickListener = generateClickListener(editorEl, contentEl) + contentEl.addEventListener("click", clickListener, true) + const htmlEl = editorEl.querySelector("textarea") const observer = new MutationObserver((mutationList, observer) => { cleanContent(contentEl) @@ -432,6 +433,7 @@ function setupEditor (editorEl) { cleanContent(contentEl) htmlEl.value = contentEl.innerHTML + fixContent(contentEl) } // TODO: por ahora confiamos, quizás queremos filtrar estilos? diff --git a/app/assets/stylesheets/editor.scss b/app/assets/stylesheets/editor.scss index af7ec76a..dcfa9528 100644 --- a/app/assets/stylesheets/editor.scss +++ b/app/assets/stylesheets/editor.scss @@ -14,7 +14,6 @@ } .selected { outline: #f206f9 solid medium; } - .selected-unactive { outline: gray solid medium; } img, video, iframe, audio { width: 100%;