uhyohyo.net

JavaScript初級者から中級者になろう

三章第一回 イベントプロパティ

このページの最終更新日:

今回は要素のイベントプロパティについて解説します。

HTMLのイベント属性

この内容は基礎第五回でも解説しました。HTML要素にイベントに対応した属性をつけるというものでした。


<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p onclick="console.log('click');">test</p>
  </body>
</html>

このようにonclick属性をつけた場合、その要素がクリックされた場合にその中身が実行されます。


<!doctype html>
<html>
  <head>
    <title>test</title>
    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }
    </script>
  </head>
  <body>
    <p onclick="aaa();">test</p>
  </body>
</html>

このように、別の場所にあるscript要素で関数などを作って、それをonclickで呼び出すことも可能です。

さまざまなイベント

イベントには、クリックのほかにもさまざまな種類があります。


<!doctype html>
<html>
  <head>
    <title>test</title>
    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }
    </script>
  </head>
  <body>
    <p style="background-color:yellow" onmouseover="aaa();">test</p>
  </body>
</html>

このonmouseoverという属性のイベントが実行されるタイミングは、その要素の上にマウスが乗ったときです。どこまでがp要素の範囲か分かりやすいように、スタイルシートで色をつけてみました。

逆に、その要素からマウスが離れたときのイベントもあります。

<!doctype html>
<html>
  <head>
    <title>test</title>
    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }
    </script>
  </head>
  <body>
    <p style="background-color:yellow" onmouseout="aaa();">test</p>
  </body>
</html>

ここで、どの属性にも属性名の最初に「on」がついています。実は、このonの後ろがイベント名です。つまり、click、mouseover、mouseoutなどになります。

だから、「onclick」という属性は、「イベントclickが起きたとき」という意味にとらえることができます。

他にも、さまざまなイベントがあります。

<!doctype html>
<html>
  <head>
    <title>test</title>
    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }
    </script>
  </head>
  <body onload="aaa();">
    <p>test</p>
  </body>
</html>

body要素にonloadという属性がついています。つまり、イベント名は「load」であるということが分かります。

このloadイベントは読み込みが完了したときに発生します。主にbody要素につけてページの読み込みが完了したときにスクリプトを実行することができます。また、例えばimg要素につけた場合その画像の読み込み完了を意味します。loadイベントはユーザー側が特に何か行動を起こすというわけではありませんが、これもイベントの一種です。

次の例のように、loadイベントを使うことで、head要素内に書かれた関数などを、ページの読み込みが完了してから呼び出すことができます。これは、前回までに見たような「ページの一番最後にscript要素を置く」というような工夫が不要になるという利点があります。(ただし、この用途にはDOMContentLoadイベントのほうが適切なことが多いです。これはそのうち紹介します。)

<!doctype html>
<html>
  <head>
    <title>test</title>
    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }
    </script>
  </head>
  <body>
    <form action="http://www.google.com/" onsubmit="aaa();">
      <p>
        <input type="submit" value="送信">
      </p>
    </form>
  </body>
</html>

今度は、form要素にsubmitというイベントがついています。これは、送信されたときです。送信ボタンを押すと、aaa関数によってログが表示された後ページが切り替わります。

イベントプロパティ

さて、ではイベントプロパティの説明に入ります。これは、JavaScriptから上のイベントを操作する、簡単な方法です。

サンプルを見てみます。


<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="abcd">test</p>

    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }

      var p = document.getElementById('abcd');
      p.onclick = aaa;
    </script>
  </body>
</html>

このスクリプトでは、getElementByIdでp要素のHTMLElementを取得しています。そして、そのonclickというプロパティに、aaaを代入しています。

ここで、aaaは、関数のオブジェクトであることは、一章第四回で解説しました。それを、onclickに代入しています。

名前からも想像がつく気がします。このプロパティが、この要素のclickというイベントを表しているのです。

それでは、具体的にどんな動作をするのかというと、これに関数を代入すると、イベントが発生したときに、その関数が実行されます。今回は、onclick、つまりクリックのイベントだから、p要素がクリックされたときに関数aaaが実行されるようになるというわけです。

onclickがあるから、他にonmouseover、onmouseoutなど、なんでもありえます。これらのプロパティはイベントプロパティなどと呼ばれます。

しかし、実は、このようにイベントプロパティを使うのはよくないやり方です。せっかくJavaScriptから操作できるようになったのに、何がよくないかというと、例えば次のような場合です。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="abcd">test</p>

    <script type="text/javascript">
      function aaa(){
          console.log('aaa!');
      }

      var p = document.getElementById('abcd');
      p.onclick = aaa;

      var newp = p.cloneNode(true);
      document.body.appendChild(newp);
    </script>
  </body>
</html>

さっきと同じようにpにonclickを設定したあと、cloneNode(二章第七回)で同じp要素を作っています。

そのあと、それをbody要素に追加しています。結果、bodyにはp要素が2つ含まれることになります。

さて、1つめの(上の)p要素にはonclickプロパティを設定したため、クリックすると関数aaaが呼ばれます。では、cloneNodeでつくった2つめのほうはどうでしょうか。

なんと、関数が呼ばれないはずです。ノードをそっくりコピーしてしまうはずのcloneNodeでも、イベントプロパティはコピーされないのです。

また、他にも簡単に上書きされてしまうという欠点もあります。

<!doctype html>
<html>
  <head>
    <title>test</title>
  </head>
  <body>
    <p id="abcd">test</p>

      <script type="text/javascript">
        function aaa(){
            console.log('aaa!');
        }

        var p = document.getElementById('abcd');
        p.onclick = aaa;

        p.onclick = function(){
            console.log('bbb!');
        };
    </script>
  </body>
</html>

pのonclickに関数aaaを設定したあと、別の関数を設定しています。p.onclickはプロパティだから、当然上書きされてしまいます。そのため、クリックすると関数aaaは実行されず、あとから設定した関数だけが実行されます。

さすがにここまで露骨には上書きしないでしょうが、別々の処理でどちらの処理でもイベントを設定したい場合など、知らないところで上書きしてしまう可能性はあります。

さて、それではどうするのが良い方法なのでしょうか。次回はそれを解説します。