はじめに
前回に引き続き、JavaScript(以下JS)の復習を行なっていきます。
今回は、jQueryというライブラリを使って基本的なブラウザ情報とイベントを実装していきます。
jQueryでタブメニュー切り替えを実装する。
第3回の応用編で使用したJSを書き換えて、jQueryでタブメニューの切り替えを記述していきます。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = document.getElementsByClassName("menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除("[0]は、最初の要素の意味")
document.getElementsByClassName("active")[0].classList.remove("active");
// クリックしたタブにactiveクラスを追加
this.classList.add("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
document.getElementsByClassName("show")[0].classList.remove("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
// クリックしたcoutentクラスにshowクラスを追加する
document.getElementsByClassName("content")[index].classList.add("show");
}
// タブメニューの中でクリックイベントが発生した場所を探し、下で定義したtabSwitch関数を呼び出す
tabsAry.forEach(function(value) {
value.addEventListener("click", tabSwitch);
});
});
JSだとこれだけ長いコードになるが、jQueryを使用することで短いコードで同様の動作を行うことができる。
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除("[0]は、最初の要素の意味")
$('.active').removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabs.index(this);
// クリックしたタブに対応するshowクラスを追加する
$(".content").removeClass("show").eq(index).addClass("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す
tabs.click(tabSwitch);
});
もし、JSに関して忘れた内容があれば、第3回に戻って復習してみてください。
また、JSやjQueryで用意されている関数やメソッドはリファレンス(参考文献)を確認するのが一番確実です。
どんな文法があるのか知識を増やすためにも、リファレンスをいつも見る癖をつけると良いです。
jQueryを導入
jQueryを使用するには、jQueryのライブラリを読み込む必要がある。
以下のリンク先にjQueryを読み込む記述があります。
jQueryへのリンク
リンク先のページをスクロールするとjQueryという見出しと、その下に3. x snippetという記述が見つかる。3. x snippetの下にscript
タグに囲まれた記述があるので、この記述をコピーする。
コピーした記述と記事の記述が若干異なるかもしれませんが、jQueryのバージョンが違うので問題はありません。
コピーした記述をindex.htmlのhead
内に以下のように貼り付けることで、jQueryを読み込むことができる。
jQueryは他のJSファイルよりも先に読み込まないとエラーが発生する。そのため、JSファイルよりも上にjQueryの読み込みを記述する。今回はmain.jsに読み込みよりも上に記述をする。
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="stylesheet/style.css">
<link rel="stylesheet" type="text/js" href="js/index.js">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="./main.js"></script>
<title>Tab Menu Sample</title>
</head>
main.jsの下にjQueryの記述を追加し、以降の作業を進めるとjQueryの読み込み前に関数を実行してしまうため、画像のようなエラーが発生します。**
HTML要素を取得する
jQueryでのHTML/CSSの操作はJSと同じ。
- HTML要素を取得する
- 取得したHTMLを操作する
main.jsを以下のように編集し、HTML要素を取得する
menu_itemクラス要素を取得するために、以下の記述をmain.jsの一番下に追記する。
$(function() {
console.log($(".menu_item"));
});
追記できたらindex.htmlをブラウザで表示して、開発ツールのコンソールを確認。(command + option + i)
コンソールを確認すると画像のように出力されるはず。
コンソールに出力されているのは、クラス属性の値がmenu_itemのHTML要素の情報。
また、JSのdocument
にあたるのが、$(ドルマーク)
。
$
のあとにセレクタと呼ばれるHTMLの指定方法を記述することで、HTML要素が取得できる。
$("セレクタ名")
jQueryは様々なセレクタを用意している。よく使用するセレクタは以下の4つ
・ IDセレクタ
・ クラスセレクタ
・ 要素セレクタ
・ 属性セレクタ
IDセレクタ
HTMLのid属性で指定するセレクタのこと。
IDセレクタは、取得したいHTML要素のid属性に#(ハッシュ)を付けたもの
をセレクタとして利用する。
$("#idSelector") // idがidSelectorの要素を取得
クラスセレクタ
HTML要素のclass属性で指定するセレクタのこと。
クラスセレクタは、取得したいHTML要素のclass属性の値に.(ドット)を付けたもの
をセレクタとして利用する。
$(".classSelector") // classがclassSelectorの要素をすべて取得
要素セレクタ
h1やpのようなHTML要素を対象としてセレクタのこと。
クラスセレクタは、取得したいHTML要素の属性名をそのまま
セレクタとして利用する。
$("h1") // h1要素をすべて取得
属性セレクタ
HTMLのタグの属性値を指定したい場合、$("[ 属性 = '値' ]")
で属性セレクタを取得できる。
$("input[ type='radio' ]"); // <input type="radio">のHTML要素を取得する
要するに、JavaScriptで書いていたDOM要素の取得を全て共通の$("セレクタ名")
で書き換えることができる!
セレクタを指定した場合、相当する全てのHTML要素が取得される。そのため、idセレクタは1つしか要素が取得されないが(id属性の値は被ることがないため)、他のセレクタでは複数の属性が取得される可能性がある。
JSのセレクタ取得部分を全てjQueryで書き換える
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = document.getElementsByClassName("menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除("[0]は、最初の要素の意味")
document.getElementsByClassName("active")[0].classList.remove("active");
// クリックしたタブにactiveクラスを追加
this.classList.add("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
document.getElementsByClassName("show")[0].classList.remove("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
// クリックしたcoutentクラスにshowクラスを追加する
document.getElementsByClassName("content")[index].classList.add("show");
}
// タブメニューの中でクリックイベントが発生した場所を探し、下で定義したtabSwitch関数を呼び出す
tabsAry.forEach(function(value) {
value.addEventListener("click", tabSwitch);
});
});
↓
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除("[0]は、最初の要素の意味")
$(".active")[0].classList.remove("active");
// クリックしたタブにactiveクラスを追加
this.classList.add("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
$(".show")[0].classList.remove("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
// クリックしたcoutentクラスにshowクラスを追加する
$(".content")[index].classList.add("show");
}
// タブメニューの中でクリックイベントが発生した場所を探し、下で定義したtabSwitch関数を呼び出す
tabsAry.forEach(function(value) {
value.addEventListener("click", tabSwitch);
});
});
一文が短くて見やすいものになりましたね。
クリックイベントを実装
クリックイベントの取得はclick()
を使用。
JSの場合、クリックイベントが発生した場所を確認するため、forEach文を使って配列の中身を1つ1つ確認していた。
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
function tabSwitch(){
// 省略
}
tabsAry.forEach(function(value) {
// タブメニューの中でクリックイベントが発生した場所を探し、下で定義したtabSwitch関数を呼び出す
value.addEventListener("click", tabSwitch);
});
例えて言うなら、タンスから目的の物を見つけるために毎回1段1段開けて確認する状態。
jQueryでclick()
を使用する場合、セレクタを指定すればクリックした要素の値を簡単に取り出してくれる。
よって、配列に変換する必要もなく、以下のようにすっきりとしたコードに書き換えられる。
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
function tabSwitch() {
// 省略
}
tabs.click(tabSwitch);
これで、変数tabsに入っているmenu_itemクラスの中身がクリックイベントが発生したら、tabSwitch関数を呼び出してくれる。
さらに、クルックされた要素を特定する必要がある。this
を使うことで、イベントが発生した要素を取得できる。
this
関数の中でthisを使うと、イベントの発生元となった要素を取得することができる。thisは、使用する場面によって取得できるものが異なる。
ここでは全ての用途の説明は割愛するが、this
はJSで、非常によく使用される。
実際にクリックした要素を取得できるか確認するために、tabSwitch
と言う関数の中にconsole.log(this);
を加えてクリックした要素を取得できるか確認。
function tabSwitch(){
console.log(this);
// 処理
}
以下の画像のように、コンソール上にクリックしたaタグ
を取得し、出力する。
this
はJSの機能。そのためthis
で取得した要素は、JSで使用するDOM要素になっている。
jQueryで使う場合は、$(this)
と指定しないとエラーになる。
① "tabs.click(tabSwitch)"で引数のtabsSwitch関数を呼び出す。
② 「tabsSwitch関数の中のthis」=「クリックした要素を取得する」と言う意味
console.log
はデバック用で書いたので、コンソール上で正しくDOMを取得できているのを確認したら、削除する。
クラスの操作をjQueryで書き換える
JSではclassList
を使用して、クラスの追加や削除をしていたが、jQueryはクラスを追加・削除するメソッドが用意されている。
メニュータブの切り替えの実装についてのおさらい
例)「Ruby」のタブをクリックした場合
① タブのデザインが適用されている"activeクラス"を削除する
② クリックされたタブに"activeクラスを追加する"
③ "showクラス"を削除する
④ "menu_itemクラス"からクリックしたタブと対応する"showクラス"を追加する
HTMLのactiveクラスとshowクラスにどんなCSSがあたっているのかは、style.cssの中身を直接確認する。
①~④の手順でタブ機能を実装する。
①クリックしたタブのクラス要素を削除する
HTMLのactiveクラスを削除するために、jQueryで用意されているremoveClass()
を使用する。
removeClass()
JSはclassList.remove()
と言う書き方をしていたが、jQueryはremoveClass()
というメソッドが用意されている。
classList.remove()
と違い[0]
と指定しなくても、最初の要素を指定してくれる。
以下のように編集する。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
this.classList.add("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
$(".show").removeClass("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
// クリックしたcontentクラスにshowクラスを追加する
$(".content")[index].classList.add("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す。
tabs.click(tabSwitch);
});
②クリックしたタブにクラス要素を追加する
JSで書いた新しいクラスを追加するclassList.add()
と同じように、jQueryもaddClass()
というメソッドがある。
addClass()
addClass()
もremoveClass()
と同様に[0]
と要素を指定する必要がない。
また、this
をjQueryで使える文法に変える必要があるため、$(this)
に書き換える。
thisを書き換えない場合はタブは反応せず
Uncaught TypeError: this.addClass is not a function
とコンソールに表示される。
以下のようにコードを編集する。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
$(".show").removeClass("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
// クリックしたcontentクラスにshowクラスを追加する
$(".content")[index].classList.add("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す。
tabs.click(tabSwitch);
});
これでクラスが追加できるようになったので、挙動を確認する。
$(".content")[index].classList.add("show");
はJSの書き方だが、現時点ではこのままにしておく。
コードをさらにリファクタリングする
jQueryで書けるところを全て書き換えて見やすいコードに編集する。
下記の配列とindexOf()
に注目
// tabsを配列に変換する
tabsAry = Array.prototype.slice.call(tabs);
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabsAry.indexOf(this);
JSだけで書く場合、.manu_items
のような集合したDOM要素のうち、何番目の要素がクリックされたかを取得するために、indexOf()
を使用する必要があった。
しかし、indexOf()
は配列に対してだけ使えるので、集合したDOM要素を配列に変換する必要があった。
この部分のコードを短くするために、jQueryで用意されているindex()
を使用する。
index()
index()
は配列に変換しなくても、集合したDOM要素から引数に指定したDOMと同じ要素番号を戻す。
index("セレクタ") // セレクタと一致したDOMの要素番号を戻す
index()
を使用すれば配列に変換する必要がなくなるので、以下のように編集できる。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
$(".show").removeClass("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabs.index(this);
// クリックしたcontentクラスにshowクラスを追加する
$(".content")[index].classList.add("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す。
tabs.click(tabSwitch);
});
eq()
引数を要素番号に取り、集合したDOM要素から選択できる。
eq() // セレクタと一致したDOMの要素番号を戻す
以下のように編集して書き換える。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// コンテンツの全てのshowクラスのうち、最初の要素を削除
$(".content").removeClass("show");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabs.index(this);
// クリックしたタブに対応するshowクラスを追加する
$(".content").eq(index).addClass("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す
tabs.click(tabSwitch);
});
これで、addClass
を使ってshowクラスの追加ができるようになった。
さらに、contentクラスからshowクラスを削除するのは、クラスを追加するのと一緒に一行で書くことができる。
window.addEventListener("load", function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabs.index(this);
// showクラスを削除した後、クリックしたcontentクラスにshowクラスを追加する
$(".content").removeClass("show").eq(index).addClass("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す。
tabs.click(tabSwitch);
});
これで③~④の「showクラスを削除した後、contentクラスからクリックしたタブの要素番号を指定して、showクラスを追加する」という記述を一行で表すことができた。
HTMLの読み込みをjQueryで書く
HTMLの読み込みが終わってからscriptタグを読み込むために、最初に以下の記述を使っていた。
window.addEventListener("load", function() {
// 処理
});
jQueryの場合、以下のように書くことができる
$(function() {
// 処理
}
これの方が記述が簡単なので、書き換える。
$(function() {
// タブのDOM要素を取得し、変数で定義
let tabs = $(".menu_item");
// クラスの切り替えをtabSwitch関数で定義
function tabSwitch() {
// 全てのactiveクラスのうち、最初の要素を削除
$(".active").removeClass("active");
// クリックしたタブにactiveクラスを追加
$(this).addClass("active");
// 何番目の要素がクリックされたかを、配列tabsから要素番号を取得
const index = tabs.index(this);
// showクラスを削除した後、クリックしたcontentクラスにshowクラスを追加する
$(".content").removeClass("show").eq(index).addClass("show");
}
// タブがクリックされたらtabSwitch関数を呼び出す。
tabs.click(tabSwitch);
});
最後にもう一度、実装する流れをおさらいすると...
例)「Ruby」のタブをクリックした場合
① タブのデザインが適用されている"activeクラス"を削除する
② クリックされたタブに"activeクラスを追加する"
③ "showクラス"を削除する
④ "menu_itemクラス"からクリックしたタブと対応する"showクラス"を追加する
この①~④の「ビジネスロジックを自分で組む立てる力」がエンジニアにとってとても大事。
そのために、分からないことをいきなり検索せず、紙などにどういった流れで実装すれば、実現することができるか仮説を立ててから調べるようにすると良い。
今回はここまで
[次回] (#)に続く(制作中)