2013年8月6日火曜日

コンテキストメニューなChrome拡張機能の作り方

2014-08-02 追記
content script内だけで完結する(background.jsとの通信が発生しない)シンプルなコンテキストメニューをお探しならこちらのエントリが参考になると思います→Chromeアプリで長押しコンテキストメニュー


上の画像のようなコンテキストメニューをChrome拡張機能で実現する方法をご紹介します。

まずはプロジェクト構成から。

プロジェクト構成

  • manifest.json
  • main.js
  • 128.png

Chrome拡張機能(Extensions)の典型的なファイル構成ですね。
基本的に必要なのは manifest.json と js本体 の2つだけ。
ちなみに 128.png はアイコン画像です。

manifest.json
{
  "name": "My Context Menu Extension",
  "description": "Sample Extension using Context Menus.",
  "version": "0.7",
  "permissions": [
    "contextMenus"
  ],
  "background": {
    "scripts": ["main.js"],
    "persistent": false
  },
  "icons": {
    "128": "128.png"
  },
  "manifest_version": 2
}

"persistent": false は拡張機能の無駄なメモリ消費を抑えるために Event Pages を使うためのおまじない。詳しくはよんちゅBlogさんのエントリが参考になるかと思います。

main.js
/**
 * コンテキストメニュークリック時の処理
 */
function onClickHandler(info, tab) {
  console.log(info.menuItemId + ' clicked.')
  // ラジオボタンやチェックボックスメニューが押された時
  if (info.menuItemId == "radio_menu1_id" ||
    info.menuItemId == "radio_menu2_id" ||
    info.menuItemId == "checkbox_menu1_id" ||
    info.menuItemId == "checkbox_menu2_id") {
    console.log(" checked:" + info.checked + ", wasChecked:" + info.wasChecked);
  }
  // テキスト選択型メニューが押された時
  else if (info.menuItemId == "selection_menu_id") {
    console.log(" selectionText:" + info.selectionText);
  }
};

/** 
 * コンテキストメニューにクリック時の処理を登録
 */
chrome.contextMenus.onClicked.addListener(onClickHandler);

/** 
 * 拡張機能のインストール時にコンテキストメニューをセットアップ
 */
chrome.runtime.onInstalled.addListener(function() {
  // まずはノーマルなメニュー
  chrome.contextMenus.create({
    "title": "Normal Menu",
    "id": "normal_menu_id"
  });
  console.log("Normal Menu created.");

  // 次はテキスト選択時に出現するメニュー
  chrome.contextMenus.create({
    "title": "Selection Menu",
    "contexts": [ "selection" ],
    "id": "selection_menu_id"
  });
  console.log("Normal Menu created.");

  // 次は子要素を持つメニュー
  chrome.contextMenus.create({
    "title": "Parent Menu",
    "id": "parent_menu_id"
  });
  chrome.contextMenus.create({
    "title": "Child Menu 1",
    "parentId": "parent_menu_id",
    "id": "child_menu1_id"
  });
  chrome.contextMenus.create({
    "title": "Child Menu 2",
    "parentId": "parent_menu_id",
    "id": "child_menu2_id"
  });
  console.log("Parent Menu created.");

  // 次はラジオボタン付きメニュー
  chrome.contextMenus.create({
    "title": "Radio Menu 1",
    "type": "radio",
    "id": "radio_menu1_id"
  });
  chrome.contextMenus.create({
    "title": "Radio Menu 2",
    "type": "radio",
    "id": "radio_menu2_id"
  });
  console.log("Radio Menu created.");

  // 最後はチェックボックス付きメニュー
  chrome.contextMenus.create({
    "title": "Checkbox Menu 1",
    "type": "checkbox",
    "id": "checkbox_menu1_id"
  });
  chrome.contextMenus.create({
    "title": "Checkbox Menu 2",
    "type": "checkbox",
    "id": "checkbox_menu2_id"
  });
  console.log("Checkbox Menu created.");
});


インストールと実行


インストール方法はいまさら説明する必要もありませんね。(もし忘れてしまった方はHelloWorldを参考にしてください)

上のサンプルをインストールすると、コンソールには下のようにログ出力されます。

Normal Menu created. main.js:33
Normal Menu created. main.js:41
Parent Menu created. main.js:58
Radio Menu created. main.js:71
Checkbox Menu created. main.js:84

そしてコンテキストメニューを上から順番に実行すると、

normal_menu_id clicked. main.js:7
selection_menu_id clicked. main.js:7
 selectionText:akirattii main.js:18
child_menu1_id clicked. main.js:7
child_menu2_id clicked. main.js:7
radio_menu1_id clicked. main.js:7
 checked:true, wasChecked:false main.js:14
radio_menu2_id clicked. main.js:7
 checked:true, wasChecked:false main.js:14
checkbox_menu1_id clicked. main.js:7
 checked:true, wasChecked:false main.js:14
checkbox_menu2_id clicked. main.js:7
 checked:true, wasChecked:false main.js:14

このようにログが表示されます。
※選択型メニュー(id=selection_menu_id)は文字列が選択状態でないと出現しません。


チェック系コンテキストメニューについて思うこと


サンプルに盛り込んだラジオボタン系メニューやチェックボックス系メニューを使う場面は殆どないのではと思いますが、もし使う場合には、現在のチェック状態をグローバル変数かどこかに持たせておいて何処からでも参照できるようにしておくという工夫が必要そうですね。というのも、作成したコンテキストメニューのインスタンスにアクセスする方法が提供されていないからです。もしかすると私が知らないだけかもしれませんので、知っている方は教えていただけると助かります。


参考にしたサイト

chrome.contextMenus - Google Chrome

0 件のコメント:

コメントを投稿