script comandos javascript html5 javascript-events execcommand

comandos - Truco de Javascript para ''pegar como texto sin formato'' en execCommand



comandos de java script (9)

Tengo un editor básico basado en execCommand siguiendo la muestra presentada aquí. Hay tres formas de pegar texto dentro del área de execCommand :

  • Ctrl + V
  • Haga clic derecho -> Pegar
  • Haga clic derecho -> Pegar como texto sin formato

Quiero permitir pegar solo texto sin ningún tipo de marcado HTML. ¿Cómo puedo forzar las dos primeras acciones para pegar texto sin formato?

Solución posible: la forma en que se me ocurre es configurar oyente para eventos de teclado para (Ctrl + V) y quitar etiquetas HTML antes de pegar.

  1. ¿Es la mejor solución?
  2. ¿Es a prueba de balas para evitar que cualquier makup HTML pegado?
  3. ¿Cómo agregar oyente a Click derecho -> Pegar?

En IE11, execCommand no funciona bien. Utilizo el siguiente código para IE11 <div class="wmd-input" id="wmd-input-md" contenteditable=true> es mi cuadro div.

Leo datos del portapapeles de window.clipboardData y modif textContent y doy cursivo.

Doy un tiempo de espera para configurar el cursor, porque si no establezco el tiempo de espera, un símbolo de intercalación va al final de div.

y deberías leer clipboardData en IE11 de la siguiente manera. Si no lo haces, el carácter de nueva línea no se maneja correctamente, por lo que el símbolo de intercalación falla.

var tempDiv = document.createElement("div"); tempDiv.textContent = window.clipboardData.getData("text"); var text = tempDiv.textContent;

Probado en IE11 y Chrome. Es posible que no funcione en IE9

