jQuery」タグアーカイブ

導入から公開まで13時間!Chrome拡張機能の開発[4of6]

Chrome拡張のコードのうち、対象となるページの状態を直接読んだり変更したりできるものがコンテントスクリプトです。
だから「manifest.json」で特別に宣言するんでしょうね。

contentscript.jsのソースコード

/*
* コンテントスクリプト
*/

// パソコンに保存する情報を蓄えるオブジェクトを定義する
var condlist = {"cond":[]};

$(function(){

  var regex = /求人情報検索/;

  if (regex.test(document.body.innerText)) {
  // regexに設定した文字列が対象URL内のBodyタグ内に見つかれば、
  // バックグラウンドに通知する
    chrome.extension.sendRequest({}, function(response) {});
  } else {
  // 見つからない場合
  }


  // バックグラウンドやポップアップ等の拡張機能から
  // コンテントスクリプトへのリクエストをモニタして、
  // リクエストがきたら関数(onRequest)を実行する
  //
  // ポップアップの3種類のボタンをクリックしたとき
  // ポップアップからのリクエストを経由して呼ばれる
  chrome.extension.onRequest.addListener(onRequest);

});

function clearConditions(){
// ポップアップの「クリア」ボタンをクリックしたとき
// ポップアップからのリクエストを経由して呼ばれる
//
// パソコン内に保存していた情報を初期状態にする

  condlist = {"cond":[]};
  // condlistに溜まった情報を文字列化してパソコンに保存する。
  // これでパソコン内に保存していた情報が初期状態になる
  localStorage["condlist"] = JSON.stringify(condlist);
}

function saveConditions(){
// ポップアップの「書き出し」ボタンをクリックしたとき
// ポップアップからのリクエストを経由して呼ばれる
//
// URLページに入力された情報を一旦オブジェクトに集めてパソコン内に保存する

  // 処理前にcondlistを初期化(そうしないとどんどん溜まる)
  condlist = {"cond":[]};
  condcnt = 0;

  $("input").each(function(){
  // 「ラジオボタン」「チェックボックス」「テキスト(文字列や数字列)」
  // で設定する情報をcondlistに追加する
    str = $(this).attr("id");
    str_v = $(this).val();
    str_t = $(this).attr("type");
    if( typeof str != 'undefined' ){

	if(str_t == "radio"){
	// 「ラジオボタン」で設定する情報をcondlistに追加する
		if(typeof $(this).attr("checked") != 'undefined'){
			str_v = 1;
		}else{
			str_v = 0;
		}
		obj = {"id":str,"type":str_t,"val":str_v};
		condlist['cond'][condcnt++] = obj;

	}else if(str_t == "checkbox"){
	// 「チェックボックス」で設定する情報をcondlistに追加する
		if(typeof $(this).attr("checked") != 'undefined'){
			str_v = 1;
		}else{
			str_v = 0;
		}
		obj = {"id":str,"type":str_t,"val":str_v};
		condlist['cond'][condcnt++] = obj;

	}else if(str_t == "text"){
	// 「テキスト」で設定する情報をcondlistに追加する
		obj = {"id":str,"type":str_t,"val":str_v};
		condlist['cond'][condcnt++] = obj;

	}
    }
  });

  $("select").each(function(){
  // 「選択」で設定する情報をcondlistに追加する
    str = $(this).attr("id");
    str_v = $(this).val();
    str_t = "select";
    if( typeof str != 'undefined' ){
	obj = {"id":str,"type":str_t,"val":str_v};
        console.log("obj:"+obj);
	console.log("id="+str+" val:"+str_v+" type:"+str_t);
	condlist['cond'][condcnt++] = obj;
    }
  });

// condlistに溜まった情報を文字列化してパソコンに保存する
  localStorage["condlist"] = JSON.stringify(condlist);
}

