programing

JavaScript는 붙여넣기 이벤트에서 클립보드 데이터를 가져옵니다(크로스 브라우저).

copyandpastes 2022. 10. 19. 21:31
반응형

JavaScript는 붙여넣기 이벤트에서 클립보드 데이터를 가져옵니다(크로스 브라우저).

웹 응용 프로그램에서 붙여넣기 이벤트를 감지하고 붙여넣을 데이터를 검색하려면 어떻게 해야 합니까?

텍스트가 리치 텍스트 에디터에 붙여넣기 전에 HTML 콘텐츠를 삭제하고 싶습니다.

나중에 붙여넣은 후 텍스트를 클리닝하는 것은 가능하지만, 문제는 이전 서식이 모두 손실된다는 것이 문제입니다.예를 들어 편집기에서 문장을 쓰고 굵게 할 수 있지만, 새 텍스트를 붙여넣으면 모든 서식이 손실됩니다.붙여넣은 텍스트만 정리하고 이전 포맷은 그대로 둡니다.

이상적인 솔루션은 최신 브라우저(MSIE, Gecko, Chrome 및 Safari 등)에서 모두 작동해야 합니다.

에는 MSIE가 있습니다.clipboardData.getData()다른 브라우저에서도 비슷한 기능을 찾을 수 없었습니다.

솔루션 #1(일반 텍스트만, Firefox 22+ 필요)

IE6+, FF 22+, Chrome, Safari, 엣지(IE9+에서만 테스트 가능, 저 버전에서도 동작 가능)

HTML 또는 Firefox <= 22 붙여넣기 지원이 필요한 경우 솔루션 #2를 참조하십시오.

function handlePaste(e) {
  var clipboardData, pastedData;

  // Stop data actually being pasted into div
  e.stopPropagation();
  e.preventDefault();

  // Get pasted data via clipboard API
  clipboardData = e.clipboardData || window.clipboardData;
  pastedData = clipboardData.getData('Text');

  // Do whatever with pasteddata
  alert(pastedData);
}

document.getElementById('editableDiv').addEventListener('paste', handlePaste);
<div id='editableDiv' contenteditable='true'>Paste</div>

JSFiddle

에서는 '매개 변수를 합니다.getData비표준 함수입니다.다만, 기입시에 모든 브라우저에서 동작합니다.


솔루션 #2(HTML로 Firefox <= 22에서 작동)

IE6+, FF 3.5+, Chrome, Safari, Edge에서 테스트 완료

var editableDiv = document.getElementById('editableDiv');

function handlepaste(e) {
  var types, pastedData, savedContent;

  // Browsers that support the 'text/html' type in the Clipboard API (Chrome, Firefox 22+)
  if (e && e.clipboardData && e.clipboardData.types && e.clipboardData.getData) {

    // Check for 'text/html' in types list. See abligh's answer below for deatils on
    // why the DOMStringList bit is needed. We cannot fall back to 'text/plain' as
    // Safari/Edge don't advertise HTML data even if it is available
    types = e.clipboardData.types;
    if (((types instanceof DOMStringList) && types.contains("text/html")) || (types.indexOf && types.indexOf('text/html') !== -1)) {

      // Extract data and pass it to callback
      pastedData = e.clipboardData.getData('text/html');
      processPaste(editableDiv, pastedData);

      // Stop the data from actually being pasted
      e.stopPropagation();
      e.preventDefault();
      return false;
    }
  }

  // Everything else: Move existing element contents to a DocumentFragment for safekeeping
  savedContent = document.createDocumentFragment();
  while (editableDiv.childNodes.length > 0) {
    savedContent.appendChild(editableDiv.childNodes[0]);
  }

  // Then wait for browser to paste content into it and cleanup
  waitForPastedData(editableDiv, savedContent);
  return true;
}

function waitForPastedData(elem, savedContent) {

  // If data has been processes by browser, process it
  if (elem.childNodes && elem.childNodes.length > 0) {

    // Retrieve pasted content via innerHTML
    // (Alternatively loop through elem.childNodes or elem.getElementsByTagName here)
    var pastedData = elem.innerHTML;

    // Restore saved content
    elem.innerHTML = "";
    elem.appendChild(savedContent);

    // Call callback
    processPaste(elem, pastedData);
  }

  // Else wait 20ms and try again
  else {
    setTimeout(function() {
      waitForPastedData(elem, savedContent)
    }, 20);
  }
}

function processPaste(elem, pastedData) {
  // Do whatever with gathered data;
  alert(pastedData);
  elem.focus();
}

// Modern browsers. Note: 3rd argument is required for Firefox <= 6
if (editableDiv.addEventListener) {
  editableDiv.addEventListener('paste', handlepaste, false);
}
// IE <= 8
else {
  editableDiv.attachEvent('onpaste', handlepaste);
}
<div id='div' contenteditable='true'>Paste</div>

JSFiddle

설명.

