【連載】CPIエバンジェリストのお悩み相談室
JavaScriptでクリックした要素を検出し、classを付与する方法(前編)

©StockUnlimited

2017年7月19日
TEXT:阿部 正幸(KDDIウェブコミュニケーションズ)
皆さん、こんにちは。KDDIウェブコミュニケーションズの阿部です。私は、JavaScriptの基礎セミナーを大阪市が運営するiMedioで、かれこれ4年ほど定期開催してきましたが、今月もそのセミナー内であった質問を紹介したいと思います。先日掲載した「JavaScriptのConsole API」の使い方もその一つです。

今回は、ボタンをクリックした後に、activeのclassを付与する方法を解説します。サンプルコードも載せているので、Step by Stepで学んで行きましょう!
【本記事で学べる内容】
・ Eventlistnerを使ったイベントの処理
・ classListを使ったクラスの追加と削除
・ DOMの基礎
【お題】ボタンのクリックした後にactive classを付与したい 

[生徒からの質問]
ボタンを3つの並べた状態で、ボタンをクリックした後にactive classを付けたいです。今、ボタン1にactiveが付与されている状態でボタン2をクリックすると、1と2の両方がactiveになってしまいます。ボタン2だけをactiveにするにはどうすればよいですか?
■補足:ボタン1にclassを付けることと、再度クリックしたときにそのclassを外すことは出来ている


3つ並べたボタンのイメージ

という質問に対して、

[私の回答]
押された以外のボタンに対して、activeが付いているかチェックし、付いていたら外せばいいんじゃない?

[生徒からの質問]
それができたら質問していないですよね……。

[私の回答]
たしかに! 一回ソースコードを見せてください。

というわけで、その生徒が書いたソースコードはこちらです。buttonタグに、クラスbtn1からbtn3をつけています。

[生徒が記述したソースコード]

01  <button class="btn1">ボタン1</button>
02  <button class="btn2">ボタン2</button>
03  <button class="btn3">ボタン3</button>
04  <script>
05  $(function(){
06   $('.btn1').on("click", function(){
07    if ($('.btn1').hasClass('active')) {
08     $('.btn1').removeClass('active');
09    } else {
10     $('.btn1').addClass('active');
11    }
12   });
13  });
14  </script>

