【JavaScript 中級講座】DOMのイベントに関数を登録する
本講座では、イベントと関数の関係を学習する。 学習のメインは関数である。関数を自由に利用する事が主たる目的である。 関数を学習するために、イベントを例として活用する。
HTMLタグの操作のタイミング
002<script>
003
004//[li]タグを取得
005const items =
006 document.getElementsByTagName ( "li" ) ;
007
008//[0]
009alert ( items.length ) ;
010</script>
011</head>
012<body>
013 <ol id = "list" >
014 <li>お茶</li>
015 <li>コーヒー</li>
016 <li>水</li>
017 </ol>
018</body>
019</html>
このプログラムは、プログラマーが想定した結果にはならない。
プログラムを解説する。6行目で、「li」タグを全て取得して、
変数itemsへ代入する。
document.getElementsByTagName( [タグ名] )
Web画面の特定のタグを操作したい場合がある。 その場合、タグ名を引数に渡して、documentオブジェクトのgetElementsByTagName()関数を実行すると、 引数で指定したタグ名に一致するタグのオブジェクトを戻してくれる。 戻り値は「 HTMLCollection 」である。 HTMLCollection は配列に似ている。配列ではないが配列に似ている。
005const items =
006 document.getElementsByTagName ( "li" ) ;
007
008//[0]
009alert ( items.length ) ;
010</script>
011</head>
012<body>
013 <ol id = "list" >
014 <li>お茶</li>
015 <li>コーヒー</li>
016 <li>水</li>
017 </ol>
6行目で、documentオブジェクトのgetElementsByTagName ()関数を利用して、 liタグを取得する。getElementsByTagName ()関数の戻り値を変数itemsへ代入する。 HTMLファイルの部分に、liタグが3つ記載されている。 「お茶」「コーヒー」「水」の3つである。 変数itemsには、この3つのliタグが代入されている・・・と思われる。 しかし実際は違う。 9行目で、変数itemsの中に入った要素数を確認する。
HTMLCollectionのlengthプロパティを利用すると、要素数を取得できる。 こんかい、liタグは「お茶」「コーヒー」「水」の3つである。 9行目で「3」と表示されると思ったのだが、「0」と表示した。 原因はなんだろうか?
Webブラウザを開くと、HTMLファイルに記載されたタグがWebブラウザに読み込まれる。 HTMLタグを操作する場合、 HTMLタグが読み込まれた後に操作する必要がある。 HTMLタグが読み込まれる前に、HTMLタグは操作できない。
002<script>
003
004//[ol]タグを取得
005const ol =
006 document.getElementById ( "list" ) ;
007
008//[null]
009alert ( ol ) ;
010</script>
011</head>
012<body>
013 <ol id = "list" >
014 <li>お茶</li>
015 <li>コーヒー</li>
016 <li>水</li>
017 </ol>
018</body>
019</html>
6行目で、documentオブジェクトのgetElementById()関数を実行してタグを取得する。 関数の引数に文字列「list」を指定する。 idが「list」のタグは、13行目のolタグである。 olタグを取得して5行目の変数olへ代入する。 9行目で変数olを表示する。ここで、olタグが表示する予定だったが、 「null」と表示する。つまり、6行目のgetElementById()関数が上手く機能しなかったという事だ。 理由は、前回のプログラムと同じである。 HTMLタグが作られる前に、HTMLタグを利用した事である。
window.onloadに関数を登録する
window.load()関数に関数を登録するプログラムを見る。
002//ロード完了後、実行
003window.onload = function () {
004 alert ( "IORI" ) ;
005}
006</script>
JavaScriptをWebブラウザ上で実行すると、windowオブジェクトを利用できる。 windowオブジェクトは、Webブラウザ全体を管理するオブジェクトである。 オブジェクトとは、プロパティや便利な関数が入った箱である。 つまり、windowオブジェクトの中には、Webブラウザを管理するための便利な プロパティや関数が入っている。
windowオブジェクトのonload()関数は、 Webブラウザの読み込みが完了した時点で実行する。 では、プログラムを解説する。
002//ロード完了後、実行
003window.onload = function () {
004 alert ( "IORI" ) ;
005}
006</script>
3行目のイコール記号の右側を見る。
functionキーワードで関数を定義している。
関数の処理は4行目である。
文字列「IORI」を表示する処理であるが、いまここで関数が実行する事は無い。
3行目は、関数の定義をしているだけである。実行はしない。
さて、3行目のイコール記号の左側を見る。
これは、windowオブジェクトのonload()関数を意味する。 例を挙げる。
002//オブジェクト生成
003const IORI = { } ;
004
005//関数を定義
006IORI.onload = function () {
007 alert ( "走る" ) ;
008}
009//[走る]
010IORI.onload ( ) ;
011
012//新しい関数を登録
013IORI.onload = function () {
014 alert ( "昼寝" ) ;
015}
016//[昼寝]
017IORI.onload ( ) ;
018</script>
プログラムを解説する。3行目で空のオブジェクトを生成して、変数IORIへ代入する。
6行目で、IORIオブジェクトのonloadプロパティに関数を代入する。
IORIオブジェクトのonloadプロパティは、関数という事になる。
10行目で、onload()関数を実行すると「走る」と表示する。
13行目で、IORIオブジェクトのonlooad関数に新しい関数を代入する。
17行目で、onload()関数を実行すると、「昼寝」と表示する。
このプログラムのように、すでに存在する関数を新しい関数で上書きできる。
もういちど、今回のサンプルプログラムを見る。
002//ロード完了後、実行
003window.onload = function () {
004 alert ( "IORI" ) ;
005}
006</script>
3行目でwindowオブジェクトのonloadへ、独自に作成した関数を代入する。 windowオブジェクトのonload()関数は、 Webブラウザ読み込み後に実行する。 今回、この関数に独自に作成した関数を代入した。 つまり、Webブラウザ読み込み完了後に、独自に作成した関数が実行する。
window.onloadに関数を登録してDOM操作を実行する
いま問題になっているのは、JavaScriptを動かす時に、HTMLタグが存在しないという事である。 では、HTMLタグが読み込まれた後にJavaScriptを動かせば良い。 それが、今回見るサンプルプログラムである。
002<script>
003//ロード完了後、実行
004window.onload = function () {
005
006 //[ol]タグを取得
007 const ol =
008 document.getElementById ( "list" ) ;
009
010 //[3]
011 alert ( ol.children.length ) ;
012}
013</script>
014</head>
015<body>
016 <ol id = "list" >
017 <li>お茶</li>
018 <li>コーヒー</li>
019 <li>水</li>
020 </ol>
021</body>
022</html>
今回のプログラムは、プログラムが想定した通りに動く。
いま、Webブラウザが読み込みを完了した後に、処理を実行したい。
windowオブジェクトのonload()関数へ、実行したい関数を代入すると、
読み込み完了後にその関数が実行する。
プログラムを解説する。
004window.onload = function () {
005
006 //[ol]タグを取得
007 const ol =
008 document.getElementById ( "list" ) ;
009
010 //[3]
011 alert ( ol.children.length ) ;
012}
015<body>
016 <ol id = "list" >
017 <li>お茶</li>
018 <li>コーヒー</li>
019 <li>水</li>
020 </ol>
4行目のイコールの右側に注目する。
functionキーワードを利用して、関数を定義している。
関数の処理は、7行目から11行目までである。
この関数は、今は実行しない。
windowオブジェクトのonloadプロパティへ代入しただけである。
では、時間を進める。WebブラウザがHTMLタグの読み込みを完了すると、
windowオブジェクトのonload()関数が実行する。
windowオブジェクトのonload()関数は、7行目から11行目までの関数である。
ここで、7行目が実行する。
まず、document.getElementById()関数が実行して、
idが「list」のタグを取得する。
idが「list」のタグはolタグである。
7行目の変数olにolタグのオブジェクトが代入する。
すでにHTMLタグの読み込みは完了しているので、
変数olには、確かにolタグのオブジェクトが入る。
11行目で、olタグの子要素の数を表示する。
11行目が実行すると、「3」と表示してプログラムは終了する。
プログラムの解説は以上である。
「関数を登録する」という点をご理解頂ければと考える。
リストへonclickイベントを動的に登録する
リストがクリックされた時に、プログラムを実行する方法を学習する。
002<script>
003//ロード終了後に呼ばれる
004window.onload = function ( ) {
005
006 //[li]タグを取得
007 const items =
008 document.getElementsByTagName("li");
009
010 for ( var i = 0 ; i < items.length ; i ++ ) {
011
012 //liタグを取得
013 const li = items [ i ] ;
014
015 //liタグにイベント追加
016 li.onclick = function ( evt ) {
017
018 //liタグを取得
019 const tag = evt.target ;
020
021 //タグのラベルを表示
022 alert ( tag.textContent ) ;
023 }
024 }
025}
026</script>
027</head>
028<body>
029 <ol>
030 <li>お茶</li>
031 <li>コーヒー</li>
032 <li>水</li>
033 </ol>
034</body>
035</html>
- お茶
- コーヒー
- 水
文字列をクリックすると、クリックした文字列がダイアログに表示するプログラムである。 では、解説する。
004window.onload = function ( ) {
005
006 //[li]タグを取得
007 const items =
008 document.getElementsByTagName("li");
4行目で、window.onloadプロパティに関数を代入する。 ここで代入した関数は、Web画面のロードか完了したタイミングで実行する。 では、Web画面のロードが完了したと仮定する。 まず、8行目で「li」タグを全て取得して、変数itemsへ代入する。 変数itemsには、HTMLで記載されているliタグのHTMLCollection(配列のようなもの)が代入される。 こんかい、「お茶」「コーヒー」「水」の3つのliタグが代入される。 変数itemsの状態は次の通りである。
インデックス | 値 |
0 | お茶 |
1 | コーヒー |
2 | 水 |
011
012 //liタグを取得
013 const li = items [ i ] ;
014
015 //liタグにイベント追加
016 li.onclick = function ( evt ) {
017
018 //liタグを取得
019 const tag = evt.target ;
020
021 //タグのラベルを表示
022 alert ( tag.textContent ) ;
023 }
10行目でfor文を利用して、itemsの中身を取り出す。 for文はitemsの要素数、すなわち「3」回実行する。 for文1回目。13行目で「お茶」のliタグが取り出される。 16行目でそのliタグのonclickプロパティに値を代入する。
タグをクリックした時に何か処理をしたい場合、
onclickプロパティに関数を代入する。
こんかい、liタグがクリックされた時に、liタグに表示している文字列を、
ダイアログに表示したい。
まず、16行目でliタグのonclickプロパティに関数を代入する。
liタグがクリックされると、代入した関数が実行する。
では、関数の処理を見る。
016 li.onclick = function ( evt ) {
017
018 //liタグを取得
019 const tag = evt.target ;
020
021 //タグのラベルを表示
022 alert ( tag.textContent ) ;
023 }
「お茶」のliタグをクリックすると、19行目と22行目が実行する。 まず19行目で、引数evtのtargetプロパティを変数tagへ代入する。
ユーザーが「お茶」のliタグをクリックすると、 16行目の引数evtにMouseEventオブジェクトが渡されて関数が実行する。 MouseEventオブジェクトのtargetタグに、ユーザーがクリックしたタグが入っている。 つまり、「お茶」のliタグが、変数evtのtargetプロパティに入っている。 そのliタグを変数tagで受け取る。 こんかい、liタグの文字列を表示する。 22行目で、変数tagが参照するオブジェクト、すなわちliタグの textContentプロパティを表示する。
プログラムが実行すると、「お茶」と表示する。
さて、こんかい「お茶」のliタグを例にして解説した。
ほかの「コーヒー」も「水」も同様である。
textareaに入力した文字数をカウントする
最後に、少しツールっぽいものを作成する。 textareaに文字を入力するたびに、文字数をカウントして表示するプログラムである。
002<script>
003//読み込み完了後に呼ばれる
004window.onload = function ( ) {
005
006 //[textarea]タグを取得
007 const txt =
008 document.getElementById("txt");
009
010 //[p]タグを取得
011 const p =
012 document.getElementById("count");
013
014 //キーが上がったイベントを追加
015 txt.onkeyup = function ( evt ) {
016
017 //キーが上がった場合、文字数を取得する
018 const len = evt.target.value.length
019
020 //[p]タグへ表示
021 p.textContent = len ;
022 }
023}
024</script>
025</head>
026<body>
027 <textarea id="txt" rows="15" cols="50" ></textarea>
028 <p id="count" ></p>
029</body>
030</html>
[画面]
では、解説する。まずHTMLファイルを見る。
027 <textarea id="txt" rows="15" cols="50" ></textarea>
028 <p id="count" ></p>
029</body>
27行目でtextareaタグを記述して、id属性の値を「txt」とする。 28行目でpタグを記述して、id属性の値を「count」とする。 こんかい、textareaに文字を入力するたびに文字数をカウントして、 pタグへ表示する処理を書く。
- textareaに文字を入力するタイミングで、関数を実行する
- 関数内でtextareaの文字をカウントする
- 文字数をpタグへ表示する
この手順でプログラムを書く。では、プログラムを見る。
004window.onload = function ( ) {
005
006 //[textarea]タグを取得
007 const txt =
008 document.getElementById("txt");
009
010 //[p]タグを取得
011 const p =
012 document.getElementById("count");
013
014 //キーが上がったイベントを追加
015 txt.onkeyup = function ( evt ) {
016
017 //キーが上がった場合、文字数を取得する
018 const len = evt.target.value.length
019
020 //[p]タグへ表示
021 p.textContent = len ;
022 }
023}
4行目で、windowオブジェクトのonloadプロパティに関数を代入する。 HTMLの読み込みが完了した時点で、関数が実行する。 7行目で、textareaタグのオブジェクトを取得して変数txtへ代入する。 11行目で、pタグのオブジェクトを取得して、変数pへ代入する。 15行目で、textareaオブジェクトのonkeyupプロパティに関数を代入する。
いま、ユーザーがキーを入力するたびに何か処理をしたい。 ユーザーがキーを入力するたびに実行する関数は、 onkeyupプロパティに入っている関数である。 つまり、onkeyupプロパティに関数を代入すると、 キーが上がるたびに関数が実行する。 では、キーが上がるたびに何をするのだろうか?
014 //キーが上がったイベントを追加
015 txt.onkeyup = function ( evt ) {
016
017 //キーが上がった場合、文字数を取得する
018 const len = evt.target.value.length
019
020 //[p]タグへ表示
021 p.textContent = len ;
022 }
ユーザーが文字を入力して、キーを持ち上げたタイミングで、 18行目と21行目が実行する。 まず18行目で、・・・、多くの処理を1行で実行している。
プログラム | 置換え | 解説 |
evt.target | KeyboardEvent.target | textareaオブジェクトを取得 |
evt.target.value | textarea.value | テキストエリアの文字を取得 |
evt.target.value.length | textareaの文字.length | テキストエリアの文字数を取得 |
15行目のfunctionの引数evtのtargetプロパティには、 onkeyupの関数が実行した、そのタグが入っている。 こんかい、textareaタグのonkeyupが実行した。 つまり、functionの引数evtのtargetプロパティには、textareaタグが入っている。 一般的には、イベント発生元のタグが targetプロパティに入っている、と言う。
こんかい、ユーザーがテキストエリアに文字を入力する。 それがイベントである。文字を入力するたびにイベントが発生する。 イベント発生元は、テキストエリアとなる。
014 //キーが上がったイベントを追加
015 txt.onkeyup = function ( evt ) {
016
017 //キーが上がった場合、文字数を取得する
018 const len = evt.target.value.length
019
020 //[p]タグへ表示
021 p.textContent = len ;
022 }
18行目で、テキストエリアの文字数を変数lenへ代入する。 21行目で、pタグのtextContentプロパティに変数lenの値を代入する。 以上にて、ユーザーが文字を入力するたびに、テキストエリアの文字数が、pタグに記載される。
まとめ
document.getElementsByTagName( [タグ名] )