Scroll page back to the top

Online calculator with jQuery and PHP

Download Exercise FilesDemo
 
 

Today we will learn how to build a calculator, which allows us to perform simple calculations such as adding, deducting, multiplying and dividing. To build it we will use jQuery and a tiny bit of PHP.

To start with - download the exercise files and place the entire content of the start folder inside of the root of your project.

Open index.html and in between the opening and closing body tags create the wrapper div and the structure of our calculator:

<div id="wrapper">
	
	<div id="calculator">
	
		<div id="calculatorResult">0.00</div>
		
		<ul id="calculatorKeyboard">	
			
			<li data-value="1">1</li>
			<li data-value="2">2</li>
			<li data-value="3">3</li>
			<li data-value="+" class="operator">+</li>
			
			<li data-value="4">4</li>
			<li data-value="5">5</li>
			<li data-value="6">6</li>
			<li data-value="-" class="operator">-</li>
			
			<li data-value="7">7</li>
			<li data-value="8">8</li>
			<li data-value="9">9</li>
			<li data-value="*" class="operator">*</li>
			
			<li data-value="0" class="double">0</li>
			<li data-value="." class="operator">.</li>			
			<li data-value="/" class="operator">/</li>
			
			<li data-value="c" class="double summary">C</li>
			<li data-value="=" class="double summary">=</li>
						
		</ul>
		
	</div>
	
</div>

As you can see our calculator structure is enclosed within the div with the id calculator. The display is represented by the div with the id calculatorResult and the keyword is simply an unordered list. The key value is stored within the data-value attribute of the specific key (li tag) - this gives you more flexibility when it comes to a visual representation of the specific key, as values are separate to what you want to display in between the opening and closing li tags.

Our index.html file is now completed so you can save and close it.

Now open the core.js file, which you'll find inside of the js folder. Right at the top start with the definition of the new object called (not surprisingly) calculatorObject:

var calculatorObject = {

};

Inside of the new object create the following properties:

defaultValue : '0.00',
operators : ['+', '-', '*', '/'],
sequence : [],
cycleFinished : false,
urlCalculate : '/mod/calculate.php',

The defaultValue is the value which is displayed when the calculator first loads and whenever we reset it. The operators is the array of all possible calculation types represented by its operator i.e. adding is represented by the '+' symbol etc.

The sequence is an empty array, which will be used to store values and operators to create a calculation string, which we'll later send to PHP to get the result. The cycleFinished is telling us whether the equal key has been pressed or not and urlCalculate is the url to the PHP file where the calculation takes place.

The first method we will create is going to determine whether the given value is a number (integer / decimal).
We'll give it a name of isNumber:

isNumber : function(value) {
	return typeof value !== 'undefined' && !isNaN(parseFloat(value)) && isFinite(value);
}

The next method will perform the call to the PHP string sending the calculation string in order to get the result and display it in the display area. This specific method is called calculate and will be triggered whenever someone presses the '=' key:

calculate : function() {
	jQuery.post(
		calculatorObject.urlCalculate, 
		{ sequence : calculatorObject.sequence }, 
		function(data) {
			if (!data.error) {
				$('#calculatorResult').html(data.result);				
				calculatorObject.cycleFinished = true;
				calculatorObject.sequence = [];
			}
		}, 
	'json');
}

As you can see we are calling the jQuery's post() method passing the value assigned to the urlCalculate property as the first parameter and sequence, which contains the collected values and operators as second parameter.

On callback we execute the function, which first checks whether the json response from the PHP code contains the negative value assigned to the error index and if so - it replaced the existing value within the calculatorResult with the returned one.

After this, we set the cycleFinished to true and reset our sequence array.

The last method of our calculatorObject is called trigger:

