勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

指定したサイト内でマウスホイールの進む戻る操作時、方向キークリックに変換するブラウザ拡張機能(アドオン)の作成方法

  拡張機能 ブラウザ

指定したサイト内でマウスホイールの進む戻る(左右)の操作を行った際にその操作は無効化し、方向キーの左右をクリックさせたことにするブラウザ拡張機能(アドオン)を作成したい。Chrome限定、サイトによっては動作しない可能性があるものの、とりあえずは動作したので以下に作成方法をメモ。

 

事前準備

(必要に応じて)アイコン画像の作成

アイコン画像ジェネレーター等でアイコン画像を作成しておく。今回は128x128サイズのpng画像を「128.png」というファイル名で作成した。

ディレクトリの用意

以下ディレクトリをPC内に作成しておく。以降拡張機能に関するファイルはmouse_change内に作成する。

 

拡張機能の作成

拡張機能のための各種設定ファイル(manifest.json)

今回はChrome限定でFirefoxは非対応のためbrowser_specific_settingsは不要。

{
    //開発仕様
    "manifest_version": 3,

    //拡張機能名
    "name": "マウスホイールクリック変更",

    //バージョン
    "version": "1.0",

    //拡張機能の説明
    "description": "マウスホイールで進む戻る選択時に矢印キーの左右をクリック",

    //アイコン設定
    "icons": {
        "128": "icons/128.png"
    },

    //拡張機能APIの使用設定
    "permissions": [
        //ユーザーデータの保存、取得、変更
        "storage",

        //ブラウザのタブシステムを使用
        "tabs"
    ],

    //拡張機能が操作できるページ
    "host_permissions": [
        //全てのURL
        "<all_urls>"
    ],

    //アイコンの外観と動作
    "action": {
        //アイコンファイルのパス
        "default_icon": "icons/128.png",

        //ポップアップ(ダイアログ)のパス
        "default_popup": "popup.html"
    },

    //対象サイトと読み込むファイルの設定
    "content_scripts": [
        {
            //対象サイトを全てに設定
            "matches": ["<all_urls>"],

            //使用するJavaScriptファイルのパス
            "js": ["main.js"]
        }
    ]
}

メイン処理用のJS(main.js)

console.log('main.js');

//有効なドメインかチェック
let valid_check = false;

//ストレージからデータを取得
chrome.storage.sync.get(

    //データが存在しない場合の初期値を空配列にする
    { target_domain: [] }, 

    //完了時のコールバック関数
    function( items ){

        //登録されているドメイン一覧
        const domain_list = items.target_domain;

        //ドメインが登録されていない場合は終了
        if( !domain_list.length ){
            return false;
        }

        //現在表示中のホスト名
        const current_host = window.location.hostname;

        //登録されているドメイン一覧内に現在表示中のホスト名が存在しない場合は終了
        if( !domain_list.includes(current_host) ){
            return false;
        }

        valid_check = true;
    }
);

//ポインティングデバイス(マウスホイール)によるページ遷移の標準動作をブロックする
document.addEventListener('mouseup', function( event ){

    //有効なドメインじゃない場合は終了
    if( !valid_check ){
        return false;
    }

    if (event.button === 3 || event.button === 4) {
        event.preventDefault();
    }
});

//ポインティングデバイス(マウスホイール)の進む・戻るクリック時は矢印キーをJS側でクリック
document.addEventListener('pointerdown', function( event ){

    //有効なドメインじゃない場合は終了
    if( !valid_check ){
        return false;
    }

    if( event.button === 3 ){
        const rightArrowEvent = new KeyboardEvent('keydown', {
            key: 'ArrowLeft',
            code: 'ArrowLeft',
            keyCode: 37,
            which: 37,
            bubbles: true
        });

        document.dispatchEvent(rightArrowEvent);
    }
    if (event.button === 4) {
        const rightArrowEvent = new KeyboardEvent('keydown', {
            key: 'ArrowRight',
            code: 'ArrowRight',
            keyCode: 39,
            which: 39,
            bubbles: true
        });

        document.dispatchEvent(rightArrowEvent);
    }
});

ポップアップ側処理用のJS(popup.js)

console.log('popup.js');

