toolbar auxiliar
This commit is contained in:
parent
5f8c368541
commit
ef66f6ad5a
4 changed files with 100 additions and 43 deletions
|
@ -1,3 +1,15 @@
|
|||
function setAuxiliaryToolbar (editorEl, toolbarName) {
|
||||
const toolbarEl = editorEl.querySelector(`*[data-editor-auxiliary-toolbar]`)
|
||||
for (const otherEl of toolbarEl.childNodes) {
|
||||
if (otherEl.nodeType !== Node.ELEMENT_NODE) continue
|
||||
otherEl.classList.remove("editor-auxiliary-tool-active")
|
||||
}
|
||||
if (toolbarName) {
|
||||
const auxEl = editorEl.querySelector(`*[data-editor-auxiliary="${toolbarName}"]`)
|
||||
auxEl.classList.add("editor-auxiliary-tool-active")
|
||||
}
|
||||
}
|
||||
|
||||
const marks = {
|
||||
bold: {
|
||||
selector: "strong",
|
||||
|
@ -146,6 +158,8 @@ const typesWithProperties = {
|
|||
mark: {
|
||||
selector: marks.mark.selector,
|
||||
updateInput (el, editorEl) {
|
||||
setAuxiliaryToolbar(editorEl, "mark")
|
||||
|
||||
const markColorInputEl = editorEl.querySelector(`*[data-prop="mark-color"]`)
|
||||
markColorInputEl.disabled = false
|
||||
markColorInputEl.value = el.style.backgroundColor ? rgb2hex(el.style.backgroundColor) : "#f206f9"
|
||||
|
@ -166,6 +180,8 @@ const typesWithProperties = {
|
|||
img: {
|
||||
selector: blocks.img.selector,
|
||||
updateInput (el, editorEl) {
|
||||
setAuxiliaryToolbar(editorEl, "img")
|
||||
|
||||
const imgFileEl = editorEl.querySelector(`*[data-prop="img-file"]`)
|
||||
imgFileEl.disabled = false
|
||||
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
|
||||
|
@ -217,6 +233,8 @@ const typesWithProperties = {
|
|||
audio: {
|
||||
selector: blocks.audio.selector,
|
||||
updateInput (el, editorEl) {
|
||||
setAuxiliaryToolbar(editorEl, "audio")
|
||||
|
||||
const audioFileEl = editorEl.querySelector(`*[data-prop="audio-file"]`)
|
||||
audioFileEl.disabled = false
|
||||
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
|
||||
|
@ -254,6 +272,8 @@ const typesWithProperties = {
|
|||
video: {
|
||||
selector: blocks.video.selector,
|
||||
updateInput (el, editorEl) {
|
||||
setAuxiliaryToolbar(editorEl, "video")
|
||||
|
||||
const videoFileEl = editorEl.querySelector(`*[data-prop="video-file"]`)
|
||||
videoFileEl.disabled = false
|
||||
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
|
||||
|
@ -291,6 +311,8 @@ const typesWithProperties = {
|
|||
pdf: {
|
||||
selector: blocks.pdf.selector,
|
||||
updateInput (el, editorEl) {
|
||||
setAuxiliaryToolbar(editorEl, "pdf")
|
||||
|
||||
const pdfFileEl = editorEl.querySelector(`*[data-prop="pdf-file"]`)
|
||||
pdfFileEl.disabled = false
|
||||
// XXX: No se puede cambiar el texto, ¡esto puede ser confuso!
|
||||
|
|
|
@ -346,6 +346,11 @@ function setupEditor (editorEl) {
|
|||
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")
|
||||
|
@ -354,8 +359,7 @@ function setupEditor (editorEl) {
|
|||
el.classList.remove("selected-unactive")
|
||||
}
|
||||
|
||||
let parentEl = range.commonAncestorContainer
|
||||
if (parentEl.nodeType !== Node.ELEMENT_TYPE) parentEl = parentEl.parentElement
|
||||
setAuxiliaryToolbar(editorEl)
|
||||
|
||||
for (const [name, type] of Object.entries(typesWithProperties)) {
|
||||
let i = 0
|
||||
|
@ -420,6 +424,12 @@ function setupEditor (editorEl) {
|
|||
type.setupInput(editorEl, contentEl)
|
||||
}
|
||||
|
||||
document.addEventListener(editorBtn("mark"), () => setAuxiliaryToolbar(editorEl, "mark"))
|
||||
document.addEventListener(editorBtn("img"), () => setAuxiliaryToolbar(editorEl, "img"))
|
||||
document.addEventListener(editorBtn("audio"), () => setAuxiliaryToolbar(editorEl, "audio"))
|
||||
document.addEventListener(editorBtn("video"), () => setAuxiliaryToolbar(editorEl, "video"))
|
||||
document.addEventListener(editorBtn("pdf"), () => setAuxiliaryToolbar(editorEl, "pdf"))
|
||||
|
||||
cleanContent(contentEl)
|
||||
htmlEl.value = contentEl.innerHTML
|
||||
}
|
||||
|
|
|
@ -23,6 +23,27 @@
|
|||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.editor-toolbar {
|
||||
position: sticky;
|
||||
top: 0px;
|
||||
background: white;
|
||||
}
|
||||
|
||||
.editor-primary-toolbar, .editor-auxiliary-toolbar {
|
||||
display: block;
|
||||
overflow-x: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.editor-auxiliary-toolbar {
|
||||
& > * {
|
||||
display: none;
|
||||
}
|
||||
.editor-auxiliary-tool-active {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
ol, ul { margin: 0; }
|
||||
|
||||
.editor-content {
|
||||
|
|
|
@ -1,52 +1,56 @@
|
|||
= form_with do
|
||||
.editor
|
||||
%button{:data => {:button => "bold"}} Bold
|
||||
%button{:data => {:button => "italic"}} Italic
|
||||
%button{:data => {:button => "deleted"}} Deleted
|
||||
%button{:data => {:button => "underline"}} Underline
|
||||
%button{:data => {:button => "mark"}} Mark
|
||||
%button{:data => {:button => "h1"}} H1
|
||||
%button{:data => {:button => "h2"}} H2
|
||||
%button{:data => {:button => "h3"}} H3
|
||||
%button{:data => {:button => "h4"}} H4
|
||||
%button{:data => {:button => "h5"}} H5
|
||||
%button{:data => {:button => "h6"}} H6
|
||||
%button{:data => {:button => "ul"}} Lista desordenada
|
||||
%button{:data => {:button => "ol"}} Lista ordenada
|
||||
%button{:data => {:button => "left"}} Left
|
||||
%button{:data => {:button => "center"}} Center
|
||||
%button{:data => {:button => "right"}} Right
|
||||
%br/
|
||||
// TODO: generar IDs para labels
|
||||
.editor-toolbar
|
||||
.editor-primary-toolbar
|
||||
%button.btn{:data => {:button => "bold"}} Bold
|
||||
%button.btn{:data => {:button => "italic"}} Italic
|
||||
%button.btn{:data => {:button => "deleted"}} Deleted
|
||||
%button.btn{:data => {:button => "underline"}} Underline
|
||||
%button.btn{:data => {:button => "mark"}} Subrayar
|
||||
%button.btn{:data => {:button => "h1"}} H1
|
||||
%button.btn{:data => {:button => "h2"}} H2
|
||||
%button.btn{:data => {:button => "h3"}} H3
|
||||
%button.btn{:data => {:button => "h4"}} H4
|
||||
%button.btn{:data => {:button => "h5"}} H5
|
||||
%button.btn{:data => {:button => "h6"}} H6
|
||||
%button.btn{:data => {:button => "ul"}} Lista desordenada
|
||||
%button.btn{:data => {:button => "ol"}} Lista ordenada
|
||||
%button.btn{:data => {:button => "left"}} Left
|
||||
%button.btn{:data => {:button => "center"}} Center
|
||||
%button.btn{:data => {:button => "right"}} Right
|
||||
%button.btn{:data => {:button => "img"}} Imágen
|
||||
%button.btn{:data => {:button => "video"}} Video
|
||||
%button.btn{:data => {:button => "audio"}} Audio
|
||||
%button.btn{:data => {:button => "pdf"}} PDF
|
||||
// TODO: generar IDs para labels
|
||||
|
||||
%label{:for => "mark-color"} Color de resaltado:
|
||||
%input{:type => "color", :data => {:prop => "mark-color"}}/
|
||||
%br/
|
||||
// HAML cringe
|
||||
.editor-auxiliary-toolbar{:data => {:editor => {:auxiliary => {:toolbar => ""}}}}
|
||||
%div{:data => {:editor => {:auxiliary => "mark"}}}
|
||||
%label{:for => "mark-color"} Color de resaltado:
|
||||
%input{:type => "color", :data => {:prop => "mark-color"}}/
|
||||
|
||||
%label{:for => "img-file"} Archivo de la imágen:
|
||||
%input{:type => "file", :data => {:prop => "img-file"}}/
|
||||
%label{:for => "img-alt"} Descripción de imágen:
|
||||
%input{:placeholder => "Un álbum", :type => "text", :data => {:prop => "img-alt"}}/
|
||||
%button{:data => {:button => "img"}} Insertar imágen
|
||||
%br/
|
||||
%div{:data => {:editor => {:auxiliary => "img"}}}
|
||||
%label{:for => "img-file"} Archivo de la imágen:
|
||||
%input{:type => "file", :data => {:prop => "img-file"}}/
|
||||
%label{:for => "img-alt"} Descripción de imágen:
|
||||
%input{:placeholder => "Un álbum", :type => "text", :data => {:prop => "img-alt"}}/
|
||||
|
||||
%label{:for => "audio-file"} Archivo de la audio:
|
||||
%input{:type => "file", :data => {:prop => "audio-file"}}/
|
||||
%button{:data => {:button => "audio"}} Insertar audio
|
||||
%br/
|
||||
%div{:data => {:editor => {:auxiliary => "audio"}}}
|
||||
%label{:for => "audio-file"} Archivo de la audio:
|
||||
%input{:type => "file", :data => {:prop => "audio-file"}}/
|
||||
|
||||
%label{:for => "video-file"} Archivo de la video:
|
||||
%input{:type => "file", :data => {:prop => "video-file"}}/
|
||||
%button{:data => {:button => "video"}} Insertar video
|
||||
%br/
|
||||
%div{:data => {:editor => {:auxiliary => "video"}}}
|
||||
%label{:for => "video-file"} Archivo de la video:
|
||||
%input{:type => "file", :data => {:prop => "video-file"}}/
|
||||
|
||||
%label{:for => "pdf-file"} Archivo de la PDF:
|
||||
%input{:type => "file", :data => {:prop => "pdf-file"}}/
|
||||
%button{:data => {:button => "pdf"}} Insertar PDF
|
||||
%br/
|
||||
%div{:data => {:editor => {:auxiliary => "pdf"}}}
|
||||
%label{:for => "pdf-file"} Archivo de la PDF:
|
||||
%input{:type => "file", :data => {:prop => "pdf-file"}}/
|
||||
|
||||
%label{:for => "link-href"} URL de link:
|
||||
%input{:type => "url", :data => {:prop => "link-href"}}/
|
||||
%div{:data => {:editor => {:auxiliary => "link"}}}
|
||||
%label{:for => "link-href"} URL de link:
|
||||
%input{:type => "url", :data => {:prop => "link-href"}}/
|
||||
|
||||
.editor-content{:contenteditable => "true"}
|
||||
%h1
|
||||
|
|
Loading…
Reference in a new issue