【jQuery】選択した商品の合計額を表示させる自動計算フォームを作る

商品購入や見積もりフォームで、ページ上に現在の合計額を表示させたいというリクエストにヒイヒイ言いながら対応したあの日のメモ。

○○円以上で送料無料とか、割引価格に切り替え用のチェックボタンも対応可能。

こんなフォーム(デモあり)

商品(項目)ごとに値段(数値)があって、セレクトボックスで個数を切り替えると合計金額が自動的に更新されるフォームです。

こういうやつ。

一応デモページ

やったこと

スクリプトの内容を順番に記します。

ちなみに、フォームの1かたまりのHTMLはこんな感じです。

<div class="form-box">
	<p class="buy_itemu_menu" data-price="2500">人力飛行機
		<span class="kakaku">(定価 2,500円/会員価格 2,300円)</span>
	</p>
	<select name="人力飛行機数量">
		<option data-num="0" value="0個" selected>0個</option>
		<option data-num="1" value="1個">1個</option>
		<option data-num="2" value="2個">2個</option>
		<option data-num="3" value="3個">3個</option>
	</select>
</div>

2行目のクラス名「buy_itemu_menu」に「data-price」属性を追加し、価格を設定します。そのとなり5行目のselectタグ内のoptionにそれぞれ「data-num」属性を追加し、個数を数字で取得できるようにしています。

セレクトボックスの切り替えを判別できるようにする

まずは計算を実行するためのスイッチを設定します。

