jQueryまとめ

1. jQueryの基本

HTML要素を取得する

jQueryを使えばDOMから要素を取得することはいとも簡単. 次のように. var element = $(selector); selectorは要素を特定する文字列. これはCSSのセレクタとほぼ同じ記法なので,CSSに慣れ親しんでいる人ならば迷わずに使えるだろう. 以下にいくつか例を示す.
var element = $('#title') // IDがtitleの要素を取得
var elements = $('h1'); // h1タグをすべて取得
elements = $('.wrapper') // クラスがwrapperの要素をすべて取得
elements = $('ul a.active') // ulタグの子要素aタグでクラス名がactiveのものをすべて取得
ここまでの例をみても,要素の指定方法(セレクタ)はCSSのそれに合わせて設計されていることが良く分かる. ネイティブなJavaScriptコードだとdocument.getElementById("ID");などと書く必要があり,これが結構大変… jQueryならばCSSセレクタの如く要素をシンプルに指定し,取得できる.

jQueryオブジェクト

$(selector)記法で取得した要素の実態はjQueryオブジェクトとなっている点に注意. これは必ず配列になっている. JavaScriptのオブジェクトと配列の関係についてはこちらの過去記事を参考されたい. document.getElementById("ID");などとまったく同じもの(ピュアなJavaScriptコードで得た要素と同じもの)を得たければ,次のようにすれば良い.
var element = $('.wrapper');
var pureElement = element[0];
console.log(pureElement.className); // "wrapper"
このように,配列(jQueryオブジェクト)の要素を取得するだけで,ピュアなJavaScriptによる要素の操作(例えばelement.className)が行えるようになる. とは言え,上の例のようにHTML要素の属性値を取得したい場合はjQueryの.attr(name)関数を使うことも出来る.
var element = $('.wrapper');
console.log(element.attr('class')); // "wrapper"
こちらのほうがシンプルかつ,ブラウザ間の互換性を気にせずに利用できるので,私は好きだ.

n番目の要素を取得する

var elements = $('.myClass')のようにHTML要素を取得すると,クラス名がmyClassの要素すべてが取得される. これはbodyタグ内上から順に取得され,配列(jQueryオブジェクト)となる. もしも,具体的に何番目のmyClassが取得したい,という必要がある場合.eq(index)関数を使ってみよう.
<div class="myClass">First Element</div>
<div class="myClass">Second Element</div>
<div class="myClass">Third Element</div>
<div class="myClass">Fourth Element</div>
<div class="myClass">Fifth Element</div>
var elements = $('.myClass');
console.log(elements.eq(2).text()); // "Third Element"
.eq(index)indexは0からはじまる整数. 上の例では2なので(0から数えるので)3番目の要素を取得したことになる(配列のインデックスと同じ). 例では.text()関数を"つなげる"(詳細はこの章を参照)ことで,要素の内容(テキスト)を出力している.

要素が取得出来たか否かを調べる

もし要素が取得出来なければ,そのjQueryオブジェクトの中身は"空っぽ"の配列となる. つまりjQueryオブジェクトの要素数lengthを調べれば,要素を取得出来たか否か,判別できる.
var element = $('#bigfoot');
if (element.length) {
  console.log('存在する!');
}
else {
  console.log('残念,いなかった…');
}
JavaScriptでは0false,0以外の数値trueと等価なので,上記のif文で簡単に判別出来る仕組み. ナイス!

DOMが準備出来たら処理をする

head内にスクリプト(scriptタグやインラインのJavaScriptコードなど)を書いている場合,bodyタグがロードされる前に(DOMが構築される前に)スクリプトが実行されてしまうため,要素を取得出来ない. DOMの構築が終えてから処理が実行されると嬉しい. .ready(handler)関数はそのために存在する.
$(document).ready(function(){
  // DOMがロードされたら実行したい処理を書く
});

ハンドラ

.ready(handler)handlerは関数である(ハンドラ関数). 上の例では無名関数を使ってシンプルにしているが,事前に定義した関数名を記述しても全く問題ない. 次のように.
function foo() {
  // DOMがロードされたら実行したい処理
}