onpastediv 가지고 있다handlePaste했습니다. 즉, 이 함수는 하나의 인수입니다.event이치노은 리리 of of of of of of of of of of of of of of이다.clipboardData이 이벤트의 속성: 비 브라우저의 클립보드 액세스를 활성화합니다. 에서는, IE 에 상당합니다.window.clipboardData API는 조금 다릅니다.

아래 리소스 섹션을 참조하십시오.


handlepaste★★★★

이 함수는 두 개의 분기가 있습니다.

는 '아까부터'가합니다.event.clipboardData 다음 '아까운지', '아까운지', '아까운지', '아까운지'를 확인해 보세요.typestext/filter'('text/filter')가 포함되어 .types 중 일 수 .DOMStringList는 '알겠습니다'를 사용하여 확인합니다.contains method를 하여 indexOf 'plain 'text합니다.이 모든 조건이 충족되면 솔루션 #1과 같이 진행합니다.단, 'text/plain'이 아닌 'text/html'을 사용합니다.Chrome Firefox 22+입니다.

이 메서드가 지원되지 않는 경우(다른 모든 브라우저)

  1. DocumentFragment
  2. 요소를 비우다
  3. " "에 주세요.waitForPastedData

waitforpastedata★★★★

이 함수는 먼저 붙여넣은 데이터에 대해 폴링(20ms당 1회)합니다.이 데이터는 바로 표시되지 않기 때문에 필요합니다.데이터가 나타나면:

  1. 내부 저장변수에 대한 편집 가능한 div(지금은 붙여넣은 데이터)의 HTML
  2. DocumentFragment에 저장된 콘텐츠를 복원합니다.
  3. 검색된 데이터로 'processPaste' 함수를 호출합니다.

processpaste★★★★

붙여넣은 데이터로 임의 작업을 수행합니다.이 경우 데이터에 경고만 하면 됩니다. 원하는 대로 할 수 있습니다.붙여넣은 데이터는 데이터 삭제 프로세스를 통해 실행할 수 있습니다.


커서 위치 저장 및 복원

실제 상황에서는 선택을 이전에 저장한 후 나중에 복원해야 합니다(contentEditable <div>커서 위치 설정).그런 다음 사용자가 붙여넣기 작업을 시작했을 때 커서가 있던 위치에 붙여넣은 데이터를 삽입할 수 있습니다.

MDN 자원

DocumentFragment 사용을 제안하고 clipboardData.types 문자열 대신 DOMStringList를 사용하여 Firefox에서 오류를 포착한 Tim Down 덕분입니다.

Firefox가 버전 22에서 지원을 추가함에 따라 모든 주요 브라우저가 붙여넣기 이벤트에서 클립보드 데이터에 액세스할 수 있게 되었습니다.예를 들어 Nico Burns의 답변을 참조하십시오.

과거에는 이것이 일반적으로 크로스 브라우저 방식으로 가능하지 않았다.을 '붙여넣기', '붙여넣기'를 수 .pasteevent. 이는 최신 브라우저에서는 가능하지만 일부 오래된 브라우저(특히 Firefox < 22)에서는 가능하지 않습니다.

오래된 브라우저를 지원해야 할 경우 Firefox 2+, IE 5.5+ 및 Safari 또는 Chrome과 같은 WebKit 브라우저에서 사용할 수 있는 약간의 해킹이 필요합니다.TinyMCE와 CKEditor의 최신 버전에서는 다음 기술이 사용됩니다.

  1. 키 누르기 이벤트 핸들러를 사용하여 ctrl-v / shift-ins 이벤트 검출
  2. 오프스크린(왼쪽 후 " " " "를 돌립니다." ( " - 1000px ) 。designMode 및 call " " " 입니다.focus() 수 있습니다.
  3. 를하고, 텍스트 영역을 하고, 「」(1밀리초)를 회전시킵니다.designMode를 다시 켜면 사용자 선택이 복원되고 텍스트가 붙여넣습니다.

이 기능은 키보드 붙여넣기 이벤트에만 적용되며 컨텍스트 또는 편집 메뉴에서 붙여넣기할 수 없습니다.붙여넣기 이벤트가 발생할 때까지 캐럿을 텍스트 영역으로 리디렉션하기엔 너무 늦습니다(최소한 일부 브라우저에서는).

Firefox 2를 지원해야 할 경우 해당 브라우저의 WYSIWYG 에디터 iframe 문서가 아닌 상위 문서에 텍스트 영역을 배치해야 합니다.

단순 버전:

document.querySelector('[contenteditable]').addEventListener('paste', (e) => {
    e.preventDefault();
    const text = (e.originalEvent || e).clipboardData.getData('text/plain');
    window.document.execCommand('insertText', false, text);
});

사용. clipboardData

데모: http://jsbin.com/nozifexasu/edit?js,output

Edge, Firefox, Chrome, Safari, Opera 테스트 완료.

Document.execCommand()는 이제 사용되지 않습니다.


