概要
クリップボードにコピーするための主要なブラウザー API は 3 つあります。
非同期クリップボード API [navigator.clipboard.writeText]
- Chrome 66 (2018 年 3 月)で利用可能なテキスト中心の部分
- アクセスは非同期で、JavaScript Promisesを使用します。セキュリティ ユーザー プロンプト (表示される場合) がページ内の JavaScript を中断しないように記述できます。
- テキストは、変数から直接クリップボードにコピーできます。
- HTTPS 経由で提供されるページでのみサポートされます。
- Chrome 66 ページでは、非アクティブなタブは、権限を求めるプロンプトなしでクリップボードに書き込むことができます。
document.execCommand('copy')
(非推奨)
- 2015 年 4 月までの時点で、ほとんどのブラウザーがこれをサポートしています (下記のブラウザー サポートを参照してください)。
- アクセスは同期的です。つまり、セキュリティ プロンプトの表示やユーザー操作が完了するまで、ページ内の JavaScript を停止します。
- テキストは DOM から読み取られ、クリップボードに配置されます。
- 2015 年 4 月までのテスト中、クリップボードへの書き込み中に許可プロンプトが表示されるのは Internet Explorer のみでした。
コピー イベントのオーバーライド
- コピー イベントのオーバーライドに関するクリップボード API ドキュメントを参照してください。
- コピー イベントからクリップボードに表示される内容を変更できます。プレーン テキスト以外の他の形式のデータを含めることができます。
- 質問への直接的な回答ではないため、ここでは説明しません。
一般的な開発ノート
コンソールでコードをテストしている間は、クリップボード関連のコマンドが機能するとは思わないでください。一般に、ページはアクティブ (Async Clipboard 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('コピー')
この投稿の残りの部分では、document.execCommand('copy')
API のニュアンスと詳細について説明します。
ブラウザのサポート
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
要素を表示せずにテキストをクリップボードにコピーしたいことがあります。これは、これを回避する方法の 1 つの例です (基本的に、要素を挿入し、クリップボードにコピーし、要素を削除します)。
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 ドラフト仕様は、
https ://w3c.github.io/clipboard-apis/ にあります。
サポートされていますか?
document.queryCommandSupported('copy')
true
コマンドが「ブラウザでサポートされている」場合に返されます。
- 今呼び出された場合に成功する場合は
document.queryCommandEnabled('copy')
戻ります。コマンドがユーザーが開始したスレッドから呼び出されたこと、およびその他の要件が満たされていることを確認します。true
document.execCommand('copy')
ただし、ブラウザーの互換性の問題の例として、2015 年 4 月から 10 月までの Google Chrome は、ユーザーが開始したスレッドからコマンドが呼び出された場合にのみ返さtrue
れました。document.queryCommandSupported('copy')
以下の互換性の詳細に注意してください。
ブラウザの互換性の詳細
ユーザーのクリックの結果として呼び出される/ブロックdocument.execCommand('copy')
でラップされた単純な呼び出しは、最も互換性のある使用法を取得しますが、以下にはいくつかの条件があります。try
catch
document.execCommand
、document.queryCommandSupported
またはへの呼び出しは、 /ブロックdocument.queryCommandEnabled
でラップする必要があります。try
catch
ブラウザの実装とブラウザのバージョンが異なると、 を返す代わりに呼び出されたときに、異なるタイプの例外がスローされますfalse
。
さまざまなブラウザーの実装はまだ流動的であり、Clipboard APIはまだドラフト段階であるため、忘れずにテストを行ってください。