$(document).ready(foo);
ちなみに,関数によってはjQueryよりハンドラに引数が与えられる(この引数は省略可).
$('#button').click(function(evt){
  console.log(evt);
});

.click(handler)はその要素がクリックされるとハンドラが実行されるjQuery関数である. このハンドラに渡される引数(上の例ではevtと名付けた)はクリックイベントオブジェクトになる. 何が与えられるかはjQuery公式サイトの各ドキュメンテーションを読むとよく理解できると思うので参考されたい(.clickのAPIドキュメントはこちら). この引数を利用すれば,より高度な処理を行うことが出来るようになる.

さて,ハンドラ内で$(this)と書くと,jQueryの関数が適用された要素を取得することが出来る(上の場合$('#button')). これを利用すると,次のようなことを実現出来る.

$('.alert-button').each(function(){
  $(this).click(function(){
    console.log('CLICK!');
  });
});
alert-buttonクラスの要素をクリックすると'CLICK!'とコンソールに表示される. 仕組みは簡単. .each(handler)関数はjQueryオブジェクト(配列)をひとつづつ取り出してくれる関数. 取り出されたひとつひとつ,つまり$(this).click(handler)関数を付加している. 該当するクラス名の要素すべてに同じ処理を付加したい場合,この書き方を思い出せば良い. ハンドラ関数についてもっとよく理解したければ,次のように様々な情報をコンソールへ表示すると理解の助けになることと思われる.
$('.alert-button').each(function(i){
  console.log(i);
  $(this).click(function(e){
    console.log(e);
    console.log($(this));
  });
});
これで.each(handler)が何をしているのか,$(this)が何を指しているのか,与えられたハンドラの引数が何なのかをよりハッキリと見てとれることと思う.

2. HTML要素のスタイルを操作する

クラスの追加

.addClass(className)関数でクラスを追加できる.
<h1 class="oldClass">Title</h1>
$('h1').addClass('newClass');
<h1 class="oldClass newClass">Title</h1>
.attr(name, value)関数でHTML要素の属性値を直接操作することも出来る.
<h1 class="myClass oldClass">Title</h1>
$('h1').attr('class', 'newClass');
<h1 class="newClass">Title</h1>
この場合は属性値をそのままセットしてしまうので,今まであったクラス名はキレイさっぱり消えてしまう点に注意(書き換えられてしまう). もちろんこの関数はクラス名の操作だけでなく,HTMLの属性ならば何でも操作できる.

クラスの削除

特定のクラスを削除するには.removeClass(className)関数を使う.
<h1 class="oldClass newClass">Title</h1>
$('h1').removeClass('oldClass');
<h1 class="newClass">Title</h1>
.toggleClass(className)関数というものもある. これは呼び出した時にclassNameがあれば削除し,なければ追加する関数である.
$('#button').click(function(){
  $('div')toggleClass('show');
});
上の例では,#buttonをクリックする度に,div要素にクラス名showが追加されたり削除されたりする. jQueryのヴァージョンによっては動作が不安定な関数ではあるが,覚えておいて損はないだろう.

クラスの置換

不思議なことにjQueryには.toggleClass(className)関数のようなものはあっても.replaceClass(...)という関数は無い. クラス名を置換したい場合は削除と追加を"つなげる"ことで実現する.
<h1 class="oldClass">Title</h1>
$('h1').removeClass('oldClass').addClass('newClass');
<h1 class="newClass">Title</h1>
jQueryではこのように関数を"つなげる"ことで一連の処理を記述することが出来るよう設計されている. 処理の流れとしては左から右へと処理されるので,まずはじめにクラスoldClassが削除され,次いでnewClassが追加される. これが面倒だと思われた方は次のように.replaceClass(oldClass, newClass)関数(プラグイン)を自作すると良い.

.replaceClass(oldClass, newClass)プラグイン by berniecc

(function ($) {
  $.fn.replaceClass = function (pFromClass, pToClass) {
    return this.removeClass(pFromClass).addClass(pToClass);
  };
}(jQuery));
これで.replaceClass(oldClass, newClass)として利用することが出来る. EZ!

要素を隠す/表示する

