JQueryでエクセル風に購入代金合計を計算・表示しよう(私流)

  • 2020年7月15日
  • 2020年7月18日
  • JQuery
  • 48view
  • 0件

このブログでは、私なりに勉強し、また、開発した手法を惜しみなく書いていきたいので、ぜひ訪問してください。

今日は、WEB上でエクセル風に、購入代金を計算できるプログラムを考えてみましょう。

submitで別ファイルにページ遷移して戻ってくるというような方法もありますが、その場合は、画面がちらつきますし、いったん書かれたデータをもう一度書くことになるため、あまりスマートではありません。

ここでは、JQueryを使って、ページ遷移することなく、WEBページ上で、あたかもエクセルを操作するかのように自由に合計計算をしてくれる方式を実現してみましょう。

「JQuery」って使ったことないという人は、<head>内に読み込むだけで使えるようになるため、ぜひやってみてください。

CDN方式を使えば、何らダウンロードもインストールも必要なくて、ただ単に二行ほど、コピーして書き込んでいただくだけで使えるようになります。

以下、フォーマットを作成してからJQueryの作成に入りますが、HTMLやCSSについてよくお分かりの方は読み飛ばしてください。

まずはフォーマット作成

JQueryのプログラムを書くより前に、まず、HTMLとCSSでファーマットを作成しましょう。

ここで、簡便のため、表は3行だけという固定にして、最大で3つの種類まで合計が出せるようにしてみましょう。

商品は、「アンパン」と「カレーパン」と「クロワッサン」でいきましょうか。

値段は、それぞれ180円、220円、250円としておきましょう。

目指すのは、次のような表です。

左の商品は、セレクトボックス で選択できるようにします。(これはChromeでの画面です。Safariなどではセレクトボックス のスタイルが多少変わります。)

そして、選択したと同時に、単価が表示され、個数の方は初期値として1を表示します。

その時、既に、単価 ✖️  1の計算で小計が表示され、ついで合計も表示されるようにします。

<html>
<head>
  <style>
  </style>
</head>
<body>
  <table class="mytable">
    <?php for($nn=0; $nn<=2; $nn++){ ?>
     <tr>
       <th></th>
       <td></td>
       <td></td>
       <td></td>
     </tr>
    <?php } ?>
  </table>
</body>
</html>
<script>
</script>

これが骨格になります。

ここのテーブルの中身を充実させて、JQueryのプログラムを書けば仕上がります。

JQeuryのCDN方式の読み込みは、<head>内にあとで書く2行をコピーしていただけばそのまま使えます。

テーブルは、画面の真ん中に、左端を5%空けて、40%の幅で作りましょう。

そして、それぞれのカラムの幅は、テーブル幅のそれぞれ40%、25%、10%、25%としましょうか。

テーブル行に、<?php for($nn=0; $nn<=2 $nn++) ?>と、<?php } ?>と入れましたが、このように、ループの命令をHTMLの中に入れて、この両者に挟まれたHTMLを3回書かせるというようなことができます。

セル内に入力できるようにする

次にテーブルの各セル内で入力ができるようにします。

セレクトボックス の基本形は次のようになります。

<select>
  <option value="---">---</option>
  <option value="アンパン">アンパン</option>
  <option value="カレーパン">カレーパン</option>
 <option value="クロワッサン">クロワッサン</option>
</select>

次に金額や個数のところですが、これはinputのボックスを使いましょう。

基本形は次のようになります

<input type="text" name="price[]" value="">

あとで、送信する場合がありますので、「name=”price[]”」というように付けておくと良いでしょう。(ここでは送信はしないので活用しません)

では、これらを組み込んだコードを描いてみましょう。

