JavaScript でクリップボードにコピーするにはどうすればいいですか? 質問する

JavaScript でクリップボードにコピーするにはどうすればいいですか? 質問する

テキストをクリップボードにコピーするにはどうすればよいですか (マルチブラウザ)?

関連している:Trello はどのようにしてユーザーのクリップボードにアクセスするのでしょうか?

ベストアンサー1

概要

クリップボードにコピーするための主なブラウザ API は 3 つあります。

  1. 非同期クリップボード API [navigator.clipboard.writeText]

    • テキスト中心の部分は以下で利用可能Chrome 66 (2018 年 3 月)
    • アクセスは非同期であり、JavaScript の約束セキュリティ ユーザー プロンプト (表示される場合) がページ内の JavaScript を中断しないように記述できます。
    • 変数からテキストを直接クリップボードにコピーできます。
    • HTTPS 経由で提供されるページでのみサポートされます。
    • Chrome 66 では、非アクティブなタブは権限プロンプトなしでクリップボードに書き込むことができます。
  2. document.execCommand('copy')非推奨)��

    • 2015 年 4 月現在、ほとんどのブラウザがこれをサポートしています (以下のブラウザ サポートを参照)。
    • アクセスは同期的です。つまり、セキュリティ プロンプトの表示やユーザーによる操作が完了するまで、ページ内の JavaScript は停止されます。
    • テキストは DOM から読み取られ、クリップボードに配置されます。
    • 2015 年 4 月までのテストでは、クリップボードへの書き込み中に権限プロンプトが表示されたのは Internet Explorer のみでした。
  3. コピーイベントのオーバーライド

    • クリップボードAPIドキュメントを参照コピーイベントのオーバーライド
    • 任意のコピー イベントからクリップボードに表示される内容を変更でき、プレーン テキスト以外の他の形式のデータを含めることができます。
    • 質問に直接答えていないため、ここでは説明しません。

一般的な開発メモ

コンソールでコードをテストしている間は、クリップボード関連のコマンドが機能することを期待しないでください。通常、ページはアクティブである必要があります (非同期クリップボード API) または、( document.execCommand('copy')) がクリップボードにアクセスできるようにするには、ユーザーの操作 (ユーザークリックなど) が必要です。詳細については、以下を参照してください。

重要(2020/02/20にここに記載)

この投稿は元々クロスオリジン IFRAME の権限の廃止その他IFRAME「サンドボックス」埋め込まれたデモの「コード スニペットの実行」ボタンと「codepen.io の例」が一部のブラウザー (Chrome や Microsoft Edge を含む) で動作しないようにします。

開発するには、独自の Web ページを作成し、そのページを HTTPS 接続経由で提供してテストおよび開発を行います。

コードが動作することを示すテスト/デモ ページを次に示します。https://deanmarktaylor.github.io/clipboard-test/

非同期 + フォールバック

新しい Async Clipboard API のブラウザー サポートのレベルにより、document.execCommand('copy')ブラウザー カバレッジを良好にするには、このメソッドにフォールバックする必要があるでしょう。

以下に簡単な例を示します (このサイトに埋め込むと動作しない可能性があります。上記の「重要」の注意をお読みください)。

function fallbackCopyTextToClipboard(text) {
  var textArea = document.createElement("textarea");
  textArea.value = text;
  
  // Avoid scrolling to bottom
  textArea.style.top = "0";
  textArea.style.left = "0";
  textArea.style.position = "fixed";

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Fallback: Copying text command was ' + msg);
  } catch (err) {
    console.error('Fallback: Oops, unable to copy', err);
  }

  document.body.removeChild(textArea);
}
function copyTextToClipboard(text) {
  if (!navigator.clipboard) {
    fallbackCopyTextToClipboard(text);
    return;
  }
  navigator.clipboard.writeText(text).then(function() {
    console.log('Async: Copying to clipboard was successful!');
  }, function(err) {
    console.error('Async: Could not copy text: ', err);
  });
}

var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

(codepen.io の例は動作しない可能性があります。上記の「重要」の注意をお読みください) このスニペットは Stack Overflow の埋め込みプレビューではうまく動作しないことに注意してください。ここで試すことができます:https://codepen.io/DeanMarkTaylor/pen/RMRaJX?editors=1011

非同期クリップボード API

Chrome 66 では、権限 API を介して「権限をリクエスト」し、クリップボードへのアクセスをテストする機能があることに注意してください。

var text = "Example text to appear on clipboard";
navigator.clipboard.writeText(text).then(function() {
  console.log('Async: Copying to clipboard was successful!');
}, function(err) {
  console.error('Async: Could not copy text: ', err);
});

document.execCommand('コピー')

この投稿の残りの部分では、API のニュアンスと詳細について説明しますdocument.execCommand('copy')

ブラウザのサポート

JavaScriptは document.execCommand('copy') サポートが拡大しました。ブラウザの更新については、以下のリンクを参照してください。 非推奨)��

簡単な例

(このサイトに埋め込むと動作しない可能性があります。上記の「重要」の注意をお読みください)

var copyTextareaBtn = document.querySelector('.js-textareacopybtn');

