概観
クリップボードにコピーするための3つの主要なブラウザーAPIがあります。
- 非同期クリップボードAPI
[navigator.clipboard.writeText]
- Chrome 66(2018年3月)でテキストに焦点を当てた部分が利用可能
- アクセスは非同期であり、JavaScript Promiseを使用します。セキュリティユーザープロンプト(表示されている場合)がページ内のJavaScriptを中断しないように記述できます。
- テキストは変数から直接クリップボードにコピーできます。
- HTTPS経由で提供されるページでのみサポートされます。
- Chrome 66では、アクティブなタブのページは、権限のプロンプトなしでクリップボードに書き込むことができます。
document.execCommand('copy')
- ほとんどのブラウザーは、2015年4月現在、これをサポートしています(下記のブラウザーサポートを参照)。
- アクセスは同期的です。つまり、セキュリティプロンプトの表示とユーザーインタラクションを含めて完了するまで、ページ内のJavaScriptを停止します。
- テキストはDOMから読み取られ、クリップボードに配置されます。
- 2015年4月までのテスト中、クリップボードへの書き込み中にアクセス許可のプロンプトが表示されるのはInternet Explorerのみでした。
- コピーイベントのオーバーライド
- コピーイベントのオーバーライドについては、クリップボード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( 'copy')
この投稿の残りの部分では、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 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 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 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
完全なクリップボード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はまだドラフトであるため、必ずテストを行ってください。