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

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

得点の集計(1)

概要

高度な配列の操作

複数の製品の得点を効率よく管理するためには配列を使いこなさなければなりません。初心者にとって配列の処理は想像しにくく難しく感じると思うのですが、必要になるケースも多いので慣れるようにしょう。

製品抽出のサンプルでは「製品ごとの得点の集計」だけでなく「得点ごとにソート」する必要もあり、最も難しい部分なので次回と2回に分けて説明していきます。この2回を乗り切れば、後は簡単なので挫けずにいきましょう。

解説

「製品を探す」ボタンがアクティブの時だけクリックできるようにする

前々回(回答の確認)で全ての質問に回答したら「製品を探す」ボタンにクラス属性activeを付加してデザインを変更しました。これに合わせてactiveのクラス属性が付いた「製品を探す」ボタンをクリックできるようにしましょう。

サンプル(calc1/01.html)を開いてreadyイベント内に以下の処理が追加されていることを確認して下さい。

$(function () {
	$("#result").hide();
	$("ul>li").click(quesFunc);
	//---「製品を探す」ボタンが有効の時だけクリックできるように
	$("#checker").on("click", "#searchButton.active", calcFunc);
});

clickイベントは構文がシンプルですが、動的な要素に対応できません(→参考:使い方「イベント(2)」)。つまり後からプログラムによってactiveのクラス属性を付加した要素には利用できません。ですので5行目のようにonを利用します。onの構文は複雑ですが覚えるようにしましょう。

セレクタの部分に「.active」が含まれていることを確認して下さい。これによってactiveのクラスが付加された時(全ての質問に回答した時)にだけクリックできるようになります。このサンプルではクリックされたらcalcFuncを実行するようにしていますが、calcFuncは以下の様にアラートを表示するだけです。

//---計算開始
function calcFunc(){
	alert("calcFunc");
}

これらのことを踏まえて、まずは質問に回答していない状態で「製品を探す」ボタンをクリックしてください。まだacitveのクラスが付加されていないので、クリックしてもアラートは表示されません。次にすべての質問に回答して、acitveクラスが付加された後でクリックして下さい。するとアラートが表示されるはずです。この様にして「製品を探す」ボタンが有効のときだけ得点を集計するようにします。

最後にonではなくclickイベントを利用したサンプルでclcikが動的な要素に対応していないことを確認しておきます。サンプル(calc1/01b.html)を開いてreadyイベント内の処理が以下の様にonがclickに変更されているのを確認して下さい。

$(function () {
	$("#result").hide();
	$("ul>li").click(quesFunc);
	//---clickイベントは動的な要素に対応していません
	$("#searchButton.active").click(calcFunc);
});

clickでは動的な要素に対応していないため、すべての質問に回答した後で「製品を探す」ボタンをクリックしてもアラートは表示されません。

回答結果からプロパティを作成

前回作成したscoreObjから得点を取得するためには、選択した選択肢のIDからプロパティ名を作成しなければなりません。サンプル(calc1/02.html)を開いてcalcFuncが以下の様に変更されているのを確認して下さい。

function calcFunc(){
	//---選択された選択肢からプロパティ名を作成
	for (var i=0; i<selectArray.length; i++) {
		propName = "q" + i + "_" + selectArray[i];
		alert(propName);
	}
}

前々回(回答の確認)の最初に説明したように、回答したIDはselectArrayに記憶されます(ラジオボタンの処理にも利用しました)。3行目のfor文ではselectArrayの要素数(つまり質問の数)だけ処理を繰り返すようにしています。

そしてポイントは4行目で、ここで回答結果からプロパティ名を作成します。まず前回作成したscoreObjのプロパティ名は「q」から始まりますから、最初は「q」を書きます。続いて質問の番号ですが、これはfor文で利用している変数iを利用します(0〜4になります)。そして「_」を挟んで最後に選択した選択肢のidをselectArrayから取得してプロパティ名(q1_2等)となります。これは変数propNameに代入しました。

最後にアラートでプロパティ名を表示するようにしたので、質問に全て回答して「製品を探す」ボタンをクリックし、プロパティ名が質問の数(5つ)アラートで表示されることを確認して下さい。

得点リストの取得

続いて、作成したプロパティ名と前回作成したscoreObjから各製品ごとの得点リストを取得します。
サンプル(calc1/03.html)を開いてcalcFuncが以下の様に変更されているのを確認して下さい。

