選択した文字をclipboardにコピーするbookmarkletをchatGPTで添削する
2023-02-16 10:07:23 転記した
空行やインデント、コードブロック記法は手作業で加工した
takker.icon
以下は、任意のウェブサイトで選択している文字列をクリップボードにコピーするブックマークレットです。
このコードにバグがあれば、指摘して下さい。またより効率的な書き方や、様々な状況(エラー処理やクロスブラウザ対応)に対処できるように書き換えられる方法があれば、それも教えて下さい。
code:js
javascript:(async()=>{const text=window.getSelection();try{await navigator.clipboard.writeText(text);}catch(){alert("Failed to copy.");}})()
chatGPT.icon
このコードは、ウェブページで選択されているテキストをクリップボードにコピーするブックマークレットですね。
このコードには、次のような問題点があります。
1. クリップボード API の writeText メソッドは、非標準的な API であり、すべてのブラウザでサポートされているわけではありません。そのため、クリップボード API がサポートされていないブラウザでは、エラーが発生します。
2. writeText メソッドは、Promise オブジェクトを返します。そのため、try-catch 構文でエラーをキャッチしようとしていますが、Promise の reject ハンドラーを指定する必要があります。
3. 例外処理として、alert 関数を呼び出していますが、このような処理はより良いエラー処理とは言えません。
このコードをより効率的な書き方や、様々な状況に対処できるように書き換える方法を示します。
1. クリップボード API のサポート状況を確認する
まず、クリップボード API がサポートされているかどうかを確認する必要があります。
code:js
if (navigator.clipboard) {
// クリップボード API がサポートされている場合
} else {
// クリップボード API がサポートされていない場合
}
2. writeText メソッドを使用してクリップボードにコピーする
クリップボード API がサポートされている場合、writeText メソッドを使用してクリップボードにコピーできます。
code:js
navigator.clipboard.writeText(text).then(function() {
// コピーに成功した場合
}).catch(function(error) {
// コピーに失
takker.icon
続けて下さい
chatGPT.icon
3. 例外処理を追加する
クリップボード API の writeText メソッドが reject された場合、エラーを処理する必要があります。
代替手段として、以下のように、HTML5 の execCommand メソッドを使用することもできます。execCommand メソッドは、クリップボードにコピーする際にも使用できます。
code:js
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(function() {
// コピーに成功した場合
}).catch(function(error) {
// コピーに失敗した場合
// HTML5 の execCommand メソッドを使用する
const copyFrom = document.createElement("textarea");
copyFrom.textContent = text;
document.body.appendChild(copyFrom);
copyFrom.select();
document.execCommand("copy");
document.body.removeChild(copyFrom);
});
} else {
// クリップボード API がサポートされていない場合
// HTML5 の execCommand メソッドを使用する
const copyFrom = document.createElement("textarea");
copyFrom.textContent = text;
document.body.appendChild(copyFrom);
copyFrom.select();
document.execCommand("copy");
document.body.removeChild(copyFrom);
}
以上が、より効率的な書き方や、様々な状況に対処できるように書き換えられる方法です。
takker.icon
ありがとうございます。いくつか質問があります。
問題点2について
try-catch構文ではPromiseのエラーをキャッチできないと書かれましたが、非同期のアロー関数で包んであるので、try-catch構文でキャッチできるのではないでしょうか?
chatGPT.icon
そうですね。非同期のアロー関数でPromiseを包んでいるため、その中でのエラーはtry-catch構文でキャッチすることができます。
ですが、問題は、try-catch構文でエラーをキャッチすること自体が正しい処理であるかどうかです。
Promise の reject ハンドラーを指定することで、Promise の reject された状態を処理することができます。そのため、Promise の reject ハンドラーを使用することをおすすめします。
以下は、Promise の reject ハンドラーを使用した例です。
code:js
navigator.clipboard.writeText(text).then(function() {
// コピーに成功した場合
}).catch(function(error) {
// コピーに失敗した場合
});
ちなみに、非同期のアロー関数でPromiseを包んでいる場合、async-await構文を使用することもできます。
以下は、async-await構文を使用した例です。
code:js
async function copyToClipboard() {
try {
await navigator.clipboard.writeText(text);
} catch (error) {
// コピーに失敗した場合
}
}
takker.icon
rejectではなくtry-catch構文を使うことによるデメリットがわかりませんでしたが、ひとまず置いておきます。
次の質問です。writeTextが失敗した場合にexecCommandを実行するようコーディングなされたようですが、execCommandも失敗してしまった場合はどのような処理を書けばいいでしょうか?
execCommandは最新のFirefoxなどで利用できないので、失敗する可能性は十分あります。
chatGPT.icon
そうですね。execCommand メソッドも、すべてのブラウザでサポートされているわけではありません。そのため、execCommand メソッドが失敗しても、対応する処理を書く必要があります。
以下は、execCommand メソッドが失敗した場合に、代替手段として alert 関数を使用する例です。
code:js
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(function() {
// コピーに成功した場合
}).catch(function(error) {
// コピーに失敗した場合
// HTML5 の execCommand メソッドを使用する
try {
const copyFrom = document.createElement("textarea");
copyFrom.textContent = text;
document.body.appendChild(copyFrom);
copyFrom.select();
document.execCommand("copy");
document.body.removeChild(copyFrom);
} catch (error) {
// execCommand メソッドが失敗した場合
alert("Failed to copy.");
}
});
} else {
// クリップボード API がサポートされていない場合
// HTML5 の execCommand メソッドを使用する
try {
const copyFrom = document.createElement("textarea");
copyFrom.textContent = text;
document.body.appendChild(copyFrom);
copyFrom.select();
document.execCommand("copy");
document.body.removeChild(copyFrom);
} catch (error) {
// execCommand メソッドが失敗した場合
alert("Failed to copy.");
}
}
もちろん、alert 関数ではなく、別のエラー処理を行うこともできます。
例えば、HTML5 の Notification API を使用して、通知を表示するようにするといったこともできます。
以上が、execCommand メソッドが失敗した場合に対処する方法です。