web-dev-qa-db-ja.com

JavaScriptが貼り付けイベントでクリップボードデータを取得する(クロスブラウザ)

Webアプリケーションは、貼り付けイベントを検出して貼り付けるデータを取得する方法を教えてください。

テキストをリッチテキストエディタに貼り付ける前に、HTMLコンテンツを削除したいです。

後で貼り付けた後のテキストのクリーニングは機能しますが、問題は以前の書式設定がすべて失われることです。たとえば、エディタで文を書いて太字にすることはできますが、新しいテキストを貼り付けると、すべての書式設定が失われます。貼り付けたテキストだけをきれいにし、以前の書式はそのまま残します。

理想的には、このソリューションは最新のすべてのブラウザ(MSIE、Gecko、Chrome、Safariなど)で機能するはずです。

MSIEにはclipboardData.getData()がありますが、私は他のブラウザのための同様の機能を見つけることができませんでした。

270
Alex

この答えを書いて以来状況は変わりました:Firefoxがバージョン22でサポートを追加したので、すべての主要なブラウザは現在ペーストイベントでクリップボードデータにアクセスすることをサポートします。例については、 Nico Burnsの答え を参照してください。

これまでは、ブラウザ間ではこれは不可能でした。理想はpasteイベント で貼り付けられたコンテンツを取得できることですが、最近のブラウザ では可能ですが、古いブラウザ(特にFirefox <22)では不可能です。

古いブラウザをサポートする必要がある場合、できることはかなり複雑で、Firefox 2以降、IE 5.5以降、およびSafariやChromeなどのWebKitブラウザで機能するというちょっとしたハックです。 TinyMCEとCKEditorの最近のバージョンではこのテクニックが使われています。

  1. キー押下イベントハンドラを使用してctrl-v/shift-insイベントを検出する
  2. そのハンドラーで、現在のユーザー選択を保存し、textarea要素を画面外(左に-1000pxなど)に追加し、designModeをオフにしてtextareaでfocus()を呼び出すと、キャレットが移動してペーストが効果的にリダイレクトされます。
  3. Textarea値を格納し、textareaをドキュメントから削除し、designModeをオンに戻し、ユーザーの選択を復元してテキストを貼り付ける別の関数を呼び出すために、イベントハンドラで非常に短いタイマー(たとえば1ミリ秒)を設定します。

これはキーボードの貼り付けイベントにのみ有効で、コンテキストメニューや編集メニューからの貼り付けはできません。 pasteイベントが発生する頃には、キャレットをテキストエリアにリダイレクトするには遅すぎます(少なくとも一部のブラウザでは)。

まれにFirefox 2をサポートする必要がある場合は、そのブラウザでWYSIWYGエディタのiframeのドキュメントではなく、親のドキュメントにtextareaを配置する必要があることに注意してください。

139
Tim Down

解決策1(プレーンテキストのみでFirefox 22以降が必要)

IE 6以降、FF 22以降、Chrome、Safari、Edgeで動作します(IE 9以降でのみテストされていますが、より低いバージョンでも動作するはずです)。

HTMLまたはFirefox <= 22の貼り付けのサポートが必要な場合は、解決策2を参照してください。

HTML

<div id='editableDiv' contenteditable='true'>Paste</div>

JavaScript

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

JSFiddle: https://jsfiddle.net/swL8ftLs/12/

このソリューションではgetData関数にパラメータ 'Text'を使用していますが、これは標準ではありません。ただし、執筆時点ではすべてのブラウザで機能します。


解決策2(HTML版、Firefox用の<= 22)

IE6 +、FF 3.5+、Chrome、Safari、Edgeでテスト済み

HTML

<div id='div' contenteditable='true'>Paste</div>

JavaScript

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

JSFiddle: https://jsfiddle.net/nicoburns/wrqmuabo/23/

説明

