デザイナーにも分かりやすいjQuery入門講座|jQueryの使い方

このエントリーをはてなブックマークに追加
索引
1章:短編集
2章:診断系コンテンツ
3章:製品抽出系コンテンツ
番外:Simulation Game

カテゴリ切替(2)

概要

機能の完成

前回はjQueryで記事を並べるところまで作成しました。今回はメニューをクリックしたら、そのカテゴリの記事だけを表示して、残りの記事はメニューの背後に隠すようにします。

解説

メニュークリック時の処理

メニューをクリックした時の処理を作成します。サンプル(cate2/01.html)を開きjQueryに以下の処理が追加されていることを確認して下さい。

ポイントは2行目のthis.idとsplitを利用したテクニックです。これはタブメニュー(2)の「どのタブがクリックされたか取得」でも説明しました。よく利用するテクニックなので忘れてしまった方は再確認して下さい。

//---メニュークリック
$('.cateButton').click(function(){
	var cate = this.id.split("_")[1];
	alert(cate);
});

メニューに設定したclass属性は「btn_ + カテゴリ名」で命名されているため、splitによって「btn_」を除いたカテゴリ名だけが取得されます。サンプルではalertで取得したカテゴリ名を表示するようにしたので、実際にメニューをクリックしてカテゴリ名が取得できていることを確認して下さい。

メニューをクリックした時の処理

前項で取得したカテゴリを前回作成した「setPosFunc」に渡して、それによってカテゴリを切り替えるようにします。サンプル(cate2/02.html)を開いて、jQueryが以下の様に変更されているのを確認して下さい。

function setPosFunc(cate){//---カテゴリを受け取る
	var posNo = 0;
	$("#newsArticle>div").each(function(index, elem) {
		var myY = posNo*newsHeight + "px";
		$(elem).stop().animate({top:myY});
		posNo++;
	});
}
$(function(){
	setPosFunc();
	$('.cateButton').click(function(){
		var cate = this.id.split("_")[1];
		setPosFunc(cate);//---カテゴリを渡す
	});
});

変更点は2点だけです。まずメニューをクリックした時の処理(13行目)でアラートを表示するのをやめて、代わりにsetPosFuncを実行している点です。この際、取得したカテゴリ情報(変数cate)を引数として渡しているのがポイントです。

そしてsetPosFunc(1行目)では引数を受け取れるように、引数の部分に変数cateを設定しました。
このサンプルでは、まだsetPosFunc内で変数cateを利用していません。次項で利用します。

setPosFuncで引数を受け取るようにしたので、最初に記事を並べる時に実行したsetPosFuncでも引数を渡さないといけません。最初は全ての記事を表示するのでAllのメニューを設定するため、id属性(btn_all)の「all」を引数として渡します。

サンプル(cate2/02b.html)を開き、jQueryが以下の様に変更されているのを確認して下さい。

$(function(){
	setPosFunc("all");//---最初はALL
	$('.cateButton').click(function(){
		var cate = this.id.split("_")[1];
		setPosFunc(cate);
	});
});

変更点は2行目のsetPosFuncを実行する部分で、引数として「all」を送るようにした点だけです。setPosFuncでは、まだ受け取った引数を利用していないので機能しません。次項で切替の処理を作成していきます。

すべての記事のclassを確認

記事を慰労させるためには、各記事のカテゴリ情報を取得しなければなりません。
サンプル(cate2/03.html)を開いてsetPosFuncが以下の様に変更されているのを確認して下さい。

追加したのは2,3行目の部分ですが2行目はコメントなので、実質3行目だけを追加しました。

$("#newsArticle>div").each(function(index, elem) {
	//---記事の要素からclass属性の値を取得
	var myClass = $(elem).attr("class");
	var myY = posNo*newsHeight + "px";
	$(elem).stop().animate({top:myY});
	posNo++;
});

まず確認するのは1行目のeachメソッドに設定したfunctionで受け取っている引数elemです。ここにはeachメソッドの前に設定したセレクタ、つまり#newsArticle>div(記事の要素)の要素が順番に送られてきます。
eachメソッドの構文は複雑ですが、意外と利用頻度が高いので覚えるようにしましょう。