function restoreConditions(){
// ポップアップの「読み込み」ボタンをクリックしたとき
// ポップアップからのリクエストを経由して呼ばれる
//
// パソコン内に保存されていた情報を、URLページの入力・選択フィールドに
// 設定する

  // パソコン内に保存されていた情報を、処理し易いようにオプジェクト
  // に変換してcondlistに設定する
  condlist = JSON.parse(localStorage["condlist"]);

  // まずラジオボタンやチェックボックスを全部オフしておく
  $('input').removeAttr("checked");

  // 入力・選択フィールドの種類に従い情報を設定する
  for(var i=0; i < condlist['cond'].length; i++){
    var cond = condlist['cond'][i];
    var itag = $("#"+cond.id);

    if(cond.type == "checkbox"){
      if(cond.val != 0) itag.attr("checked","checked");
    }else if(cond.type == "radio"){
      if(cond.val != 0) itag.attr("checked","checked");
    }else if(cond.type == "text"){
      itag.val(cond.val);
    }else if(cond.type == "select"){
      itag.val(cond.val);
    }
  }
}

function onRequest(request, sender, sendResponse) {
// ポップアップの3種類のボタンをクリックしたとき
// ポップアップからのリクエストを経由して呼ばれる
//
// パソコン内に保存されていた情報を、URLページの入力・選択フィールドに
// 設定する

  if(request.greeting == "restore"){
  // リクエストのメッセージ内容に従い処理を分ける
    restoreConditions();
  }else if(request.greeting == "save"){
  // リクエストのメッセージ内容に従い処理を分ける
    saveConditions();
  }else if(request.greeting == "clear"){
  // リクエストのメッセージ内容に従い処理を分ける
    clearConditions();
  }
  sendResponse({});
};

(つづく>>>)

関連する記事

導入から公開まで13時間!Chrome拡張機能の開発[1of6]
導入から公開まで13時間!Chrome拡張機能の開発[2of6]
導入から公開まで13時間!Chrome拡張機能の開発[3of6]
導入から公開まで13時間!Chrome拡張機能の開発[4of6]
導入から公開まで13時間!Chrome拡張機能の開発[5of6]
導入から公開まで13時間!Chrome拡張機能の開発[6of6]

お世話になったリンク

Chrome Extensions API リファレンス
Sample Extensions - Google Chrome Extensions
ぷりんすの開発メモ: Chrome拡張機能のマニフェストVesrsion2対応についてのメモ
ChromeExtensionを作ってみる | ぼんぼるにっき
Chrome Extension でデバッグを行う - 日頃の行い
ハローワークの「求人情報検索」ページ

導入から公開まで13時間!Chrome拡張機能の開発[6of6]

最初の記事に書いた苦労したポイントについて補足したいと思います。

苦労したポイント

  • 生のjavascriptではなく、jQueryを使えるようにするにはどうすればいい?
  • 対象ページの内容を変更する方法は?contentscriptによる方法とexecuteScriptがある?
  • backgroundを含む拡張部分とcontentscriptとはDOMを共有しないので変数や関数が互いに参照できない。その場合の通信方法はどうするの?
  • デバッグはどうすればいい?background.jsを含む拡張部分。contentscript部分。

生のjavascriptではなく、jQueryを使えるようにするにはどうすればいい?

これは「manifest.json」に明記すればよいです。例外として「popup.html」を見ていただければ分かるようにHTML中に記述しています。

対象ページの内容を変更する方法は?contentscriptによる方法とexecuteScriptがある?

「manifest.json」にcontentscriptとして宣言すれば「対象ページ」の内容を変更できます。

jQuery使いなら「contentscript.js」でもjavascriptそのものではなくjQueryを使いたいはず。その際は「manifest.json」にcontentscript宣言に「jQuery.js」等を追加してあげればよいです。「対象ページ」でjQueryが使われている場合でも版数の違いなどを気にすることなく宣言できるそうです。

バックグラウンドコードからexecuteScript関数を使って対象ページの内容を変更する方法もありますが、複雑な処理には向かないような印象でした。具体例については参照リンクを見ていただければと思います。

backgroundを含む拡張部分とcontentscriptとはDOMを共有しないので変数や関数が互いに参照できない。その場合の通信方法はどうするの?

リクエスト(メッセージ)のやりとりで実現します。拡張部分のコードとcontentscriptではリクエスト(メッセージ)のやりとりの際の引数が違います。

