前回は、Bloggerとして、コードを綺麗に表示するためのJavaScriptライブラリである「highlight.js」の使い方について解説しました。今回は、その「highlight.js」を使用して表示したコードブロックの右側にコピーボタンを配置し、クリックするとコードをコピーできる機能を実装したいと思います。
まだ「highlight.js」の導入方法が分からない場合は、前回の記事をご覧いただくか、以下の記事を確認してみてください。
それでは、まず最初に、今回作成するコードの実行イメージをご紹介します。投稿する記事のHTML内にある<pre>
と<code>
で囲まれた部分に対して処理を適用していきます。処理の具体的な内容は後ほど説明します。この要素にボタンを追加し、全体をコードコンテナーとして<div>
タグで囲むことで、特定のCSSを適用できるようにします。
その後、追加したコピーボタンがクリックされた際の処理を実装し、最後にボタンやコード部分のスタイリングに関するCSSを記述して、実装を完成させます。
まずは、以下のJavaScriptコードを、HTMLの</body>
タグの直前に挿入してください。
<script> //<![CDATA[
document.addEventListener("DOMContentLoaded", function() {
const codeBlocks = document.querySelectorAll("pre code");
codeBlocks.forEach(function(codeBlock) {
const codeContainer = document.createElement("div");
codeContainer.className = "code-container";
codeBlock.parentNode.insertBefore(codeContainer, codeBlock);
codeContainer.appendChild(codeBlock);
const copyButton = document.createElement("button");
copyButton.textContent = "Copy";
copyButton.className = "copy-button";
codeContainer.appendChild(copyButton);
copyButton.addEventListener("click", function() {
const codeText = codeBlock.textContent;
const tempTextArea = document.createElement("textarea");
tempTextArea.value = codeText;
document.body.appendChild(tempTextArea);
tempTextArea.select();
document.execCommand("copy");
document.body.removeChild(tempTextArea);
copyButton.textContent = "Copied!";
setTimeout(function() {
copyButton.textContent = "Copy";
}, 2000);
});
});
});
//]]></script>
次に、スタイリングを適用するためのカスタマイズ用CSSを、追加します
カスタマイズ版のCSSの入力方法がわからない場合は、こちらの記事を参考にしてください
.code-container {
position: relative;
margin: 2em 0;
padding: 0;
line-height: 1;
font-size: 15px;
background: #292f36;
border-radius: 4px;
overflow: hidden;
}
pre code {
display: block;
margin: 0;
padding: 2em 1em 1em;
line-height: 1.4;
overflow: auto;
color: #f8f8f8;
}
.copy-button {
position: absolute;
top: 0;
right: 0;
padding: 5px 10px;
background-color: #444;
border: none;
cursor: pointer;
font-size: 12px;
color: #fff;
transition: background-color 0.3s ease;
}
.copy-button:hover {
background-color: #666;
}
コードの解説
このコードは、HTMLページ内のコードブロックを選択し、それぞれのコードブロックにコピー用ボタンを追加するJavaScriptの処理を行います。コードがどのように構成されているか、以下に説明します。
コードの読み込み待ち
document.addEventListener("DOMContentLoaded", function() {
// ...
});
この部分は、HTML文書が読み込まれたときに実行される処理を定義しています。DOMContentLoaded
イベントは、HTMLの要素が解析され、構築された後に発生します。これにより、ページの構成が完了する前にJavaScriptが実行されるのを防ぐことができます。
コードブロックの選択
const codeBlocks = document.querySelectorAll("pre code");
この部分は、ページ内のすべての <pre>
タグ内の <code>
タグを選択しています。これにより、ページ内のすべてのコードブロックを取得できます。
各コードブロックに対する処理
codeBlocks.forEach(function(codeBlock) {
// ...
});
この部分は、codeBlocks
に対して forEach
メソッドを使用して、各コードブロックに対する処理を行います。各コードブロックに対して同じ手順が実行されます。
コードブロックを包む の作成と配置
const codeContainer = document.createElement("div");
codeContainer.className = "code-container";
codeBlock.parentNode.insertBefore(codeContainer, codeBlock);
codeContainer.appendChild(codeBlock);
この部分では、各コードブロックを包むための <div>
要素を作成し、その要素に対してクラス名を設定しています。そして、新しく作成した <div>
要素をコードブロックの前に挿入し、コードブロック自体をその中に移動させています。これにより、コードブロックをコピー用ボタンと共にまとめて操作できるようになります。
コピー用ボタンの追加とクリック時の処理
const copyButton = document.createElement("button");
copyButton.textContent = "Copy";
copyButton.className = "copy-button";
codeContainer.appendChild(copyButton);
copyButton.addEventListener("click", function() {
// ...
});
この部分は、各コードブロックの <div>
要素内にコピー用のボタンを追加しています。ボタンのテキストやクラス名を設定しています。また、コピー用ボタンがクリックされたときの処理を追加しています。
コードのコピーとボタンの状態変更
const codeText = codeBlock.textContent;
const tempTextArea = document.createElement("textarea");
tempTextArea.value = codeText;
document.body.appendChild(tempTextArea);
tempTextArea.select();
document.execCommand("copy");
document.body.removeChild(tempTextArea);
copyButton.textContent = "Copied!";
setTimeout(function() {
copyButton.textContent = "Copy";
}, 2000);
この部分では、ボタンがクリックされたときの具体的な処理が行われます。まず、コードブロック内のテキストを取得し、一時的なテキストエリアを作成してそのテキストを設定します。その後、テキストエリアを一時的に <body>
要素に追加し、テキストを選択してコピー操作を実行します。最後に、ボタンのテキストを “Copied!” に変更しています。
CSSの解説
-
.code-container:
position: relative;
: 要素の配置方法を指定しています。この場合、親要素に対して相対的な位置を使用します。margin: 2em 0;
: 上下のマージン(余白)を2emに設定しています。要素と要素の間に余白ができます。padding: 0;
: 要素内のコンテンツと要素の境界との間のパディング(余白)を0に設定しています。line-height: 1;
: 行の高さをフォントサイズに合わせて1に設定しています。行間の調整に影響します。font-size: 15px;
: テキストのフォントサイズを15ピクセルに指定しています。background: #292f36;
: 背景色をダークグレーに設定しています。border-radius: 4px;
: 要素の角の丸み(ボーダーの曲線の半径)を4ピクセルに設定しています。overflow: hidden;
: 要素内にコンテンツがはみ出た場合に表示を切り捨てる設定です。
-
pre code:
display: block;
: 要素をブロックレベル要素として表示するように指定しています。独自の行を占有します。margin: 0;
: 要素の外側のマージン(余白)を0に設定しています。padding: 2em 1em 1em;
: 要素内のパディング(余白)を設定しています。上に2em、下に1em、左右に1emのパディングを持ちます。line-height: 1.4;
: 行の高さを1.4に設定しています。行間の調整に影響します。overflow: auto;
: コンテンツが要素の範囲を超えた場合にスクロールバーを表示する設定です。color: #f8f8f8;
: テキストの色を白色に設定しています。
-
.copy-button:
position: absolute;
: 要素の配置方法を指定しています。この場合、親要素に対して絶対的な位置を使用します。top: 0; right: 0;
: 要素を親要素の右上隅に配置するための位置指定です。padding: 5px 10px;
: パディング(余白)を指定しています。上下に5px、左右に10pxの余白を持ちます。background-color: #444;
: ボタンの背景色をダークグレーに設定しています。border: none;
: ボーダー(枠線)をなしに設定しています。cursor: pointer;
: ボタン上にカーソルを持っていった際にポインターに変わるように指定しています。font-size: 12px;
: フォントサイズを12ピクセルに設定しています。color: #fff;
: テキストの色を白色に設定しています。transition: background-color 0.3s ease;
: 背景色の変化にトランジション効果を追加しています。
-
.copy-button:hover:
– background-color: #666;: ボタンにマウスホバーした際の背景色をやや明るいダークグレーに変更しています。
実際の表示例
高さ制限を入れたい場合
高さ制限が欲しい時は以下のようにCSSを書き換えることで適用できます。
pre code {
display: block;
margin: 0;
padding: 2em 1em 1em;
max-height: 240px;
line-height: 1.4;
overflow: auto;
color: #f8f8f8;
}
今回はBloggerで表示したコードの右側にコピーボタンを追加する方法を紹介しました。これを追加することでより読みやすい記事を作成できるようになると思いますのでぜひ実装してみてください。