あと何回で歯医者が終わるか待ち遠しい、エディター若栁です。
エディターが学ぶ初めてのプログラミング、第7回をお送りします。
HTMLのファイルを見直してみた
一通り前の回で、動作の不具合も直ったスロットゲームですが、自分で書いたHTMLのコードを改めて見たところ、
1 2 |
<input type="button" value="start" onclick="start_slot();"> <input type="button" value="stop" onclick="stop_slot();"> |
ボタンの動作を制御するJavaScriptのonclick属性が、HTMLの中に書かれていました。
別に動くからいいじゃーん。はい、動きます。ただ、HTML(構造)やJavaScript(動き)、CSS(見た目)とそれぞれ役割が違います。
これについてはセマンティックWebという考え方があるそうで、IT用語辞典 e-Wordから一部説明を引用します。
コンピュータに文書や情報の持つ意味を正確に解釈させ、文書の関連付けや情報収集などの処理を自動的に行わせる技術
コンピュータ側に、より正確に解釈させるため、HTMLは.htmlファイルに、JavaScriptは.jsファイルに混在させずにちゃんと書こうぜ、っていうことです。それを踏まえて、今回は、JavaScriptは.jsファイルに記述しよう!onclickを書き直そう!の回をお送りします。
onclick属性をaddEventListenerで書き換える
onclick属性は、○○が△△されたら□□する、というように、特定の要素(○○)に対して処理を行うきっかけ(△△)があったら、処理をする(□□)という橋渡しの役割をします。これを.jsファイルに書き換える場合には、addEventListnerを使います。
1 |
[取得したい要素].addEventListner("何がきっかけか", 処理させたい関数名 ); |
[取得したい要素]:先ほどの説明でいうと、○○にあたる部分、今回はスタートとストップのボタンですが、ここではスタート側のみ記述していきます。元の.htmlファイルではidを使って指定していなかったので、以下のように書き直します。
1 |
<input type="button" value="start" id="start"> |
HTML側で付与されたidを参照するために「このidを持っている要素を、ページの中から見つけてくる!」と指示を出す必要があります。この指示を出すには、document.getElementByIdを使います。今回はこのコは詳しく触れません 。また後日。
1 |
document.getElementById("取得したい要素のid"); |
今回は、startというidをもつ要素を取ってきてほしいので、
1 |
document.getElementById("start"); |
これを最初に出てきたaddEventListenerと組み合わせます。取得した要素を、start_btn変数に入れています。
1 2 |
var start_btn = document.getElementById("start"); start_btn.addEventListener("何がきっかけか", 処理させたい関数名); |
残った2つは、何をしたら→クリックしたら、どの関数→start_slot なので、それぞれを書き直して、できたー!
1 2 3 4 5 6 7 8 |
var start_btn = document.getElementById("start"); start_btn.addEventListener("click", start_slot); function start_slot() { picture1 = Math.floor(Math.random() * 3 + 1); //以下省略 } |
・・・と思ったのですが、スロットが回ってくれません。
GoogleChromeのデベロッパーツールでエラー内容を確認してみました。デベロッパーツールについては「クローム 検証ツール」「クローム デベロッパーツール」等で使い方を検索してみてください。
デベロッパーツールで検証した結果、エラーは以下のとおり。
1 |
Uncaught TypeError: Cannot read property 'addEventListener' of null |
「エラーの種類:キャッチできず nullの’addEventListener’プロパティが読み取れない」
なぜnullになるのかを想定してみると、
- 書いたコードがどこか間違っていてnullになっている
- それ以外の理由で要素が取得できなくてnullになっている
1つ目のコード間違いについては、「見た目は間違っていない、けど、実はどこかに見落としがあるかも」・・・と自分を疑って、念のため、.htmlファイルの中、bodyの閉じタグ直前に直接scriptタグを入れてみました。もしコードに間違いがあれば、どこに書いたとしても同じエラーになるはずですが・・・、動きました。つまり今回のエラーはコード間違いが原因ではない、とわかりました。まずは一歩前進。
では、どこが問題なのか?addEventListenerは、直前のstart_btnという変数を受けているので、そこの値が取れているか?を確認する必要がありそうです。
1 2 |
var start_btn = document.getElementById("start"); start_btn.addEventListener("click", start_slot); |
結論から言うと、addEventListenerの前にある、start_btn、つまりgetElementById(“start”)の値が取れていなかったことがnullの原因でした。
htmlファイル内のscriptタグの位置
外部の.jsファイルを読み込もうとするとエラーになり、.htmlファイルに直接書くとエラーが出ない。
となると、問題は.jsファイルやその中身ではなさそうです。それを踏まえて、.htmlファイルを確認しました。
1 2 3 4 5 6 7 8 9 10 11 12 |
<head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/Javascript" src="slot.js"></script> </head> <body> <!-- 省略 --> <form> <input type="button" value="start" id="start" > <input type="button" value="stop" id="stop" > </form> </body> |
ページは上から順番に読み込まれて処理されていくので、.jsファイル読み込み・処理〜bodyの中身読み込み、の順番になります。id=”start”を持つ要素が読み込まれていない、値が無いのでnullがかえってくるんですね・・・。
直接scriptタグの中にJavaScriptを書いた時には、
1 2 3 4 5 6 7 8 9 10 11 12 |
<!-- 省略 --> <input type="button" value="start" id="start"> <input type="button" value="stop" id="stop"> <!-- 省略 --> <script> <!-- 省略 --> var start_btn = document.getElementById("start"); start_btn.addEventListener("click", start_slot); <!-- 省略 --> </script> |
getElementByIdが実行されるタイミングに、id=”start”を持つ要素は読み込まれているので処理ができました。
最終的に、外部の.jsファイルを読み込ませるタグを、bodyの閉じタグ直前に移動して、無事にスロットが動作するようになりました。めでたし。
今回は、addEventListenerについてお送りしました。