copyTextareaBtn.addEventListener('click', function(event) {
  var copyTextarea = document.querySelector('.js-copytextarea');
  copyTextarea.focus();
  copyTextarea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }
});
<p>
  <button class="js-textareacopybtn" style="vertical-align:top;">Copy Textarea</button>
  <textarea class="js-copytextarea">Hello I'm some text</textarea>
</p>

複雑な例: 入力を表示せずにクリップボードにコピーする

上記の簡単な例は、画面上にtextareaまたは要素が表示されている場合に最適です。input

場合によっては、input/textarea要素を表示せずにテキストをクリップボードにコピーしたいことがあります。これは、この問題を回避する方法の一例です (基本的には、要素を挿入し、クリップボードにコピーし、要素を削除します)。

Google Chrome 44、Firefox 42.0a1、Internet Explorer 11.0.8600.17814 でテスト済み。

(このサイトに埋め込むと動作しない可能性があります。上記の「重要」の注意をお読みください)

function copyTextToClipboard(text) {
  var textArea = document.createElement("textarea");

  //
  // *** This styling is an extra step which is likely not required. ***
  //
  // Why is it here? To ensure:
  // 1. the element is able to have focus and selection.
  // 2. if the element was to flash render it has minimal visual impact.
  // 3. less flakyness with selection and copying which **might** occur if
  //    the textarea element is not visible.
  //
  // The likelihood is the element won't even render, not even a
  // flash, so some of these are just precautions. However in
  // Internet Explorer the element is visible whilst the popup
  // box asking the user for permission for the web page to
  // copy to the clipboard.
  //

  // Place in the top-left corner of screen regardless of scroll position.
  textArea.style.position = 'fixed';
  textArea.style.top = 0;
  textArea.style.left = 0;

  // Ensure it has a small width and height. Setting to 1px / 1em
  // doesn't work as this gives a negative w/h on some browsers.
  textArea.style.width = '2em';
  textArea.style.height = '2em';

  // We don't need padding, reducing the size if it does flash render.
  textArea.style.padding = 0;

  // Clean up any borders.
  textArea.style.border = 'none';
  textArea.style.outline = 'none';
  textArea.style.boxShadow = 'none';

  // Avoid flash of the white box if rendered for any reason.
  textArea.style.background = 'transparent';


  textArea.value = text;

  document.body.appendChild(textArea);
  textArea.focus();
  textArea.select();

  try {
    var successful = document.execCommand('copy');
    var msg = successful ? 'successful' : 'unsuccessful';
    console.log('Copying text command was ' + msg);
  } catch (err) {
    console.log('Oops, unable to copy');
  }

  document.body.removeChild(textArea);
}


var copyBobBtn = document.querySelector('.js-copy-bob-btn'),
  copyJaneBtn = document.querySelector('.js-copy-jane-btn');

copyBobBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Bob');
});


copyJaneBtn.addEventListener('click', function(event) {
  copyTextToClipboard('Jane');
});
<div style="display:inline-block; vertical-align:top;">
  <button class="js-copy-bob-btn">Set clipboard to BOB</button><br /><br />
  <button class="js-copy-jane-btn">Set clipboard to JANE</button>
</div>
<div style="display:inline-block;">
  <textarea class="js-test-textarea" cols="35" rows="4">Try pasting into here to see what you have on your clipboard:

  </textarea>
</div>

その他の注意事項

ユーザーがアクションを起こした場合にのみ機能する

すべてのdocument.execCommand('copy')呼び出しは、クリック イベント ハンドラーなどのユーザー アクションの直接の結果として実行する必要があります。これは、ユーザーが予期しないときにクリップボードが混乱するのを防ぐための対策です。

を参照してくださいGoogle Developersの投稿はこちら詳細については。

クリップボード API

完全な Clipboard API ドラフト仕様は、次の場所にあります。クリップボード

サポートされていますか?

  • document.queryCommandSupported('copy')trueコマンドがブラウザでサポートされている場合は返されます。
  • 今呼び出された場合に成功するかどうかdocument.queryCommandEnabled('copy')返します。コマンドがユーザーが開始したスレッドから呼び出され、その他の要件が満たされていることを確認します。truedocument.execCommand('copy')

ただし、ブラウザの互換性の問題の例として、2015 年 4 月から 10 月までの Google Chrome は、コマンドがユーザーが開始したスレッドから呼び出された場合trueにのみ戻りました。document.queryCommandSupported('copy')

互換性の詳細については下記をご覧ください。

ブラウザ互換性の詳細

ユーザーのクリックの結果として呼び出される/ブロックdocument.execCommand('copy')でラップされた単純な呼び出しでは、最大限の互換性が得られますが、次の使用法にはいくつかの条件があります。trycatch

document.execCommand、 、document.queryCommandSupported呼び出しはすべて/ブロックdocument.queryCommandEnabledで囲む必要がありますtrycatch

異なるブラウザの実装とブラウザのバージョンでは、 を返す代わりに呼び出されたときに異なるタイプの例外がスローされますfalse

さまざまなブラウザの実装はまだ流動的であり、クリップボード APIまだドラフト段階なので、テストを忘れずに行ってください。

おすすめ記事