Javascript трюк для " вставить как обычный текст` в execCommand
у меня есть базовый редактор на основе execCommand после примера, представленного здесь. Есть три способа вставить текст в execCommand площадь:
Ctrl+V
- Щелкните Правой Кнопкой Мыши - > Вставить
- Щелкните Правой Кнопкой Мыши - > Вставить Как Обычный Текст
Я хочу, чтобы вставить только текст без HTML-разметки. Как я могу заставить первые два действия вставить обычный текст?
возможно Решение: как я могу думать о том, чтобы установить прослушиватель для ключевых событий для (Ctrl+V) и полосы HTML теги перед вставкой.
- это лучшее решение?
- это пуленепробиваемый, чтобы избежать каких-либо HTML разметки в пасте?
- как добавить слушателя в правый клик - > вставить?
9 ответов:
Он будет перехватывать
pasteсобытие, отменитьpaste, и вручную вставить текстовое представление буфера обмена:
http://jsfiddle.net/HBEzc/. Это должно быть самое надежное:
- он ловит все виды оклейки (Ctrl+V, контекстное меню и т. д.)
- это позволяет получить данные буфера обмена непосредственно в виде текста, так что вам не придется делать уродливые хаки, чтобы заменить HTML.
Я однако не уверен в кросс-браузерной поддержке.
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); });
Я не мог получить принятый ответ здесь, чтобы работать в IE, поэтому я сделал некоторые разведку вокруг и пришел к этому ответу, который работает в IE11 и последних версиях Chrome и 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); } });
близкое решение как pimvdb. Но это работа FF, Chrome и 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); } });
конечно, вопрос уже ответил и тема очень старая, но я хочу предоставить свое решение, как это просто чистый:
Это внутри моего paste-event на моем 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); }остальное-часть из другого SO-post, который я больше не мог найти...
обновление 19.11.2014: другой так-пост
Firefox не позволяет вам получить доступ к данным буфера обмена, поэтому вам нужно будет сделать "хак", чтобы заставить его работать. Я не смог найти полное решение, однако вы можете исправить его для ctrl+v пасты, создав текстовую область и вставив ее вместо этого:
//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); }
Я также работал над простой текстовой вставкой, и я начал ненавидеть все ошибки execCommand и getData, поэтому я решил сделать это классическим способом, и это работает как шарм:
$('#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); });код с моими обозначениями можно найти здесь: 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(); } }выше код работает для меня в IE10 и IE11, а теперь также работает в Chrome и Safari. Не тестировался в Firefox.
в IE11, execCommand не работает хорошо. Я использую ниже код для IE11
<div class="wmd-input" id="wmd-input-md" contenteditable=true>моя коробка разд.Я читаю данные из буфера обмена из окна.clipboardData и изменить div textContent и дать каре.
Я даю тайм-аут для установки каретки, потому что если я не устанавливаю тайм-аут, каретка идет в конец div.
и вы должны прочитать clipboardData в IE11 ниже способом. Если вы этого не сделаете, newline caracter не обрабатывается должным образом, поэтому каретка идет неправильный.
var tempDiv = document.createElement("div"); tempDiv.textContent = window.clipboardData.getData("text"); var text = tempDiv.textContent;протестировано на IE11 и chrome. Это может не работать на 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);
ни один из опубликованных ответов действительно не работает в кросс-браузере, или решение более сложное:
- команда
insertTextне поддерживается IE- С помощью
pasteкоманды приводит к ошибке переполнения стека в IE11то, что работало для меня (IE11, Edge, Chrome и FF), заключается в следующем:
$("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>обратите внимание, что пользовательский обработчик вставки требуется только / работает для
contenteditableузлы. А какtextareaи равниныinputполя вообще не поддерживают вставку HTML-контента, поэтому здесь ничего не нужно делать.
Comments