はじめに
同一画面には重複したID名は設定してはいけません。
常識だとは思いますが複数人でプロジェクトを回していると気付いたら同一ID名が存在していた、なんてことあるかと思います。
人間が目で見て重複しているかどうか判断してもいいですが、部分テンプレートが複数にまたがっていたりすると探すのも大変です。
できあがった画面で調べられたら便利だなという発想から作成を開始しました。
使用イメージ
- URL欄横のブラウザアイコンをクリックするとサーチを開始
- サーチが終わるとアラートで通知
- 重複したものはコンソールに表示される
ソースコード
// backgroundで動くjs
// ブラウザ上部のアイコンをクリックすることで発火し、content.jsの方にメッセージを飛ばす(トリガー)
chrome.browserAction.onClicked.addListener(function(tab) {
/**
* 第一引数: タブのID
* 第二引数: ポストするキーとバリュー
* 第三引数: コールバック関数(レスポンスが戻ってきた時に実行される)
*/
chrome.tabs.sendMessage(tab.id, { trigger: "on" },
function(msg) {
console.log("background側のconsole:", msg);
});
});
$(function(){
/**
* @param object message backgroundからポストされた値
* オブジェクトになっていてmessage.trigger = 'on'のような形になっている
* @param sender
* @sendResponse
* これらは2つとも宣言してないとsendResponseが最後に返せなかったので設定した
*
* backgroundからメッセージが送られてきた時(ブラウザボタンをクリックされた時)に発火する
*/
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
// 意図したbackground.jsからの送信でない場合は弾く
if(message.trigger !== 'on'){
return false;
}
var ids = [];
// 画面の全要素に対してループを回す(やや遅い可能性あり)
$.each($("*"), function(){
var id = $(this).attr("id");
if(typeof(id) !== "undefined"){
// undefined以外の全idを配列に保持
ids.push(id);
}
});
/**
* 重複したもののみを検出する
* @see http://qiita.com/cocottejs/items/7afe6d5f27ee7c36c61f
*/
var not_unique = ids.filter(function (x, i, self) {
return self.indexOf(x) === i && i !== self.lastIndexOf(x);
});
if(ids.length === 0){
console.log('重複したID要素はありませんでした');
} else {
console.log('重複したID要素: ');
console.log(not_unique);
}
alert('結果はconsoleを確認してください');
sendResponse('Done');
});
});
解説
全体処理フロー
-
background.js
でブラウザアイコンにonClick
イベントを設定する - ブラウザアイコンがクリックされると
background.js
のイベントが発火 -
sendMessage
でcontent_scripts
の方にメッセージを送信 -
content_scripts
はmanifest.json
に指定されているjsが対象 -
search_not_unique_id.js
内にonMessage
イベントを配置、これがメッセージを受信した時に発火する - 中で「現在表示しているページに対して」重複してるIDを検索する
-
sendResponse
でsearch_not_unique_id.js
からbackground.js
にレスポンスを返す
browser action
ChromeのURL欄の右横のアイコンの部分のこと
今回はここをクリックすることをトリガーにしたかった
background page
その拡張が裏側で持っている拡張用のページのこと
この拡張の作成時、background
の方でIDの検索のメイン処理を行っていて、バックグラウンドのページに対して検索をかけてしまいうまくいかない状態でハマりました
バックグラウンドからフロント側(今表示しているタブ側)にメッセージ送信することでトリガーを実現できました
バックグラウンドのページを見るためには以下の画像のようにすると要素が見える
おわりに
やってることはすごくシンプルで、コード自体は一瞬で完成しました。
どちらかというとこれをChrome拡張の形に落とし込むのにやや手間取りました。
browser_action
, backgroud page
について良い勉強になりました!
ブラウザアイコンクリック時にポップアップを出したりするのもこのあたりの応用でいけそうなので、次回はこのあたりを触ってみたい