주의: 서버측에서도 입출력 체크(PHP strip-tag 등)

라이브 데모

Chrome/FF/IE11에서 테스트 완료

Chrome/.IE를 사용하다이러한 브라우저는<div>각 새 줄에 대한 요소.여기에 이에 대한 게시물이 있습니다. 이 게시물은 콘텐츠 가능한 요소를 다음과 같이 설정하여 수정할 수 있습니다.display:inline-block

강조 표시된 HTML을 선택하여 여기에 붙여넣습니다.

function onPaste(e){
  var content;
  e.preventDefault();

  if( e.clipboardData ){
    content = e.clipboardData.getData('text/plain');
    document.execCommand('insertText', false, content);
    return false;
  }
  else if( window.clipboardData ){
    content = window.clipboardData.getData('Text');
    if (window.getSelection)
      window.getSelection().getRangeAt(0).insertNode( document.createTextNode(content) );
  }
}


/////// EVENT BINDING /////////
document.querySelector('[contenteditable]').addEventListener('paste', onPaste);
[contenteditable]{ 
  /* chroem bug: https://stackoverflow.com/a/24689420/104380 */
  display:inline-block;
  width: calc(100% - 40px);
  min-height:120px; 
  margin:10px;
  padding:10px;
  border:1px dashed green;
}

/* 
 mark HTML inside the "contenteditable"  
 (Shouldn't be any OFC!)'
*/
[contenteditable] *{
  background-color:red;
}
<div contenteditable></div>

여기 Tim Downs 제안서에 대한 개념 증명을 화면 밖의 텍스트 영역과 함께 작성했습니다.다음은 암호입니다.

<html>
<head>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.min.js"></script> 
<script language="JavaScript">
 $(document).ready(function()
{

var ctrlDown = false;
var ctrlKey = 17, vKey = 86, cKey = 67;

$(document).keydown(function(e)
{
    if (e.keyCode == ctrlKey) ctrlDown = true;
}).keyup(function(e)
{
    if (e.keyCode == ctrlKey) ctrlDown = false;
});

$(".capture-paste").keydown(function(e)
{
    if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){
        $("#area").css("display","block");
        $("#area").focus();         
    }
});

$(".capture-paste").keyup(function(e)
{
    if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)){                      
        $("#area").blur();
        //do your sanitation check or whatever stuff here
        $("#paste-output").text($("#area").val());
        $("#area").val("");
        $("#area").css("display","none");
    }
});

});
</script>

</head>
<body class="capture-paste">

<div id="paste-output"></div>


    <div>
    <textarea id="area" style="display: none; position: absolute; left: -99em;"></textarea>
    </div>

</body>
</html>

코드 전체를 복사하여 하나의 html 파일에 붙여넣고 클립보드에서 (ctrl+v를 사용하여) 텍스트 붙여넣기를 시도하기만 하면 됩니다.

IE9 및 Firefox, Chrome 및 Opera의 새로운 버전에서 테스트했습니다.꽤 잘 작동한다.또한 원하는 키 조합을 사용하여 이 기능을 트리거할 수 있는 것도 좋습니다.물론 jQuery 소스를 포함하는 것도 잊지 마십시오.

이 코드를 사용해 주세요.또, 개선점이나 문제가 있으면, 투고해 주세요.또, 저는 Javascript 개발자가 아니기 때문에, 뭔가 빠뜨린 것이 있을지도 모릅니다(=>자신의 테스트를 실시합니다).

l2aelba anwser에 근거합니다.이것은 FF, Safari, Chrome, IE(8,9,10 및 11)에서 테스트되었습니다.

    $("#editText").on("paste", function (e) {
        e.preventDefault();

        var text;
        var clp = (e.originalEvent || e).clipboardData;
        if (clp === undefined || clp === null) {
            text = window.clipboardData.getData("text") || "";
            if (text !== "") {
                if (window.getSelection) {
                    var newNode = document.createElement("span");
                    newNode.innerHTML = text;
                    window.getSelection().getRangeAt(0).insertNode(newNode);
                } else {
                    document.selection.createRange().pasteHTML(text);
                }
            }
        } else {
            text = clp.getData('text/plain') || "";
            if (text !== "") {
                document.execCommand('insertText', false, text);
            }
        }
    });

이것은 set Timeout()을 사용하지 않습니다.

이 훌륭한 기사를 사용하여 크로스 브라우저 지원을 실현했습니다.