onpastedivイベントにはhandlePaste関数がアタッチされていて、単一の引数(pasteイベントのeventオブジェクト)が渡されています。私たちにとって特に興味深いのは、このイベントのclipboardDataプロパティで、ブラウザ以外のブラウザでクリップボードにアクセスできるようにすることです。 IEで同等のものはwindow.clipboardDataですが、これは少し異なるAPIを持ちます。

下記の参考文献のセクションを参照してください。


handlepaste関数:

この関数には2つの分岐があります。

最初のevent.clipboardDataの存在をチェックし、それがtypesプロパティに 'text/html'が含まれているかどうかをチェックします(typesDOMStringListメソッドを使ってチェックされるcontains、またはindexOfメソッドを使ってチェックされる文字列)。これらの条件がすべて満たされている場合は、 'text/plain'ではなく 'text/html'を使用することを除いて、解決策1と同様に進めます。これは現在ChromeとFirefox 22以降で動作します。

この方法がサポートされていない場合(他のすべてのブラウザ)、

  1. 要素の内容をDocumentFragmentに保存します
  2. 要素を空にする
  3. waitForPastedData関数を呼び出す

waitforpastedata関数:

この関数は最初に貼り付けられたデータをポーリングします(20msに1回)。これは、すぐには表示されないため必要です。データが表示されたら

  1. 編集可能なdivのinnerHTML(現在は貼り付けられたデータ)を変数に保存します
  2. DocumentFragmentに保存されているコンテンツを復元します
  3. 取得したデータで 'processPaste'関数を呼び出します

processpaste関数:

貼り付けたデータで任意のことをします。この場合、私たちはデータに警告します、あなたはあなたが好きなことを何でもすることができます。あなたはおそらく何らかの種類のデータサニタイズプロセスを通して貼り付けられたデータを走らせたいでしょう。


カーソル位置の保存と復元

実際の施設では、おそらく選択を前に保存し、後で元に戻すことをお勧めします( contentEditable <div>にカーソル位置を設定します )。その後、ユーザーが貼り付け操作を開始したときにカーソルがあった位置に貼り付けたデータを挿入できます。

リソース:

DocumentFragmentの使用を提案し、clipboardData.typesの代わりに文字列ではなくDOMStringListを使用しているためFirefoxでエラーが発生したことをお詫び申し上げますTim Downに感謝します。

283
Nico Burns

単純版:

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のテスト済み。


注:サーバー側でも入出力をチェックすることを忘れないでください( PHPストリップのように)タグ

119
l2aelba

ライブデモ

Chrome/FF/IE11でテスト済み

これらのブラウザはそれぞれの新しい行に<div>要素を追加するというChrome/IEの煩わしさがあります。これについての投稿があります ここ そしてcontenteditable要素を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>
25
vsync

私は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>

コード全体を1つのhtmlファイルにコピーして貼り付け、クリップボードからテキストを(ctrl-vを使用して)文書の任意の場所に貼り付けます。

私はIE9とFirefox、ChromeとOperaの新しいバージョンでそれをテストしました。かなりうまくいきます。また、この機能を試すために彼が好むどんなキーの組み合わせでも使用できるのは良いことです。もちろん、jQueryのソースを含めることを忘れないでください。

このコードをお気軽に使用してください。改善点や問題点がある場合は投稿してください。私はJavascript開発者ではないので、何かを逃したかもしれません(=>あなた自身のテストをしてください)。

15
JanM

l2aelbaに基づいています。これは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);
            }
        }
    });
10
tmorell

これはsetTimeout()を使用しません。

私は この 素晴らしい記事をクロスブラウザサポートを達成するために使っています。

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

このコードは貼り付け前の選択ハンドルで拡張されています。 demo

9
user669677

これは、onpasteイベントとミューテーションオブザーバをサポートするすべてのブラウザで機能するはずです。

このソリューションはテキストだけを取得することを超えたステップを踏みます、それは実際にそれが要素に貼り付けられる前に貼り付けられたコンテンツを編集することを可能にします。

それは満足のいく、onpasteイベント(すべての主要ブラウザでサポートされています)および突然変異観察者(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);

