localで構築したシステムのデータベースでクリックしたら「コピーできる機能があれば便利だねー」との意見をもらって実装。
localでSSLを使う方法もあるのだけど、今回はSSL無しのため、navigator.clipboard.writeText() が使えません。
現在は非推奨ですが document.execCommand('copy'); を使っていきます。
まずはわかりやすくコードを書きます。
<div class="input_box"><input type="text" value="test1" readonly></div>
<div class="input_box"><input type="text" value="test2" readonly></div>function copyToClipboardFallback(textfield) {
textfield.select();
try {
document.execCommand("copy");
console.log("クリップボードにコピーされました: " + textfield);
let span = document.createElement('span');
span.setAttribute("class","copied");
span.innerText = "コピーしました";
textfield.before(span);
} catch (err) {
console.error("クリップボードへのコピーに失敗しました: ", err);
}
}
let cp_inputs = document.querySelectorAll('input[type="text"]');
for (let i = 0; i < cp_inputs.length; i++) {
cp_inputs[i].addEventListener('click',function(){
copyToClipboardFallback(cp_inputs[i]);
},false);
}
CSSはコピーした際にコピーしましたとミニポップアップします。
@keyframes copied_anime{
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
div.input_box{
position:relative;
}
div.input_box .copied{
position: absolute;
top:-1em;
background: rgba(0, 0, 0, 0.5);
color:white;
font-size: 0.8em;
padding:1px 3px;
border-radius: 3px;
animation: copied_anime 1s ease-out forwards;
animation-delay: 400ms;
}
div.input_box input[type="text"]{
border:none;
padding:2px 2px;
}
こんな感じ。
JavaScript最適化
JavaScript最適化します。
非推奨されている書き方でしたので最適化。
async function copyToClipboardFallback(textfield) {
textfield.select();
try {
// navigator.clipboardを優先的に使用
if (navigator.clipboard) {
await navigator.clipboard.writeText(textfield.value);
} else {
document.execCommand("copy"); // 互換性のためのフォールバック
}
console.log("クリップボードにコピーされました: " + textfield.value);
// 「コピーしました」メッセージの表示処理
let span = textfield.previousElementSibling;
if (!span || !n_span.classList.contains("copied")) {
span = document.createElement("span");
span.className = "copied";
span.innerText = "コピーしました";
textfield.before(span);
// 数秒後にメッセージを削除
setTimeout(() => span.remove(), 1500);
}
} catch (err) {
console.error("クリップボードへのコピーに失敗しました: ", err);
}
}
document.querySelectorAll('input[type="text"]').forEach(input => {
input.addEventListener("click", () => copyToClipboardFallback(input));
});
