前のページでは、簡単なブックマークレットから始まって、徐々に複雑なコードと解説、デバッグ方法などを解説しました。
今回は
- 「キーワードをハイライト表示」するブックマークレット
- ブックマークレットが「うまく動作しない場合の対処法」
について解説していきます。
サンプルコード:キーワードをハイライト表示
以下は、キーワードを入力して、現在のページ内のテキストの中から一致する部分をハイライト表示するブックマークレットの例です。
javascript:(function() {
let keyword = prompt('キーワードを入力してください:');
if (keyword === null || keyword === '') {
return;
}
let regex = new RegExp(keyword, 'g');
let body = document.body;
let textNodes = getTextNodesIn(body);
for (let i = 0; i < textNodes.length; i++) {
let node = textNodes[i];
let matches = node.nodeValue.match(regex);
if (matches && matches.length > 0) {
let fragment = document.createDocumentFragment();
let lastIndex = 0;
for (let j = 0; j < matches.length; j++) {
let index = node.nodeValue.indexOf(matches[j], lastIndex);
let before = node.nodeValue.substring(lastIndex, index);
let highlighted = document.createElement('span');
highlighted.style.backgroundColor = 'yellow';
highlighted.style.color = 'blue'
highlighted.textContent = matches[j];
fragment.appendChild(document.createTextNode(before));
fragment.appendChild(highlighted);
lastIndex = index + matches[j].length;
}
let after = node.nodeValue.substring(lastIndex);
fragment.appendChild(document.createTextNode(after));
node.parentNode.replaceChild(fragment, node);
}
}
function getTextNodesIn(node) {
let textNodes = [];
if (node.nodeType === Node.TEXT_NODE) {
textNodes.push(node);
} else {
let children = node.childNodes;
for (let i = 0; i < children.length; i++) {
textNodes = textNodes.concat(getTextNodesIn(children[i]));
}
}
return textNodes;
}
})();
このブックマークレットは、最初にキーワードを入力するプロンプトを表示し、ユーザが入力したキーワードを元に、現在のページ内のテキストの中から一致する部分を検索して、ハイライト表示します。
ただし、このブックマークレットは、ページのDOMを書き換えるため、元のページを修正することになります(リドローすれば元に戻ります)。
ハイライトの色を変えたい場合は(上記コード19-20行目)
highlighted.style.backgroundColor = 'yellow';
highlighted.style.color = 'blue'
の部分を変更してみてください。
サンプルコードの解説
このブックマークレットの主な処理を以下に解説します。
- ユーザからキーワードを入力するプロンプトを表示する(上記コード2行目)。
let keyword = prompt('キーワードを入力してください:');
- 入力されたキーワードを正規表現オブジェクトに変換する(上記コード6行目)。
let regex = new RegExp(keyword, 'g');
- 現在のページのテキストノードを取得する(上記コード7-8行目)。
let body = document.body;
let textNodes = getTextNodesIn(body);
- テキストノードの中から、キーワードに一致する部分を検索してハイライト表示する。
[j]番目の一致する部分について、その前後のテキストを抜き出してHTML要素を作成し、DocumentFragmentに追加します。
HTML要素は、以下のように作成されます(上記コード10-21行目)。
for (let i = 0; i < textNodes.length; i++) {
let node = textNodes[i];
let matches = node.nodeValue.match(regex);
if (matches && matches.length > 0) {
let fragment = document.createDocumentFragment();
let lastIndex = 0;
for (let j = 0; j < matches.length; j++) {
let index = node.nodeValue.indexOf(matches[j], lastIndex);
let before = node.nodeValue.substring(lastIndex, index);
let highlighted = document.createElement('span');
highlighted.style.backgroundColor = 'yellow'; // ハイライト色を指定
highlighted.style.color = 'black'; // 文字色を指定
highlighted.textContent = matches[j]; // ハイライト表示する文字列を指定
5. ハイライト表示するテキストノードを、作成したHTML要素で置き換える(上記コード25-30行目)。
}
let after = node.nodeValue.substring(lastIndex);
fragment.appendChild(document.createTextNode(after));
node.parentNode.replaceChild(fragment, node);
}
}
以上が、このブックマークレットの主な処理になります。
このブックマークレットでは、ユーザが入力したキーワードに一致するテキストを、ページ内でハイライト表示することができます。
ブックマークレットがうまく動作しない場合の対処法
開発者ツールのコンソールでは正常に動作するのに、ブックマークレットにしたとたん、エラーが出るという場合があります。
- 開発者ツールのコンソール
- 正常に動作
- ブックマークレットを作成
- 動作しない
つまり、コードは正しいはずなのに・・・??? というときですね。
そういった時に試したい対処法を紹介します。
原因:改行やタブ文字が自動的に挿入される
お使いのブラウザによっては、ブックマークレットのコードをコピー&ペーストした際に、改行やタブ文字が自動的に挿入されることがあります。
これらの不要な改行やタブ文字が原因で、コードが正しく実行されない場合があります。
以下の手順で、改行やタブ文字を削除してコードを実行してみてください。
- ブックマークレットのソースコードを開く ブックマークレットのソースコードを開く
- ブックマークレットを作成し、ブックマークバーに登録
- ブックマークバーにあるブックマークの右クリックメニューから「編集」を選択
- URL欄に登録したJavaScriptのコードが表示されるため、そこからコピー
- 改行やタブ文字を削除する
- コードの中に改行やタブ文字が含まれている場合は、それらを削除する
- また、コード中にある全角文字なども、一部のブラウザではエラーの原因となる場合がある
- そのため、全角文字などを半角文字に置き換えることも考慮する
- コードの中に改行やタブ文字が含まれている場合は、それらを削除する
- ブックマークレットを実行する 修正したコードをブックマークバーから実行して、正しく動作するか確認する
改行やタブ文字が原因でエラーが出る場合は、上記の手順で削除してみると改善されることがあります。
しかし、やってみると、案外面倒だし、うまくいかない場合もあります。
そこで、下記のような「ブックマークレット作成(コードを短縮化してブックマークレットを作成)」してくれるサイトのサービスを利用しましょう(外部リンク)。
短縮化されたブックマークレットのコードは以下の様な感じです。
javascript:!function(){let e=prompt("キーワードを入力してください:");if(null===e||""===e)return;let t=new RegExp(e,"g"),n=function e(t){let n=[];if(t.nodeType===Node.TEXT_NODE)n.push(t);else{let l=t.childNodes;for(let t=0;t<l.length;t++)n=n.concat(e(l[t]))}return n}(document.body);for(let e=0;e<n.length;e++){let l=n[e],o=l.nodeValue.match(t);if(o&&o.length>0){let e=document.createDocumentFragment(),t=0;for(let n=0;n<o.length;n++){let d=l.nodeValue.indexOf(o[n],t),c=l.nodeValue.substring(t,d),r=document.createElement("span");r.style.backgroundColor="yellow",r.style.color="blue",r.textContent=o[n],e.appendChild(document.createTextNode(c)),e.appendChild(r),t=d+o[n].length}let n=l.nodeValue.substring(t);e.appendChild(document.createTextNode(n)),l.parentNode.replaceChild(e,l)}}}();void(0);
ぎっしり詰まっていて、プログラマーでもちょっと目をそむけたくなる気がしますよね。
まとめ: JavaScriptのDOM操作の重要性と今後の展望
本記事では、JavaScriptのDOM操作について、基礎的な知識からブックマークレットを使ったサンプルコードまでを紹介しました。
DOM操作は、Webアプリケーションの開発において非常に重要な技術のひとつであり、Webページにおいて動的な操作を実現するために欠かせないものです。
例えば・・・
- 利用用途:
- フォームの入力値の検証や更新
- ダイナミックなコンテンツの生成
- スタイルの変更
- など、さまざまな用途に利用されている
- JavaScriptを用いたフロントエンド開発
- 近年、一層注目を集めている
- DOM操作を実行可能なライブラリやフレームワークの開発
- Web開発におけるJavaScriptの利用がますます広がっている
- SPA (Single Page Application) の普及
- これにより、動的なWebアプリケーションの需要が高まっている
- DOM操作によって、より快適なユーザーエクスペリエンスを提供することが求められている
今後も、Webアプリケーションの開発において、JavaScriptの重要性は高まると考えられます。
ブラウザの性能向上に伴い、さらに高度なDOM操作が可能になることで、より多様で、より快適なWebアプリケーションが実現されることでしょう。
コメント