POPSブログ

jQuery toggleクリック関数を使用しないアコーディオン

198

  Category:  jquery2013/02/03 pops 

jquery クリック関数(アニメ用関数では無い)、toggle() が「非推奨」であり、jquery-1.9系では削除されました。現在jquery-1.9.0.jsが正式にリリースされましたので、toggle()を使用しないアコーディオン (Accordion clickタイプ) について考えてみます。

 

toggleクリック関数を使用しないアコーディオン


jquery toggleクリック関数(アニメ用関数では無い)、toggle() がjquery-1.9系では削除されました。またjquery-2.0系では「IE7.8」に対応しないなど、色々な面で大きな違いがありますが、.......


toggle()を使用しないアコーディオン (Accordion clickタイプ) について考えてみます。


新規のサイトで無い限りスグサマjquery-2.0系に移行するとは考え難いです。jquery-1.9系、jquery-2.0系ではかなり混乱する、そのために色々と調べているが実に困った事だ。結構混乱するワ、頭がバグるワ。ワタシの「バグ脳」では、1-2年落ち着いてからでないと使えないな。


さて、toggle を使用しないで「アコーディオン」を作った時、どのような作り方があるか考えてみます。


1. toggleクリック関数を使用した例
2. toggleクリック関数を使用しない、Example
3. サンプル accordion の簡単な説明
4. 単純効率化をはかる、、、その他
5. jquery-migrate.jsを使用すれば前の形式でも可動します。(要確認)


以上の順序で、サンプルを交えて書いて行きます。何時もながら少々長くなります。


下記に掲載の4種類のほかに、さらに「単純効率化オブジェクトを保存した」JSなど、アコーディオンのサンプルは、「デモ専用ページ」で表示します。

demo6

● デモページは[jqury-1.9]で動作しています。


toggleクリック関数は、jquery-1.9でサポート停止


以下の関数が jquery-1.9系 拠り使用出来ないが、その外の toggle() アニメ関数などはそのまま使用出来る。以外と便利だったので残念。(jquery-1.8系を10年間くらい使うと言う手もある)

これが廃止になる

toggle(fn, fn2, [fn3, fn4,...])

$("対象要素名").toggle(
	function () {
		hoge処理
	},
	function () {
		hage処理
	}
);

toggleクリック関数を使用した例


このページでは jquery-1.6.4、だから動作しますが、下記の accordion 29 に書き換えれば良い訳です。

accordion 29b、toggleクリック関数使用の例 (jquery-1.8系まで)

表示/非表示 切り替え

MENUブロック1

MENUブロック2

MENUブロック3


JSの例

//Accordion
(function($){
	//accordion29b
	$(function(){
		$('#accordion-29b').find('div').hide();
		//toggle
		$('#accordion-29b').find('h3').toggle(function () {
				$(this).addClass('active');
				$(this).next('div').show();
			},
			function () {
				$(this).removeClass('active');
				$(this).next('div').hide();
			});
		//hover
		$('#accordion-29b').find('h3').hover(function () {
			$(this).toggleClass('hovered');
		});
	});
})(jQuery);

通常のclick関数に置き換えて、toggle処理出来るように工夫すれば良い様である。

Accordionの場合は toggle() slideToggle() fadeToggle() toggleClass() など使用すると簡単に出来る。
jqueryでは「簡単に出来る様に用意している」が正しい表現かも知れない。

$("対象要素名").click(function () {
	この中を、toggle処理出来るように構成する
});

-----------------------------------------------------

accordion29 表示非表示の切り替えの例
$(function(){
	$('#accordion-29').find('div').hide();
	$('#accordion-29').find('h3').click(function () {
		$(this).toggleClass("active");
		$(this).next('div').toggle();
	});
});

内部、toggle() は、表示非表示の切り替え関数である。これはアニメ用だから使用できる。


toggleクリック関数を使用しない、Example


ulの影響が大きく「レイアウト」が崩れるので、「dl dt」で作成した。dl dtの場合の特性に注意ください。

jquery-1.4.4以上(fadeToggle)、jquery-1.6.4、最近のものでは、jquery-1.8.2.min.js、jquery-1.9.0.min.js及びjquery-2.0.0b1.min.jsでOK

● 以下「デモページ」のものと若干の違い有り。


accordion 29

開いたままのタイプ。

表示/非表示 切り替え

MENUブロック1

MENUブロック2

MENUブロック3


accordion 30

開いたままのタイプ。

Slide

MENUブロック1

MENUブロック2

MENUブロック3


accordion 31

