[javascript] execCommand에서 ‘일반 텍스트로 붙여 넣기’에 대한 Javascript 트릭

execCommand여기에 소개 된 샘플을 기반으로 한 기본 편집기가 있습니다. execCommand영역 내에 텍스트를 붙여 넣는 세 가지 방법이 있습니다.

  • Ctrl+V
  • 마우스 오른쪽 버튼 클릭-> 붙여 넣기
  • 오른쪽 클릭-> 일반 텍스트로 붙여 넣기

HTML 마크 업없이 일반 텍스트 만 붙여 넣기를 허용하고 싶습니다. 처음 두 작업을 강제로 일반 텍스트를 붙여 넣을 수 있습니까?

가능한 해결책 : 내가 생각할 수있는 방법은 ( Ctrl+ V)에 대한 keyup 이벤트에 대한 리스너를 설정 하고 붙여 넣기 전에 HTML 태그를 제거하는 것입니다.

  1. 최상의 솔루션입니까?
  2. 붙여 넣을 때 HTML 마크 업을 피하는 것이 방탄입니까?
  3. 오른쪽 클릭-> 붙여 넣기에 리스너를 추가하는 방법은 무엇입니까?


답변

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


답변

물론 질문은 이미 답변되었고 주제는 매우 오래되었지만 간단하고 깨끗한 솔루션을 제공하고 싶습니다.

이것은 내 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- 포스트에서 온 것입니다 …


업데이트 19.11.2014 :
다른 SO 포스트


답변

게시 된 답변 중 어떤 것도 브라우저 간 작동하지 않거나 솔루션이 너무 복잡합니다.

  • 이 명령 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 콘텐츠 붙여 넣기를 전혀 지원하지 않으므로 여기에서 아무것도 수행 할 필요가 없습니다.


답변

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 에서 찾을 수 있습니다
.