プログラミングを始める前にindex.html、js/sampleCalc.jsの中も覗いてみましょう。電卓の見た目や基本的なプログラムの構造はあらかじめこちらの方で勝手書いておきました。イチからやるのも楽しいですが、今回はサンくらいから始めましょう。
<div id="buttonAdd" class="button op opFree" data-value="add">+</div>
...
<div id="buttonMAdd" class="button mOp" data-value="mAdd">m+</div>
...
<div id="button7" class="button num" data-value="7">7</div>
全てのボタンに個別のID属性を持たせて、一意にDOMアクセスしやすいようにしています。が、実際に使う事はないかもしれません。class属性にはデザイン分離によるCSSの都合で複数のクラスを指定しています。クラス名のうち、数字のボタンにはnum[1]を、演算子にはop[2]を、メモリー計算用にはmOp[3]を割り当てています。こちらはグループ化する場合にも役に立つと思います。
Note
他にも幾つかクラスを割り当てられている要素がありますが、ほとんどデザイン上の都合ですので無視してください。
もうひとつ、各ボタンにはdata-value属性を持たせて値を格納しています。ボタンを押したとき、プログラムにどのボタンが押されたのか知らせる必要がありますので、この値を参照して渡す事にします。data-value属性は私が勝手に付けた属性ですがjQueryからも簡単に扱えます。タグに紐づかせたいデータなどがある場合に便利です。
Note
data-*属性はW3Cで検討されているHTML5の仕様の一つですが(3.2 Elements — HTML5)、jQueryでは以前より同様の仕組みがありました。HTML5への採用、仕様の検討を受け同じように扱える仕組みが導入されました(.data() – jQuery API)。
とはいえ、両者には若干の違いがあり注意が必要な場合もあります。興味がある方は調べてみるといいですよ。
function SampleCalc() {
this.total = 0;
this.stack = '0';
this.operator = '';
this.last = 'num'; // 'num': 数字, 'op': 演算子
this.mTotal = 0;
}
一番最初にはnewを使って呼び出される事を想定したコンストラクタ関数を用意しています。このコンストラクタが行う事は内部変数の初期化です。変数名が適当なので気になる方は各自適当に変更してください。
Note
newで何が行われているかざっくりと説明しますと、まず空のオブジェクトを作成しthisでアクセスできるようにします。そして呼び出されたコンストラクタ関数で特に指定がなければ、最後にそのthisを返します。
SampleCalcのコンストラクタでは、オブジェクトを作ってそのオブジェクトに幾つかの内部変数を持たせて初期化し、最後にそのオブジェクトを返している事になります。
計算を行うという事はどういう事でしょう。足し算を例に計算式を考えると、
足される数 + 足す数 = 答え
となります。数値が二つあって、どのように計算するのか演算子があって、それで答えが出ます。出た答えは、そのまま続けて計算を行う場合には足される数になりますので同じものとして扱えそうです。数値の保持する変数と演算子を保持する変数、それぞれ一つずつの三つの変数が少なくとも必要そうです。
それから複数桁の数値を入力する場合には連続して数字を入力します。そして、演算子などの他の入力が行われるとそれまでに入力されていた数字を数値として確定します。直前の入力が何であったかを知る必要がありそうです。これにも一つ変数を用意しましょう。数値連続入力中の値を保持する変数も必要ですが、これは計算が終わると破棄する事ができる足す数用の変数を使い回しましょう。途中経過を兼ねますから、基本的にスクリーンに表示されるのはこの変数の値になりそうです。
最後にメモリー計算用の変数も一つ用意しておきます。こちらは計算に必要な変数は流用できるので、足される数(答え)の一つだけです。
第一項(足される数)と計(答え)を保持する。
第二項(足す数)を保持する。数字入力中の値を保持するためにも用いる。
演算子を保持する。
直前の入力が何であったかを保持する。numだったら数字、opだったら演算子など。
メモリー計算用の第一項を保持する。
これらの変数を操作して計算させて行きます。
コンストラクタ関数の下には、それぞれの処理を行うメソッドを定義する為のプログラムがあります。prototype継承を用いた一度に定義する書き方です。ボタンの機能(グループ)、計算を行うもの、画面に表示するもの毎にわけてメソッドを定義しています。一足先にサンプルとして作ってみた私の定義です。
SampleCalc.prototype = {
inputValue: function (value) {
},
inputOperator: function (newOperator) {
},
equal: function () {
},
clear: function () {
},
calculate: function () {
},
mCalculate: function (mOperator) {
},
push: function (value) {
}
};
数字ボタンが押された時に呼び出すメソッド。
演算子ボタンが押された時に呼び出すメソッド。
イコールボタンが押された時に呼び出すメソッド。
クリアボタンが押された時に呼び出すメソッド。
入力された数値と演算子を元に計算を行うメソッド。
メモリー計算ボタンが押された時に呼び出すメソッド。計算も行う。
入力途中の値を退避し、画面に表示するメソッド。
これまた名前がちょっとあれなので気になる方は各自適当にお願いします。これらのメソッドに各機能を実装するのが今回の目標ですが、何も私の想定するサンプル通りに実装する必要はありません。思い通りいろいろな方法で実装するといいと思いますよ。
$(function () {
var calc = new SampleCalc();
});
最後に上記のような記述があります。無名関数の中を先に見ると、変数calcにnewを用いてコンストラクタ関数を呼び出してオブジェクトを作成しています。この時点でprototype拡張されたメソッドなども使えるようになりますので、それ以降calc変数を用いてそれらを使う事になります。
では、最初の$は何でしょう。これは今回いろいろな面倒な事を肩代わりしてもらう為にも採用したJavaScriptライブラリjQueryの独自関数で、引数を与えるとその時の状況に合わせて最適な処理を行ってくれるモノです。この場合、渡された処理をDOM構築後に実行してくれます。DOM構築後とはざっくり読み込みが終わったらと考えてください。
Note
実際には、:
jQuery(document).ready(function () {
...
});
を省略した書き方ですが、一般的に省略形が使われます。
DOM構築後では各ボタンが要素として存在するようになり扱う事が可能になったと言う事です。この中にボタンと処理を紐付ける処理などを記述していきます。
脚注
[1] | Numberの略。 |
[2] | Operationの略。 |
[3] | Memory Operationの略。 |