ネットニュースのコメントをみると
あの○○のニュース見たくないんですが、この記事だけ見えなくする方法てありませんか??
サムネ写真見るだけでもイライラするので…
こんなコメントがあります。そこで指定した単語を非表示にするアドオンを作ることにしました。
みんなよろこべ。
俺が登録したNGワードを含む文やリンクを非表示にするアドオンをつくってやったぞ。
嬉々としてコメント返ししたのですが、なんと予想に反して(予想通り?)低評価の嵐です。
結局みんな○○のことが好きなんじゃね?
冗談はこれくらいにして作成することにします。
まずmanifest.jsonというファイルを作成して以下の書きます。
manifest.json
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
{ "manifest_version": 2, "name": "指定したキーワードを含む文とリンクを非表示に", "version": "1.0", "content_scripts": [ { "matches": ["<all_urls>"], "js": ["hide-ng-words.js"] } ], "options_ui": { "page": "options.html" }, "permissions": ["storage"], "applications": { "gecko": { "id": "hide-ng-words@example.com" } } } |
前回との違いは非表示にするキーワードを指定するための設定ができるようにするためにoptions.htmlを用意していることです。options.htmlは以下のようにします。
除外したいキーワードとそれをどんな文字に置き換えるか、このアドオンが動作しているときはそれが一目でわかるようにページが色つきの枠で囲われるようにします。枠で囲うだけなら前回のFirefoxのアドオンをつくって公開してみるを流用することができそうです。
options.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> </head> <body> <form> <p><label>Border color</label><input type="text" id="color" ></p> <p><label>除外したキーワードを置き換える</label><input type="text" id="aftertext" ></p> <p><label>除外したいキーワード(改行)</label><br> <textarea id="keywords" cols="50" rows="10"></textarea></p> <button type="submit">Save</button> </form> <script src="options.js"></script> </body> </html> |
設定を保存したり読み出す処理はJavaScriptでおこないます。
SaveボタンがクリックされたらSaveOptions関数が実行されます。そして設定欄に入力した文字列がストレージ内に保存されます。
options.js
1 2 3 4 5 6 7 8 9 10 |
document.querySelector("form").addEventListener("submit", SaveOptions); function SaveOptions(e) { e.preventDefault(); browser.storage.sync.set({ color: document.querySelector("#color").value, keywords: document.querySelector("#keywords").value, aftertext: document.querySelector("#aftertext").value, }); } |
また設定のページが読み込まれたら保存されているデータを読み出して、現在どのような設定がされているか確認できるようにします。ここでは保存されているデータをテキストボックスに表示させているだけです。ただし除外するキーワードは改行区切りとし、空白行は除外します。
RestoreOptions関数は”color”、”keywords”、”aftertext”をストレージに保存します。
options.js
1 2 3 4 5 6 7 8 9 10 11 12 |
document.addEventListener("DOMContentLoaded", RestoreOptions); function RestoreOptions() { var getting1 = browser.storage.sync.get("color"); getting1.then(SetCurrentColor, onError); var getting2 = browser.storage.sync.get("keywords"); getting2.then(SetCurrentKeywords, onError); var getting3 = browser.storage.sync.get("aftertext"); getting3.then(SetCurrentAfterText, onError); } |
RestoreOptions関数内で呼び出されている関数を示します。
options.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
function SetCurrentColor(result) { document.querySelector("#color").value = result.color || "black"; } function SetCurrentKeywords(result) { if(result.keywords != null){ let arr = []; let keywords = result.keywords.split('\n'); for(let i=0; i<keywords.length; i++){ if(keywords[i] != '') arr.push(keywords[i]); } document.querySelector("#keywords").value = arr.join('\n'); } else document.querySelector("#keywords").value = ""; } function SetCurrentAfterText(result) { document.querySelector("#aftertext").value = result.aftertext || ""; } function onError(error) { console.log(`Error: ${error}`); } |
次にネットサーフィン時に設定されているキーワードを含む文とリンクを非表示にする処理を示します。manifest.json内にある”hide-ng-words.js”部分です。
ここではストレージから”color”、”keywords”、”aftertext”を読み出してグローバル変数に格納しています。最後に後述する自作関数 HideNgWords関数を呼び出しています。
hide-ng-words.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
let color; let keywords = ""; let aftertext = ""; var getting1 = browser.storage.sync.get("color"); getting1.then((item)=>{ color = "black"; if (item.color) color = item.color; var getting2 = browser.storage.sync.get("keywords"); getting2.then((item)=>{ keywords = item.keywords; var getting3 = browser.storage.sync.get("aftertext"); getting3.then((item)=>{ aftertext = item.aftertext; HideNgWords(); }, OnError); }, OnError); }, OnError); |
自作関数 HideNgWordsはページにcolorで指定された色の枠をつけます。そしてkeywordsを改行で区切って配列に変換してからこれらの要素を含む文やリンクを非表示にしています。
hide-ng-words.js
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
function HideNgWords(){ document.body.style.border = "5px solid " + color; if (!keywords || keywords == "") return; let removeTexts = keywords.split('\n'); let body = document.body; // リンク、段落、見出しの要素を取得 let anchors = body.querySelectorAll("a"); let paragraphs = body.querySelectorAll("p"); let headline1s = body.querySelectorAll("h1"); let headline2s = body.querySelectorAll("h2"); let headline3s = body.querySelectorAll("h3"); let headline4s = body.querySelectorAll("h4"); // リンク、段落、見出しのなかに配列の要素と一致するものがあれば非表示にする HideNgElements(anchors, removeTexts); HideNgElements(paragraphs, removeTexts); HideNgElements(headline1s, removeTexts); HideNgElements(headline2s, removeTexts); HideNgElements(headline3s, removeTexts); HideNgElements(headline4s, removeTexts); } |
HideNgElements関数を示します。第一引数で渡された要素の配列のなかに第二引数で渡された文字列の配列の要素のどれかが一致する場合、その要素をaftertextで置き換えます。
hide-ng-words.js
1 2 3 4 5 6 7 8 |
function HideNgElements(elements, removeTexts){ for(let element of elements) { for(let i=0; i<removeTexts.length; i++) { if(removeTexts[i] != '' && element.textContent.indexOf(removeTexts[i]) != -1) element.textContent = aftertext; } } } |
OnError関数はエラー時にそれをコンソールに表示させるためのものです。
hide-ng-words.js
1 2 3 |
function OnError(error) { console.log(`Error: ${error}`); } |