デバッグ方法はどうすればいい?background.jsを含む拡張部分とcontentscript部分

コンテントスクリプト部分については、対象ページを表示した状態でいつものデバッグツールを起動すればよいです。バックグラウンド部分では、Chromeの「設定」「拡張機能」画面にある「page_backgound.html」をクリックした状態でいつものデバッグツールを起動すればよいです。ポップアップ部分についてはHTMLにスナップショットを表示するdivタグを用意しておいてデバッグ内容を表示するようにすればよいような。

Chrome拡張は、作る楽しさ、使う楽しさが満載な仕組み

以上、これまで各コードについてひとつずつソースコードを提示してきましたが、各コード(ファイル)の役割は次のようになると思います。

  • background.js:ハブ的役割を持つコード。
  • popup.html, popup.js:利用者にユーザインタフェースを提供するコード。
  • contentscript.js:対象ページを処理するコード。
  • manifest.json:役割定義

Chrome拡張開発によりいろいろできそうに思いました。もちろん既に誰かが作成した便利なものを探して使うのが、もっともコストがかからない便利な方法だと思います。

でも、自分のニーズや悩みにぴったり来るものがない場合には、javascriptやHTMLなどをちょっとかじっていさえすれば、とても便利な、世界でひとつしかないブラウザ環境が手に入ります。

例えば、ページの文字が小さくてみえずらい場合には、ブラウザの機能を使って少しだけ大きな文字にすることもできますが、こうした拡張を作って好きなだけ拡大してみる。特定の英単語のみ拡大するような拡張機能も簡単に作成できます。

とにかくChrome拡張は、作る楽しさ、使う楽しさが満載な仕組みだと思います。

以上です。

関連する記事

導入から公開まで13時間!Chrome拡張機能の開発[1of6]
導入から公開まで13時間!Chrome拡張機能の開発[2of6]
導入から公開まで13時間!Chrome拡張機能の開発[3of6]
導入から公開まで13時間!Chrome拡張機能の開発[4of6]
導入から公開まで13時間!Chrome拡張機能の開発[5of6]

お世話になったリンク

Chrome Extensions API リファレンス
Sample Extensions – Google Chrome Extensions
ぷりんすの開発メモ: Chrome拡張機能のマニフェストVesrsion2対応についてのメモ
ChromeExtensionを作ってみる | ぼんぼるにっき
Chrome Extension でデバッグを行う – 日頃の行い
ハローワークの「求人情報検索」ページ

以上です。ありがとうございました。

導入から公開まで13時間!Chrome拡張機能の開発[5of6]

本Chrome拡張は特定のページでのみ有効となるページアクションに対応したものです。ブラウザアクションというものもあります。いづれの場合にもオムニバー付近にChrome拡張のアイコンが現れてそのChrome拡張が有効であることをユーザに通知してくれます(アイコンの定義がないと通知されません)。

ユーザがアイコンをクリックすると拡張機能が起動されます。ポップアップWindowはそうしたUIの一つです。本Chrome拡張でもポップアップWindowを出しています。見た目(html)と動作(js)のファイルで構成されます。

popup.htmlのソースコード

<!DOCTYPE html>
<head>
<script src='jquery.js'></script>
<script src='popup.js'></script>
</head>
<body>
<div id="title">HWIS Cooker</div>
<button class="roundCorner" id=restoreAll>読み込み</button>
<button class="roundCorner" id=saveAll>書き出し</button>
<button class="roundCorner" id=clearAll>クリア</button>
<div id="status"></div>
</body>
</html>

popup.jsのソースコード

/*
* ポップアップ
*/

$(function(){
  $("button#restoreAll").live("click",function(){
  // クリックされたときコンテントスクリプトへリクエスト(メッセージ)を送付
	onSendRestoreRequest();
  });
  $("button#saveAll").live("click",function(){// クリックされたとき
  // クリックされたときコンテントスクリプトへリクエスト(メッセージ)を送付
	onSendSaveRequest();
  });
  $("button#clearAll").live("click",function(){// クリックされたとき
  // クリックされたときコンテントスクリプトへリクエスト(メッセージ)を送付
	onSendClearRequest();
  });
});

