Vue.js Cart

by shigetak

HTML

<script src="https://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/semantic.css">
	<!-- navigation bar -->
	<nav class="navbar navbar-default">
		<div class="container-fluid">
			<div class="container">
			  <a class="navbar-brand">
				  <i class="glyphicon glyphicon-shopping-cart"></i> Vue.js shoping cart
			  </a>
		  </div>
		</div>
	</nav>
	  
	<div class="container">
		<div class="row">
			<div class="col-md-4">
				<ul class="list-group">
					<li v-for="product in products" class="list-group-item">
						{{ product.name }}   
						<div class="pull-right">単価 ¥ {{ product.price }} 円
							<button id="plusBtn" v-show="notInCart(product)" v-on:click=" addToCart(product)" class="btn btn-xs btn-primary">
								+
							</button>
							<span v-show="!notInCart(product)" class="glyphicon glyphicon-ok-circle text-success"></span>
						</div>
					</li>
				</ul>
			</div>
			<div class="col-md-4">
				<div class="panel panel-default">
				  <div class="panel-heading">
					  <span class="glyphicon glyphicon-shopping-cart"></span>
					  Total (<span v-text="total"></span>)
				  </div>
				  <div class="panel-body">
					  <span v-show="!count" class="text-muted">Cart empty</span>
						<li v-for="item in cart_items" class="list-group-item">
							{{ item.qty }} &times; {{ item.name }} {{ item.price }}
							<div class="pull-right">
								<button v-on:click="decQty(item)" class="btn btn-xs btn-default">
									-
								</button>
								<button v-on:click="addQty(item)" class="btn...

CSS

body {
	background-color: #f4f4f4;
}

JavaScript

$('#showmodal').click(function() {
	$('.fullscreen.modal').modal('show');
});

$('.plzclick').click();
$('#plusBtn').trigger('click');

var dataUrl = 'http://rcart.eek.jp/used1r/dist/all.utf8.json' ;

$(function() {
$.getJSON(dataUrl, function(result) {
    var
      ulObj = $("#demo"),
      len = result.length;

    for(var i = 0; i < len; i++) {
      ulObj.append($("<li>").attr({"id":result[i].id}).text(result[i].name));
    }
  });
});

$.when(
    $.ajax({
        type: 'GET',
        url: dataUrl,
        dataType: 'jsonp',
     //   jsonpCallback: 'blockJSON'
    })
)
.done(function() {
	$("div").fadeOut()
})
.fail(function() {
	console.log('error');
});

const products= [
  {'id': 1, 'name': 'ぷろだくと1ですProduct 1', 'price': 12950},
  {'id': 2, 'name': 'product2 ぷろだくと2', 'price': 4035}
];
var v = new Vue({
			el: 'body',
			data: {
				products: products,
				cart_items: []
			},
			computed: {
				count: function() {
					return this.cart_items.length;
				},
				total: function() {
					return _.reduce(this.cart_items, function(n, cart_item) {
						return cart_item.price * cart_item.qty + n;
					}, 0).toFixed(2);
				}
			},
			methods: {
      	notInCart: function(product) {
        	var ids = _.pluck(this.cart_items, 'id');
          return !_.contains(ids, product.id);
        },
				addToCart: function(product) {
        	var cart = Vue.util.extend({}, product);
	        var ids = _.pluck(this.cart_items, 'id');
     
					if (!_.contains(ids, product.id)) {
	          cart.qty = 1;       
						this.cart_items.push(cart);
					}
				},
        addQty: function(product) {
        	product.qty = product.qty +1;
        },
				decQty: function(product) {
					product.qty -= 1;
					if (product.qty <= 0) {
						this.cart_items.$remove(product);
					}
				}
			}
		});