$(document).on("focus", "input[type=text],textarea", function (e) {
    var t = e.target;
    if (!$(t).data("EventListenerSet")) {
        //get length of field before paste
        var keyup = function () {
            $(this).data("lastLength", $(this).val().length);
        };
        $(t).data("lastLength", $(t).val().length);
        //catch paste event
        var paste = function () {
            $(this).data("paste", 1);//Opera 11.11+
        };
        //process modified data, if paste occured
        var func = function () {
            if ($(this).data("paste")) {
                alert(this.value.substr($(this).data("lastLength")));
                $(this).data("paste", 0);
                this.value = this.value.substr(0, $(this).data("lastLength"));
                $(t).data("lastLength", $(t).val().length);
            }
        };
        if (window.addEventListener) {
            t.addEventListener('keyup', keyup, false);
            t.addEventListener('paste', paste, false);
            t.addEventListener('input', func, false);
        }
        else {//IE
            t.attachEvent('onkeyup', function () {
                keyup.call(t);
            });
            t.attachEvent('onpaste', function () {
                paste.call(t);
            });
            t.attachEvent('onpropertychange', function () {
                func.call(t);
            });
        }
        $(t).data("EventListenerSet", 1);
    }
}); 

이 코드는 붙여넣기 전에 선택 핸들을 사용하여 확장됩니다: 데모

붙여넣은 텍스트를 지우고 현재 선택한 텍스트를 붙여넣은 텍스트로 바꾸는 은 매우 간단한 일입니다.

<div id='div' contenteditable='true' onpaste='handlepaste(this, event)'>Paste</div>

JS:

function handlepaste(el, e) {
  document.execCommand('insertText', false, e.clipboardData.getData('text/plain'));
  e.preventDefault();
}

Nico의 답변에 대한 코멘트를 하기에는 너무 길었습니다.이것은 파이어폭스에서는 (댓글에 따라) 더 이상 동작하지 않는다고 생각합니다.또한 Safari에서는 동작하지 않았습니다.

우선 클립보드에서 직접 읽을 수 있게 되었습니다.다음과 같은 코드 대신:

if (/text\/plain/.test(e.clipboardData.types)) {
    // shouldn't this be writing to elem.value for text/plain anyway?
    elem.innerHTML = e.clipboardData.getData('text/plain');
}

용도:

types = e.clipboardData.types;
if (((types instanceof DOMStringList) && types.contains("text/plain")) ||
    (/text\/plain/.test(types))) {
    // shouldn't this be writing to elem.value for text/plain anyway?
    elem.innerHTML = e.clipboardData.getData('text/plain');
}

에는 'Firefox'가types which라는 DOMStringList는, 「」를 하고 있지 않습니다.test.

가 "Firefox"에 않는 한.contenteditable=truesyslog.syslog.syslog.

마지막으로 Firefox는 포커스가 다음 위치에 있지 않는 한 확실하게 붙여넣기를 허용하지 않습니다.textarea.contenteditable=true 또아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아,아.

  • display:none
  • visibility:hidden
  • 제로 사이즈가 아니다

VNC 에뮬레이터를 는 JS VNC가 ).textarea등)에 붙여넣습니다. 하면 때로는 , 두 페이스트를 두 번 않도록 때에.가 클리어되었을 때)에 실패하여 필드가 초점을 잃었고 다음에도 정상적으로 회복되지 않았습니다.focus()내가 생각해낸 해결책은 그것을 에 두는 것이다.z-order: -1000display:none1pxx1px로

Safari에서는두이 적용됩니다 Safari가 합니다.textarea 않은 것display:none.

이것은 온페이스트이벤트 및 변환 옵서버를 지원하는 모든 브라우저에서 동작합니다.

이 솔루션은 텍스트만 가져오는 것이 아니라 실제로 붙여넣은 콘텐츠를 요소에 붙여넣기 전에 편집할 수 있습니다.

콘텐츠 대응 온페이스트 이벤트(모든 주요 브라우저에서 지원)와 변환 옵저버(Chrome, Firefox 및 IE11+에서 지원)를 사용하여 동작합니다.

순서 1

콘텐츠 가능한 HTML 요소 만들기

<div contenteditable="true" id="target_paste_element"></div>

순서 2

Javascript 코드에 다음 이벤트를 추가합니다.

document.getElementById("target_paste_element").addEventListener("paste", pasteEventVerifierEditor.bind(window, pasteCallBack), false);

변환 옵서버는 비동기적으로 호출되므로 past CallBack을 바인드해야 합니다.

순서 3

다음 함수를 코드에 추가합니다.

function pasteEventVerifierEditor(callback, e)
{
   //is fired on a paste event. 
    //pastes content into another contenteditable div, mutation observer observes this, content get pasted, dom tree is copied and can be referenced through call back.
    //create temp div
    //save the caret position.
    savedCaret = saveSelection(document.getElementById("target_paste_element"));

    var tempDiv = document.createElement("div");
    tempDiv.id = "id_tempDiv_paste_editor";
    //tempDiv.style.display = "none";
    document.body.appendChild(tempDiv);
    tempDiv.contentEditable = "true";

    tempDiv.focus();

    //we have to wait for the change to occur.
    //attach a mutation observer
    if (window['MutationObserver'])
    {
        //this is new functionality
        //observer is present in firefox/chrome and IE11
        // select the target node
        // create an observer instance
        tempDiv.observer = new MutationObserver(pasteMutationObserver.bind(window, callback));
        // configuration of the observer:
        var config = { attributes: false, childList: true, characterData: true, subtree: true };

        // pass in the target node, as well as the observer options
        tempDiv.observer.observe(tempDiv, config);

    }   

}



