読者です 読者をやめる 読者になる 読者になる

そんな今日この頃の技術ネタ

本家側に書くほどでもない小ネタ用

Chrome拡張機能を作ってみる その2. UIを作成する、設定を保存する

前回に引き続きChrome拡張機能を作ってみる話。

blue1st-tech.hateblo.jp

今回はHTMLでUIを構成したり、設定を保存したりしてみる。

「ページのタイトルとURLを事前に指定したフォーマットでクリップボードに保存する」というお題で作ってみた。

github.com


今回は以下のファイルで構成している。

  • 定義ファイルmanifest.json
  • 設定画面options.htmlとそこから呼ぶoptions.js
  • ポップアップ画面popup.htmlとそこから呼ぶpopup.js
  • 共通で使用するsetting.js
  • icon.png


定義ファイルmanifest.js

{
    "manifest_version": 2,
    "name": "Title Capture",
    "description": "表示タブのタイトルを任意のフォーマットで取得して共有しやすくする",
    "version": "0.3",
    "browser_action": {
        "default_icon": "icon.png",
        "default_title": "Title Capture",
        "default_popup": "popup.html"
    },
    "permissions": [
        "tabs"
    ],
    "options_page": "options.html"
}

前回とは異なりページ自体に手を加える必要はないことからconstant_script項および駆動させるために使用していたbackground項は無し。

代わりにbrowser_action項のdefault_popupにUIとなるHTMLファイルを記述しているのと、設定画面用にpopup_pagesにもHTMLファイルを指定している。

実働部分となるJavascriptはそれぞれのHTML内で呼び出している。


共通ライブラリsetting.js

今回の要件では設定=クリップボードへ書き出す際のフォーマット文字列の読み書きを行う必要がある。

これはJavascriptのLocalStorageを用いることにした。

function load_setting() {
    return localStorage["pattern"] ? localStorage["pattern"] : '<a href="${url}"><img src="${favIconUrl}"></img>${title}</a>'
}

function save_setting(pattern) {
    localStorage["pattern"] = pattern;
}

空の場合は初期設定を返すようにした。


設定画面機能options.htmloptions.js

拡張機能のオプションで表示されるUIとその機能を作成する。

今回はフォーマット文字列を保存したいので簡潔に1つのフォームを持つ画面として設計した。

<!DOCTYPE html>
<html lang="en">
    <head>
       <meta charset="UTF-8">
       <title>Title Capture</title>
       <script src="setting.js"></script>
       <script src="options.js"></script>
   </head>
    <body style="background-color:#666">
        <div>
            <h2>変数</h2>
            <p><code>${url}</code>: URL</p>
            <p><code>${title}</code>: タイトル</p>
            <p><code>${favIconUrl}</code>: アイコンのURL</p>
        </div>
        <div>
            <textarea id="text-format" style="width:80%"></textarea>
        </div>
        <div>
            <button id="btn-save">Save!</button>
        </div>
    </body>
</html>


また、実際に機能として動作させるため、先程のsetting.jsに加えてフォームをコントロールするoptions.jsを作成した。

window.onload = function(){
    var btn = document.getElementById("btn-save");
    var textarea = document.getElementById("text-format");

    // initialize
    var init = function(){
        var pattern = load_setting();
        textarea.textContent = pattern;
    };
    init();

    // set save event
    btn.addEventListener("click", function(){
        save_setting(textarea.value);
        alert("save!");
    });
}

画面ロード時にLocalStorageより既存の文字列を読み取ってtextareaに表示、ボタンを押されたらtextareaの文字列をLocalStorage保存。

これで最低限の設定の読み書きはできた。


ポップアップ画面機能popup.html&popup.js

アイコンを押された際に表示するUIとしてpopup.htmlを作成した。

素のままでは使用しづらい大きさの表示となってしまうため、htmlタグにmin-widthを指定している。

<!DOCTYPE html>
<html lang="en" style="min-width:400px;">
<head>
   <meta charset="UTF-8">
   <title></title>
   <script src="setting.js"></script>
   <script src="popup.js"></script>
</head>
<body style="background-color:#666">
    <div>
        <textarea id="url-space" style="width:100%"></textarea>
    </div>
    <div>
        <button id="btn-copy" style="width:100%">Copy!</button>
    </div>
</body>
</html>


こちらもsetting.jsとともに実働部分のpopup.jsを作成した。

chrome.tabs.getSelected(null, function(tab){
    var title = tab.title;
    var url = tab.url;
    var favIconUrl = tab.favIconUrl;
    
    var text = load_setting();
    text = text.replace(/\$\{title\}/g, title);
    text = text.replace(/\$\{url\}/g, url);
    text = text.replace(/\$\{favIconUrl\}/g, favIconUrl);

    var textarea = document.getElementById("url-space");
    textarea.textContent = text;
});

window.onload = function(){
    var btn = document.getElementById("btn-copy");
    btn.addEventListener("click", function(){
        var textarea = document.getElementById("url-space");
        textarea.select();
        document.execCommand("copy");
    })
}

表示しているタブの情報を読み取って設定された文字列を置換して目的の文字列を作成しtextareaの値として設定。

これをボタンが押されたらクリップボードに保存する。

クリップボード周りの操作はセキュリティ的なものの関係上ちょっと面倒くささがあって、 調べた限りでは現在のブラウザでは直に文字列を挿入するといった手段は使えないようだ。

一旦HTML要素として作成しそれを選択させ、なおかつユーザの操作をトリガーとした動作によってはじめてコピーできる。

文字列置換も本当はevalを使ってパターン文字列をテンプレートリテラルとして扱いたかったのだが、 拡張機能でのevalの使用はセキュリティ的に色々制限があるらしく、 ちょっと面倒くさかったしこだわるだけの必然性もなかったので単純な文字列の置き換えとして対処。


使ってみる

導入まわりは前回と同じなので割愛し、実際に使用してみる行程。

アイコン右クリックで「オプション」がメニューとして表示される。

f:id:blue1st:20161218234131p:plain:w600


欲しい形式を指定して保存。

f:id:blue1st:20161218234214p:plain:w800


アイコンをクリックすると、指定したとおりのフォーマットで文字列が生成され、 ボタンでクリップボードに書き込まれることが確認できる。

f:id:blue1st:20161218234527p:plain:w800


資料集めの時のURLメモやメールやチャットでの展開、そしてブログ用のリンク作成なんかの効率化に役立つんじゃないかと思う。

Google Chrome HACK

Google Chrome HACK