.hide().show()を使って,要素を隠したり,表示させたりすることが出来る.
$('.navigator').hide(); // '.navigator'を隠す
$('.navigator').show(); // '.navigator'を表示する
これらの関数がやっていることは,対象の要素のスタイルにdisplay: none;を追加あるいは削除すること. これはインラインで追加されるので,例えば.hide()した後の要素は次のようになる.
<div class="navigator" style="display: none;">コンテンツ</div>

要素が隠れているか否か判別する

jQueryには.hide()で隠れていたり,CSSでdisplay: none;と指定されていることを判断する方法がある. .is(selector)関数を使う方法だ. この関数はその要素がselectorの条件に該当する場合trueを,しない場合falseを返す. selector:visibleを指定することで隠れているか否かを判別できる.
if ($('.navigator').is(':visible')) {
  console.log('.navigatorはそこにある!');
}
else {
  console.log('.navigatorは隠されている!');
}
注意: この判別方法の注意点はdisplay: none;の場合のみfalseとなる点である. 例えばopacity: 0;visibility: hidden;などと指定されて目に見えない状態でも,この判別方法ではtrueとなってしまう. 要素がそこにレンダリングされているか,またはされていないかを判別しているものと考えた方が良い. selectorには':visible'以外にも':hidden'(display: none;ならtrue)や,HTML要素名を直接指定することも出来る. .is(selector)関数の詳細については公式のAPIドキュメントを参照されたい.

3. HTML要素を操作する

HTML要素を挿入する

.append(content)を使うことでHTML要素を挿入することが出来る.
<div class="wrapper"></div>
$('.wrapper').append('<span>Hello Friends!!</span>');
<div class="wrapper">
  <span>Hello Friends!!</span>
</div>
もちろんcontentに任意の要素を指定することで,HTML要素を操作することも出来る.
<h1 class="title">TITLE</h1>
<div class="wrapper"></div>
$('.wrapper').append($('.title'));
<div class="wrapper">
  <h1 class="title">TITLE</h1>
</div>

HTML要素を包む

.wrap(wrappingElement)で任意の要素をwrappingElementで包むことが出来る.
<div class="wrapper">
  <span class="item">First Item!</span>
  <span class="item">Second Item!</span>
</div>
$('.item').wrap('<div class="new-item"></div>');
<div class="wrapper">
  <div class="new-item">
    <span class="item">First Item!</span>
  </div>
  <div class="new-item">
    <span class="item">Second Item!</span>
  </div>
</div>
また,.wrapAll(wrappingElement)は任意の要素すべてをまとめてまるっと包んでくれる.
<div class="wrapper">
  <span class="item">First Item!</span>
  <span class="item">Second Item!</span>
</div>
$('.item').wrap('<div class="new-item"></div>');
<div class="wrapper">
  <div class="new-item">
    <span class="item">First Item!</span>
    <span class="item">Second Item!</span>
  </div>
</div>

HTML要素を入れ替える/取得する

.html(html5string)で任意の要素内を差し替えることが出来る.
<div class="wrapper">
  <span>Hello Friends!!</span>
</div>
$('.wrapper').html('<strong>REPLACED!!!</strong>');
<div class="wrapper">
  <strong>REPLACED!!!</strong>
</div>
この関数は引数無しで使うと,該当要素内のHTMLをそのまま返してくれる.
<div class="wrapper">
  <span>Hello Friends!!</span>
</div>
console.log( $('.wrapper').html() ); // <span>Hello Friends!!</span>

HTML要素内のテキストを変える/取得する

.text(text)を使うことで,任意のHTML要素内のテキストを書き換えることが出来る.
<div class="wrapper">
  <span>Hello Friends!!</span>
</div>
$('span').text('Hi Everyone!!!');
<div class="wrapper">
  <span>Hi Everyone!!!</span>
</div>
ちなみに,textにHTMLを書くとエスケープされるので,HTML要素にはならず,書いたとおりのテキストがブラウザ上に表示されることになる.
<div class="wrapper"></div>
$('.wrapper').text('<span>Hello Friends!!</span>');
<div class="wrapper">
  &lt;span&gt;Hi Everyone!!!&lt;/span&gt;