function pasteMutationObserver(callback)
{

    document.getElementById("id_tempDiv_paste_editor").observer.disconnect();
    delete document.getElementById("id_tempDiv_paste_editor").observer;

    if (callback)
    {
        //return the copied dom tree to the supplied callback.
        //copy to avoid closures.
        callback.apply(document.getElementById("id_tempDiv_paste_editor").cloneNode(true));
    }
    document.body.removeChild(document.getElementById("id_tempDiv_paste_editor"));

}

function pasteCallBack()
{
    //paste the content into the element.
    restoreSelection(document.getElementById("target_paste_element"), savedCaret);
    delete savedCaret;

    pasteHtmlAtCaret(this.innerHTML, false, true);
}   


saveSelection = function(containerEl) {
if (containerEl == document.activeElement)
{
    var range = window.getSelection().getRangeAt(0);
    var preSelectionRange = range.cloneRange();
    preSelectionRange.selectNodeContents(containerEl);
    preSelectionRange.setEnd(range.startContainer, range.startOffset);
    var start = preSelectionRange.toString().length;

    return {
        start: start,
        end: start + range.toString().length
    };
}
};

restoreSelection = function(containerEl, savedSel) {
    containerEl.focus();
    var charIndex = 0, range = document.createRange();
    range.setStart(containerEl, 0);
    range.collapse(true);
    var nodeStack = [containerEl], node, foundStart = false, stop = false;

    while (!stop && (node = nodeStack.pop())) {
        if (node.nodeType == 3) {
            var nextCharIndex = charIndex + node.length;
            if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
                range.setStart(node, savedSel.start - charIndex);
                foundStart = true;
            }
            if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
                range.setEnd(node, savedSel.end - charIndex);
                stop = true;
            }
            charIndex = nextCharIndex;
        } else {
            var i = node.childNodes.length;
            while (i--) {
                nodeStack.push(node.childNodes[i]);
            }
        }
    }

    var sel = window.getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
}

function pasteHtmlAtCaret(html, returnInNode, selectPastedContent) {
//function written by Tim Down

var sel, range;
if (window.getSelection) {
    // IE9 and non-IE
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
        range = sel.getRangeAt(0);
        range.deleteContents();

        // Range.createContextualFragment() would be useful here but is
        // only relatively recently standardized and is not supported in
        // some browsers (IE9, for one)
        var el = document.createElement("div");
        el.innerHTML = html;
        var frag = document.createDocumentFragment(), node, lastNode;
        while ( (node = el.firstChild) ) {
            lastNode = frag.appendChild(node);
        }
        var firstNode = frag.firstChild;
        range.insertNode(frag);

        // Preserve the selection
        if (lastNode) {
            range = range.cloneRange();
            if (returnInNode)
            {
                range.setStart(lastNode, 0); //this part is edited, set caret inside pasted node.
            }
            else
            {
                range.setStartAfter(lastNode); 
            }
            if (selectPastedContent) {
                range.setStartBefore(firstNode);
            } else {
                range.collapse(true);
            }
            sel.removeAllRanges();
            sel.addRange(range);
        }
    }
} else if ( (sel = document.selection) && sel.type != "Control") {
    // IE < 9
    var originalRange = sel.createRange();
    originalRange.collapse(true);
    sel.createRange().pasteHTML(html);
    if (selectPastedContent) {
        range = sel.createRange();
        range.setEndPoint("StartToStart", originalRange);
        range.select();
    }
}
}

코드 기능:

  1. 누군가 ctrl-v, contextmenu 또는 기타 수단을 사용하여 붙여넣기 이벤트를 실행합니다.
  2. 붙여넣기 이벤트에서 콘텐츠 가능한 새 요소가 생성됩니다(콘텐츠 가능한 요소는 상승된 권한을 가집니다).
  3. 대상 요소의 캐럿 위치가 저장됩니다.
  4. 포커스가 새 요소로 설정됩니다.
  5. 컨텐츠가 새로운 요소에 페이스트 되어 DOM 에 렌더링 됩니다.
  6. 변환 옵서버는 이것을 검출합니다(돔트리와 내용에 대한 모든 변경을 등록합니다).다음으로 돌연변이 이벤트를 기동합니다.
  7. 붙여넣은 콘텐츠의 돔이 변수로 복제되어 콜백으로 돌아갑니다.임시 요소가 파괴됩니다.
  8. 콜백은 복제된 DOM을 수신합니다.캐럿이 복원됩니다.대상에 추가하기 전에 편집할 수 있습니다.요소.이 예에서는 캐럿을 저장/복원하고 HTML을 요소에 붙여넣기 위해 Tim Downs 함수를 사용하고 있습니다.