function calcFunc(){
	for (var i=0; i&<selectArray.length; i++) {
		propName = "q" + i + "_" + selectArray[i];
		var scoreList = scoreObj[propName];//---得点リストの取得
		alert(scoreList)
	}
}

4行目でscoreObjにプロパティ名(propName)を利用して得点リストを取得し、変数scoreListに代入するようにしました。最後にアラートで表示するようにしたので、質問に回答した後「製品を探す」ボタンをクリックし、選択した選択肢の得点リストがアラートで表示されることを確認して下さい。

製品ごとの得点を集計(1)

ここまでは比較的簡単なのですが、次が大変です。下図のように各製品ごとの得点を合計しなければなりません。

難しい部分なので少しずつ説明していきます。まずは配列の内の最初の要素だけを足してみましょう(上記の例では65になります)。サンプル(calc1/04.html)を開いてcalcFuncが以下の様に変更されているのを確認して下さい。

function calcFunc(){
	var total = 0;//---合計用の変数
	for (var i=0; i<selectArray.length; i++) {
		propName = "q" + i + "_" + selectArray[i];
		var scoreList = scoreObj[propName];
		//---totalに0番目の得点を足していく
		total += Number(scoreList[0]);
	}
	alert(total);
}

まず2行目で合計得点用の変数totalを作成し、初期値として0を設定しました。for文の中には7行目を追加しただけです。7行目で変数totalにscoreListの0番目の要素を足していき(csvから取得したデータは数値でも文字列となっているため、Numberを利用して数値に変換してから足さないといけません)、for文が終わった後(質問の数だけ繰り返した後)で合計をアラートで表示します。

全ての質問に0番目(左端)の選択肢で回答して、画像の例と同じ条件にして試してみて下さい。「製品を探す」ボタンをクリックすると画像の例の最初の要素の合計である65が表示されると思います。

製品ごとの得点を集計(2)

1つの製品の得点を合計するのであれば変数(サンプルではtotal)を利用すれば良いのですが、複数の製品の得点を合計するには配列を利用しなければなりません。サンプル(calc1/05.html)を開いてcalcFuncが以下の様に変更されているのを確認して下さい。

function calcFunc(){
	//---製品の数だけ要素を用意
	var totalArray = [0,0,0,0,0,0];
	for (var i=0; i<selectArray.length; i++) {
		propName = "q" + i + "_" + selectArray[i];
		var scoreList = scoreObj[propName];
		//---0番目の計算
		totalArray[0] += Number(scoreList[0]);
		//---1番目の計算
		totalArray[1] += Number(scoreList[1]);
		//---2番目の計算
		totalArray[2] += Number(scoreList[2]);
		//---3番目の計算
		totalArray[3] += Number(scoreList[3]);
		//---4番目の計算
		totalArray[4] += Number(scoreList[4]);
		//---5番目の計算
		totalArray[5] += Number(scoreList[5]);
	}
	alert(totalArray);
}

まず3行目で製品ごとの得点を格納する配列totalArrayを作成しました。そして8行目〜18行目にかけて各製品の得点を合計しています。複雑そうに見えますが、前回のサンプルと考え方は同じです。例えば8行目の処理と、前項の7行目の処理を比較して下さい。左辺が変数totalから配列totalArrayの各要素に変更されているだけです。

結果として全ての質問に左端の回答(0番目の選択肢)を選択して「製品を探す」ボタンをクリックすると、前項の最初の図の結果と同じように「65,68,70,88,56,49」と表示されます。

このサンプルでは分かりやすいように製品の数(配列totalArrayの要素数)だけ似た処理を繰り返しましたが、このような場合はfor文を利用して短く記述します。サンプル(calc1/05b.html)を開いてcalcFuncが以下の様に変更されているのを確認して下さい。

function calcFunc(){
	var totalArray = [0,0,0,0,0,0];
	for (var i=0; i<selectArray.length; i++) {
		propName = "q" + i + "_" + selectArray[i];
		var scoreList = scoreObj[propName];
		//---for文を利用
		for (var j=0; j<totalArray.length; j++) {
			totalArray[j] += Number(scoreList[j]);
		}
	}
	alert(totalArray);
}

7行目のfor文によって変数jは0からtotalArrayの要素数未満まで(つまり0〜5)繰り返されます。この変数jを8行目で利用することでサンプルcalc/05.htmlとまったく同じ処理を手短に書くことができます。実際にcalc/05.htmlの時と同じように回答して、同じ結果になることを確認して下さい。

ひとまず今回はここで終了です。次回も引き続き得点の集計について説明します。