イベントハンドラの設定
HTMLとJavaScriptの分離
- いままでの記述では、イベントハンドラはHTML内に記述していました
- 定義とイベントが発生する位置がばらばらでわかりにくくなっています
- Webページを作成する際は、HTMLとスクリプトは分けて記述することが推奨されています
スクリプトによるイベントハンドラ
- イベントハンドラに関数名、または関数式を代入します
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>JavaScriptの練習</title> <script> function showImage() { var htmlstr = ""; for(var i=1; i<=3; i++) { htmlstr += "<img src='img/sweets" + i + ".jpg'>"; } document.getElementById( 'imageArea' ).innerHTML = htmlstr; } document.getElementById( 'btn' ).onclick = showImage; </script> </head> <body> <button id="btn">読込</button> <div id="imageArea">ここに画像が読み込まれます。</div> </body> </html>
実行するとコンソールにエラーメッセージが表示されます。
- 「onclickイベントハンドラを設定する対象の要素が存在しない」というような内容です
イベントハンドラが実行される過程
- HTMLタグは、基本的に上から順に解釈されます
- そして scriptタグ内の処理を実行しているときは、以降のタグの読み込みはストップしています
- つまり、追加した行の段階では、まだ「btn」というID値をもつ要素が読み込まれていない状態です
- その状態で、getElementByIdメソッドを実行すると、要素が見つからないため、戻り値は null(オブジェクトが無いことを表す値)になります
- nullに対してonclickイベントハンドラを設定することはできないので、エラーが発生していました
いままでの記述のように、bodyの終了タグの上に scriptを移動してくると解決します。
現在では、scriptの記述する位置がその位置に設定されているのも、そういう理由からです。
しかし、分離という目的からはずれています。
引数のある関数をイベントハンドラに設定する
- イベントらハンドラに対して関数式で匿名関数を代入し、匿名関数の中で引数をつけて呼び出します
- 引数が必要な関数は、匿名関数で包みます
《引数が無い場合》
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>JavaScriptの練習</title> <script> function showImage() { var htmlstr = ""; for(var i=1; i<=3; i++) { htmlstr += "<img src='img/sweets" + i + ".jpg'>"; } document.getElementById( 'imageArea' ).innerHTML = htmlstr; this.disabled = true; } window.onload = function() { document.getElementById( 'btn' ).onclick = showImage; }; </script> </head> <body> <button id="btn">読込</button> <div id="imageArea">ここに画像が読み込まれます。</div> </body> </html>
《引数がある場合》
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <title>JavaScriptの練習</title> <script> function showImage(number) { var htmlstr = "<img src='img/sweets" + number + ".jpg'>"; document.getElementById( 'imageArea' ).innerHTML = htmlstr; } window.onload = function() { document.getElementById( 'btn' ).onclick = function() { showImage(1); }; }; </script> </head> <body> <button id="btn">読込</button> <div id="imageArea">ここに画像が読み込まれます。</div> </body> </html>
- この場合、1番目の画像ののみが表示されます