jquery - son - Activar evento en nueva línea en contenido editable div.
en html, onblur y onfocus son: (4)
Aquí hay un comienzo para ti. Ni siquiera me molestaría en intentar adivinar diferentes implementaciones de navegador. En su lugar, aplíquelo presionando el foco en un área de texto oculta y luego realice pruebas basadas en una nueva línea (p. Ej., textarea.value.match(//n$/)
).
Eso debería manejar todos los casos de uso, y el resto es simplemente simular el carácter y la selección a través del rango. Hay plugins que existen solo para este propósito.
JavaScript
var contentEditable = document.querySelector(''.content pre''),
textarea = document.querySelector(''.content textarea'');
contentEditable.addEventListener(''click'', function() {
textarea.focus();
contentEditable.classList.add(''pseudo-focus'');
});
textarea.addEventListener(''keyup'', function(e) {
contentEditable.innerText = textarea.value;
if (textarea.value.match(//n$/)) {
alert(''newline'');
}
});
HTML
<div class="content">
<pre id="editable" contenteditable></pre>
<textarea></textarea>
</div>
Ejemplo de JSFiddle
Estoy intentando escuchar un evento que indique que se ha creado una nueva línea en un div editable de contenido. El propósito es, finalmente, mostrarle al usuario algunas opciones cada vez que se crea una nueva línea vacía y el cursor en esa línea, o si el usuario hace clic en la posición del cursor en una línea actualmente vacía.
En mi libro, parece que hay cuatro eventos que llevarían al usuario a estar en una nueva línea dentro de una división de contenidos:
- presionando enter
- pegar contenido que tiene una nueva línea vacía al final
- Al hacer clic, el cursor (línea parpadeante) se mueve a una línea vacía.
- usando las teclas de flecha para moverse a una nueva línea
Por supuesto, en una división contentediable, una nueva línea significa cosas diferentes para diferentes navegadores, en Chrome parece crear <div><br/></div>
, pero después de haber navegado tan cerca, parece que otros navegadores pueden crear <div><p></p></div>
o quizás <span>
etiquetas.
Ahora he tratado de resolver esto un par de veces y solo tengo que hacerlo. ¿Es realmente la mejor manera de escuchar los nuevos elementos que se agregan bajo esa división y / o verificar si la posición de intercalación se encuentra actualmente dentro de etiquetas de ''nueva línea'' vacías? comprobar que cada vez que se mueve el caret parece altamente ineficiente, ¿hay una mejor manera de hacerlo?
Para resumir para tldr; gente
- ¿Hay una mejor manera de verificar si hay nuevas líneas en los divs editables de contenido?
- ¿Cómo dispararía un evento basado en eso de manera eficiente?
Solo si esto está dentro de un contexto Angular y también tengo jQuery (la respuesta puede elegir usar o no usar estas bibliotecas).
----- editar -----
Hasta el momento, las respuestas se han centrado en la creación de nuevos "eventos" de línea y en el seguimiento de esos eventos, tal vez encuestar la posición de intercalación es una forma más confiable de determinar si la intercalación está en una línea vacía o no.
Esto es lo que hice:
$("#main").keyup(function (e) {
if (e.which == 13) {
doSomething();
}
});
$("#main").on("click", "div:has(br)", function () {
doSomething();
});
$("#main").on("paste", function () {
setTimeout(function () {
debugger;
if ($(''#main'').children().last().children().last().has(''br'').length >0) {
doSomething();
}
}, 100);
});
function doSomething(){
alert("new line...");
}
He probado este código en Chrome y Edge. Edge eliminó la línea vacía cuando copié y pegué desde el bloc de notas.
http://codepen.io/tzach/pen/XbGWjZ?editors=101
angular
.module(''app'', [])
.directive(''contenteditable'', function ($timeout) {
return {
link: function($scope, element, attrs) {
element.css(''white-space'', ''pre'');
element.on(''keypress'', function (e) {
if (e.keyCode === 13) {
$timeout(function () {
onNewLine();
}, 100);
}
});
element.on(''paste'', function (e) {
$timeout(function () {
var text = element.text();
var textRows = text.split(''/n'');
var html = element.html();
var htmlRows = html.split(''<br>'');
if (textRows[textRows.length - 1].trim() == '''' ||
htmlRows[htmlRows.length - 1].trim() == '''') {
onNewLine();
}
},0);
});
element.on(''click'', function(e) {
var html = e.target.innerHTML;
var text = e.target.innerText;
if (text === ''/n'' || html.toLowerCase() === ''<br>'') {
onNewLine();
}
});
function onNewLine() {
alert(''new empty line'');
}
}
}
});
Las otras respuestas hasta ahora discutidas sobre el monitoreo de eventos que crean una nueva línea dentro de un div editable de contenido. Sin embargo, por los esfuerzos realizados hasta ahora, parece que esta no es una forma confiable de monitorear si el usuario ha llevado el caret a una nueva línea.
A pesar de las preocupaciones de que tener un evento setInterval sea un poco pesado y se sume a la sobrecarga, tal vez esta sea solo mi percepción. He probado lo siguiente en Firefox y Chrome en OSX.
function getNewLines() {
console.log(document.getSelection());
if (document.getSelection().anchorNode) {
var node = document.getSelection().anchorNode;
var nodeContents = "";
if (node.innerHTML) {
nodeContents = node.innerHTML.toLowerCase();
} else {
nodeContents = node.innerHTML;
}
if (nodeContents !== undefined) {
if (nodeContents === "" || nodeContents == "<br>" || nodeContents ==
"<br/>" || nodeContents.substr(nodeContents.length - 5) == "<br/>" ||
nodeContents.substr(nodeContents.length - 4) == "<br>") {
console.log("you are on a new line :]");
} else {
console.log(''nope not a new line'');
}
} else {
console.log(''nice try, but no not a new line'');
}
}
}
setInterval(getNewLines, 100);
<div contenteditable="true">
<p>Lets get started!</p>
</div>
nota al margen: el comportamiento de las nuevas líneas en el contenido editable parece variado, pero en Firefox noté que imitará los elementos existentes en el campo. es decir, si está utilizando <div></div>
, firefox usará <div></div>
, si está utilizando <p></p>
firefox hará lo mismo