</div>
なお,この関数も.html()同様,引数無しで使うと,任意のHTML要素内のテキストを取得することができる. ただし,要素の中にもうひとつ要素がある場合,その中のテキストまですべて取得してしまう点に注意.
<div class="wrapper">
  <span>Hello Friends!!</span>
  <div>
    <span>Feelin <b>Pretty</b> Good!</span>
  </div>
</div>
console.log( $('.wrapper').text() ); // Hello Friends!! Feelin Pretty Good!

4. イベント

クリックイベント

.click(handler)を使ってクリックイベントをバインドする(要素にイベントをくっつける)ことが出来る.
<div class="button">
  Click Me!!
</div>
$('.button').click(function(){
  console.log('Clicked!');
});
これで”Click Me!!”と書かれたdiv要素をクリックすると,コンソールに"Clicked!"と表示される.

マウスホバーイベント

.hover(handlerIn, handlerOut)を使ってマウスホバーイベントをバインドすることが出来る. マウスカーソルが任意の要素の上に乗っかるとhandlerInが実行され,カーソルが要素上から離れるとhandlerOutが実行される.
<div class="house">
  Come Here!!
</div>
$('.house').hover(function(){
  console.log('Welcome!');
}, function(){
  console.log('See ya!');
});
これで"Come Here!"と書かれたdiv要素上にマウスカーソルを乗せるとコンソール上に"Welcome!"と表示され,カーソルが要素上から離れると"See ya!"と表示されるようになる.

リサイズイベント/オリエンテーション変更の検知

.resize(handler)を使うとウィンドウサイズがユーザーによって変更されたときにhandlerが実行されるようになる. スマートフォンやタブレットではオリエンテーション,すなわち縦表示(ポートレート)と横表示(ランドスケープ)が切り替わった際にhandlerが実行されるようになる.
$(window).resize(function(){
  console.log('Resized/Orientation Changed!');
});
ただし,一部のAndroidスマートフォンのブラウザでは対応していない模様. より確かな方法で実装したい場合(なるべく多くのブラウザをサポートしたい場合)はネイティブなJSコードを書いた方が良い. 詳細はDavid Walsh氏のブログにまとまっているので一読を勧める.

5. アニメーション

フェードイン

.fadeIn()を使うことで要素をフェードインさせることが出来る. ただし,事前に該当要素を.hide()などで隠しておく必要あり(CSSによるdisplay: none;指定でも良い).

See the Pen jQuery FadeIn by Hideyuki Tabata (@seeker5084) on CodePen.

フェードインの時間(Duration)を変えるにはミリ秒を数値で渡す他,'fast'と'slow'というキーワードを渡す方法がある.
$('.box').fadeIn(); // デフォルトは400ミリ秒でフェードイン
$('.box').fadeIn('slow'); // 600ミリ秒とちょっとゆったりフェードイン
$('.box').fadeIn('fast'); // 200ミリ秒と少し早めにフェードイン
$('.box').fadeIn(1000); // この場合1秒かけてフェードイン
また,フェードイン完了時に実行させたい処理がある場合,次のようにハンドラを追記することもできる.
$('.box').fadeIn(function(){
  console.log('What up!');
});
これでフェードインが完了した直後,コンソールに’What up!’と表示される. もちろん,ハンドラとDurationを両方書くこともできる.
$('.box').fadeIn('fast', function(){
  console.log('What up!');
});
なおこの関数によるフェードイン中の処理として,まず該当要素のdisplay: none;が削除され(あるいは打ち消され),opacityプロパティが徐々に1へと変化することでフェードイン効果を演出している.

フェードアウト

.fadeOut(duration, handler)で任意のHTML要素をフェードアウトさせることが出来る. 前提条件として該当要素を事前に表示させておく必要あり(display: none;という指定が無ければ良い).

See the Pen jQuery FadeOut by Hideyuki Tabata (@seeker5084) on CodePen.

こちらも.fadeIn(duration, handler)同様,Durationやハンドラを指定することが出来る. なおフェードアウト中,該当要素はopacityプロパティが徐々に0へと変化することでフェードアウトし,0になった直後display: none;となる.

カスタムアニメーション