ミューテーションオブザーバは非同期に呼び出されるため、pasteCallBackをバインドする必要があります。

ステップ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または他の手段を使ってpasteイベントを起動します
  2. 貼り付けイベントで、contenteditableを持つ新しい要素が作成されます(contenteditableを持つ要素は昇格された特権を持ちます)
  3. ターゲット要素のキャレット位置が保存されます。
  4. フォーカスは新しい要素に設定されます
  5. コンテンツは新しい要素に貼り付けられ、DOMにレンダリングされます。
  6. ミューテーションオブザーバはこれをキャッチします(ドムツリーとコンテンツへのすべての変更を登録します)。その後、突然変異イベントを発生させます。
  7. 貼り付けられたコンテンツのDOMは、変数に複製されてコールバックに返されます。一時的な要素は破壊されます。
  8. コールバックは複製されたDOMを受け取ります。キャレットが復元されます。ターゲットに追加する前にこれを編集できます。素子。この例では、キャレットの保存/復元とHTMLの要素への貼り付けにTim Downs関数を使用しています。

Tim Down氏 に感謝します。

貼り付けイベントで文書に貼り付けられたコンテンツを取得する

5
Mouser

貼り付けられたテキストをきれいにするおよび現在選択されているテキストを貼り付けられたテキストで置き換える問題はかなり簡単です。

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

これはNicoの答えに対するコメントには長すぎた。私はもうFirefoxで動くとは思わないし(コメントによると)、そのまま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にはtypesname__が実装されていないDOMStringListname__であるtestname__フィールドがあるからです。

次のFirefoxは、フォーカスがcontenteditable=trueフィールドにない限り、貼り付けを許可しません。

最後に、Firefoxは、フォーカスがcontenteditable=trueだけでなくtextareaname__(またはおそらく入力)にない限り、確実に貼り付けを許可しません。

  • display:noneではありません
  • visibility:hiddenではありません
  • ゼロサイズではない

JS VNCエミュレータ上で貼り付けができるようにテキストフィールドを非表示にしようとしていました(つまり、リモートクライアントに行き、実際に貼り付けるtextareaname__などはありませんでした)。上記のテキストフィールドを非表示にしようとするとうまくいく場合がありましたが、通常は2度目の貼り付けに失敗しました(または同じデータを2回貼り付けるのを防ぐためにクリアされました)。 focus()にもかかわらずそれです。私が思いついた解決策は、それをz-order: -1000に配置し、それをdisplay:noneにし、それを1px 1pxにし、そしてすべての色を透明にすることでした。やあ.

Safariでは、上記の2番目の部分が適用されます。つまり、display:noneではないtextareaname__が必要です。

4
abligh

テキスト入力に貼り付けている場合は私には解決策は貼り付けイベントにイベントリスナーを追加することです。貼り付けイベントは入力が変更される前にテキストが変更される前に行われるので、貼り付けハンドラ内で遅延関数を作成し、その中で入力ボックスで貼り付けで行われた変更を確認します。

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

この解決策は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フィルタについていくらかの仕事をするべきです

2
TomWan

これは私のために働いた:

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);" />
2
Timmy Duncan
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;
1
Ivan

簡単な解決策:

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

このようにしてこれを行うことができます。

貼り付け前後のイベントにこの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を持つので新しく挿入されたものを識別することができます、そしてあなたはあなたの古いフォーマットを保つことができるように新しく作成された要素から単にstyle/class/id属性を取り除きます。

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

ブラウザでその内容を編集可能なdivに通常どおりに貼り付けて、貼り付け後にカスタムテキストスタイルに使用されるすべてのspan要素をテキスト自体と交換します。これはInternet Explorerや私が試した他のブラウザではうまくいくようです...

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

このソリューションは、あなたがjQueryを実行していて、あなたが編集可能なあなたのコンテンツのテキストフォーマットを望まないと仮定していますdivs.

プラス面は、それが超単純だということです。

1
DaveAlger

これは上記の既存のコードですが、私は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);
    }        
});
0
Ravi Selvaraj