JavaScript

レシピ

文字列

文字列を置き換えてハイライト表示する

文字列の置き換えとHTMLを組み合わせて、ワード検索機能を想定したハイライト表示の実装方法について解説します。

この記事のポイント

  • replaceメソッドの第2パラメータに独自の関数を指定する
  • テキストを置き換えたときにHTMLタグを加える

目次

簡単なワード検索機能を実装する

文字列の置き換えを行うreplaceメソッドを使い、HTML要素に含まれるワードをem要素で囲むことでハイライト表示する機能の実装方法を解説します。
次のようなシンプルなワード検索のイメージです。

検索したいワードを入力して「検索」ボタンを押す

ここで検索ワードを入力して「検索」ボタンを押すと、次のように該当したワードがハイライトされます。

検索実行すると該当したワードをハイライトする

実動作のサンプルページはこちらをご覧ください。

まずは全体のソースコードを共有します。

コード例

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<title>簡単なワード検索のサンプルページ | GRAYCODE JavaScript</title>
	<script>
		window.addEventListener('DOMContentLoaded', function(){

			document.getElementById("button_search").addEventListener("click",function(){

				var p_elements = document.querySelectorAll('p');
				var search_word = document.getElementById("search_word").value;
				var reg = new RegExp( search_word, "gi");

				for(var pi=0; pi < p_elements.length; pi++) {

					var p_text = p_elements[pi].textContent;

					p_elements[pi].innerHTML = p_text.replace( reg, function( match_word){
						return "" + match_word + "";
					});			
				}
			});

		});
	</script>
	<style>
		input {
			margin-right: 10px;
			padding: 10px;
			width: 150px;
			height: 40px;
			font-size: 100%;
			border: 2px solid #333;
			border-radius: 5px;
			box-sizing: border-box;
			vertical-align: top;
		}
		button {
			padding: 0 20px;
			height: 40px;
			color: #fff;
			font-size: 100%;
			border: none;
			border-radius: 5px;
			background: #e3376c;
			vertical-align: top;
		}
		em {
			display: inline-block;
			padding: 0px 5px;
			font-weight: bold;
			font-style: normal;
			color: #333;
			background-color: #ecde00;
		}
	</style>
</head>
<body>
<h1>JavaScriptレシピ</h1>
<p>I like cat.</p>
<p>Cat is so pretty.</p>
<p>Black cat, White cat, Brown cat.</p>
<input type="text" id="search_word" value="">
<button id="button_search">検索</button>
</body>
</html>

以降はこちらのソースコードを使いながら、次の順番でコードの役割を解説し、実装内容を確認していきます。
(JavaScriptの解説を主目的とするためHTMLとCSSは解説を行いません)

  1. 1. イベントリスナーを設定
  2. 2. ページ内のテキストを取得
  3. 3. 入力した検索ワードを取得
  4. 4. replaceメソッドで検索ワードを置き換える

イベントリスナーを設定

まずは「検索」ボタンが押されたときのイベントリスナーを設定します。
script要素内の以下のコードに注目してください。

コード例

window.addEventListener('DOMContentLoaded', function(){

  document.getElementById("button_search").addEventListener("click",function(){

    // ここに実行する処理を記述
  });

});

イベントリスナーが2つあり、入れ子になっています。
外側のイベント「DOMContentLoaded」はページ読み込みが完了したタイミングで発生し、内側のイベントclickid属性button_search」の要素がクリックされたら発生します。

今回の場合はページ読み込みが完了したら検索ボタンのクリックに関するイベントリスナーを登録する内容になります。
ここまでの設定で、検索ボタンが押されたら「// ここに実行する処理を記述」の箇所に書いたコードが実行されるようになりました。

ページ内のテキストを取得

続いて、イベントリスナーの中に記述コードをみていきましょう。
まずは最初の1行から。

コード例

var p_elements = document.querySelectorAll('p');

querySelectorAllメソッドは指定したHTML要素を全て取得することができます。
今回はページ中にある以下の全てのp要素を取得し、変数p_elementsに代入しています。

取得するHTML

<p>I like cat.</p>
<p>Cat is so pretty.</p>
<p>Black cat, White cat, Brown cat.</p>