trigger : function(obj) {

	if (obj.length > 0) {
	
		obj.find('ul li').live('click', function() {
		
			$(this).siblings('li').removeClass('active');
			$(this).addClass('active');
			
			var thisItem = $(this).attr('data-value');
			
			var thisValue = $('#calculatorResult').text();
			
			
			
			
			
			
			
		}
		
	}
	
}

The above is simply checking whether the object, which we are passing as a parameter has been found on the page and if so - it uses the jQuery's live() method to bind the 'click' event to this specific object.

When the click event occurs the first thing that happens is the removal of the active class from all li tags, which are the siblings of the clicked one. Next we select the clicked li tag by applying the same class to it.

The thisItem variable stores the value assigned to the data-value attribute of the clicked element and the thisValue one gets the current content of the calculatorResult div.

Now it's time to either push the value to the sequence array or simply display it in our calculatorResult div.

After the line:

var thisValue = $('#calculatorResult').text();

create a switch statement with the thisItem variable as the argument:

switch(thisItem) {
					
	
	
}

The first case will be executed when the equal key is pressed:

case '=':
					
calculatorObject.sequence.push(thisValue);
calculatorObject.calculate();

break;

The above case puts the value from the calculatorResult to the sequence array and calls the calculate() method, which takes care of the rest.

The next case will be executed when the reset button (C) is pressed:

case 'c':
					
calculatorObject.sequence = [];
$('#calculatorResult').html(calculatorObject.defaultValue);

break;

This case first clears the sequence array and puts the default value into the display div.

Now it's time to have a look at the joined case for all operators. Rather than typing the operators, we will use the index of our operators array:

case calculatorObject.operators[0]:
case calculatorObject.operators[1]:
case calculatorObject.operators[2]:
case calculatorObject.operators[3]:

if (calculatorObject.cycleFinished) {
	calculatorObject.cycleFinished = false;
}

calculatorObject.sequence.push(thisValue);

if (calculatorObject.sequence.length > 0) {	
	
	if (calculatorObject.isNumber(calculatorObject.sequence[calculatorObject.sequence.length-1])) {
		calculatorObject.sequence.push(thisItem);
	} else {
		calculatorObject.sequence[calculatorObject.sequence.length-1] = thisItem;
	}

} else {

	calculatorObject.sequence.push(calculatorObject.defaultValue);
	calculatorObject.sequence.push(thisItem);
	
}

$('#calculatorResult').html(thisItem);

break;

First if statement checks whether the operator has been clicked after we've clicked the equal button, in which case it sets the cycleFinished property of our object back to false. This is to make sure that if we got the result we can now continue with it rather than reset it to null.

The following line of code adds the value from the display to the sequence array.

Next, we have the if / else statement, where we check if the sequence array is not empty and if not we check if the last value in the array is of a numerical type and if so - we add the operator as the next item in the array - otherwise we replace the last item with the new operator.

The else statement simply puts the default value (0.00) into the sequence array followed by the clicked operator.

The last line within this case simply puts the selected operator into the display.

Now it's time for the last - default case:

default:
					
if (jQuery.inArray(thisValue, calculatorObject.operators) === -1) {

	if (thisValue !== calculatorObject.defaultValue) {
	
		if (calculatorObject.cycleFinished) {
			calculatorObject.cycleFinished = false;
			$('#calculatorResult').html(thisItem);
		} else {
			$('#calculatorResult').html(thisValue + thisItem);
		}
		
	} else {
		$('#calculatorResult').html(thisItem);
	}

} else {
	$('#calculatorResult').html(thisItem);
}

The first thing we do here is to check whether the currently displayed value is NOT inside of the operators array and if not we check whether it is also not a default value. If both conditions are true, then we check whether the value assigned to the cycleFinished property is set to true and if it is we change it to false and replace the display value with the one associated with the pressed key. Otherwise we concatenate the display value with the new one.

The else statements simply replaces the display value with the new one.

Now that our switch statement is completed, the last thing we need to do inside of our core.js file is to call the relevant method from within DOM:

$(function() {

	calculatorObject.trigger($('#calculator'));

});

You can now save and close the file, navigate to the mod directory and open the calculate.php file for editing.

Inside of the calculate.php we first check whether the sequence array has been sent using $_POST request. Then we filter our array ensuring that it only contains the numerical values or one of the four, allowed operators. Then we check if our $values array is not empty and create a $calculation variable, which contains the php statement in a form of a string, to later pass it over to the eval() function for executing. The result is assigned to the $value variable and returned back to the javascript using the json_encode() function as a result index - formatted using number_format() function:

<?php
if (isset($_POST['sequence'])) {
	
	$values = array_filter($_POST['sequence'], function($value) {
	    return is_numeric($value) || in_array($value, array('+', '-', '/', '*'));
	});
	
	if (!empty($values)) {
		
		$calculation = 'return ('.implode(' ', $values).');';
		$value = eval($calculation);
		echo json_encode(array('error' => false, 'result' => number_format($value, 2)));
	
	} else {
		echo json_encode(array('error' => true, 'call' => 2));
	}
	
} else {
	echo json_encode(array('error' => true, 'call' => 1));
}

You can now save and close the calculate.php file and test your new calculator.

 
 
 

Discussion (1 comment)

 
Page 1 of 1
  • First
  • Previous
  • 1
  • Next
  • Last
 
 
Add a comment
Add Comment