知識の枝

"All is well"

クリック&コピーをhtmlに実装する

約210日前 2021年4月30日15:49
デジタル
HTML CSS

改訂履歴


2021/4/28 投稿
2021/5/20 改訂1「4.2 - Clipboard API」を追加

1. 背景


Djangoを使った開発中に覚えたことを備忘録として残します。

今回はhtmlに埋め込まれた文字列をワンクリックでクリップボートに保存する方法を解説します。


2. ゴール


htmlテンプレートに生成された文字列をワンクリックでコピーする。


3. はじめに


やりたいことのイメージはこんな感じです。



上記はタスクアプリの画面です。
完了したタスクにリンク機能を付けたかったので「URL」を入力するフィールドを設定してあります。
models.py
class Task(models.Model):
"""Task info"""
task = models.CharField(verbose_name='やること', max_length=255, blank=True, null=True)
link = models.CharField(verbose_name='リンク', max_length=255, blank=True, null=True) #この部分です。

def __str__(self):
return self.task
完了したタスクの「link」フィールドにURLが入っていた場合、その内容をコピーできるようにしたいと思います。


4. ワンクリックコピー


4.1 - execCommand("Copy")


htmlテンプレートで「link」が入力されているか否かで処理を分岐します。

コピーの手法はここを参考にさせて頂きました。ありがとうございます。
clipboard-bootstrap.html

html
タスクに「link」が入力されていたら実行されるコード
{% if task.link %}
<div class="form-group row">
<input id="CopyTarget" value="{{task.link}}" type="hidden">
<button type="button" class="btn btn-outline-success" onclick="CopyToClipboard()" data-toggle="tooltip" data-placement="top" title="リンクをコピー">
<i class="fas fa-copy"></i>
</button>
</div>
{% endif %}


コピーの対象となる内容(URL)を「inputタグ」に入力します。
<input id="CopyTarget" value="{{task.link}}" type="hidden">
「value="●●"」の●●の部分がコピーされる部分です。

今回はタスクモデルの「link」フィールドが対象ですので、「value="{{ task.list }}"」となっています。

「task」の部分は
「contextとしてviews.pyのビューで定義されている文字」
もしくは
「テンプレート内for文でカウンタ変数として定義されている文字」 です。

「type="hidden"」とすることでコピー対象の文字列がウェブページ上に表示されない ようにしています。
ここを参考にさせて頂きました。ありがとうございます。
隠しフィールドを設置する


次にクリックするボタンを設置します。
スペースの都合上ボタンは小さくしたかったのでアイコンを採用しています。
<i class="fas fa-copy"></i>
上記はFontAwesomeです。

ボタン枠の見た目はBootstrapを採用しています。
class="btn btn-outline-success"


クリックしたらコピーするスクリプトを実行するよう設定しています。
onclick="CopyToClipboard()"



さて、そのスクリプトをhtml内に設置しましょう。
スクリプトは下記です。
<script>
function CopyToClipboard() {
// コピー対象をJavaScript上で変数として定義する
var copyTarget = document.getElementById("CopyTarget");

// コピー対象のテキストを選択する
copyTarget.select();

// 選択しているテキストをクリップボードにコピーする
document.execCommand("Copy");

// コピーをお知らせする
alert("コピーしました : " + copyTarget.value);
}
</script>

「copyTarget」という変数を用意し、html内の「CopyTarget」IDを持つ要素を対象とします。
var copyTarget = document.getElementById("CopyTarget");


次に対象要素の内容を選択します。今回の場合「value="{{task.link}}"」の部分です。
copyTarget.select();


コピーを実行します。
document.execCommand("Copy");


最後に「コピーしました」とアラートを出します。
alert("コピーしました : " + copyTarget.value);


これでクリックしてコピーする機能が実装されました。





改訂1

4.2 - Clipboard API


上記4.1項の方法ではコピー出来ない事象が発生した為、別の方法を解説します。
こちらは動作確認が取れました。

「Clipboard API」というものを使います。

4.1項と同様にJavascriptを使用して実装します。

下記コードを<body>タグの好きな場所に設置して下さい。
html
<script>
function copyTextToClipboard(text) {
navigator.clipboard.writeText(text)
alert("コピーしました : " + text);
}
</script>

「text」という変数の部分にコピーさせたい文字列を渡します。

html内での使い方の例です。
html
<button type="button" class="btn btn-outline-success" onclick="copyTextToClipboard('exampletext')" data-toggle="tooltip" data-placement="top" title="リンクをコピー">
<i class="fas fa-copy"></i>
</button>


スクリプトの呼び出し方は「onclick」て行います。
onclick="copyTextToClipboard('exampletext')"


ここでは「copyTextToClipboard」というスクリプトに「exampletext」という文字列を渡しました。

スクリプト内の「text」が上記「exampletext」に置き換わって実行されます。
<script>
function copyTextToClipboard(exampletext) {
navigator.clipboard.writeText(exampletext)
alert("コピーしました : " + exampletext);
}
</script>
動作は4.1項と全く同じになります。

1点気を付けるのはスクリプトに渡す文字列は「''」で囲みましょう。



5. さいごに


デザイン上の問題でコピー対象を表示させたくないとき。
コピー対象をドラッグ&「Ctrl+C」する動作がめんどくさいとき。

今回の手法が便利なので取り入れて下さい。