.animate(properties, options)を使うことでフェードエフェクト以外のアニメーションを付加することができる. これは多くのCSSプロパティにアニメーションを付与できることを意味する. 例えば,width: 100px;div要素を幅50pxにまでアニメーションで狭めつつ,opacityも0.5にしたいときは,次のように記述する.
$('div').animate({
  width: '50px',
  opacity: 0.5;
});
この場合,CSSプロパティ名はlowerCamelCase記法となる点に注意. つまり,border-widthborderWidth,line-heightlineHeightと書く. ハイフンは無くし,最初は小文字,ハイフン直後の文字だけ大文字で書く(これはネイティブなJSでCSSプロパティを操作したことがある方ならば直ぐに理解出来るはず). 特別な演算子+=(インクリメント)や-=(デクリメント)を使うことで,実行されるごとに値をインプリメント,デクリメントさせることも可能. 次の例では.buttonをクリックする毎に.boxrightプロパティの値が-20pxづつ変化する.

See the Pen jQuery Animate Position Right by Hideyuki Tabata (@seeker5084) on CodePen.

また,フェードエフェクトと同様,Durationとイベント完了後に実行されるハンドラを書くことも可能.

See the Pen jQuery Animate Opacity by Hideyuki Tabata (@seeker5084) on CodePen.

上の例ではCSSのopacityプロパティを1.5秒(1500ミリ秒)かけて0.25まで変化させ,アニメーションが完了したらalert()で”BOO!”と表示するようにしている. このように様々なCSSプロパティをアニメーションさせることが出来る. 下の例では特殊な文字列toggleをCSSプロパティの値に指定している. これは呼び出される毎にそのCSSプロパティの値が,0と初期値(下の例の場合height: 200px;)とを行ったり来たりするようになる. 文字通り,値がトグルする.

See the Pen jQuery Animate Height by Hideyuki Tabata (@seeker5084) on CodePen.

一部特殊なCSSプロパティ,例えばtransform: rotate(ndeg)などはこの書式でアニメーションさせることが出来ない. このような特殊なCSSプロパティはstep関数を使うことで実現出来る. 記述は少し複雑になるが,jQuery UIを使わず,jQueryだけでRotateなどを実現させたい場合に有効である.

See the Pen jQuery Animate Rotate by Hideyuki Tabata (@seeker5084) on CodePen.

今までは.animate()にひとつのオブジェクト(CSSプロパティの最終値)のみ引数として渡していたが,今回は2つのオブジェクトを渡している. 1つ目は今まで同様,最終値をここでは適当な名前(上の例では180までをdegという名前)で渡している. 2つ目のオブジェクトが肝である. 中にはdurationstepという2つのプロパティがある. durationは文字通りアニメーションの時間で,こちらは省略しても構わない. 2つ目のプロパティstep関数が良い仕事をする. この関数の引数(上の例ではnowと名付けた引数)はアニメーションが一コマ一コマ動くごとに,値が初期値から最終値(180)になるまで刻々と変化して行く. 特殊なCSSプロパティの値にこの引数を指定してやれば,アニメーションが実現出来る仕組みとなっている. 素晴らしい! ちなみに,transormプロパティにベンダープレフィックスをつけたい場合はstep関数内を次のようにすれば良い.
...
  step: function(now) {
    $(this).css({
      '-webkit-transform': 'rotate('+now+'deg)',
      '-moz-transform': 'rotate('+now+'deg)',
      '-ms-transform': 'rotate('+now+'deg)',
      '-o-transform': 'rotate('+now+'deg)',
      'transform': 'rotate('+now+'deg)'});
  }
...
なお,step関数を使う場合(お気づきかと思うが),CSSプロパティはlowerCamelCase記法ではなく,ハイフンを用いた通常の記法となる点に注意. .animate()関数に渡す2つ目の引数(オブジェクト)には様々なプロパティやコールバック関数を指定することが出来,大変便利である. 詳細は公式サイトのAPIページを参照されたいが,アニメーションが途中で中断したときに呼び出されるコールバック関数やアニメーションが失敗したときに呼び出されるコールバック関数などもあるので,より高度なアニメーション制御が出来る.

アニメーションの遅延

.delay(duration)を使うことでアニメーションの開始を遅らせることが出来る.

See the Pen jQuery Animate with Delay by Hideyuki Tabata (@seeker5084) on CodePen.

