実現したいこと
汎用的に使える事を目的としたtext highlight系のスクリプトを作成しています。
window.addEventListenerのloadだけでは、Google画像検索ページだとかYahoo!トップページだとかYouTubeなどの縦に長いサイトに対して、途中でページが新たに継ぎ足された場合、その領域にまでは再度処理を行ってくれません。
これを解消させる為に、
setInterval
とsetTimeout
で何回か繰り返したのちにイベントを停止させることも試みましたが、この処理がかさむほどに動作も重くなって最悪メモリが解放されます。
https://blog.ikappio.com/check-page-height-change-with-javascript/#イベントリスナーで高さをチェックする
こちら様のサイトを参考にして、カスタマイズしてみたのですがGoogle画像検索タブページやYouTubeなどでは反応しないか、反応したとしてもScroll動作などが重くなってしまいます。
Google画像検索タブページやYouTubeなどでもScrollの動作や画面表示などに悪影響を与えることなく可視領域外にも安定的に処理を反映させるいい方法はないでしょうか?
該当のソースコード
JavaScript
1 2// const timerId = setInterval(() =>{ 3function _my_highlight_scope() { 4 let lastClientHeight = 0; 5 //------------------------------------// 6 7 // load 及び Scroll の複数イベントハンドラを登録。 8 function _highlight_event_scroll() { 9 let _URL = new Array(); 10 let _TXT = new Array(); 11 let _CSS = new Array(); 12 13 // include (指定URL包含) 14 // 正規表現を分割したいので、いったん以下の方法で改行編集してから代入 15 let total_url = new RegExp([ 16 // Google検索 17 /^(.*)www.google.(co.jp|com)\/search\?q.*$/i, 18 // Yahoo!トップ 19 /|^(.*)\/\/www.yahoo.co.jp\/?$/i, 20 // teratail 21 /|^https?:\/\/teratail.com\/.*$/i, 22 // YouTube 23 /|^https?:\/\/www.youtube.com\/?.*$/i, 24 ].map((r)=> { 25 return r.source 26 }).join('')); 27 28 //------------- 29 // exclude (指定URL除外 ) 30 // Google画像検索ページを除外していたが、最も執着している内容になったので急遽コメントアウト 31 let url = location.href; 32 // if (url.search(/.*&source=lnms\&tbm=isch\&.*/) !== -1) return; 33 // if (url.search(/.*&tbm=isch\&(source|ved|sa)=.*/) !== -1) return; 34 // if (url.indexOf('&sclient=img&ei=') !== -1) return; 35 36 let fxed_css = 'color:unset; font-weight:unset;'; 37 38 //ハイライトその1 39 _URL.push(total_url); 40 _TXT.push(/(JavaScript)/i); //任意のhighlightしたい単語を指定。 41 // パステルブルー 42 _CSS.push('background:#00CCFF;' + fxed_css); 43 //------------- 44 45 //ハイライトその2 46 _URL.push(total_url); 47 _TXT.push(/(chrome)/i); 48 // エメラルドグリーン 49 _CSS.push('background:#2fffb4;' + fxed_css); 50 //------------- 51 52 //ハイライトその3 53 _URL.push(total_url); 54 _TXT.push(/(firefox)/i); 55 // オレンジ色 56 _CSS.push('background:#FFA45DFF;' + fxed_css); 57 //------------- 58 59 //------------------------------------// 60 61 // if(lastClientHeight !== (document.body.clientHeight)||(document.documentElement.clientHeight)){ 62 if (lastClientHeight !== (document.body.clientHeight)) { 63 64 //------------------------------------// 65 66 for (ind in _URL) { 67 if (_URL[ind].test(window.location.href) == true) { 68 for (let tx = document.evaluate('//text()[normalize-space(.)!=""]', document, null, 6, null), t, i = 0; t = tx.snapshotItem(i); i++) { 69 let before = t.textContent, 70 st, matched = false; 71 72 // 特定のtag要素は除外する 73 // ブックマーク時にハイライト部分のタイトルが消滅するので <TITLE> 除外 74 // コピペするときに消滅するので <TEXTAREA> <INPUT> を除外 75 if( 76 t.parentNode.tagName=='STYLE'||t.parentNode.tagName=='SCRIPT'|| 77 t.parentNode.tagName=='TITLE'||t.parentNode.tagName=='META'|| 78 t.parentNode.tagName=='TEXTAREA'||t.parentNode.tagName=='INPUT'|| 79 t.parentNode.tagName=='VIDEO'||t.parentNode.tagName=='IMG' // || 80 ) continue; 81 82 while ((st = before.search(_TXT[ind])) != -1) { 83 t.parentNode.insertBefore(document.createTextNode(before.substr(0, st)), t); 84 85 let elem_s = document.createElement('span'); 86 // 自作したspan要素にclass名付与 87 elem_s.className = 'highlight_color'; 88 t.parentNode.appendChild(elem_s); 89 90 with(t.parentNode.insertBefore(document.createElement('span'), t)) 91 textContent = RegExp.$1, 92 style.cssText = _CSS[ind]; 93 94 //↓これで選択範囲と競合しない 95 if (window.getSelection().toString()) { 96 _CSS.remove(); 97 } 98 99 // elem_s.classList.add("notranslate"); 100 matched = true; 101 // 否定処理? 102 before = before.substr(st + RegExp.$1.length); 103 if (matched) t.textContent = before; 104 105 } 106 } 107 } 108 } 109 110 //------------------------------------// 111 112 // body要素の可視部の高さが0だった場合イベントを初期化します。 113 init(); 114 // 直前の高さを保持し直す 115 lastClientHeight = document.body.clientHeight; 116 // ||document.documentElement.clientHeight; 117 118 } // body要素の可視部の高さが0だった場合、イベント再起。 119 update(); 120 121 //------------------------------------// 122 123 }; 124 window.addEventListener('load', _highlight_event_scroll, false); 125 window.addEventListener('scroll', _highlight_event_scroll, false); 126 // window.addEventListener('wheel', _highlight_event_scroll, false); 127 //------------------------------------// 128}; 129_my_highlight_scope(); 130 131// },1500); 132// setTimeout(() => { clearInterval(timerId); //alert('stop'); 133// }, 30000); 134
試したこと
コード欄にコメントアウトで残骸を残していますが、
document.documentElement.clientHeight;
を使うと、YouTubeでも反応しますがScroll動作が極端に重くなってしまいます。
setInterval
とsetTimeout
で何回か繰り返したのちにイベントを停止させることも試みましたがこの処理がかさむほどに動作も重くなって最悪メモリが解放され画面が真っ白になります。
wheel
なども動作が重くなります。
補足情報(FW/ツールのバージョンなど)
9/19 23:40頃 補足
指定URL包含の仕方が正しくなかった(余計なサイトもincludeしていた)ので、大まかにその部分だけ修正しました。
9/21 18:30頃 追記
なんとかYouTubeで安定的にhighlightする方法を編み出しました。
consoleログのエラーも抑えました。上記のコード内容とは少々違うけどね...
とは言え、私が作成したもの以上に素晴らしい回答が付く可能性も考えてこのままにしておきます。
私の方法は汎用的なものとYouTube専用のものとを分けざるを得ない書き方です。
できれば両方とも使えるようにまとめられれば望ましいと考えています。
あとGoogle画像ページだけは綺麗に処理できない。YouTube以上に難しいです...
あなたの回答
tips
プレビュー