Welcome to JS Bin
Load cached copy from
 
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Ember Starter Kit</title>
  <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/normalize/3.0.1/normalize.css">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
  <script src="http://builds.emberjs.com/tags/v1.10.0/ember-template-compiler.js"></script>
</script>
  <script src="http://builds.emberjs.com/tags/v1.10.0/ember.debug.js"></script>
</head>
<body>
<script type="text/x-handlebars">
<header>
  {{link-to "商品一覧" "products"}}
  {{link-to "カート" "cart"}}
</header>
<main>
  {{outlet}}
</main>
</script>
<script type="text/x-handlebars" data-template-name="products/index">
<h1>注目の商品</h1>
<ul>
  {{#each product in model}}
    <li>{{link-to product.name "products.show" product}}</li>
  {{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="products/show">
<h2>{{model.name}}</h2>
<a target="_blank" {{bind-attr href=model.url}}>詳しく見る</a>
${{model.price}} USD
<button {{action "addCart" model}}>カートに入れる</button>
</script>
<script type="text/x-handlebars" data-template-name="cart">
<h1>注文確認</h1>
<table>
  <tr>
    <th>商品名</th>
    <th>価格(USD)</th>
    <th>個数</th>
    <th>小計</th>
  </tr>
  {{#each orderLine in model}}
    <tr>
      <td>{{orderLine.product.name}}</td>
      <td>{{orderLine.product.price}}</td>
      <td>{{orderLine.count}}</td>
      <td>${{orderLine.price}}</td>
    </tr>
  {{/each}}
</table>
<hr>
合計金額: ${{totalPrice}} USD
</script>
</body>
</html>
 
html, body {
  margin: 20px;
  color: #222;
}
header, main {
  max-width: 800px;
  margin: auto;
}
header {
  border-bottom: #ddd solid 1px;
}
a {
  color: #222;
}
a:hover {
  color: #555;
}
header a {
  display: inline-block;
  text-decoration: none;
  padding: 10px 2px;
  width: 100px;
  text-align: center;
  border-radius: 4px 4px 0 0;
  border: 1px solid #ddd;
  border-bottom: none;
}
header a:hover {
  background-color: #eee;
}
header a.active, header a.active:hover {
  color: #222;
  cursor: default;
  background-color: white;
  border-bottom: white solid 1px;
  margin-bottom: -1px;
}
button {
  border: 1px solid transparent;
  border-radius: 4px;
  background-color: white;
  color: black;
  border: #ddd solid 1px;
  padding: 4px;
}
button:hover {
  background-color: #eee;
}
th, td {
  padding: 4px 16px;
}
td {
  border-top: 1px solid #ccc;
  border-bottom: 1px solid #ccc;
  text-align: right;
}
 
App = Ember.Application.create();
App.Router.map(function() {
  this.resource('products', {path: '/'}, function() {
    this.route('show', {path: 'products/:id'});
  });
  this.resource('cart');
});
App.ProductsRoute = Ember.Route.extend({
  model: function() {
    return App.Product.all();
  },
  actions: {
    addCart: function(product) {
      this.controllerFor('cart').addProduct(product);
      
      this.controllerFor('cart').save();
      this.transitionTo('cart');
    }
  }
});
App.ProductsShowRoute = Ember.Route.extend({
  model: function(params) {
    return this.modelFor('products').findBy('id', Number(params.id));
  }
});
App.CartController = Ember.ArrayController.extend({
  totalPrice: function() {
    return this.mapBy('price').reduce(function(total, price) {
      return total + price;
    }, 0);
  }.property('@each.price'),
  addProduct: function(product) {
    var orderLine = this.get('model').findBy('product', product);
    if (!orderLine) {
      orderLine = App.OrderLine.create({
        product: product
      });
      this.pushObject(orderLine);
    }
    orderLine.incrementProperty('count');
  },
  save: function() {
    var ids = [];
    this.forEach(function(orderLine) {
      var i;
      var count = orderLine.get('count');
      var productId = orderLine.get('product.id');
      for (i = 0; i < count; i++) {
        ids.push(productId);
      }
    });
    localStorage.setItem('cart-product-ids', JSON.stringify(ids));
  },
  restore: function() {
    var idsString = localStorage.getItem('cart-product-ids');
    var ids;
    if (idsString) {
      ids = JSON.parse(idsString);
    } else {
      ids = [];
    }
    var products = ids.map(function(id) {
      return App.Product.find(id);
    });
    products = products.compact();
    products.forEach(function(product) {
      this.addProduct(product);
    }, this);
  }
});
App.Product = Ember.Object.extend({
  id: null,
  name: null,
  price: 0,
  url: null
});
App.Product.reopenClass({
  data: [],
  all: function() {
    return App.Product.data;
  },
  find: function(id) {
    return this.all().findBy('id', Number(id));
  }
});
App.Product.data.pushObjects([
  App.Product.create({
    id: 1,
    name: 'ステッカー',
    price: 6.0,
    url: 'http://devswag.com/products/ember-sticker'
  }),
  App.Product.create({
    id: 2,
    name: 'Tシャツ',
    price: 22.0,
    url: 'http://devswag.com/products/ember-js-tshirt'
  }),
  App.Product.create({
    id: 3,
    name: 'ぬいぐるみ',
    price: 10.0,
    url: 'http://devswag.com/products/ember-mascot-tomster'
  })
]);
App.OrderLine = Ember.Object.extend({
  product: null,
  count: 0,
  price: function() {
    return this.get('product.price') * this.get('count');
  }.property('product.price', 'count')
});
App.initializer({
  name: 'restore-cart',
  initialize: function(container, app) {
    container.lookup('controller:cart').restore();
  }
});
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x