上の例ではまず,.animate()が実行され,その後500ミリ秒の.delay()(遅延)があり,それから.fadeOut()している. このようにアニメーションに関する種々の関数や.delay()などを数珠つなぎにすることで複数のアニメーションエフェクトを一連のアニメーションとして”つなげる”ことが出来る.

複数のアニメーションエフェクトを同時に実行させる

前章までで紹介した方法ではアニメーションは”つなげた”順番に着々と実行されていた. しかし,フェードインしながら移動させたい場合のように,複数のアニメーションエフェクトを同時に実行させたい時もある. そんなときは.animate()関数に渡す2つ目の引数(オブジェクト)のqueueプロパティをfalseに設定する. 次のように.

See the Pen jQuery Animate Queue by Hideyuki Tabata (@seeker5084) on CodePen.

アニメーションを同時に実行させた後,少し遅延させて,別のアニメーションを実行させたい場合は,上のコード全体をsetTimeout()やらPromise()やらで包んで,それらのコールバック関数内に遅延後に実行させたいアニメーションを書いてやれば良い. jQueryにばかり固執せずネイティブなJSにも活躍してもらったほうが,この場合はキレイに書けると私は信じている. ハザー!

6. 応用編

IEか否か判断してIE用のCSSプロパティを適用する

今までに紹介したテクニックと少しのHTML知識を利用して,ブラウザ判定をすることが出来る. 具体的にはIEか否かを判定させることが出来る. これはHTMLの条件付きコメントとの合わせ技で実現する. 次の例ではIE9未満か否かを判定している.
<!--[if lt IE 9]>
  <div id="ltIE9">お使いのブラウザは最新ではありません!</div>
<![endif]-->
$(document).ready(function(){
  if ($('#ltIE9').length) {
    console.log('お使いのブラウザはIE9未満');
  }
});
もしも,閲覧者のブラウザがIEのヴァージョン9未満(lt = less than)ならば,条件付きコメントにより,ltIE9というIDのついたdiv要素がbodyに追加される. $(document).ready(handler)とすればbody内の要素を確実に取得出来る. これで,IE9未満ならば$('#ltIE9')が取得出来,そうでなければ取得できないので,if文の中には入らない仕組み. if文の中に,例えばhtmlタグにltIE9などのクラスを追加する処理を書けば,IEのバージョンに応じたCSSを記述することも可能になる. こんな風に.
$(document).ready(function(){
  if ($('#ltIE9').length) {
    $('html').addClass('ltIE9'); // #ltIE9が取得できたらhtmlタグにクラス名"ltIE9"を追加
  }
});
hr {
  opacity: .5;
}

/* IEのヴァージョン9未満の場合のみ,filterプロパティで不透明度を指定出来る */
.ltIE9 hr {
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
  filter: alpha(Opacity=50);
}
これは上の例の様に,opacityプロパティを指定する際に都合が良い(<=IE8まではfilterで透明度を指定して,IE9ではfilterを無効化してopacityにして…などと煩わしいことをせずに済む). 以前はjQueryにもブラウザ判定する機能が入っていたのだが,現在はプラグイン化されて(jQuery本体から追い出されて)しまった. 下記のようにhtmlタグ自体を条件付きコメントで囲う方法もある. これならばJavaScriptが無効なブラウザで閲覧しても適切なスタイルを適用させることが出来る(ただ,個人的には頭でっかちなこの方法をあまり好きにはなれない).
<!DOCTYPE html>
<!--[if lte IE 8]><html class="lteIE8"><![endif]-->
<!--[if IE 9]><html class="IE9"><![endif]-->
<!--[if gt IE 9]><!-->
<html>
<!--<![endif]-->
...
またはModernizrを利用する方法もある. こちらのほうがより確実なのは間違いないが,今回はjQueryに限ったまとめ記事として書いているので,ここでは詳細は割愛する. このテクニックが役立つケースは非常にレアだろうが,一応こんなことも出来るということは覚えておいて損はしないはずである.
864015723185044137 http://www.storange.jp/2017/10/jquery.html http://www.storange.jp/2017/10/jquery.html jQueryまとめ 2017-10-12T21:10:00+09:00 http://www.storange.jp/2017/10/jquery.html Hideyuki Tabata 200 200 72 72