jQueryで複数の要素を個別にフェードイン・フェードアウトの概要
注意 ※バージョンや環境によっては正常に動作しない可能性があります。
トリガーを押すと表示されるのは変わりませんが、表示できる要素は1つだけのフェードイン・フェードアウトです。
トリガーを押す動作がされたときに、fadeToggleで要素のフェードイン・フェードアウトをするのと同時に、他の要素をfadeOutさせています。
このソースは長くなるので、改良版として、html側でdata属性をつけるのと、fadeOutをforとifで記述することで、コードを短くしていますが、for・if部分は他にいい方法ないかな~と考え中です。
最初に勉強した言語がC言語だったのですが、その際に学んだアルゴリズムなどはfor・ifが多かったので、その時の影響なのかすぐにfor・ifで書きたくなってしまいます。
動作サンプル
トリガーlong-trigger-1
トリガーlong-trigger-2
トリガーlong-trigger-3
中身long-element-1
中身long-element-2
中身long-element-3
何も表示していない状態でどれかのトリガーを押すと、表示される。
何かが表示されている時に、別のトリガーを押すと、表示されているものが消えて、押した要素が表示される。
ソースコード
HTML
<div class="long-trigger1"> <p>トリガーlong-element-1</p> </div> <div class="long-trigger2"> <p>トリガーlong-element-2</p> </div> <div class="long-trigger3"> <p>トリガーlong-element-3</p> </div> <div class="long-element-1"> <p>中身long-element-1</p> </div> <div class="long-element-2"> <p>中身long-element-2</p> </div> <div class="long-element-3"> <p>中身long-element-3</p> </div>
css
.long-element-1, .long-element-2, .long-element-3{ display:none; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; padding: .5rem; margin-top: .5rem; } .long-trigger1, .long-trigger2, .long-trigger3{ background-color: #bdffc6; }
jQuery
$(function() { $('.long-trigger1').click(function() { $('.long-element-1').stop().fadeToggle(1000); $('.long-element-2').stop().fadeOut(0); $('.long-element-3').stop().fadeOut(0); }); $('.long-trigger2').click(function() { $('.long-element-2').stop().fadeToggle(1000); $('.long-element-1').stop().fadeOut(0); $('.long-element-3').stop().fadeOut(0); }); $('.long-trigger3').click(function() { $('.long-element-3').stop().fadeToggle(1000); $('.long-element-1').stop().fadeOut(0); $('.long-element-2').stop().fadeOut(0); }); });
ソースコードの説明
HTMLでは各トリガーと各表示要素が紐づくようにクラスを設定しています。
トリガー1がクリックされると、要素1が動くというように、トリガーと中身が紐づくようなjQuerで設定をしてます。
要素は1つだけ出したいので、トリガー1がクリックされたときに、要素2か要素3が表示されている場合は、時間0でフェードアウトする設定を追加しています。
トリガー2、トリガー3も同じ設定をしているので、コードとしては長くなります。
表示の要素に対してのトリガークリック時に他の要素に対しては消える
改良版では、data属性を使用することにより、トリガーに使うクラスを1つにし、各要素に連番の数字をつけることで、forとifでコードを短くしています。
改良版動作サンプル
トリガーelement-1
トリガーelement-2
トリガーelement-3
中身element-1
中身element-2
中身element-3
動作は元のものと同じ。
改良版ソースコード
HTML
<div class="trigger" data-target="element-1"> <p>トリガーelement-1</p> </div> <div class="trigger" data-target="element-2"> <p>トリガーelement-2</p> </div> <div class="trigger" data-target="element-3"> <p>トリガーelement-3</p> </div> <div class="element-1"> <p>中身element-1</p> </div> <div class="element-2"> <p>中身element-2</p> </div> <div class="element-3"> <p>中身element-3</p> </div>
css
.element-1, .element-2, .element-3{ display:none; background-color: #fff; border: 1px solid rgba(0, 0, 0, 0.125); border-radius: 0.25rem; padding: .5rem; margin-top: .5rem; } .trigger{ background-color: #bdffc6; }
jQuery
$(function(){ $(".trigger").click(function () { var targetName = '.' + $(this).data('target'); $(targetName).stop().fadeToggle(1000); for(var i=1; i<4; i++){ var hantei = '.element-' + i; if(hantei != targetName){ $(hantei).stop().fadeOut(0); } } }); });
ソースコードの説明
data属性についは、下の記事をご確認ください。こちらと全く同じです。
トリガーには全て同一のクラスを指定し、data属性でユニーク化しています。data属性をそのまま要素のクラスとして指定し、fadeToggleを動作させています。
その後のfadeOutの設定は、forとifで短縮しています。
プログラミングではお馴染みの変数iを使用したループです。
iの初期値は1で(var i=1)、ループごとにiは1ずつ増えて(i++)、ループは4未満まで(iが1、2、3の時の3回で処理が行われる)という設定をしています。
要素はelment-の後に数字で3つ作ってありますが、ループ時に文字列でその3つを作っています。「elemnet-」にforでループするiの数字をくっつけて、変数に代入しています。
そのクラスに対してfadeOutの処理が行われる形です。
そのままループさせると、クリックして表示したい要素まで消えてしまいます。なので、ループの中で表示させたい要素以外にfadeOutが動作するように、if分で判定を入れています。
表示したい要素は、クリック時に取得した要素のクラス名で判定できるので、それ以外のクラス名が来た時には、fadeOutするように「!=」で条件式を書いてあります。
今回トリガー3つに要素3つなので、ループが3回で終わるようになっていますが、iの数字を変えれば他の数でも対応できます。
3つぐらいならばコードの量にそんなに差はないですが、同時に10個とかになると、元のコードだと冗長です。forとifで書くことで、短くすることができます。
コードが短くなる分、可読性があがりメンテナンスが楽になります。ただ欠点としては、コードになれていない人にとっては、ぱっと見では何をしているコードなのかわからなくなるところです。
Webサイトの場合、フロントエンドエンジニアの方ならばjQueryは常識かもですが、HTMLとCSSだけを書くコーダーさんとか、デザイナーよりのコーダーさんだと、JavaScriptのスキルはあんまり…ということもあるため、わかりやすい記述にしていおいた方が安全、ということもたまにあります。
トリガーとボタンの数が少なければ、見やすさを重視しても良いのかな~とは思います。
まとめ
対にする要素に名前を付ける時、数字で連番を振るのはよくあることですし、すぐに思いつくことかと思います。
その要素に対して、同じ動作をする場合は、その要素を1つ1つ上から書くのではなく、繰り返し処理で書きたくなります。
ですが、WebサイトでのjQueryとなると、なんとかforとかなしで書けないかな~と考えたくなります。個人的な思いでしかないのですが、特にweb上ではむやみに繰り返し処理をしたくない、という思いがあります。
ただ、fadeoutの判定は、if文以外で思い浮かばなかったのと連番での操作なため、単純にコードが短くなったのでforとifを採用しました。なんか他にあると良いのですが。
data属性に関しては、JavaScriptの変数指定にハイフンを使えないのですが、クラス名と変数名とでみんなどうやって名前決めてるの? みたいな感じで調べていたら、data属性ってのがある、という記事を見つけて、似たようなことをしている記事があったので、それを参考にしました。
ただ、ボタンが2つとか3つとかならば、最初に書いたコードのほうがわかりやすいですし、変数がどうこうみたいなことを考えなくて良いので、デザイナーよりのweb担当者でも管理しやすいのかな~と思ったりします。
コードを書く側としては、短くて単純なほうが良いのですが、現実世界の様々な条件の中に当てはめると、一概にこっちが良い、とは言えないので、その時々の環境に合わせて選択するのが良いのかな、と思います。