AngularJS: A Walk-Through - Week 3

Sample web application from week 3 of the course AngularJS: A Walk-Through. <http://angularjs-walk.blogspot.com/>

by John Tucker

HTML

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.9/angular.min.js"></script>
<link rel="stylesheet" href="//dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/bootstrap.min.css">
<!--  Store Header  -->
<header>
    <h1 class="text-center">Flatlander Crafted Gems</h1>
    <h2 class="text-center">– an Angular store –</h2>
</header>

<!--  Products Container  -->
<div class="list-group">
    <!--  Product Container  -->
    <div class="list-group-item" ng-repeat="product in store.products">
        <h3>{{product.name}} <em class="pull-right">{{product.price | currency}}</em></h3>
        
        <!-- Image Gallery  -->
        <div ng-controller="GalleryController as gallery"  ng-show="product.images.length">
            <div class="img-wrap">
                <img ng-src="{{product.images[gallery.current]}}" />
            </div>
            <ul class="img-thumbnails clearfix">
                <li class="small-image pull-left thumbnail" ng-repeat="image in product.images">
                    <img ng-src="{{image}}" />
                </li>
            </ul>
        </div>
        
        <!-- Product Tabs  -->
        <section ng-controller="TabController as tab">
            <ul class="nav nav-pills">
                <li ng-class="{ active:tab.isSet(1) }">
                    <a href ng-click="tab.setTab(1)">Description</a>
                </li>
                <li ng-class="{ active:tab.isSet(2) }">
                    <a href ng-click="tab.setTab(2)">Specs</a>
                </li>
                <li ng-class="{ active:tab.isSet(3) }">
                    <a href ng-click="tab.setTab(3)">Reviews</a>
                </li>
            </ul>
            
            <!--  Description Tab's Content  -->
            <div ng-show="tab.isSet(1)">
                <h4>Description</h4>
                <blockquote>{{product.description}}</blockquote>
            </div>
            
            <!--  Spec Tab's Content  -->
            <div...

CSS

.ng-invalid.ng-dirty {
  border-color: red;
}
.ng-valid.ng-dirty {
  border-color: green;
}

JavaScript

(function() {
    var app = angular.module('gemStore', []);
    
    app.controller('StoreController', function() {
        this.products = gems;
    });
    
    app.controller("TabController", function() {
        this.tab = 1;
        
        this.isSet = function(checkTab) {
            return this.tab === checkTab;
        };
        
        this.setTab = function(setTab) {
            this.tab = setTab;
        };
    });
    
    app.controller('GalleryController', function(){
        this.current = 0;
        
        this.setCurrent = function(imageNumber){
            this.current = imageNumber || 0;
        };
    });
    
    app.controller("ReviewController", function(){
        
        this.review = {};
        
        this.addReview = function(product){
            this.review.createdOn = Date.now();
            product.reviews.push(this.review);
            this.review = {};
        };
    });
    
    var gems = [{
        name: 'Azurite',
        description: "Some gems have hidden qualities beyond their luster, beyond their shine... Azurite is one of those gems.",
        shine: 8,
        price: 110.50,
        rarity: 7,
        color: '#CCC',
        faces: 14,
        images: [
            "http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/images/gem-02.gif",
            "http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/images/gem-05.gif",
            "http://dhg7upb7j7jqa.cloudfront.net/shaping_up_with_angular_js/assets/demo/images/gem-09.gif"
        ],
        reviews: [{
            stars: 5,
            body: "I love this gem!",
            author: "[email protected]",
            createdOn: 1397490980837
        }, {
            stars: 1,
            body: "This gem sucks.",
            author: "[email protected]",
            createdOn: 1397490980837
        }]
    }, {
        name: 'Bloodstone',
        description: "Origin of the Bloodstone is unknown, hence its low value. It has...