3行目の処理では、この要素「elem」に対しattrメソッドを利用してclass属性の値を取得しています。取得した値を確認できるようにalertを追加したサンプルを用意したのですが記事の数(12個)分のアラートが開くので注意して下さい。→サンプル:(cate2/03b.html

//---記事の要素からclass属性の値を取得
var myClass = $(elem).attr("class");
alert(myClass);

あとはクリックされた「メニューのカテゴリ」と「記事のカテゴリ」を比較し、同じものだけを表示して残りをメニューの背後に隠せば完成です。

同じカテゴリだけを表示

ここから少し難しくなるので、段階的に少しずつ説明していきます。サンプル(cate2/04.html)を開いてsetPosFuncが以下の様に変更されているのを確認して下さい。

追加したのはif文の仕組み(5行目,9行目)だけです。if文ではメニューのクリック処理から引数として渡されたカテゴリ(変数:cate)と前項で取得した記事のカテゴリ(変数:myClass)を比較して、同じ時だけ記事を配置するようにしただけです。記事を配置する処理(6〜8行目)に変更はありません。

function setPosFunc(cate){
	var posNo = 0;
	$("#newsArticle>div").each(function(index, elem) {
		var myClass = $(elem).attr("class");
		if (myClass == cate) {
			var myY = posNo*newsHeight + "px";
			$(elem).stop().animate({top:myY});
			posNo++;
		}
	});
}

しかし実際のサンプルは記事が表示されず、1箇所に重なったままです。この原因は、最初に実行した以下の処理で渡している引数「all」のためです。

$(function(){
	setPosFunc("all");	
	$('.cateButton').click(function(){
		var cate = this.id.split("_")[1];
		setPosFunc(cate);
	});
});

記事のclassにはallは存在しないので、表示されないのです。それでは困るので引数で渡される変数cateがallの場合も表示するようにします。

サンプル(cate2/04b.html)を開いてsetPosFunc内のif文が以下の様に変更されているのを確認して下さい。

if (myClass == cate || cate == "all") {
	var myY = posNo*newsHeight + "px";
	$(elem).stop().animate({top:myY});
	posNo++;
}

条件文に「cate == "all"」を追加したので、変数cateがallだった場合も記事を表示するようになります。結果として、このサンプルでは最初に全ての記事が表示されるようになります。
論理演算子「||」は「または」と理解すると良いでしょう。これによって条件式の意味は「クリックしたメニューのカテゴリと記事のカテゴリが同じ、またはカテゴリがallの時」に記事を表示するようになります。

しかしメニューをクリックすると、一部の記事は移動しているのですが、全体としては正常に機能していません。これは異なるカテゴリの記事を隠す処理をしていないためです。この処理を追加して完成となります。

異なるカテゴリは隠す。そして完成

サンプル(cate2/05.html)を開いてsetPosFunc内のif文の後にelse文が追加されていることを確認して下さい。この処理によってカテゴリが異なる記事の要素は6行目の処理によって、-40pxの位置に移動されます(これはメニューに隠れるような位置です)。

if (myClass == cate || cate == "all") {
	var myY = posNo*newsHeight + "px";
	$(elem).stop().animate({top:myY});
	posNo++;
}else{
	$(elem).stop().animate({top:"-40px"});
}

結果としてカテゴリが一致する記事は表示され、異なる記事はメニューの背後(-40pxの位置)に隠れるようになります。最後に、この-40pxの位置についてもマジックナンバーの削除をしておきましょう。サンプル(cate2/05b.html)を開いてjQueryが以下の様に変更されているのを確認して下さい。

var newsHeight = 30;
var hidePos = -40;		
function setPosFunc(cate){
	var posNo = 0;
	$("#newsArticle>div").each(function(index, elem) {
		var myClass = $(elem).attr("class");
		if (myClass == cate || cate == "all") {
			var myY = posNo*newsHeight + "px";
			$(elem).stop().animate({top:myY});
			posNo++;
		}else{
			$(elem).stop().animate({top:hidePos});
		}
	});
}

1行目で-40を変数hidePosに代入しました(隠す位置ということが分かりやすいようにhidePosとしました)。そして12行目で利用しています。
animateメソッドの値には、数値を利用することもできます。その場合は単位の「px」は必要ありません。
→参考:使い方-汎用的なアニメ(1)のメモ

これで最低限の機能は完成しましたが次回に続きます。次回はcssを追加して少し見栄えを良くし、メニューボタンをラジオボタンに変更して、現在選択されているカテゴリが分かりやすくなるようにします。