6行目の $('.btn1').on("click", function(){ は、btn1をクリックすることで、7行目の if ($('.btn1').hasClass('active')) { で、btn1にactiveが付いているかどうかを判定し、クラスを付けたり消したりしています。

このままソースコードを使うのであれば、btn1 のクリック検出時に、$('.btn2').removeClass('active'); 、 $('.btn3).removeClass('active'); の処理を追加することで動作します。

しかし、下記の理由からソースコードを1から作り直すことにしました。

[理由]
ヽ謄椒織鵑class名を変えないと動作しない
▲椒織鵑料減時にJavaScriptを書き変えないといけない
jQueryを使ったコードが記述されている(レスポンスを考えるとネイティブで記述する方が望ましい)

まず初めに今回の完成系を見てみましょう。今回のゴールです。

こちらのサンプルコードで動作を確認できます。
url. http://shared-blog.kddi-web.com/sandbox/javascript/click/

[仕様はこちら]
●ボタンをクリックすると、activeクラスが付与される
●クリックしたボタンにactiveクラスがついている場合は削除
●クリックしたボタン以外に、activeクラスが付いている場合はクラスを削除
●HTML、CSSの準備 
まず、HTMLとCSSを用意します。
index.html
<!DOCTYPE html>
<html>
<head>
<title>TEST</title>
<meta charset="UTF-8">
<style type="text/css">
 .btn{
  width: 200px;
  height: 30px;
  margin: 5px;
  outline: none;
 }
 .active{
  background-color: #666;
 }
</style>
</head>
<body>
<button class="btn">ボタン1</button>
<button class="btn">ボタン2</button>
<button class="btn">ボタン3</button>
</body>
</html>
<button> タグを使いボタンを3つ設置し、各ボタンに「btn」クラスを付与します。このボタンをクリックすると、activeクラスが付与されるプログラミングをします。

●JavaScriptでの実装 
■Step1: 
<button>がクリックされたイベントを取得します。クリックイベントは、addEventListenerで取得します。書式は下記の通りです。
●参考:Mozilla Developer Network
url. https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener

構文:
target.addEventListener(type, listener[, options]);

type: 
イベントの種類(click、mouseorverなど)
url. https://developer.mozilla.org/en-US/docs/Web/Events listener
オブジェクトか関数を指定

まず btn クラスが付与されたDOM要素を取得し、正しく取得できたかコンソール画面に出力します。

<script>
 var btn = document.getElementsByClassName(‘btn’);
 console.dir(btn);
</script>
実行結果:


btnクラスが付与されたDOMを取得できました。今回は3つボタンを設置していますので[0]、[1]、[2]の3要素を取得することができました。この取得したDOMに対して、EventListenerを登録し、クリック時の動作を付けていきます。

<script>
 var btn = document.getElementsByClassName('btn');
 btn[0].addEventListener("click", function(){
  console.log('クリックされました');
 });
</script>
実行結果:
上記コードを追加し、「ボタン1」をクリックすると、コンソール画面に「クリックされました」と出力されます。btn[0]に対してaddEventListenerを設定していますが、これだけではボタン1のクリックしか検出できません。ボタン2、ボタン3と指定をする場合はbtn[1]、btn[2]とそれぞれ記述します。

しかし、上記方法ではボタンの数が増えたり減ったりした場合にJavaScriptのコードを書き換える必要がでてくるので、手間になってしまいます。そこで下記のように、for文を使い、ボタンの個数分ループをし、イベントリスナーに登録します。

<script>
 // ボタンのDOM要素を取得
 var btn = document.getElementsByClassName('btn');

 // ボタンの個数分ループ
 // 変数「i」に現在のループ回数が代入される
 for (var i = btn.length - 1; i >= 0; i--) {

  // 各ボタンをイベントリスナーに登録
  btn[i].addEventListener("click", function(){
   console.log('クリックされました');
  });
 }
</script>
■Step2:
クリックしたボタンにactiveクラスを追加、再度クリックでactiveクラスを削除します。クラスの追加や削除はDOM要素のclassListを使います。また、classListには便利なメソッドあります。

・add: クラスの追加
・remove: クラスの削除
・toggle: クラスが付いていたら削除、付いていなかったら追加
・contains: 特定のクラスが含まれているか確認
引用: Mozilla Developer Network
url. https://developer.mozilla.org/ja/docs/Web/API/Element/classList
<script>
  // ボタンのDOM要素を取得
 var btn = document.getElementsByClassName('btn');

 // ボタンの個数分ループ
 // 変数「i」に現在のループ回数が代入される
 for (var i = btn.length - 1; i >= 0; i--) {

  // 各ボタンをイベントリスナーに登録
  btn[i].addEventListener("click", function(){
   // activeクラスの追加と削除
   // thisは、クリックされたオブジェクト
   this.classList.toggle('active');
  });
 }
</script>
このコードを追加することで、クリックしたボタンにactiveクラスが追加されたり削除されたりします。だんだん出来上がってきました。

次に、クリックしたボタン以外にactiveクラスが付いていた場合、クラスを削除する方法をご紹介したいと思いますが、記事が長くなってきましたので、また次回でご紹介します。
>>>「CPIエバンジェリストのお悩み相談室」の目次はこちら

[筆者プロフィール]
阿部 正幸(あべ まさゆき) | KDDIウェブコミュニケーションズ/エバンジェリスト
システム開発会社で大規模なシステム開発を経験後、Web制作会社でプログラマー兼ディレクターとして従事。その後、KDDIウェブコミュニケーションズに入社、レンタルサーバーCPIのプロダクトマネージャーに就任。ACE01、SmartReleaseをリリース後、現職の「エバンジェリスト」としてWeb制作に関する様々なイベントに登壇。Drupal(g.d.o Japan)日本コミュニティー、HTML5 funなどに所属し、OSSを世に広げる活動やWeb制作に関する情報を発信している。

●CPIフタッフブログ
 URL:http://shared-blog.kddi-web.com/

● CPI LINE@のご案内
http://shared-blog.kddi-web.com/other/215