document.getElementById("wmd-input-md").addEventListener("paste", function (e) { if (!e.clipboardData) { //For IE11 e.preventDefault(); e.stopPropagation(); var tempDiv = document.createElement("div"); tempDiv.textContent = window.clipboardData.getData("text"); var text = tempDiv.textContent; var selection = document.getSelection(); var start = selection.anchorOffset > selection.focusOffset ? selection.focusOffset : selection.anchorOffset; var end = selection.anchorOffset > selection.focusOffset ? selection.anchorOffset : selection.focusOffset; selection.removeAllRanges(); setTimeout(function () { $(".wmd-input").text($(".wmd-input").text().substring(0, start) + text + $(".wmd-input").text().substring(end)); var range = document.createRange(); range.setStart(document.getElementsByClassName("wmd-input")[0].firstChild, start + text.length); range.setEnd(document.getElementsByClassName("wmd-input")[0].firstChild, start + text.length); selection.addRange(range); }, 1); } else { //For Chrome e.preventDefault(); var text = e.clipboardData.getData("text"); var selection = document.getSelection(); var start = selection.anchorOffset > selection.focusOffset ? selection.focusOffset : selection.anchorOffset; var end = selection.anchorOffset > selection.focusOffset ? selection.anchorOffset : selection.focusOffset; $(this).text($(this).text().substring(0, start) + text + $(this).text().substring(end)); var range = document.createRange(); range.setStart($(this)[0].firstChild, start + text.length); range.setEnd($(this)[0].firstChild, start + text.length); selection.removeAllRanges(); selection.addRange(range); } }, false);


Firefox no te permite acceder a los datos del portapapeles, por lo que tendrás que hacer un "truco" para que funcione. No he podido encontrar una solución completa, sin embargo, puedes arreglarla para ctrl + v pastas creando un área de texto y pegando a eso en su lugar:

//Test if browser has the clipboard object if (!window.Clipboard) { /*Create a text area element to hold your pasted text Textarea is a good choice as it will make anything added to it in to plain text*/ var paster = document.createElement("textarea"); //Hide the textarea paster.style.display = "none"; document.body.appendChild(paster); //Add a new keydown event tou your editor editor.addEventListener("keydown", function(e){ function handlePaste() { //Get the text from the textarea var pastedText = paster.value; //Move the cursor back to the editor editor.focus(); //Check that there is a value. FF throws an error for insertHTML with an empty string if (pastedText !== "") document.execCommand("insertHTML", false, pastedText); //Reset the textarea paster.value = ""; } if (e.which === 86 && e.ctrlKey) { //ctrl+v => paste //Set the focus on your textarea paster.focus(); //We need to wait a bit, otherwise FF will still try to paste in the editor => settimeout window.setTimeout(handlePaste, 1); } }, false); } else //Pretty much the answer given by pimvdb above { //Add listener for paster to force paste-as-plain-text editor.addEventListener("paste", function(e){ //Get the plain text from the clipboard var plain = (!!e.clipboardData)? e.clipboardData.getData("text/plain") : window.clipboardData.getData("Text"); //Stop default paste action e.preventDefault(); //Paste plain text document.execCommand("insertHTML", false, plain); }, false); }


Intercepte el evento de paste , cancele el pegado e inserte manualmente la representación de texto del portapapeles: http://jsfiddle.net/HBEzc/ . Este debería ser el más confiable:

  • Captura todo tipo de pegar (Ctrl + V, menú contextual, etc.)
  • Te permite obtener los datos del portapapeles directamente como texto, para que no tengas que hacer feos hacks para reemplazar HTML.

Sin embargo, no estoy seguro del soporte para navegadores cruzados.

editor.addEventListener("paste", function(e) { // cancel paste e.preventDefault(); // get text representation of clipboard var text = e.clipboardData.getData("text/plain"); // insert text manually document.execCommand("insertHTML", false, text); });


Ninguna de las respuestas publicadas parece funcionar de manera cruzada o la solución es demasiado complicada:

  • El comando insertText no es compatible con IE
  • El uso del comando paste genera un error de desbordamiento de pila en IE11

Lo que funcionó para mí (IE11, Edge, Chrome y FF) es el siguiente:

$("div[contenteditable=true]").off(''paste'').on(''paste'', function(e) { e.preventDefault(); var text = e.originalEvent.clipboardData ? e.originalEvent.clipboardData.getData(''text/plain'') : window.clipboardData.getData(''Text''); _insertText(text); }); function _insertText(text) { // use insertText command if supported if (document.queryCommandSupported(''insertText'')) { document.execCommand(''insertText'', false, text); } // or insert the text content at the caret''s current position // replacing eventually selected content else { var range = document.getSelection().getRangeAt(0); range.deleteContents(); var textNode = document.createTextNode(text); range.insertNode(textNode); range.selectNodeContents(textNode); range.collapse(false); var selection = window.getSelection(); selection.removeAllRanges(); selection.addRange(range); } };

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <body> <textarea name="t1"></textarea> <div style="border: 1px solid;" contenteditable="true">Edit me!</div> <input /> </body>

Tenga en cuenta que el controlador de pegado personalizado solo es necesario / funciona para los nodos contenteditable . Sin embargo, tanto textarea como input campos de input simple no admiten pegar contenido HTML en absoluto, por lo que no es necesario hacer nada aquí.


No pude obtener la respuesta aceptada aquí para trabajar en IE, así que hice un poco de exploración y llegué a esta respuesta que funciona en IE11 y las últimas versiones de Chrome y Firefox.

$(''[contenteditable]'').on(''paste'', function(e) { e.preventDefault(); var text = ''''; if (e.clipboardData || e.originalEvent.clipboardData) { text = (e.originalEvent || e).clipboardData.getData(''text/plain''); } else if (window.clipboardData) { text = window.clipboardData.getData(''Text''); } if (document.queryCommandSupported(''insertText'')) { document.execCommand(''insertText'', false, text); } else { document.execCommand(''paste'', false, text); } });


Por supuesto, la pregunta ya está respondida y el tema es muy antiguo, pero quiero brindarle mi solución, ya que es simple y está limpio:

Esto está dentro de mi evento de pegar en mi contenteditable-div.

var text = ''''; var that = $(this); if (e.clipboardData) text = e.clipboardData.getData(''text/plain''); else if (window.clipboardData) text = window.clipboardData.getData(''Text''); else if (e.originalEvent.clipboardData) text = $(''<div></div>'').text(e.originalEvent.clipboardData.getData(''text'')); if (document.queryCommandSupported(''insertText'')) { document.execCommand(''insertHTML'', false, $(text).html()); return false; } else { // IE > 7 that.find(''*'').each(function () { $(this).addClass(''within''); }); setTimeout(function () { // nochmal alle durchlaufen that.find(''*'').each(function () { // wenn das element keine klasse ''within'' hat, dann unwrap // http://api.jquery.com/unwrap/ $(this).not(''.within'').contents().unwrap(); }); }, 1); }

La parte else es de otra publicación SO que ya no pude encontrar ...

ACTUALIZACIÓN 19.11.2014: La otra publicación SO


También estaba trabajando en un texto sin formato y comencé a odiar todos los errores de execCommand y getData, así que decidí hacerlo de la manera clásica y funciona como un encanto:

$(''#editor'').bind(''paste'', function(){ var before = document.getElementById(''editor'').innerHTML; setTimeout(function(){ var after = document.getElementById(''editor'').innerHTML; var pos1 = -1; var pos2 = -1; for (var i=0; i<after.length; i++) { if (pos1 == -1 && before.substr(i, 1) != after.substr(i, 1)) pos1 = i; if (pos2 == -1 && before.substr(before.length-i-1, 1) != after.substr(after.length-i-1, 1)) pos2 = i; } var pasted = after.substr(pos1, after.length-pos2-pos1); var replace = pasted.replace(/<[^>]+>/g, ''''); var replaced = after.substr(0, pos1)+replace+after.substr(pos1+pasted.length); document.getElementById(''editor'').innerHTML = replaced; }, 100); });

El código con mis anotaciones se puede encontrar aquí: http://www.albertmartin.de/blog/code.php/20/plain-text-paste-with-javascript


Una solución cercana como pimvdb. Pero funciona de FF, Chrome e IE 9:

editor.addEventListener("paste", function(e) { e.preventDefault(); if (e.clipboardData) { content = (e.originalEvent || e).clipboardData.getData(''text/plain''); document.execCommand(''insertText'', false, content); } else if (window.clipboardData) { content = window.clipboardData.getData(''Text''); document.selection.createRange().pasteHTML(content); } });


function PasteString() { var editor = document.getElementById("TemplateSubPage"); editor.focus(); // editor.select(); document.execCommand(''Paste''); } function CopyString() { var input = document.getElementById("TemplateSubPage"); input.focus(); // input.select(); document.execCommand(''Copy''); if (document.selection || document.textSelection) { document.selection.empty(); } else if (window.getSelection) { window.getSelection().removeAllRanges(); } }

El código anterior funciona para mí en IE10 e IE11 y ahora también funciona en Chrome y Safari. No probado en Firefox.