KnockoutJs Ex. with Toastr
HTML
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<link rel="stylesheet" href="http://codeseven.github.com/toastr/toastr.css">
<script src="http://codeseven.github.com/toastr/toastr.js"></script>
<h2>Your seat reservations</h2>
<table>
<thead><tr>
<th>Reservation for</th><th>Meal</th><th>Surcharge</th><th></th>
</tr></thead>
<tbody data-bind="foreach: seats">
<tr>
<td><input data-bind="value: name" /></td>
<td><select data-bind="options: $root.meals, value: initialMeal, optionsText: 'mealName'"></select></td>
<td data-bind="text: formattedPrice"></td>
<td><button data-bind="cl ick: $root.removeSeat, enable: $root.seats().length > 1">Remove seat</button></td>
</tr>
</tbody>
</table>
<div id="feedback" style="display: none; position: absolute; right: 20px; bottom: 20px;"></div>
<h3 id="totalVal" data-bind="visible: totalSurcharge() > 0">
Total surcharge: $<span data-bind="text: totalSurcharge().toFixed(2)"></span>
</h3>
<button data-bind="click: addSeat, enable: seats().length < 5">Reserve another seat</button>
JavaScript
// MODELS
// Class to represent a row in the seat reservations grid
function SeatReservation(name, initialMeal) {
var self = this;
self.name = ko.observable(name);
self.initialMeal = ko.observable(initialMeal);
self.formattedPrice = ko.computed(function() {
var price = self.initialMeal().price;
return price ? "$" + price.toFixed(2) : "None";
});
}
// Class to represent a Meal
function Meal(mealName, price) {
var self = this;
self.mealName = mealName;
self.price = price;
}
// VIEW MODEL
// Overall viewmodel for this screen, along with initial state
function ReservationsViewModel() {
var self = this;
// Non-editable catalog data - would come from the server
self.meals = [
new Meal("Smelly sambo", 0),
new Meal("KFC", 10.99),
new Meal("Lamb chop", 25.95),
new Meal("A big fuckoff steak", 40.00)
];
// Editable data
self.seats = ko.observableArray([
new SeatReservation("John", self.meals[0]),
new SeatReservation("Paul", self.meals[1]),
new SeatReservation("Ringo", self.meals[2]),
new SeatReservation("George", self.meals[3])
]);
self.shouldShowRemovedMessage = ko.observable(false);
self.shouldShowAddedMessage = ko.observable(false);
// Operations
self.addSeat = function() {
self.seats.push(new SeatReservation("", self.meals[0]));
toastr.info("", "A new reservation slot has been added.", toastrOverrides);
}
// Operations
self.removeSeat = function(seatReservation) {
self.seats.remove(this);
var resName = seatReservation.name();
if (resName.length === 0) {
resName = "<em>Anonymous</em>";
}
toastr.success("Reservation for '" + resName + "' has been removed.", "", toastrOverrides);
}
self.totalSurcharge = ko.computed(function() {
var total = 0;
for (var i = 0; i < self.seats().length; i++) {
...