- 動作確認したブラウザ
- Windows10 Pro 64bit
- GoogleC hrome 78.0
- Fire Fox 70.0
- Microsoft Edge 44.18362
- Internet Explorer バージョン11.418
- MacOS Mojave 10.14.6
- Google Chrome 78.0
- Fire Fox 70.0
- Safari 13.0
- Windows10 Pro 64bit
やりたいこと
[クリップボードへコピーする]ボタンをクリックすると画面に表示されている「コピー内容」がクリップボートに設定(コピー)されるようにしたい。
[コピー]ボタンでクリップボードへコピーする方法
後続に記載した[失敗したこと]で[(解決)...]となっているところには他の方法も記載しています。
function onClickCopy() {
// コピー対象のpタグオブジェクトを取得する.
let pTag = document.getElementById('copyTarget');
// コピー内容を選択する.
let range = document.createRange();
range.selectNodeContents(pTag);
let selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
// 選択したものをコピーする.
document.execCommand('copy');
// コピー内容の選択を解除する.
selection.removeAllRanges();
}
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" charset="utf-8">
<script src="https://code.jquery.com/jquery-1.11.0.min.js" integrity="sha256-spTpc4lvj4dOkKjrGokIrHkJgNA0xMS98Pw9N7ir9oI=" crossorigin="anonymous"></script>
<script src="copyUseJavaScript.js"></script>
</head>
<body>
<div id="area">
<p id="copyTarget">コピー内容</p>
<input type="button" id="copy" value="クリップボードへコピーする" onclick="onClickCopy();">
</div>
</body>
</html>
失敗したこと
コピーイベントを捕まえてClipboardAPIを利用したら、どこでコピーしても処理が動いてしまった。
- (参考)クリップボードを使ったコピーとペースト - Qiita
- (参考)Document.execCommand() - Web API | MDN
- (参考)ClipboardEvent.clipboardData - Web API | MDN
ボタンのクリック処理でコピーイベントを発生させて、そのイベントを捕まえてClipboard APIを利用してクリップボードへコピーしたい内容を設定した。結果、画面のどこかでコピーをすればボタンをクリックしなくても処理は動いてしまう。もう決まった文字以外がコピーできない状態に・・・・。
$(window).on('load', function () {
document.addEventListener('copy', function(e) {
// コピー内容を取得する.
let copyTarget = $('#copyTarget').text();
// クリップボートにコピー内容を設定する.
e.clipboardData.setData('text/plain' , copyTarget);
// もともとのコピーイベントを中止する.
e.preventDefault();
});
});
function onClickCopy() {
if(window.clipboardData){
// IEの場合の処理.
let copyTarget = $('#copyTarget').text();
window.clipboardData.setData('Text' , copyTarget);
} else {
// IE以外の場合の処理.
// コピーイベントを発生させる.
document.execCommand('copy');
}
}
(解決)ボタンクリックイベントでコピーイベントの処理を1回分だけ登録したらコピーできた。
コメントで @lhankor_mhy さんから教えていただいた方法です。once
オプションが決め手です。
Safariではコピーができませんでした。理由がよく判らなくてモヤつきます。
※. 動作確認はMacのブラウザでしかしていません。
function onClickCopy() {
// ...省略...
// IE以外の場合の処理.
// コピーイベントでの処理を登録する(1回のみ).
copyOverrideOnce(copyTarget);
// コピーイベントを発生させる.
document.execCommand('copy');
}
}
function copyOverrideOnce(s) {
document.addEventListener('copy', function(e) {
e.clipboardData.setData('text/plain', s);
e.preventDefault();
},
{once:true}
);
}
<p>
を選択状態にできなくてコピーできなかった。
document.execCommand('copy');
は選択されているものをコピーするので、コピー内容を選択できないとコピーできません。
最初は、pタグは選択できないことに気が付かず・・・jQueryを使わないでオブジェクトを取得したところエラーになって気が付きました。
function onClickCopy() {
// let pTag = $('#copyTarget');
let pTag = document.getElementById('copyTarget');
pTag.focus();
// ★★コピー内容を選択する...ことはpタグなのでできない★★
pTag.select();
// 選択したものをコピーする.
document.execCommand('copy');
}
(解決)<p>
を選択状態にしてコピーでた。
上記のサイト様を参考に(ほぼコピペ)したら<p>
を選択状態にしてコピーできました
コードは一番上に記載しているものです。
(解決)<p>
の内容を一時エリア(input)に設定して、そこを選択するようにしてコピーした。
以下の順番で処理してコピーしてみました。
-
<p>
の値を取得する - コピー内容を一時的に格納するinputオブジェクトを作成する
- inputオブジェクトをbodyの最後に追加する
- inputオブジェクトの内容を選択する
- 選択したものをコピーする
- 欠点:画面が狭い場合、動的にオブジェクトを配置するため画面が一瞬揺れる
コピー内容を設定する一時エリアを非表示にしたらコピーできなかった。
もしかしたら、「コピーできない」というより「選択できない(copyInput.select();
ができない)」のかもしれません。
document.execCommand('copy');
は選択されているものをコピーするので選択できないからコピーできないだけかもしれません。
function onClickCopy() {
// コピー内容を一時的に格納するinputオブジェクトを作成する.
let copyInput = $('<input type="text">');
// ★★表示しないとコピーされない★★
copyInput.css('display', 'none');
copyInput.val(copyTarget);
// inputオブジェクトをbodyの最後に追加する.
$('body').append(copyInput);
// inputオブジェクトの内容を選択する.
copyInput.focus();
copyInput.select();
// 選択したものをコピーする.
document.execCommand('copy');
// inputオブジェクトを削除する.
copyInput.remove();
}
コピー内容を一時的に格納するinputオブジェクトが見えてしまった。
一瞬だけど見えてしまった・・・inputだけでは調整しづらいです。
function onClickCopy() {
// コピー内容を一時的に格納するinputオブジェクトを作成する.
let copyInput = $('<input type="text">');
// ★★CSSをうまく設定しないと見えてしまいます★★
copyInput.css({'position':'absolute','right':'0'});
copyInput.val(copyTarget);
// inputオブジェクトをbodyの最後に追加する.
$('body').append(copyInput);
// inputオブジェクトの内容を選択する.
copyInput.focus();
copyInput.select();
// 選択したものをコピーする.
document.execCommand('copy');
// inputオブジェクトを削除する.
copyInput.remove();
}
(解決)コピー内容を一時的に格納するinputオブジェクトをdivオブジェクトで囲ってスタイルを設定して見えないようにした。
- (参考)要素を画面外で表示したいとき
function onClickCopy() {
// コピー内容を一時的に格納するinputオブジェクトを作成する.
let copyInput = $('<input type="text">');
copyInput.css({'position':'absolute','right':'0'});
copyInput.val(copyTarget);
// inputオブジェクトを子要素に持つdivオブジェクトを作成する.
let copyArea = $('<div>');
copyArea.css({'position':'absolute','left':'0'});
copyArea.append(copyInput);
// divオブジェクトをbodyの最後に追加する.
$('body').append(copyArea);
// inputオブジェクトの内容を選択する.
copyInput.focus();
copyInput.select();
// 選択したものをコピーする.
document.execCommand('copy');
// divオブジェクトを削除する.
copyArea.remove();
}