2017年12月26日火曜日

javascriptのリスナー登録について

現在Firefox Web Extensionsでサイドバー内にボタンを配置し、動作させるアドオンを作成しているのですが、リスナーの登録で結構な時間詰まってしまったので報告がてら書き残しておきます。
なお、コレはFirefox Web Extensionsだけでなく、普通にWebサイトを組む上でも同じようです。

症状としてはリスナーに登録したのに動いてくれないというよくあるやつです。

方法1

まずはaddEventListenerを使ってリスナーに登録する方法です

HTML-----------------------------------------------------------------------
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="Content-Script-Type" content="text/javascript" />

        <title>TEST</title>
        <script type="text/javascript" charset="UTF-8" src="sidebar.js"></script>
    </head>
    <body>
        <input type="button" id="test_button" value="TEST" />
    </body>
</html>
---------------------------------------------------------------------------

javascript-------------------------------------------------------------------
document.getElementById("test_button").addEventListener("click", function() {
    console.log("OK");
}, false);
---------------------------------------------------------------------------

このソースだとページを開いた時に以下の通りエラーが発生します。

Error-----------------------------------------------------------------------
TypeError: document.getElementById(...) is null
---------------------------------------------------------------------------

サイドバーではなく、普通にFirefox、Google Chromeで上記HTMLを開いて実行してみても、やはりコンソールに同じエラーが発生しました。

方法2

また、onclickを使った方法も試しました。

HTML-----------------------------------------------------------------------
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="Content-Script-Type" content="text/javascript" />

        <title>TEST</title>
        <script type="text/javascript" charset="UTF-8" src="sidebar.js"></script>
    </head>
    <body>
        <input type="button" id="test_button" value="TEST" onclick="hoge();"/>
    </body>
</html>
---------------------------------------------------------------------------

javascript-------------------------------------------------------------------
function hoge() {
    console.log("OK");
}
---------------------------------------------------------------------------

この場合はコンソールにエラーこそは発生しませんでしたが、同じくボタンを押してもコンソールにONの文字は表示されませんでした。

しかし上記と同じようにサイドバーではなく、Firefoxで上記HTMLを開いて試してみたところ、コンソールにONが表示されました。

方法3(解決編)

色々と調べた結果、最終的に以下のソースでうまく動くことが出来ました。

HTML---------------------------------------------------------------------
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="Content-Script-Type" content="text/javascript" />

        <title>TEST</title>
        <script type="text/javascript" charset="UTF-8" src="sidebar.js"></script>
    </head>
    <body>
        <input type="button" id="test_button" value="TEST" />
    </body>
</html>
---------------------------------------------------------------------------

javascript-----------------------------------------------------------------
window.addEventListener('DOMContentLoaded', function() {
    document.getElementById("test_button").addEventListener("click", hoge, false);
}, {once: true });

function hoge() {
    console.log("OK");
}
---------------------------------------------------------------------------

どうやらタイミングの問題のようで、ちゃんとDOMに読み込まれた後でリスナーを登録しないとダメみたいです。これって結構基本なのかも・・・
しかし、ほんとjavascriptは同期が取れてないというところで苦労する事多すぎですね・・・

ちなみに方法2のWeb Extensionsのサイドバーでだけ動かなかった理由は分からずじまいです。
知ってる方いらっしゃったらコメントをお願いいたします。

その他調べていく中で知った事

今回の問題とは無関係でしたが、同じような問題として陥りそうなものを幾つか知ったのでお知らせしておきます。

1.フォーム部品のnameやidとonclickで呼び出す関数名が重複していたら関数が動作しない
参照:https://qiita.com/nekoneko-wanwan/items/b8b1e2a5bb0a438bb3b4

2.既に同名の関数がある場合はユーザ定義の関数が動作しない
参照:https://www.bhnt.co.jp/blog/%E9%9B%91%E8%A8%98/firefox-javascript-onclick%E3%81%8C%E5%8A%B9%E3%81%8B%E3%81%AA%E3%81%84%EF%BC%9F/

2に関しては参照先ページ下部のコメントをご覧ください。正直ちょっと不明確な情報ですが、可能性としてはありそうです。
なお、記事として見つけたというだけで、実際に参照記事の状態を再現してテストなどはしていません。あくまでも参考までという事で。

0 件のコメント:

コメントを投稿