Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert calculator to a knockout component #48

Merged
merged 1 commit into from
Jun 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 1 addition & 34 deletions calculator.html → index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,43 +16,10 @@
<div class="row">
<!-- ko foreach: calculators -->
<div class="col-lg-6 col-md-4 col-sm-6 col-xs-12 calculator">
<div class="row">
<div class="col-xs-12">
<h3>Calculator</h3>
<input class="form-control" type="text" data-bind="value: input" />
</div>
</div>
<div class="row buttons">
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '7')">7</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '4')">4</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '1')">1</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '0')">0</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '8')">8</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '5')">5</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '2')">2</button>
<button class="btn btn-block" data-bind="click: addMultiplication">&times;</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '9')">9</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '6')">6</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '3')">3</button>
<button class="btn btn-block" data-bind="click: addDivision">&divide;</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: clear">C</button>
<button class="btn btn-block" data-bind="click: addPlus">+</button>
<button class="btn btn-block" data-bind="click: addMinus">-</button>
<button class="btn btn-block" data-bind="click: equal">=</button>
</div>
</div>
<!-- ko component: 'calculator' --><!-- /ko -->
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tell knockout to include a 'calculator' component here

<button class="btn btn-block btn-danger remove-button" data-bind="click: $parent.removeCalculator, visible: $parent.calculators().length> 1">Remove</button>

</div>
<!-- /ko -->

</div>
<div class="row">
<div class="col-xs-12">
Expand Down
5 changes: 5 additions & 0 deletions lib/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,10 @@
};
}

ko.components.register('calculator', {
Copy link
Collaborator Author

@massimocode massimocode Jun 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Register the 'calculator' component, telling knockout where to find the JS and HTML for the component. Notice how the template is prefixed by text! which means that require JS (the module loader) will load this as a text file and not as a javascript file (which wouldn't work because html is not valid javascript!)

viewModel: { require: 'lib/calculator' },
template: { require: 'text!lib/calculator.html' }
});

ko.applyBindings(new App());
}));
32 changes: 32 additions & 0 deletions lib/calculator.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="row">
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The HTML for the calculator component. Notice how there is no remove button as that is not technically part of the calculator. That is the responsibility of the App / Dashboard that hosts the calculators.

<div class="col-xs-12">
<h3>Calculator</h3>
<input class="form-control" type="text" data-bind="value: input" />
</div>
</div>
<div class="row buttons">
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '7')">7</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '4')">4</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '1')">1</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '0')">0</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '8')">8</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '5')">5</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '2')">2</button>
<button class="btn btn-block" data-bind="click: addMultiplication">&times;</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '9')">9</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '6')">6</button>
<button class="btn btn-block" data-bind="click: addNumber.bind(null, '3')">3</button>
<button class="btn btn-block" data-bind="click: addDivision">&divide;</button>
</div>
<div class="col-xs-3">
<button class="btn btn-block" data-bind="click: clear">C</button>
<button class="btn btn-block" data-bind="click: addPlus">+</button>
<button class="btn btn-block" data-bind="click: addMinus">-</button>
<button class="btn btn-block" data-bind="click: equal">=</button>
</div>
</div>
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"description": "A basic client side calculator",
"main": "calculator.html",
"scripts": {
"test": "node node_modules/mocha/bin/mocha spec --recursive --require spec/mocha-setup"
"test": "node node_modules/mocha/bin/mocha spec --recursive --require spec/mocha-setup",
"start": "node node_modules/http-server/bin/http-server"
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add an NPM script to start up the http server so that you can use the app. We now need a HTTP server because we are using the requireJS text plugin to load the html. That plugin will not work on the "file://" protocol (i.e. when you open a html file in chrome) due to security restrictions that browsers have. It requires that the file is hosted on a web server (i.e. 127.0.0.1 or localhost or something).

},
"repository": {
"type": "git",
Expand All @@ -18,12 +19,14 @@
"homepage": "https://github.com/SMH110/My-Calculator#readme",
"devDependencies": {
"chai": "^3.5.0",
"http-server": "^0.9.0",
"mocha": "^2.5.3",
"sinon": "^1.17.4",
"sinon-chai": "^2.8.0"
},
"dependencies": {
"knockout": "^3.4.0",
"requirejs": "^2.2.0"
"requirejs": "^2.2.0",
"requirejs-text": "^2.0.12"
Copy link
Collaborator Author

@massimocode massimocode Jun 28, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the Require JS text plugin. Require JS allows you to use plugins so that when the URL is prefixed by something! then the something plugin will be used to load that file, instead of the normal javascript loading method. In this case we are using the text plugin to load the HTML as text instead of as javascript (which wouldn't work).

}
}
5 changes: 4 additions & 1 deletion readMe.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#Calculator
# Calculator
A basic client side calculator
- Don't use the keyboard! Use the mouse instead.

## Installation
You need to run `npm install`, then `npm run start` then navigate to 127.0.0.1:8080 (the app requires that port 8080 is not in use by anything else).
3 changes: 2 additions & 1 deletion require-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ require.config({
'chai': 'node_modules/chai/chai',
'sinon': 'node_modules/sinon/pkg/sinon',
'sinon-chai': 'node_modules/sinon-chai/lib/sinon-chai',
'knockout': 'node_modules/knockout/build/output/knockout-latest'
'knockout': 'node_modules/knockout/build/output/knockout-latest',
'text': 'node_modules/requirejs-text/text'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the text plugin to the require JS config so that require JS knows where to find the plugin

}
});