function onSendSaveRequest() {
  chrome.tabs.getSelected(null, function(tab) {
    chrome.tabs.sendRequest(tab.id, {greeting: "save"}, function(response) {
  // リクエスト(メッセージ)にsaveを入れて、選択タブに送付
  // 選択タブへのリクエストはコンテントスクリプトで受け取れる

//      console.log(response.farewell);
    });
  });
  // Update status to let user know options were saved.
  var status = document.getElementById("status");
  $('#status').text("Saved.");
  setTimeout(function() {
	$('#status').text("");
  }, 750);
};

function onSendRestoreRequest() {
  chrome.tabs.getSelected(null, function(tab) {
    chrome.tabs.sendRequest(tab.id, {greeting: "restore"}, function(response) {
  // リクエスト(メッセージ)にrestoreを入れて、選択タブに送付
  // 選択タブへのリクエストはコンテントスクリプトで受け取れる
//      console.log(response.farewell);
    });
  });
  $('#status').text("Restored.");
  setTimeout(function() {
	$('#status').text("");
  }, 750);
};

function onSendClearRequest() {
  chrome.tabs.getSelected(null, function(tab) {
    chrome.tabs.sendRequest(tab.id, {greeting: "clear"}, function(response) {
  // リクエスト(メッセージ)にclearを入れて、選択タブに送付
  // 選択タブへのリクエストはコンテントスクリプトで受け取れる
//      console.log(response.farewell);
    });
  });
  $('#status').text("Cleared.");
  setTimeout(function() {
	$('#status').text("");
  }, 750);
};

(つづく>>>)

関連する記事

導入から公開まで13時間!Chrome拡張機能の開発[1of6]
導入から公開まで13時間!Chrome拡張機能の開発[2of6]
導入から公開まで13時間!Chrome拡張機能の開発[3of6]
導入から公開まで13時間!Chrome拡張機能の開発[4of6]
導入から公開まで13時間!Chrome拡張機能の開発[5of6]
導入から公開まで13時間!Chrome拡張機能の開発[6of6]

お世話になったリンク

Chrome Extensions API リファレンス
Sample Extensions – Google Chrome Extensions
ぷりんすの開発メモ: Chrome拡張機能のマニフェストVesrsion2対応についてのメモ
ChromeExtensionを作ってみる | ぼんぼるにっき
Chrome Extension でデバッグを行う – 日頃の行い
ハローワークの「求人情報検索」ページ

導入から公開まで13時間!Chrome拡張機能の開発[3of6]

バックグラウンドというのは「背景」とか「裏」とかいう意味ですが、Chrome拡張におけるバックグラウンドというのは、拡張機能におけるコアとかメイン機能とかハブ機能を置く場所になるでしょうか。MVC(Model、View、Control)でいえばModel部分ですかね。Googleのコードサンプルを見るとこのバックグラウンドだけのサンプルもあり、必須のコードのようです。

本拡張機能においては主にリクエスト(メッセージ)のやりとりとアイコンをクリックしたときのイベントを掴むところに使っています。対象ページの読み書きおよびパソコンへの書き出し(保存)や読み込みはコンテントスクリプトに、UIはポップアップに任せています。

パソコンへの書き出しや読み込みは、本来このバックグラウンドで行い、コンテントスクリプトとはリクエスト(メッセージ)のやりとりで情報交換すべきだったのかも知れません。簡単な機能なので今回はオプションに対応しませんでしたが、例えばオプションで、パソコンへ保存した情報をリストアップさせて、「削除」「削除しないが対象外にする」の処理させる場合、やはりハブ的な場所に保存されている方が便利だからです。

backgroud.jsのソースコード

/*
* バックグラウンド
*/

$(function(){

// コンテントスクリプトからバックグラウンドへのリクエストをモニタして、
// リクエストがきたら関数(onRequest)を実行する
chrome.extension.onRequest.addListener(onRequest);

// オムニバー右端のアイコンをクリックをモニタして、クリックがあったら
// 関数(onSendRequest)を実行する
chrome.pageAction.onClicked.addListener(onSendRequest);

});

