0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

chrome拡張機能の開発記録2

Posted at

先日、自身の二作目であるchrome拡張機能『YouTube Video Tag』をリリースしました。

今回の記事では、前回の記事には載っていない新たな学びを書き記していこうと思います。

※以下の本文では、私が作った拡張機能のソースコードを引用している所があります。全てを載せると長くなる部分は省いていますが、詳細を見たい方はChrome extension source viewerなどのツールを使うか、拡張機能をインストールしてローカルストレージのファイルを見るなどして下さい(GitHubのリポジトリは公開してないので)。


オブジェクトのディープコピーを作る

オブジェクトのディープコピーを作るには、文字列に変換(JSON.stringify)してから元に戻します(JSON.parse)。

let goods = {
    "name": "pen",
    "price": 150
};
let goods_copy = JSON.parse( JSON.stringify(goods) );

goods["price"] = 200;
console.log(goods_copy["price"]); // > 150

コールバック関数内からインスタンスを参照する

メソッド内でイベントリスナーを定義する際、コールバック関数内でthisを使うと、インスタンスではなくdocumentを指すことになり、メンバーが見つかりません(undefinedになる)。

class Hoge {
    name = "hoge";

    piyo(){
        $('#fuga-btn').on('click', function(){
            console.log (this.name); // > undefined
        });
    }
}

コールバック関数をアロー関数で定義すれば、その中で使われたthisは関数が定義された場所におけるthis――つまりインスタンスを指します。

class Hoge {
    name = "hoge";

    piyo(){
        $('#fuga-btn').on('click', () => {
            console.log (this.name); // > hoge
        });
    }
}

onメソッドの処理は重複する

jQueryのonメソッドを使ったイベントリスナーの追加は、重複します
重複させたくない場合は、onメソッドの前にoffメソッドを呼んで、既に追加されているイベントリスナーを削除する必要があります(追加されていなくてもエラーが出ることはありません。)。

例えば、私が作った拡張機能には以下のような関数があります。
「タグ要素をページに追加し、それぞれについている『削除』ボタンにイベントリスナーを追加する」という処理を行います。

addVideoTagsElem(tags){
    let tagGroupElem = $("#yvt-tag-group");
    for (let tag of tags) {
        let tagElem = /* 略 */;
        tagGroupElem.append(tagElem);
    }
    $('.yvt-btn-delete').off('click');
    $('.yvt-btn-delete').on('click', e => {
        // 略
    });
}

この関数は、タグの追加が行われる度に呼び出されます。
onメソッドを呼び出す対象要素をクラスで指定しているので、タグの追加が複数回行われると、前に追加されていたタグ要素にもイベントリスナーが追加され、重複してしまいます。

そこで、onメソッドを呼ぶ直前にoffメソッドを呼び、既存のタグ要素に追加されているイベントリスナーを削除しています。


タグ入力用ライブラリについて

私が作った拡張機能では、タグを入力する場所が二箇所あり、それぞれでタグ入力用ライブラリを使い分けています。

tagifytagsinputです。

最初はtagifyだけを使う予定でしたが、tagifyの不具合が原因で片方では使えなくなったので、別のライブラリも使うことにしました。

以下では、それぞれのライブラリを使ってみた感想などを述べていこうと思います。

tagify

tagifyはUIがキレイで、オプションなども充実していて、拡張性も高いライブラリです。
日本語の入力補完にも対応していて、delimiterの値を変更することで、全角スペース区切りにも対応します。

しかし、chrome拡張機能で使うとなったとき、いくつか問題が発生しました。

ダークテーマのページにあるテキストフォームにtagifyを適用すると、inputフォームの背景が黒くなり、入力した文字が見えなくなる。

この問題は、tagifyによって追加されたtagsタグの背景色を明示的に変更することで解決しました。

delimiterに全角スペースを指定していても、removeAllTagsメソッドでテキストフォーム内の全角スペースを削除できない。

確かに全角スペースを入力すると区切り文字として認識はされるのですが、半角スペースとは違い、全角スペースはテキストフォーム内にそのまま残ってしまいます。
この問題は、tagify.DOM.input.textContent = "";を実行し、テキストフォーム内に残った文字列を削除することで解決しました。

ページにショートカットキーが設定されている場合、tagifyを適用したテキストフォーム内でのキー入力が、ショートカットキーの機能を呼び出してしまう。

具体例を挙げると、YouTube動画ページ内にtagifyを適用したテキストフォームがある場合、その中でkjlmなどのキーを押すと、動画の再生が止まったり、シークバーが動いたり、ミュートになったりしてしまうということです。

keydownイベントが発生したらstopPropagationを実行するなど、色々試してみましたが、完全な解決には至らなかったので、私は「既存のページに追加したテキストフォームにtagifyを適用する」という使い方を断念しました。

ポップアップページでは問題なく使えました。

tagsinput

tagifyの代わりに動画ページで使うことにしたのが、このライブラリです。

特にこれにこだわる理由もないのですが、日本語の入力補完ができ、ショートカットキーが暴発することもなかったので、採用しました。

難点は、tagifyと違って全角スペースを区切り文字にできないことと、input要素のidが変更されるので、入力された値を取得するのが少しだけ面倒なことです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?