はじめに
突然ですがこのページを開いてCtrl+Fのページ内検索を開き、 x y z のいずれかの文字を検索してみてください。
このように、検索した結果がalertで表示されます。
言いたかったこと
このように、ページ内検索したテキストはコンテンツJavaScriptから検知できます。
選択したテキストや、フォームに入力したテキストが検知できるのは当然なのですが、ページ内検索テキストは今まで知りませんでした。例えば得体のしれない怪しいウェブサイトで「自分のメールアドレスが漏洩していないかな」とページ内検索、などはやっては駄目なことになりますね。気をつけましょう。
仕組み
こんなHTMLとJavaScriptを仕込んでいました。
<p hidden="until-found" id="x">x</p>
<p hidden="until-found" id="y">y</p>
<p hidden="until-found" id="z">z</p>
const list = { x: false, y: false, z: false };
setInterval(() => {
Object.keys(list).forEach(word => {
if (list[word]) { return }
if (getComputedStyle(document.getElementById(word)).contentVisibility === 'visible') {
list[word] = true;
alert(`${word}が検索されました`);
}
});
}, 100);
似たようなことをやる方法はいくつかありそうです。
::search-text 疑似要素
Chrome 144でリリースされた新しい機能で、ページ内検索でヒットした文字列の装飾を変更できます。
::search-text {
/* Styles for all search results */
}
::search-text:current {
/* Styles for the active search result */
}
詳しい仕様はこちらに https://drafts.csswg.org/css-pseudo-4/#selectordef-search-text
普通に使う分には、ヒット色が見づらくなってしまうデザインのWebサイトなどで役立ちそうですね。
背景色やシャドウなど一部の要素しか変更できないので、単に background-image: url(tracking url) は使えないし、element.pseudo('::search-text') でヒットするわけでもない(これで取得できるのは ::after ::before ::marker のみ)ですが、多分何か工夫すればJSで検知できるような気はします。
details
<details>を折りたたんでいる場合、検索にヒットすると自動で展開されます。このイベントを監視することで、検索されたことを検出できます。
hidden="until-found"
今回使った方法です。こんな属性あったんですね。ヒットするまでは Content-Visibility: hidden 扱いになります。
参考: HTML hidden グローバル属性 - HTML | MDN
雑記
最初に ::search-text の機能を知って、あれこれ検索テキストバレるじゃんspecのPrivacy Consideration書いてないの良いの?と思って調べたら、もとから出来るということを知った流れでした。皆さん賢い。
上記の素朴な実装では1文字ずつしか検知できませんし面倒ですが、やれば出来るということはそのうちに気合入ったGoogle Analytics的なやつが実装しないとも限らないわけで、エンドユーザとしてはブラウザの使い方に気をつけていこうと思います。
関連記事
HTMLDialogElement: showModal() はHTMLの長年の課題を解決する期待の星かと思ったら実際はだめな子