//ダイアログの保存ボタンをクリック時
document.getElementById('save').addEventListener('click', function(){

    //入力されたドメイン
    let domain_text = document.getElementById('domains').value;

    //改行で区切って配列化
    let lines = domain_text.split(/\r\n|\n/);

    //結果を入れる配列
    let domains = [];

    for( let i = 0; i < lines.length; i++ ){

        //前後のスペースを削除
        let trimmed = lines[i].trim();

        //文字が入っている場合、配列に追加
        if( trimmed.length ){
            domains.push(trimmed);
        }
    }

    //ストレージにデータ登録
    chrome.storage.sync.set(

        //target_domainに入力された内容を配列形式で格納
        { target_domain: domains }, 

        //完了時のコールバック関数
        function(){

            //結果表示エリアにメッセージ表示
            const result = document.getElementById('result');
            result.innerHTML = '保存しました。<br>ページをリロードします。';

            //メッセージを読む時間分遅延処理
            setTimeout(() => {

                //メッセージ非表示
                result.textContent = '';

                //指定されたプロパティを持つすべてのタブを取得
                chrome.tabs.query(
                    {
                        //タブがアクティブのもの
                        active: true, 

                        //タブが現在のウィンドウにあるもの
                        currentWindow: true 
                    },
                    function( tabs ){

                        //タブが存在する場合
                        if( tabs && tabs[0] && tabs[0].id ){

                            //リロード
                            chrome.tabs.reload(tabs[0].id);
                        }
                    }
                );
            }, 1000);
        }
    );
});

//ダイアログの読み込みが完了した際
document.addEventListener('DOMContentLoaded', function(){

    //ストレージからtarget_domainを取得
    chrome.storage.sync.get(

        //データが存在しない場合の初期値を空配列にする
        { target_domain: [] },

        //完了時のコールバック関数
        function( items ){

            //ダイアログの入力欄にtarget_domainを改行区切りで挿入
            document.getElementById('domains').value = items.target_domain.join('\n');
        }
    );
});

ポップアップ画面のHTML(popup.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="popup.css" rel="stylesheet">
</head>
<body>
    <h1>対象サイト設定</h1>
    <p>適用するドメイン(1行1件):</p>
    <textarea id="domains" placeholder="test.com"></textarea>
    <button id="save">保存</button>
    <span id="result"></span>

    <script src="popup.js"></script>
</body>
</html>

ポップアップ画面のCSS(popup.css)

body{
    width: 280px;
    padding: 12px;
    font-family: sans-serif;
    font-size: 13px;
}
textarea{
    width: 100%;
    height: 80px;
    box-sizing: border-box;
    margin-bottom: 8px;
}
button{
    width: 100%;
    padding: 6px;
    cursor: pointer;
}
#result{
    display: block;
    margin-top: 6px;
    color: #4169e1;
    text-align: center;
}

補足

ディレクトリ構造とファイル設置状況

以下のようになっていればOK。

mouse_change/
├── icons/
│   └── 128.png
├── main.js
├── manifest.json
├── popup.css
├── popup.html
└── popup.js

拡張機能のインストール

拡張機能のインストール方法は過去記事を参照。

確認方法

確認方法は過去記事を参照。

Firefoxの問題

Firefoxはセキュリティ上の問題かマウスホイールの進む戻るがJavaScriptで取得しづらいっぽい。

そのため今回はChrome限定とした。

Chromeでも正常に動作しないケース

方向キーでページ送りできるようなサイトだと正常に動作しなかった。恐らくだけど方向キークリック時にJavaScriptのイベントを仕込んでいるような場合だと正常に動かないと思われる。

 

リファレンス

Element: mouseup イベント

https://developer.mozilla.org/ja/docs/Web/API/Element/mouseup_event

Element: pointerdown イベント

https://developer.mozilla.org/ja/docs/Web/API/Element/pointerdown_event

KeyboardEvent

https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent

EventTarget: dispatchEvent() メソッド

https://developer.mozilla.org/ja/docs/Web/API/EventTarget/dispatchEvent

 - 拡張機能 ブラウザ

  関連記事

ChromeとFirefoxにて拡張機能(アドオン)にポップアップを追加する方法
ChromeとFirefoxにて拡張機能(アドオン)にポップアップを追加する方法

先日ChromeとFirefoxにてHello World表示する拡張機能(アド ...

指定サイトのaタグにblank化、クリック済みの場合は文字色を変更するブラウザ拡張機能の作成方法
指定サイトのaタグにblank化、クリック済みの場合は文字色を変更するブラウザ拡張機能の作成方法

ポップアップ内にテキストエリアを設置し、そちらにドメインを入力すると該当サイトの ...

ChromeとFirefoxにてHello World表示する拡張機能(アドオン)を作成する方法
ChromeとFirefoxにてHello World表示する拡張機能(アドオン)を作成する方法

Google Chrome / Firefoxの拡張機能(アドオン)を作ってみた ...