同時開閉タイプ。(利用価値がある!)

Slide

MENUブロック1

MENUブロック2

MENUブロック3


accordion 32

開いた所を閉じて、開くタイプ。

Slide

MENUブロック1

MENUブロック2

MENUブロック3



 

サンプル accordion の簡単な説明


HTML CSS は下記のように共通です。JSはIDを付与して操作しています。内部リストは一番問題の出ない「dl dt」で記述しました。他のページの「アコーディオン」拠り「単純効率化」しています。


HTML

#accordion-30の場合。IDが違う場合は該当のIDを記入する。


<div id="accordion-30" class="accordion-box">
	<h3>MENUブロック1</h3>
	<div class="accordion-block">
		<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		</dl>
	</div>
	<h3>MENUブロック2</h3>
	<div class="accordion-block">
		<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		</dl>
	</div>
	<h3>MENUブロック3</h3>
	<div class="accordion-block">
		<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		</dl>
	</div>
</div>
<br />

CSS

/* 日本語 */

.accordion-box {
	width:200px;
	height:auto;
	margin:0;
	padding:1px 0;
	text-align:left;
	border-bottom:1px #EEEEEE solid;
	background-color:#EEEEEE;
}

.accordion-box h3 {
	width:188px;
	height:20px;
	margin:1px 0 0 1px;
	padding:2px 0 0 10px;
	line-height:20px;
	color:#FFFFFF;
	font-size:12px;
	background:url(/main/images/arrow_7.gif) no-repeat;
	background-color:#BBBBBB;
	background-position:right 0px;
	cursor:pointer;
}
/* active */
.accordion-box h3.active {
	background-position:right -21px;
}
/* hovered */
.accordion-box h3.hovered {
	background-color:#555555;
}

.accordion-box .accordion-block {
	display:block;
	width:198px;
	margin:1px 0 0 1px;
	padding:0;
	background-color:#FFFFFF;
}
.accordion-box .accordion-block dl {
	list-style-type:none;
	display:inline-block;
	margin-left:10px;
	padding:0;
}
.accordion-box .accordion-block dl dt {
	list-style-type:none;
	width:185px;
	margin-left:0px;
	padding:0;
	text-align:left;
	font-size:12px;
	font-weight:normal;
	line-height:150%;
	border-bottom:1px #CCCCCC solid;
}
.accordion-box .accordion-block dl dt a {
	text-decoration:none;
	color:#BBBBBB;
}

「矢印画像」を使用しない時は、CSSを変更ください。JSの方は変更しないでください。
当方のCSSです、画像パスなどは環境に合わせます。


JS

toggleクリック関数を使用しないJS、(toggle形式の簡易アニメ)

「単純効率化」accordion29、accordion30、accordion31、accordion32

極力単純化しました。多少は効率よくなります。これより少し速くしたものは下記「デモページ」で表示します。