document.getElementById("target_paste_element").addEventListener("paste", pasteEventVerifierEditor.bind(window, pasteCallBack), false);


function pasteEventVerifierEditor(callback, e) {
  //is fired on a paste event. 
  //pastes content into another contenteditable div, mutation observer observes this, content get pasted, dom tree is copied and can be referenced through call back.
  //create temp div
  //save the caret position.
  savedCaret = saveSelection(document.getElementById("target_paste_element"));

  var tempDiv = document.createElement("div");
  tempDiv.id = "id_tempDiv_paste_editor";
  //tempDiv.style.display = "none";
  document.body.appendChild(tempDiv);
  tempDiv.contentEditable = "true";

  tempDiv.focus();

  //we have to wait for the change to occur.
  //attach a mutation observer
  if (window['MutationObserver']) {
    //this is new functionality
    //observer is present in firefox/chrome and IE11
    // select the target node
    // create an observer instance
    tempDiv.observer = new MutationObserver(pasteMutationObserver.bind(window, callback));
    // configuration of the observer:
    var config = {
      attributes: false,
      childList: true,
      characterData: true,
      subtree: true
    };

    // pass in the target node, as well as the observer options
    tempDiv.observer.observe(tempDiv, config);

  }

}



function pasteMutationObserver(callback) {

  document.getElementById("id_tempDiv_paste_editor").observer.disconnect();
  delete document.getElementById("id_tempDiv_paste_editor").observer;

  if (callback) {
    //return the copied dom tree to the supplied callback.
    //copy to avoid closures.
    callback.apply(document.getElementById("id_tempDiv_paste_editor").cloneNode(true));
  }
  document.body.removeChild(document.getElementById("id_tempDiv_paste_editor"));

}

function pasteCallBack() {
  //paste the content into the element.
  restoreSelection(document.getElementById("target_paste_element"), savedCaret);
  delete savedCaret;

  //edit the copied content by slicing
  pasteHtmlAtCaret(this.innerHTML.slice(3), false, true);
}


saveSelection = function(containerEl) {
  if (containerEl == document.activeElement) {
    var range = window.getSelection().getRangeAt(0);
    var preSelectionRange = range.cloneRange();
    preSelectionRange.selectNodeContents(containerEl);
    preSelectionRange.setEnd(range.startContainer, range.startOffset);
    var start = preSelectionRange.toString().length;

    return {
      start: start,
      end: start + range.toString().length
    };
  }
};

restoreSelection = function(containerEl, savedSel) {
  containerEl.focus();
  var charIndex = 0,
    range = document.createRange();
  range.setStart(containerEl, 0);
  range.collapse(true);
  var nodeStack = [containerEl],
    node, foundStart = false,
    stop = false;

  while (!stop && (node = nodeStack.pop())) {
    if (node.nodeType == 3) {
      var nextCharIndex = charIndex + node.length;
      if (!foundStart && savedSel.start >= charIndex && savedSel.start <= nextCharIndex) {
        range.setStart(node, savedSel.start - charIndex);
        foundStart = true;
      }
      if (foundStart && savedSel.end >= charIndex && savedSel.end <= nextCharIndex) {
        range.setEnd(node, savedSel.end - charIndex);
        stop = true;
      }
      charIndex = nextCharIndex;
    } else {
      var i = node.childNodes.length;
      while (i--) {
        nodeStack.push(node.childNodes[i]);
      }
    }
  }

  var sel = window.getSelection();
  sel.removeAllRanges();
  sel.addRange(range);
}

function pasteHtmlAtCaret(html, returnInNode, selectPastedContent) {
  //function written by Tim Down

  var sel, range;
  if (window.getSelection) {
    // IE9 and non-IE
    sel = window.getSelection();
    if (sel.getRangeAt && sel.rangeCount) {
      range = sel.getRangeAt(0);
      range.deleteContents();

      // Range.createContextualFragment() would be useful here but is
      // only relatively recently standardized and is not supported in
      // some browsers (IE9, for one)
      var el = document.createElement("div");
      el.innerHTML = html;
      var frag = document.createDocumentFragment(),
        node, lastNode;
      while ((node = el.firstChild)) {
        lastNode = frag.appendChild(node);
      }
      var firstNode = frag.firstChild;
      range.insertNode(frag);

      // Preserve the selection
      if (lastNode) {
        range = range.cloneRange();
        if (returnInNode) {
          range.setStart(lastNode, 0); //this part is edited, set caret inside pasted node.
        } else {
          range.setStartAfter(lastNode);
        }
        if (selectPastedContent) {
          range.setStartBefore(firstNode);
        } else {
          range.collapse(true);
        }
        sel.removeAllRanges();
        sel.addRange(range);
      }
    }
  } else if ((sel = document.selection) && sel.type != "Control") {
    // IE < 9
    var originalRange = sel.createRange();
    originalRange.collapse(true);
    sel.createRange().pasteHTML(html);
    if (selectPastedContent) {
      range = sel.createRange();
      range.setEndPoint("StartToStart", originalRange);
      range.select();
    }
  }
}
div {
  border: 1px solid black;
  height: 50px;
  padding: 5px;
}
<div contenteditable="true" id="target_paste_element"></div>