function onRequest(request, sender, sendResponse) {
//  console.log(sender.tab ?
//		"from a content script:" + sender.tab.url :
//		"from the extension");
  if(sender.tab){
    chrome.pageAction.show(sender.tab.id);
  }
  // Return nothing to let the connection be cleaned up.
  sendResponse({});
};

/*
* helloというメッセージを現在選択中のタブ(対象URLを表示しているタブ)に送信する
*/
function onSendRequest() {
  chrome.tabs.getSelected(null, function(tab) {
    chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
//      console.log(response.farewell);
    });
  });
};

(つづく>>>)

関連する記事

導入から公開まで13時間!Chrome拡張機能の開発[1of6]
導入から公開まで13時間!Chrome拡張機能の開発[2of6]
導入から公開まで13時間!Chrome拡張機能の開発[3of6]
導入から公開まで13時間!Chrome拡張機能の開発[4of6]
導入から公開まで13時間!Chrome拡張機能の開発[5of6]
導入から公開まで13時間!Chrome拡張機能の開発[6of6]

お世話になったリンク

Chrome Extensions API リファレンス
Sample Extensions – Google Chrome Extensions
ぷりんすの開発メモ: Chrome拡張機能のマニフェストVesrsion2対応についてのメモ
ChromeExtensionを作ってみる | ぼんぼるにっき
Chrome Extension でデバッグを行う – 日頃の行い
ハローワークの「求人情報検索」ページ

導入から公開まで13時間!Chrome拡張機能の開発[2of6]

今回作成公開したChrome拡張のコード(ファイル)の構成を以下に示します。

Chrome拡張のコードの構成

HWISCooker
-	manifest.json
-	background.js
-	popup.js
-	popup.html
-	images
	-	HW_19.png
	-	HW_48.png
	-	HW_128.png
-	contentscript.js
-	jquery.js

となっています。

各ファイル(js, html, png)の役割はそれぞれのファイル名が示す通りですが、実際には「manifest.json」が全てを管理しており、役割とファイル名が関連付けられています。

Manifest.jsonのソースコード

{
  "name": "HWISCooker",
  "version": "1.0",
  "description": "Tired of putting your info. eternaly? Use HWISCooker!",
  "icons": {
    "19" : "images/HW_19.png",
    "48" : "images/HW_48.png",
    "128" : "images/HW_128.png"
  },
  "page_action": {
    "default_icon": "images/HW_19.png",
    "default_title": "HWISCooker",
    "default_popup": "popup.html"
  },
  "background": {
    "scripts": ["jquery.js", "background.js"]
  },
  "content_scripts": [ {
    "matches": ["https://www.hellowork.go.jp/servicef/130020.do*"],
    "js": ["jquery.js", "contentscript.js"],
    "run_at" : "document_idle",
    "all_frames": false
  }],
  "manifest_version": 2
}

上記構成で示したファイル名の内、「manifest.json」に明記されないのは「popup.js」だけですが、これはpopup.html内で参照されているからOKなのでしょう。また、jQuery等の補助スクリプトを使いたい場合には、「manifest.json」に明記するようです。

(つづく>>>)

関連する記事

導入から公開まで13時間!Chrome拡張機能の開発[1of6]
導入から公開まで13時間!Chrome拡張機能の開発[2of6]
導入から公開まで13時間!Chrome拡張機能の開発[3of6]
導入から公開まで13時間!Chrome拡張機能の開発[4of6]
導入から公開まで13時間!Chrome拡張機能の開発[5of6]
導入から公開まで13時間!Chrome拡張機能の開発[6of6]

お世話になったリンク

Chrome Extensions API リファレンス
Sample Extensions – Google Chrome Extensions
ぷりんすの開発メモ: Chrome拡張機能のマニフェストVesrsion2対応についてのメモ
ChromeExtensionを作ってみる | ぼんぼるにっき
Chrome Extension でデバッグを行う – 日頃の行い
ハローワークの「求人情報検索」ページ

(つづく)