$("select,#kaiinnkakaku").change(function() {
	//処理を記述します。
}

「select」でセレクトボックスを指定。「.change」で対象が切り替わった時に括弧内の処理を実行するように設定。ID「kaiinnkakaku」は、後述する割引価格への切り替えボタンのスイッチです。

価格と個数を取得して配列に追加する

HTMLで設定した、価格と個数を取得します。

$("select,#kaiinnkakaku").change(function() {
	var item_price = $(".buy_itemu_menu").data("price");
	var item_select = $(".buy_itemu_menu").next("select").find("option:selected").data("num");
}

これだけだと対象要素が複数ある場合に正常に処理できないので、それぞれの内容を配列に追加できるようにします。

$("select,#kaiinnkakaku").change(function() {
	var hairetu = [];
	for(var i = 0; i < $(".buy_itemu_menu").length; i++){

		var item_price = $(".buy_itemu_menu").eq(i).data("price");
		var item_select = $(".buy_itemu_menu").eq(i).next("select").find("option:selected").data("num");

		hairetu.push(item_price * item_select);
	}
}

2行目。3行目以降のfor文で取得する値を入れておく配列用の空のハコを用意。
Array

3〜9行目。クラス名「buy_itemu_menu」の数だけ処理を実行するfor文を設定。
繰り返し処理(for文)

5、6行目。前項の価格と個数を取得する文に「.eq(i)」を追加。「.eq()」は括弧内の数字番目の要素を対象にするものです。「i」はfor文ループ回数の数字を取得しています(2行目参照)。
eq(position)

8行目。「.push」で配列に価格×個数の数値を追加しています。

つまりここまでは、アイテムごとの価格×選択した個数の数字を配列にぶっこむ操作です。

配列に追加した数字のトータル値を取得する

配列に追加された数字は[xx,xx,xx]のようにバラバラになっているので、それぞれの数字の和を求めます。

$("select,#kaiinnkakaku").change(function() {
	var hairetu = [];
	for(var i = 0; i < $(".buy_itemu_menu").length; i++){

		var item_price = $(".buy_itemu_menu").eq(i).data("price");
		var item_select = $(".buy_itemu_menu").eq(i).next("select").find("option:selected").data("num");

		hairetu.push(item_price * item_select);
	}

	var total = 0;
	for(var j = 0; j < hairetu.length; j++){
		total += hairetu[j];
	}

}

11行目。配列に追加された数字の合計を保持する変数を用意。

12〜14行目。前項で、配列に追加された中身の数だけ処理を実行するfor文を設定。

13行目。変数「total」に配列の数字を足していきます。

ここまでで、アイテムごとの価格×選択した個数の合計値を用意できました。

トータル値をHTMLに出力する

ので、あとはHTML上に出力するのみです。

$("select,#kaiinnkakaku").change(function() {
	var hairetu = [];
	for(var i = 0; i < $(".buy_itemu_menu").length; i++){

		var item_price = $(".buy_itemu_menu").eq(i).data("price");
		var item_select = $(".buy_itemu_menu").eq(i).next("select").find("option:selected").data("num");

		hairetu.push(item_price * item_select);
	}

	var total = 0;
	for(var j = 0; j < hairetu.length; j++){
		total += hairetu[j];
	}

	$("#item_price_total").val(total + "円");

}

HTMLで記述した該当inputタグのvalが、セレクトボックスを切り替えるたびに変更されるようになります。「readonly」を指定すれば通常使用で書き換えもできないので安心です。

<input id="item_price_total" class="" name="小計" value="0円" readonly>

CSSを整える

使用上は問題ありませんが、そのままだといかにも入力できそうな見た目なので、CSSでフラットなテキスト風に調整します。

#item_price_total {
	border: none;
	cursor: default;
}

通常の自動計算フォームは以上です。

送料や手数料・割引の設定

実際の業務では送料や手数料・割引の対応もしたい場面があると思います。

合計額に応じて変更できる、手数料等の設定

送料や手数料は、一律であればtotalのデフォルト値を変更すればいいのですが、一定額以上のお買い上げで無料。等の場合は少しだけ追記が必要です。

	if(total >= 3000) {
		var postage = 0;
	} else {
		var postage = 300;
	}

	$("#postage_price").val(postage + "円");
	$("#total_price").val((total + postage) + "円");

トータル値を算出した後に、その額が指定値以下の時は「postage」を足す処理です。7行目以降でHTMLに出力しています。

チェックボックスで切り替える、割引価格の設定

アイテムごとの価格×選択した個数の数字を配列にぶっこむ時に、指定のチェックボックスへのチェックの有無に応じて、取得値を操作します。

if($("kaiinnkakaku").checked == true){

	//価格別に設定したい場合
	if ( item_price > 500) {
		var item_price = item_price - 200
	} else {
		var item_price = item_price - 100
	}
	//割合で設定したい場合
//	var item_price = item_price*.8
}

指定したチェックボックスにチェックが入っていたら、500より上の時は200を引いて、それ以下の場合は100引くというものです。数字は自由に変更できます。

最終的なjsの中身はこんな風になります。

$(function() {

$("select,#kaiinnkakaku").change(function() {

	var hairetu = [];
	for(var i = 0; i < $(".buy_itemu_menu").length; i++){

		var item_price = $(".buy_itemu_menu").eq(i).data("price");
		var item_select = $(".buy_itemu_menu").eq(i).next("select").find("option:selected").data("num");

		if($("kaiinnkakaku").checked == true){

			//価格別に設定したい場合
			if ( item_price > 500) {
				var item_price = item_price - 200
			} else {
				var item_price = item_price - 100
			}
			//割合で設定したい場合
//				var item_price = item_price*.8
		}

			hairetu.push(item_price * item_select);
	}

	var total = 0;
	for(var j = 0; j < hairetu.length; j++){
		total += hairetu[j];
	}

	if(total >= 3000) {
		var postage = 0;
	} else {
		var postage = 300;
	}

	$("#item_price_total").val(total + "円");
	$("#postage_price").val(postage + "円");
	$("#total_price").val((total + postage) + "円");

});

});

きっともっとスマートな記述があると思いますが、何かの参考になれば幸いです。改善点あれば指摘してくださいませ。では、よいJQueryライフを。