web-dev-qa-db-ja.com

コピーイベントのevent.clipboardData.setData

私は多くの投稿を見てきましたが、標準とブラウザのサポートが常に変化しているように見えるため、次の2つの質問に対する明確な現在の答えを見つけることができませんでした。

  1. 「コピー」イベントハンドラー内でevent.clipboardData.setDataを使用してクリップボードを変更することは、標準に従って正当な操作ですか?

  2. Chrome/FF/Safari/IE/Chrome iOS/Android/iPhonesの最新バージョンはこれを正しくサポートしていますか?

18
kofifus

クリップボードAPIは、2016年の時点で実際に活発に開発されていましたが、それ以来物事は安定しています:

Event.clipboardData.setData()の使用がサポートされています

_'copy'_イベントハンドラー内でevent.clipboardData.setData()を使用してクリップボードを変更することは、仕様で許可されています(イベントが synthetic でない場合)。

変更がブラウザによって上書きされるのを防ぐために、イベントハンドラのデフォルトアクションを防ぐ必要があることに注意してください。

_document.addEventListener('copy', function(e){
  e.clipboardData.setData('text/plain', 'foo');
  e.preventDefault(); // default behaviour is to copy any selected text
});
_

コピーイベントをトリガーするには、execCommandを使用します

ブラウザUIを介してユーザーが行ったコピー要求を処理するだけでなく、コピーイベントをトリガーする必要がある場合は、document.execCommand('copy')を使用する必要があります。 clickハンドラーなどの特定のハンドラーでのみ機能します。

_document.getElementById("copyBtn").onclick = function() {
  document.execCommand('copy');
}
_

最新のブラウザは両方の方法をサポートしています

https://github.com/garykac/clipboard/blob/master/clipboard.md にはexecCommand(cut / copy / paste)の互換性テーブルがあります。

以下のスニペットを使用してこれをテストできます。結果をコメントしてください。

その他のリソース

テストケース

_window.onload = function() {
  document.addEventListener('copy', function(e){
    console.log("copy handler");
    if (document.getElementById("enableHandler").checked) {
      e.clipboardData.setData('text/plain', 'Current time is ' + new Date());
      e.preventDefault(); // default behaviour is to copy any selected text
    }
    // This is just to simplify testing:
    setTimeout(function() {
      var tb = document.getElementById("target");
      tb.value = "";
      tb.focus();
    }, 0);
  });
  document.getElementById("execCopy").onclick = function() {
    document.execCommand('copy'); // only works in click handler or other user-triggered thread
  }
  document.getElementById("synthEvt").onclick = function() {
    var e = new ClipboardEvent("copy", {dataType: "text/plain", data:"bar"});
    document.dispatchEvent(e);
  }
}_
_<html>
<input id="enableHandler" type="checkbox" checked>
<label for="enableHandler">Run clipboardData.setData('text/plain', ...) in the "copy" handler</label>
<p>Try selecting this text and triggering a copy using</p>
<ul>
    <li><button id="execCopy">document.execCommand('copy')</button> - should work.</li>
    <li><button id="synthEvt">document.dispatchEvent(clipboardEvent)</button> - should NOT work</li>
    <li>with keyboard shortcut - should work</li>
    <li>or from the context menu - should work</li>
</ul>
<p>If the "copy" handler was triggered, the focus will move to the textbox below automatically, so that you can try pasting from clipboard:</p>
<input type="text" id="target" size="80">_

非同期クリップボードAPIは、クリップボードを管理するより簡単な方法を提供します

実装されると、 _navigator.clipboard_ により、次のようなコードを記述できます。

_navigator.clipboard.writeText('Text to be copied')
  .then(() => {
    console.log('Text copied to clipboard');
  })
  .catch(err => {
    // This can happen if the user denies clipboard permissions:
    console.error('Could not copy text: ', err);
  });
_

Chrome 66は部分的な実装の出荷を開始し、 新しいAPIに関する記事 を公開しました。

38
Nickolay

独自のハンドラーを呼び出して削除する関数に変換することもできます

function copyStringToClipboard (string) {
    function handler (event){
        event.clipboardData.setData('text/plain', string);
        event.preventDefault();
        document.removeEventListener('copy', handler, true);
    }

    document.addEventListener('copy', handler, true);
    document.execCommand('copy');
}
13
Chad Scira

Copyイベントで要素IDをバインドし、選択したテキストを取得します。テキストを置換または変更できます。クリップボードを取得して、新しいテキストを設定します。正確なフォーマットを取得するには、タイプを「text/hmtl」に設定する必要があります。要素の代わりにドキュメントにバインドすることもできます。

 $(ElementId).bind('copy', function(event) {
    var selectedText = window.getSelection().toString(); 
    selectedText = selectedText.replace(/\u200B/g, "");

    clipboardData = event.clipboardData || window.clipboardData || event.originalEvent.clipboardData;
    clipboardData.setData('text/html', selectedText);

    event.preventDefault();
  });
3