Bakuta Andrey
{
characters: [
{
name: "Kratos",
description: "Total badass"
},
{
name: "Nathan Drake",
description: "Treasure hunter and fortune seeker"
}
]
}
var ViewModel = {
name: "Kratos",
currentActivity: ko.observable("ripping off sombody's head")
}
Oh no! This is
And he is
ko.applyBindings(ViewModel);
Oh no! This is Kratos
And he is ripping off sombody's head
Let's solve some problem
Xbox One
Be first to experience Xbox One.
The Day One Edition features a commemorative
controller and an exclusive achievement.
$499
...
Total: $1198
(function () {
var data = [
{
title: 'Xbox One',
description: 'Be first to experience Xbox One...',
price: '$499',
quantity: 1,
img: './images/consoles/xbox.png'
},
...
]
function CheckoutViewModel(data) {
ko.mapping.fromJS({ products: data }, {}, this);
}
$(function() {
ko.applyBindings(new CheckoutViewModel(data));
})
})();
<!-- ko foreach: products -->
<div class="product">
<img data-bind="attr: { src: img, alt: title }" />
<div>
<h3 data-bind="text: title"></h3>
<p data-bind="text: description"></p>
</div>
<div class="price" data-bind="text: price"></div>
<input data-bind="value: quantity" type="text" />
<span class="delete" />
</div>
<!-- /ko -->
<div>
<div class="total">
Total: <span class="total-amount">$1198</span>
</div>
<div>
<div class="checkout">
<a href="#" class="btn">Checkout</a>
</div>
</div>
</div>
var data = [
{
title: 'Xbox One',
description: 'Be first to experience Xbox One...',
price: '$499',
quantity: 1,
img: './images/consoles/xbox.png'
},
...
]
function ProductViewModel(data) {
ko.mapping.fromJS(data, {}, this);
this.formattedPrice = ko.computed(function() {
return '$' + this.price();
}, this);
}
function CheckoutViewModel(data) {
var mapping = {
products: {
create: function(options) { return new ProductViewModel(options.data); }
}
}
ko.mapping.fromJS({ products: data }, mapping, this);
}
<!-- ko foreach: products -->
<div class="product">
<img data-bind="attr: { src: img, alt: title }" />
<div>
<h3 data-bind="text: title"></h3>
<p data-bind="text: description"></p>
</div>
<div class="price" data-bind="text: formattedPrice"></div>
<input data-bind="value: quantity" type="text" />
<span class="delete" />
</div>
<!-- /ko -->
var formatMoney = function(value) {
return '$' + value;
}
function CheckoutViewModel(data) {
...
this.total = ko.computed(function() {
var total = 0;
ko.utils.arrayForEach(this.products(), function(product) {
total += product.price * product.quantity();
});
return formatMoney(total);
}, this);
}
<div>
<div class="total">
Total: <span data-bind="text: total" class="total-amount"></span>
</div>
<div>
<div class="checkout">
<a href="#" class="btn">Checkout</a>
</div>
</div>
</div>
function ProductViewModel(data) {
var mapping = {
observe: ['quantity']
}
ko.mapping.fromJS(data, mapping, this);
this.formattedPrice = ko.computed(function() {
return formatMoney(this.price)
}, this);
}
Have you noticed that their stuff is shit and your shit is stuff?
George Carlin
var clearFormat = function(price) {
return parseFloat(price.replace(/[^0-9-.]/g, ''));
},
formatMoney = function(price) {
return '$' + price;
},
storePrices = function() {
$('.price').each(function() {
$(this).next('input').data('price', clearFormat($(this).text()));
});
};
var calculateSubtotal = function(e) {
var product = e.originalEvent.currentTarget,
price = $('.price', product),
subtotal = formatMoney($(this).data('price') * parseInt($(this).val()));
price.html(subtotal);
},
calculateTotal = function() {
var total = 0;
$('input').each(function() {
var $this = $(this);
total += $this.data('price') * parseInt($this.val());
});
$('.total-amount').text(formatMoney(total));
},
$('.product').on('change', 'input', function(e) {
calculateSubtotal.call(this, e);
calculateTotal.call(this, e);
});
this.subtotal = ko.computed(function() {
return formatMoney(this.price * this.quantity());
}, this);
Fix view
<div class="subtotal" data-bind="text: subtotal"></div>
And use it when calculating total
this.total = ko.computed(function() {
var total = 0;
ko.utils.arrayForEach(this.products(), function(product) {
total += product.subtotal();
});
return total;
}, this)
ko.extenders.formatMoney = function(target) {
target.formatMoney = ko.computed(function() {
return '$' + ko.utils.unwrapObservable(this);
}, target);
return target;
};
function ProductViewModel(data) {
...
this.subtotal = ko.computed(function() {
return this.price * this.quantity();
}, this).extend({ formatMoney: true });
}
function CheckoutViewModel(data) {
...
this.total = ko.computed(function() {
var total = 0;
ko.utils.arrayForEach(this.products(), function(product) {
total += product.subtotal();
});
return total;
}, this).extend({ formatMoney: true });
}
<div class="total">
Total: <span data-bind="text: total.formatMoney" class="total-amount"></span>
</div>
...
<div data-bind="text: subtotal.formatMoney" class="subtotal"></div>
$('.product').on('click', '.delete', function(e) {
e.preventDefault();
$(e.originalEvent.currentTarget).remove();
calculateTotal();
});
function CheckoutViewModel(data) {
...
this.delete = function(product) {
this.products.remove(product);
}
}
function CheckoutViewModel(data) {
...
this.checkout = function() {
var mapping = { ignore: ['description', 'img', 'price'] };
$.ajax({
dataType: 'json',
data: ko.mapping.toJSON(this, mapping),
type: 'post'
})
.success(function() {
alert('Thank you for your order');
});
}
}
Checkout
$('.checkout a').on('click', function(e) {
e.preventDefault();
$.ajax({
dataType: 'json',
data: JSON.stringify($('form').serializeArray()),
type: 'post'
})
.success(function() {
alert('Thank you for your order');
});
});