<html>
<head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
  <style>
     .mytable {margin-left: 5%; width: 40%;}
     .mytable th {border: 1px #333 solid; height: 50px;}
     .mytable td {border: 1px #333 solid;}
     .item {width: 40%;}
     .price {width: 25%;}
     .kosu {width: 10%;}
     .shokei {width: 25%;} 
     .mytable th select {height: 96%; width: 100%; border: none; padding: 0 10px; font-size: 20px;}
     .mytable td input {height: 96%; width: 96%; border: none; text-align: right; padding: 0 10px;}
     select, input {font-size: 20px;} 
  </style>
</head>
<body>
  <table class="mytable">
    <?php for($nn=0; $nn<=2; $nn++){ ?>
     <tr>
       <th>
            <select onchange="ItemSelect(this)">
                <option value="---">---</option>
                <option value="アンパン">アンパン</option>
                <option value="カレーパン">カレーパン</option>
                <option value="クロワッサン">クロワッサン</option>
            </select>
       </th>
       <td class="price"><input type="text" name="price[]" value="" readonly></td>
       <td class="kosu"><input type="text" name="kosu[]" value="" oninput="KosuChange(this)"></td>
       <td class="shokei"><input type="text" name="shokei[]" value="" readonly></td>
     </tr>
    <?php } ?>
     <tr>
        <th>合  計</th><td></td><td></td>
        <td>
            <input id="goukei" type="text" name="goukei[]" value="">
        </td>
     </tr>
  </table>
</body>
</html>
<script>
/*ここに後のscriptが入ります。*/
</script>

ここでは、JQueryを読み込むコードを付け足した他、テーブルの<th>タグと<td>タグに、セレクトボックス とインプットボックスを付け足しました。

そして、tdタグにはそれぞれclass名を指定して、スタイルも指定しました。

スタイルは、別ファイルに書く人が多いでしょうが、私はこのようにhead内に書くことが多いです。しかし、あまり縦長にならないように、セレクターごとに横に繋げて書いています。

セレクトボックス 、インプットボックスは、それぞれ高さなどを96%にしましたが、プラウザにより、100%にすると、枠線が消えてしまう場合があるため、少し小さめにしています。この辺りはプラウザごとにテストして、必要に応じてマージンやパディンクをとっていただく必要があるかもしれません。

また、セレクトボックス とインプットボックスのそれぞれについて、パディングを定め、商品名は初期値で左詰め、数字は右詰めとしましたが、キチキチにならないように左右に10pxの余裕を持たせました。

テーブルは、border-collapse: collapse;として、テーブルとセルそれぞれにborderを指定して、枠線の隙間をなくすこともできますが、ここでは、詰めずに、最小限のスタイル指定としました。

なお、次のJQueryとの連携のため、selectタグにはonchange=”ItemSelect(this)”を、kosuのinputのところには、oninput=”KosuChange(this)”を書き加えました。

セレクトボックス の場合は、onchangeが良いでしょう。変更した時に、ItemSelectという名のJavaScriptの関数を実行してくれます。

また、個数の方は、別途書き換えても反応する(発火する)ように、onchangeではなくoninputを使いました。

onchangeだと、完全に入力が終わって、リターンキーを押したり、フォーカスが外れると反応します。ですから、一字一字書き込んだり削除をしたりするたびに反応するoninputの方が良いでしょう。

もちろん、個数自体をセレクトボックス 方式にしても良いです。

「this」とは、関数に引数として、この要素自身を引き渡すということです。

他のやり方もあり、いずれプログで整理したいと思いますが、ここでは、「this」を使い、「親要素の隣の隣の要素の子要素を書き換える」みたいなやり方を採用することとしました。

なお、価格は固定で、小計は計算の結果を反映するだけですから、ユーザーが直接書き換えられないように、「readonly」を書き込みます。

JavaScript(JQuery)で自動計算を可能にしよう

さて、いよいよ、本体のJQueryの動きです。

次の手順です。

① セレクトボックス で選択すると、単価と初期値の個数として「1」が現れ、小計(その商品の合計金額)も変わるようにする。

②別途、個数に変化があると、小計が変わるようにする。

③小計が変わるのに合わせて、合計金額も変わるようにする。

まず、①の反応のためには、selectタグにchangeイベントを書き込んでいます。ここに書き込まずに、JavaScript側で書く方法もありますが、そういうのは、いずれ将来のブログで扱うとして、ここのケースではHTMLに書き込みます。

各inputボックスにid番号を付けて単価や個数の位置を書かせてもいいですが、いちいちidを書くのも面倒なので、ここでは、JQueryのnext()のような機能を使いましょう。

次のようにします。

<select onchange="ItemSelect(this)">

個数のインプットボックスは次のようにしています。個数を変えた時にも計算結果が変わるようにするため、イベントが発火するように仕込みます。

<input type="text" name="kosu[]" value="" oninput="KosuChange(this)">

そして、スクリプト側は次のようにします。

<script>
price = [];
price['アンパン']=180;
price['カレーパン']=220;
price['クロワッサン']=250;
function ItemSelect(obj){
    var item=obj.value;  //←これは生のJavaScriptの記述法
    $(obj).parent().next().children().val(price[item]);
    $(obj).parent().next().next().children().val(1);
    $(obj).parent().next().next().next().children().val(price[item]);
    ShokeiChange();
}

function KosuChange(obj){
    var price=$(obj).parent().prev().children().val();
    var kosu=$(obj).val();
    var shokei=price*kosu;
    var shokei=shokei.toLocaleString();
    $(obj).parent().next().children().val(shokei); 
    ShokeiChange();
}

function ShokeiChange(){
   var goukei = 0;
   $(".shokei").each(function(index, element){
      var shokei=$(element).children().val().replace(/,/g, '');
      if(shokei==""){shokei='0';}
      goukei = parseInt(goukei) + parseInt(shokei);
   });
   var goukei=goukei.toLocaleString(); 
   $("#goukei").val(goukei);
}
</script>

最初に、各商品の値段を配列変数に入れておきましょう。最初の4行がそれです。ここでは、キーを数字ではなくて商品名の連想配列にしました。テーブルの最初のカラムを読み取るので、商品名の方が都合が良いからです。

その後、functionで始まる3つの関数があります。

ItemSelectは、商品名が選択された時に反応します。

KosuChangeは、個数が変更された時に反応します。

この二つの関数の最後で、ShokeiChangeが作動するようにしています。、

ShokeiChangeでは、小計欄の数字を全部足し合わすようにしています。

ここでは商品数を3つとしましたが、JQueryのeachを使っているので、行数は幾つでも対応できます。

目的のタグにたどり着くために、thisとして送られたものをobjとあるようにオプジォクトとして受けとり、JQueryで扱えるように$(obj)とした上で、次にparent()を使います。

このparent()は、セレクトボックス から親要素を取得するためです。

次にnext()で、thタグから次のtdタグを取得。

次のchildren()は、tdタグの中のinputタグを取得しています。

そして、その値を取得するために、val()を付けています。

値を取得するときは、val();となり、値を代入するときは、val(○○○);のようにします。

ShokeiChangeのeachはクラス名としてshokeiが付けられたtdタグの全てについて処理を行うという決まった書式です。

それぞれのtdタグごとに、その子要素としてのinput要素をchildren()で取得し、ついでそれぞれの値を取得します。

toLocaleString()は金額の3桁区切りとするためです。

しかし、3桁区切りとすると数字として扱われなくなりますので、次の関数内では、replaceでコンマを除去して数字に戻しています。

replace(/ , /g, ‘ ‘);の中のスラッシュは正規表現で、gは初めだけでなく全てのという意味です。これにより、全てのコンマが ‘ ‘、つまり何もなしに置き換えられます。

合計のところだけ、id=”goukei”として、htmlタグに付けました。このように、JavaScriptでは、idを使って要素を指定するのがむしろ普通です。

先ほど書いたように、テーブル内の他の各要素もidをつければよりわかりやすいかもしれませんが、煩雑にはなるので、ここではあまり使わず、thisと組み合わせて、parent()、next()、children()などを使いました。

まとめ

WEB上で表計算をさせたいというニーズは、WEBシステムはもちろんながら、一般のWEBサイトでも高まっていくのではないでしょうか。

こういうことができると、まさに、WEB上で、カスタマイズされたエクセル表が、いつでもどこでも自由に簡単に扱えることのできる道が開けるわけです。

あとは、データベースに保存したり読み取ったりする、行を追加・削除できるようにする、行を並べ替えられるようにする、などのことができれば、あなたもWEBシステム開発がすぐにできるようになるはずです。