Tim Down 에 대한 답변은 다음 게시물을 참조하십시오.

붙여넣기 이벤트에서 문서에 붙여넣은 내용 가져오기

텍스트 입력에 붙여넣을 경우 이벤트 리스너를 추가하여 이벤트를 붙여넣는 것이 효과적입니다.붙여넣기 이벤트는 입력이 변경되기 전에 발생하므로, 붙여넣기 핸들러 내부에 붙여넣기 시 발생한 입력 상자의 변경 사항을 확인하는 지연 함수를 만듭니다.

onPaste: function() {
    var oThis = this;
    setTimeout(function() { // Defer until onPaste() is done
        console.log('paste', oThis.input.value);
        // Manipulate pasted input
    }, 1);
}

심플한 솔루션:

document.onpaste = function(e) {
    var pasted = e.clipboardData.getData('Text');
    console.log(pasted)
}

가장 먼저 떠오르는 것은 구글의 closure lib http://closure-library.googlecode.com/svn/trunk/closure/goog/demos/pastehandler.html의 페이스트 핸들러입니다.

function myFunct( e ){
    e.preventDefault();

    var pastedText = undefined;
    if( window.clipboardData && window.clipboardData.getData ){
    pastedText = window.clipboardData.getData('Text');
} 
else if( e.clipboardData && e.clipboardData.getData ){
    pastedText = e.clipboardData.getData('text/plain');
}

//work with text

}
document.onpaste = myFunct;

이것은 나에게 효과가 있었다:

function onPasteMe(currentData, maxLen) {
    // validate max length of pasted text
    var totalCharacterCount = window.clipboardData.getData('Text').length;
}

<input type="text" onPaste="return onPasteMe(this, 50);" />

다음과 같이 할 수 있습니다.

붙여넣기 전 및 붙여넣기 이벤트에 이 jQuery 플러그인을 사용합니다.

$.fn.pasteEvents = function( delay ) {
    if (delay == undefined) delay = 20;
    return $(this).each(function() {
        var $el = $(this);
        $el.on("paste", function() {
            $el.trigger("prepaste");
            setTimeout(function() { $el.trigger("postpaste"); }, delay);
        });
    });
};

이제 이 플러그인을 사용할 수 있습니다.

$('#txt').on("prepaste", function() { 

    $(this).find("*").each(function(){

        var tmp=new Date.getTime();
        $(this).data("uid",tmp);
    });


}).pasteEvents();

$('#txt').on("postpaste", function() { 


  $(this).find("*").each(function(){

     if(!$(this).data("uid")){
        $(this).removeClass();
          $(this).removeAttr("style id");
      }
    });
}).pasteEvents();

설명

먼저 모든 기존 요소의 uid를 데이터 속성으로 설정합니다.

그런 다음 모든 노드의 POST PASTE 이벤트를 비교합니다.따라서 비교함으로써 새로 삽입된 것을 식별할 수 있습니다.이것들은 uid를 가지기 때문입니다.그리고 새로 작성된 요소에서 스타일/클래스/id 속성을 삭제하기만 하면 오래된 포맷을 유지할 수 있습니다.

$('#dom').on('paste',function (e){
    setTimeout(function(){
        console.log(e.currentTarget.value);
    },0);
});

브라우저의 내용 편집 가능한 div에 평소처럼 붙여넣은 다음 붙여넣기 후 사용자 정의 텍스트 스타일에 사용되는 스팬 요소를 텍스트 자체와 스왑합니다.이것은 Internet Explorer나 다른 브라우저에서도 정상적으로 동작하고 있는 것 같습니다.

$('[contenteditable]').on('paste', function (e) {
    setTimeout(function () {
        $(e.target).children('span').each(function () {
            $(this).replaceWith($(this).text());
        });
    }, 0);
});

이 솔루션에서는 jQuery를 실행하고 있으며 내용 편집 가능한 div에서 텍스트 형식을 사용하지 않는 으로 가정합니다.

좋은 점은 이것이 매우 간단하다는 것이다.

이 솔루션은 html 태그를 대체하는 것으로, 심플하고 상호 참조할 수 있습니다.이 jsfiddle을 체크해 주세요.http://jsfiddle.net/tomwan/cbp1u2cx/1/, 코어 코드:

var $plainText = $("#plainText");
var $linkOnly = $("#linkOnly");
var $html = $("#html");

$plainText.on('paste', function (e) {
    window.setTimeout(function () {
        $plainText.html(removeAllTags(replaceStyleAttr($plainText.html())));
    }, 0);
});

$linkOnly.on('paste', function (e) {
    window.setTimeout(function () {
        $linkOnly.html(removeTagsExcludeA(replaceStyleAttr($linkOnly.html())));
    }, 0);
});

