Trucco Javascript per “incolla come testo normale” in execCommand

Ho un editor di base basato su execCommand segue l’esempio presentato qui. Esistono tre modi per incollare il testo all’interno dell’area execCommand :

  • Ctrl + V
  • Fare clic destro -> Incolla
  • Fare clic destro -> Incolla come testo normale

Voglio consentire di incollare solo testo semplice senza alcun markup HTML. Come posso forzare le prime due azioni per incollare il testo normale?

Soluzione ansible: il modo in cui posso pensare è impostare listener per gli eventi di keyup per ( Ctrl + V ) e rimuovere i tag HTML prima di incollarli.

  1. È la soluzione migliore?
  2. È a prova di proiettile per evitare qualsiasi markup HTML in pasta?
  3. Come aggiungere listener al clic destro -> Incolla?

Intercetterà l’evento paste , annullerà l’ paste e inserirà manualmente la rappresentazione testuale degli Appunti:
http://jsfiddle.net/HBEzc/ . Questo dovrebbe essere il più affidabile:

  • Cattura tutti i tipi di incolla ( Ctrl + V , menu contestuale, ecc.)
  • Ti permette di ottenere i dati degli appunti direttamente come testo, in modo da non dover fare brutti scherzi per sostituire l’HTML.

Non sono sicuro del supporto cross-browser, però.

 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); }); 

Non sono riuscito a ottenere qui la risposta accettata per lavorare in IE, quindi ho fatto un po ‘di scouting e sono giunto a questa risposta che funziona in IE11 e nelle ultime versioni di Chrome e 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); } }); 

Una soluzione stretta come pimvdb. Ma funziona su 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); } }); 

Naturalmente la domanda ha già una risposta e l’argomento è molto vecchio ma voglio fornire la mia soluzione in quanto è semplice e pulita:

Questo è all’interno del mio evento paste sul mio 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 = $('
').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); }

L’altra parte proviene da un altro SO-post che non ho potuto trovare più …


AGGIORNAMENTO 19.11.2014: L’altro post SO

Firefox non ti consente di accedere ai dati degli appunti, quindi dovrai fare un ‘hack’ per farlo funzionare. Non sono stato in grado di trovare una soluzione completa, tuttavia è ansible correggerla per le paste ctrl + v creando una textarea e incollandole invece:

 //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); } 

Stavo anche lavorando su una semplice copia di testo e ho iniziato a odiare tutti gli errori execCommand e getData, quindi ho deciso di farlo in modo classico e funziona come un incantesimo:

 $('#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]+>/g, ''); var replaced = after.substr(0, pos1)+replace+after.substr(pos1+pasted.length); document.getElementById('editor').innerHTML = replaced; }, 100); }); 

Il codice con le mie annotazioni può essere trovato qui: http://www.albertmartin.de/blog/code.php/20/plain-text-paste-with-javascript

 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(); } } 

Sopra il codice funziona per me in IE10 e IE11 e ora funziona anche in Chrome e Safari. Non testato in Firefox.

In IE11, execCommand non funziona bene. Uso il seguente codice per IE11

è la mia casella di

.

Ho letto i dati degli appunti da window.clipboardData e ho modificato il testo di div e il caret.

Fornisco un timeout per l’impostazione del punto di inserimento, perché se non imposto il timeout, un segno di omissione va alla fine del div.

e dovresti leggere appuntiboardData in IE11 in basso. Se non lo fai, newline caracter non viene gestito correttamente, quindi il caret non funziona correttamente.

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

Testato su IE11 e cromato. Potrebbe non funzionare su 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); 

Nessuna delle risposte inviate sembra davvero funzionare su browser o la soluzione è complicata:

  • Il comando insertText non è supportato da IE
  • L’utilizzo del comando paste genera un errore di overflow dello stack in IE11

Quello che ha funzionato per me (IE11, Edge, Chrome e FF) è il seguente:

 $("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); } }; 
    
Edit me!