//Accordion
(function($){

	//accordion29表示/非表示 の切り替え
	$(function(){

		//一旦全部消す
		$('#accordion-29').find('div').hide();

		//active要素を指定して開く
		var no=0;
		//$('#accordion-29').find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		$('#accordion-29').find('h3').click(function () {

			//active切り替え
			$(this).toggleClass('active');
			//表示非表示
			$(this).next('div').toggle();

		});

		//hover-toggle
		$('#accordion-29').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);

//Accordion
(function($){

	//accordion30
	$(function(){

		//一旦全部消す
		$('#accordion-30').find('div').hide();

		//active要素を指定して開く
		var no=0;
		//$('#accordion-30').find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		$('#accordion-30').find('h3').click(function () {

			//active切り替え
			$(this).toggleClass('active');

			//slideToggle
			$(this).next('div').slideToggle('slow');

		});

		//hover-toggle
		$('#accordion-30').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);


//Accordion
(function($){

	//accordion31
	$(function(){

		//一旦全部消す
		$('#accordion-31').find('div').hide();

		//active要素を指定して開く
		var no=0;
		//$('#accordion-31').find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		$('#accordion-31').find('h3').click(function () {

			//slide
			$(this).next('div').slideToggle('slow')
			.siblings('div:visible').slideUp('slow');
			//activeクラス切り替え
			$(this).toggleClass('active');
			$(this).siblings('h3').removeClass('active');

		});

		//hover-toggle
		$('#accordion-31').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);


//Accordion
(function($){

	//accordion32
	$(function(){

		//一旦全部消す
		$('#accordion-32').find('div').hide();

		//active要素を指定して開く
		var no=0;
		//$('#accordion-32').find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		$('#accordion-32').find('h3').click(function () {

			//active切り替え
			$(this).toggleClass('active');

			//DL要素オブジェクトを代入
			var hitItem = $(this).next();
			//開いている要素
			var openItem = hitItem.siblings('div:visible');

			//開いている要素があれば最初に閉じる
			if (openItem.length) {
				openItem.prev().removeClass('active');
				openItem.slideUp('fast',function() {
					//其の後開く
					hitItem.slideToggle('normal');
				});
			} else {
				//開いている要素が無ければ
				hitItem.slideToggle('normal');
			}

		});

		//hover-toggle
		$('#accordion-32').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);


● accordion31の内部処理は、以下の様でも同じです。上のほうが判り易い。

//click-action
$('#accordion-31').find('h3').click(function () {

	//active切り替え
	$(this).toggleClass('active');

	//対象をslideToggleと開いてるものslideUp残りクラスremove
	$(this).next('div').slideToggle('slow')
	.siblings('div:visible').slideUp('slow').prev('h3').removeClass('active');

});


さらに「単純効率化オブジェクトを保存した」JSなど、アコーディオンのサンプルは、「デモ専用ページ」で表示します。

demo7

● デモページは[jqury-1.9]で動作しています。


初期にactive要素を指定して開く


● JSの先頭で直接開く場所を指定する

ページが表示された初期にactive要素を指定して開く事が可能です。JS先頭をご覧ください。
現在は、スクリプトが有効になっていません。有効になるように // を削除すれば指定位置を開けます。

//active要素を指定して開く、0=1番目、1=2番目、、
var no=0;
//$('#accordion-30').find('h3').eq(no).addClass('active').next('div').show();

//active要素を指定して開く、例はみな同じ結果
var no=0;

例1
$('#accordion-30').find('h3').next('div').eq(no).prev('h3').addClass("active");
$('#accordion-30').find('h3').next('div').eq(no).show();

-------------------------------------------------------------

例2
$('#accordion-30').find('h3').eq(no).addClass("active");
$('#accordion-30').find('h3').next('div').eq(no).show();

-------------------------------------------------------------

例3
$('#accordion-30').find('h3').eq(no).addClass("active").next('div').show();

● h3がactiveクラスなら開く、直接htmlに書く方法
但し、指定できるのは1箇所。下記のように直接htmlに書き込む。

HTML
<h3 class="active">MENUブロック1</h3>

-------------------------------------------------------------
JS
//h3がactiveクラスなら開く

1 eachでhasClass判定例

$('#accordion-30').find('h3').each(function () {
	if($(this).hasClass("active")) {
		$(this).next('div').show();
	}
});

-----------------------------

2 属性フィルタで探す例

$('[class="active"]','#accordion-30').next('div').show();

HTML JS の標準化


アコーディオンは「サイドメニュー」に使用されることが多いので、ある程度は標準化しておいた方が良い。

HTML基本構成

同じ構成で div dl ul に対処することが出来る。少しのJSの訂正で済む。動くのは中の div で有る
JSはそのまま使用出来るので便利だ。(CMSの場合は出力リストが違うので、JSを修正する必要がある)

<div id="要素のID名" class="accordion-box">
	<h3>MENUブロック</h3>
	<div class="accordion-block">
		<p>説明文テキスト</p>
		<p><a href="javascript:void(0);">リンク</a></p>
	</div>
</div>
--------------------
<div id="要素のID名" class="accordion-box">
	<h3>MENUブロック</h3>
	<div class="accordion-block">
		<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		</dl>
	</div>
</div>
--------------------
<div id="要素のID名" class="accordion-box">
	<h3>MENUブロック</h3>
	<div class="accordion-block">
		<ul>
		<li><a href="javascript:void(0);">リンク</a></li>
		<li><a href="javascript:void(0);">リンク</a></li>
		<li><a href="javascript:void(0);">リンク</a></li>
		</ul>
	</div>
</div>

単純効率化をはかる。


● 子の要素を指定する時、フィルターを使用した方が認識が早い。

これよりも
$('#accordion-31 > h3').click(function () {.......................

こちらが早い
$('#accordion-31').find('h3').click(function () {....................

● 同じ要素が複数回実行される場合

accordion30を例に取ると、$('#accordion-30')、は複数箇所で実行されている、jqueryはその都度、「#accordion-30」の場所を調べるのでロスがある。オブジェクトを保存すると「キャッシュ」されるので速くなる。

極力単純化しました。多少は効率よくなります。

オブジェクトを保存する、名前は何でも良い
条件 #accordion-30 が実際に存在すること
var $accordionItem=$('#accordion-30');

あるいは
var accordionItem=$('#accordion-30');
私は、こちらを使用している

---------------------------------------------

(function($){
	//accordion30
	$(function(){

		//オブジェクトを保存
		var accordionItem=$('#accordion-30');
		accordionItem.find('div').hide();

		省略

		//click-action
		accordionItem.find('h3').click(function () {

			省略

		});

		//hover-toggle
		accordionItem.find('h3').hover(function () {

			省略

		});
	});
})(jQuery);

---------------------------------------------

置き換えるだけで早くなるが、注意も必要
accordionItem.find('h3')...............

現実に、#accordion-30 が存在しないとエラーになるので注意

---------------------------------------------

置き換え無い場合、現実に、#accordion-30 が存在しない場合エラーにはならない
存在しなければ実行されない様に出来ている
$('#accordion-30')..................

jqueryの内部でエラーにならない様に処理されている

正式なものでは無い。「キャッシュ」すると早くなるの情報だけで、実際に「個人で確認」しながらエラーにならない様に構成するほか方法は無いので十分に注意ください。
状況と、処理内容に応じて「使い分け」が必要です。


オブジェクトを保存したJSの例

#accordion31の例。サンプルは「デモページ」にあります。

//Accordion
(function($){

	//accordion31
	$(function(){

		//オブジェクトを保存
		var accordionItem=$('#accordion-31');
		//一旦全部消す
		accordionItem.find('div').hide();

		//active要素を指定して開く
		var no=0;
		//accordionItem.find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		accordionItem.find('h3').click(function () {

			//slide
			$(this).next('div').slideToggle('slow')
			.siblings('div:visible').slideUp('slow');
			//activeクラス切り替え
			$(this).toggleClass('active');
			$(this).siblings('h3').removeClass('active');

		});

		//hover-toggle
		accordionItem.find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);


DIVラップなしで、UL DL 要素を直接動かす


上記の例では、UL DL 要素はDIVでラップされていますが、DIVを削除してUL DL 要素を直接動かすことも可能です。
当然CSSは変更しなければなりません。


HTML、DIVラップを削除

<div id="accordion-31" class="accordion-box">
	<h3>MENUブロック1</h3>
	<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
	</dl>
	<h3>MENUブロック2</h3>
	<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
	</dl>
</div>

JS

JSの中の [div] が [dl] に修正されただけです。ul の場合も同じですが、ul の認識が悪い場合があります。ul 自体を動かす場合はクラス名を付けたり、確実に ul が認識されるように旨く作る必要があります。

ページは「ul li」構成が多いと共に、CMS等のメニューは「h3 ul li」構成が多いので注意が必要だ。

//Accordion
(function($){

	//accordion31 DIVラップ無し
	$(function(){

		//一旦全部消す
		$('#accordion-31').find('dl').hide();

		//active要素を指定して開く
		var no=0;
		//$('#accordion-31').find('h3').eq(no).addClass('active').next('dl').show();

		//click-action
		$('#accordion-31').find('h3').click(function () {

			//slide
			$(this).next('dl').slideToggle('slow')
			.siblings('dl:visible').slideUp('slow');
			//activeクラス切り替え
			$(this).toggleClass('active');
			$(this).siblings('h3').removeClass('active');

		});

		//hover-toggle
		$('#accordion-31').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);

IDを使用しないでクラスを使用する


上記の例では、認識を速くするためにIDを使用しているが、クラス名で使用することも当然出来る。
下記のように、クラスである accordion-box を使用するか、新たにクラスを追加するかは自由。IDより認識に時間がかかる欠点がある。


HTMLの変更

<div class="accordion-box">
	<h3>MENUブロック1</h3>
	<div class="accordion-block">
		<dl>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		<dt><a href="javascript:void(0);">リンク</a></dt>
		</dl>
	</div>
</div>

JSの変更

下記のように該当部分を全て変更する。クラス名は独特の名前を付けた方が良い。( papipupepo-accordion )

IDの場合
$('#accordion-31').find('h3').......................

クラスの場合
$('.accordion-box').find('h3').......................

新たなクラスの場合
$('.クラス名').find('h3').......................

$('.accord-31').find('h3').......................

実際に上の「accordion 31」をクラス化制御したサンプルを表示してみます。


accordion 31 クラス化サンプル

同時開閉タイプ。(accord-31クラス)

Slide

MENUブロック1

MENUブロック2

MENUブロック3




HTMLサンプル

このページのサンプルは、accordion-block クラスが共通で使用されていますので、JS制御用に、accord-31 クラスを追加しました。html構造はDIVラップ付きのものです。

<div class="accordion-box accord-31">

JSサンプル

$('#accordion-31') が $('.accord-31') に変更なっただけ。


(function($){

	//accordion31 accord-31クラス
	$(function(){

		//一旦全部消す
		$('.accord-31').find('div').hide();

		//active要素を指定して開く
		var no=0;
		//$('.accord-31').find('h3').eq(no).addClass('active').next('div').show();

		//click-action
		$('.accord-31').find('h3').click(function () {

			//slide
			$(this).next('div').slideToggle('slow')
			.siblings('div:visible').slideUp('slow');
			//activeクラス切り替え
			$(this).toggleClass('active');
			$(this).siblings('h3').removeClass('active');

		});

		//hover-toggle
		$('.accord-31').find('h3').hover(function () {

			//toggle hoveredクラス
			$(this).toggleClass('hovered');

		});
	});

})(jQuery);

その他


● slideToggleをfadeToggleに変更する

slideToggleをfadeToggleにすればよい。またfadeIn() fadeOut()など旨く組み合わせる。

		//click-action
		$('#accordion-30').find('h3').click(function () {

			//active切り替え
			$(this).toggleClass('active');

			//slideToggle
			//$(this).next('div').slideToggle('slow');
			//fadeToggle
			$(this).next('div').fadeToggle('slow');

		});

//注意、jquery-1.4.4から
.fadeToggle([duration][,easing ][,complete])

● hoverのtoggleClass処理

個別に色々違う処理が出来るので便利だ
//hover
$('#accordion-31').find('h3').hover(
	function () {
		$(this).addClass('hovered');
	},
	function () {
		$(this).removeClass('hovered');
	}
);

次ぎでも機能するが、間違いやすいので確認
//hover
$('#accordion-31').find('h3').hover(function () {
	$(this).toggleClass("hovered");
});

● click()形、bind()形、on()形

全て同じである。但し、bind() では無く on() が推奨されている。( on のほうが無難だ!、jquery1-7で追加された)

動的に処理している訳でないので、通常 click() で書くようにしている。

		//click-action
		$('#accordion-10').find('h3').click(function () {
			//
		});

		$('#accordion-10').find('h3').bind('click',function () {
			//
		});

		$('#accordion-10').find('h3').on('click',function () {
			//
		});

新しい機能がつきました。バージョン変わって「削除なりました」が最近多い。
「新しい機能」に飛びつかないように、効率が悪くとも「古くからある機能」で構成したほうが良いかも!。


toggleクリック関数がなくなって困ること


以前はクリックごとに独立した関数が書けたが、これからは書けないので少し工夫が必要になる。click()の中で如何にに条件分岐をして個別に処理するかである。
下は、「activeクラス」で判定して条件分岐している。これだと個別に細やかな処理ができる。

		//click-action
		$('#accordion-10').find('h3').click(function () {

			//active切り替え
			$(this).toggleClass("active");

			if($(this).hasClass("active")) {
				//開く処理show
				$(this).next('dl').show("600");
			} else {
				//閉じる処理hide
				$(this).next('dl').hide("600");
			}

		});

● index値を得る

何らかの分岐処理を行う時の目安になる。

		//click-action
		$('#accordion-30').find('h3').click(function () {

			var index_num=$('#accordion-30').find('h3').index(this);

			略す

		});

「toggleクリック関数」は主に「メニュー」に使用されている事が多い。アニメでは、toggle() slideToggle() slideUp() slideDown()を組み合わせることが通常であるので、「toggleクリック関数」が使用できなくとも然したる不便は無い。
私の場合は、ほとんど animate() を使用するので不便を感じるのだろう。




画像

サンプル画像 / 原則 使用者が用途に応じてご用意ください。

使用背景画像

背景の位置を変えればデザインの変更が可能です。使用画像以外の画像の場合は使用者がCSSを変更ください。


透過矢印画像 arrow.gif 21x44 透過矢印画像 arrow_2.gif 20x44 透過矢印画像 arrow_7.gif 19x40 透過矢印画像 arrow_5gif 19x40
arrow arrow2 arrow7 arrow5

アコーディオン関連記事は色々とありますが、制御構造がわかるように書いていて、効率的には書いていない。

【関連記事】当方の記事: jQuery アコーディオン 1

【関連記事】当方の記事: jQuery アコーディオン 2


以上です。

 


[ この記事のURL ]


タグ:memo , Accordion , jquery

 

ブログ記事一覧



[1]