function replaceStyleAttr (str) {
    return str.replace(/(<[\w\W]*?)(style)([\w\W]*?>)/g, function (a, b, c, d) {
        return b + 'style_replace' + d;
    });
}

function removeTagsExcludeA (str) {
    return str.replace(/<\/?((?!a)(\w+))\s*[\w\W]*?>/g, '');
}

function removeAllTags (str) {
    return str.replace(/<\/?(\w+)\s*[\w\W]*?>/g, '');
}

주의: 이 솔루션에서는 '<>'와 같은 문자열을 필터링할 수 없기 때문에 뒷면의 xss 필터에 대해 몇 가지 작업을 수행해야 합니다.

이것은 위에 게시된 기존 코드이지만 IE용으로 업데이트했습니다.이 버그는 기존 텍스트가 선택되고 페이스트된 내용이 삭제되지 않는 것입니다.이것은 아래 코드로 수정되었습니다.

selRange.deleteContents(); 

아래 전체 코드 참조

$('[contenteditable]').on('paste', function (e) {
    e.preventDefault();

    if (window.clipboardData) {
        content = window.clipboardData.getData('Text');        
        if (window.getSelection) {
            var selObj = window.getSelection();
            var selRange = selObj.getRangeAt(0);
            selRange.deleteContents();                
            selRange.insertNode(document.createTextNode(content));
        }
    } else if (e.originalEvent.clipboardData) {
        content = (e.originalEvent || e).clipboardData.getData('text/plain');
        document.execCommand('insertText', false, content);
    }        
});

붙여넣기 이벤트는 사용자가 브라우저의 사용자 인터페이스를 통해 "붙여넣기" 작업을 시작할 때 실행됩니다.

HTML

<div class="source" contenteditable="true">Try copying text from this box...</div>
<div class="target" contenteditable="true">...and pasting it into this one</div>

자바스크립트

const target = document.querySelector('div.target');

target.addEventListener('paste', (event) => {
    let paste = (event.clipboardData || window.clipboardData).getData('text');
    paste = paste.toUpperCase();

    const selection = window.getSelection();
    if (!selection.rangeCount) return false;
    selection.deleteFromDocument();
    selection.getRangeAt(0).insertNode(document.createTextNode(paste));

    event.preventDefault();
});

자세한 것은 이쪽

IE11과 Chrome I 모두 일반 텍스트 복사 및 붙여넣기를 지원하기 위해 다음과 같은 기능을 사용했습니다.

IE와 chome을 구별하는 if 문과 해당 코드를 실행하는 if 문 2개가 있습니다.첫 번째 부분에서는 코드가 클립보드에서 텍스트를 읽고, 두 번째 부분에서는 선택한 텍스트가 존재하는 경우 해당 텍스트를 커서 위치에 바로 붙여넣는다.

특히 IE상의 페이스트에 대해서는 코드가 선택범위를 취득하여 선택된 텍스트를 삭제하고 클립보드에서 새로운 html 텍스트노드에 텍스트를 삽입하고 커서 위치에 텍스트노드와 텍스트 길이를 삽입하도록 범위를 재설정한다.

코드는 다음과 같습니다.

editable.addEventListener("paste", function(e) {
    e.preventDefault();

    // Get text from the clipboard.
    var text = '';
    if (e.clipboardData || (e.originalEvent && e.originalEvent.clipboardData)) {
      text = (e.originalEvent || e).clipboardData.getData('text/plain');
    } else if (window.clipboardData) {
      text = window.clipboardData.getData('Text');
    }
    
    // bool to indicate if the user agent is internet explorer
    let isIE = /Trident/.test(navigator.userAgent);
    
    if (document.queryCommandSupported('insertText') && !isIE) {
        // Chrome etc.
        document.execCommand('insertText', false, text);
        
    } else {
        // IE.
        
        // delete content from selection.
        var sel = window.getSelection();
        var range = sel.getRangeAt(0);
        document.execCommand("delete");

        // paste plain text in a new node.
        var newNode = document.createTextNode(text);

        range.insertNode(newNode);
        range.setStart(newNode, 0)
        range.setEnd(newNode, newNode.childNodes.length);

        sel.removeAllRanges;
        sel.addRange(range);
    }

}, false);

이 .document.execCommand('paste', false, text);브라우저가 여러 번 붙여넣기 이벤트를 호출하기 때문에 IE11에서는 작동하지 않습니다.그래서 범위 객체의 함수로 대체했습니다.

, IE11, 「IE11」이라고 하는 함수가 .document.execCommand('insertText', false, text);경우에 따라서는 사용할 수 없는 경우도 있기 때문에 브라우저가 IE인지, 범위 선택에 따라 코드의 일부를 실행했는지 여부를 명시적으로 확인했습니다(그렇지 않은지 참조).

언급URL : https://stackoverflow.com/questions/2176861/javascript-get-clipboard-data-on-paste-event-cross-browser

반응형