これで見出し(h1要素)を除いたページの本文にアクセスする準備が整いました。
一旦、途中のコードをスキップしますがfor文でp要素に1つずつアクセスしていきます。

コード例

for(var pi=0; pi < p_elements.length; pi++) {

  var p_text = p_elements[pi].textContent;

  // 一旦コード省略

}

for文の条件式にある通り、p_elements.lengthでページ中のp要素の数だけループを繰り返します。
その中で、各要素のtextContentプロパティを参照して、取得した本文を変数p_textに代入していきます。

入力した検索ワードを取得

先にfor文の解説に入ってしまいましたが、一度querySelectorAllメソッドに続く2行のコードに戻ります。

赤字の箇所ではid属性search_word」のinput要素から値を取得することで、入力された検索ワードを取得します。

コード例

var p_elements = document.querySelectorAll('p');
var search_word = document.getElementById("search_word").value;
var reg = new RegExp( search_word, "gi");

ここまでで、検索ボタンが押されたら入力した検索ワードを取得する流れができました。

続く1行は取得した検索ワードを使って、replaceメソッドで使う正規表現の準備を行っています。

コード例

var p_elements = document.querySelectorAll('p');
var search_word = document.getElementById("search_word").value;
var reg = new RegExp( search_word, "gi");

第1パラメータに検索ワード、第2パラメータにフラグを指定してRegExpオブジェクトを作成します。
フラグで指定している「gi」はgで「該当したワード全て」を対象とする指定となり、もう1つのiはアルファベットの大文字/小文字の区別をしない指定です。
検索ワードに「cat」と入力すると全て小文字の「cat」しかヒットしませんが、このフラグを指定することで「CAT」「Cat」「CaT」もヒットするようにできます。
もし厳密な検索を行いたいときなどで大文字/小文字の区別をしたい場合はこのフラグは省略してください。

replaceメソッドで検索ワードを置き換える

いよいよハイライト表示のための置き換えを行います。
for文の中の次の箇所でreplaceメソッドを使って置き換えていきます。

コード例

p_elements[pi].innerHTML = p_text.replace( reg, function( match_word){
  return "" + match_word + "";
});

replaceメソッドの第1パラメータには先ほど用意した正規表現の条件を渡し、第2パラメータには置き換える処理内容を渡します。
第1パラメータの条件にヒットするワードがあると第2パラメータの処理が実行され、その結果が「p_elements[pi].innerHTML」を通してp要素に代入されます。

プレーンなテキストをp要素に代入するだけであれば、テキストを取得した時と同様にtextContentプロパティを使うことでも実現できますが、今回は以下の箇所でハイライト表示のためにHTMLのem要素を加えるためinnerHTMLプロパティを使います。

第2パラメータの処理の中では、マッチしたワードを引数としてmatch_wordで受け取り、以下の箇所でハイライト表示するためにem要素の開始タグと終了タグを文字列結合し、作成した文字列を返します。
ここで作成した文字列が上記のinnerHTMLプロパティに代入されます。

コード例

return "<em>" + match_word + "</em>";

置き換えの処理を指定で一手間かかっている理由は、検索したときに大文字/小文字の区別をしない指定にしているので、元々あったテキストの大文字/小文字の表記を保つ必要があるためです。
例えば、以下のようにreplaceメソッドの第2パラメータを変更してもハイライト表示自体はできますが、本文が検索ワードに置き換わってしまいます。

コード例

p_elements[pi].innerHTML = p_text.replace( reg, "<em>" + search_word + "</em>");

この置き換えを実際に実行すると、元々のテキストは「Brown」と頭文字だけ大文字ですが、検索ワードは全て小文字の「brown」のため小文字に置き換えられてしまいます。

検索すると検索ワードに置き換わってしまう

この現象を防ぐための第2パラメータの指定でした。

以上が、検索したワードをハイライト表示するための実装内容です。

こちらの記事は役に立ちましたか?

ありがとうございます。
もしよろしければ、あわせてフィードバックや要望などをご入力ください。

コメントありがとうございます!
運営の参考にさせていただきます。