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要素につけてページの読み込みが完了したときを意味します。ユーザー側が特に何か行動を起こすというわけではありませんが、これもイベントの一種です。

loadイベントを使うことで、head要素内に書かれた関数などを、ページの読み込みが完了してから呼び出すことができます。

<!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など、なんでもありえます。このとき、このonclickなどのプロパティが、イベントプロパティと呼ばれたりします。

しかし、実は、このようにイベントプロパティを使うのはよくないやり方です。せっかく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を設定したあと、今度は関数bbbを設定しています。プロパティだから、当然上書きされてしまいます。そのため、クリックすると関数aaaは実行されず、関数bbbだけが実行されます。

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

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