Knockout - Template Debugging (more involved)

by johnpapa

HTML

<script src="https://github.com/downloads/SteveSanderson/knockout/knockout-2.0.0.debug.js"></script>
<div class="page">
    <div id="main">
        <div class="leftFloat">
            <ul style="width:980px">
                <!-- ko template: {foreach:productsToShow, beforeRemove:hideProducts}  -->
                <li class="mediumProductSquares" >
                    <!-- ko template: {name: 'productTmpl'}  -->
                    <!-- /ko -->
                </li>
                <!-- /ko -->
            </ul>
        </div>
    </div>
</div>

<script id="productTmpl" type="text/html">
    
    <!-- debugging -->
    <!-- photoUri should be photoUrl -->
    <div data-bind="text: ko.toJSON($data)"></div>
    <br/>
    <pre data-bind="text: JSON.stringify(ko.toJS($data), null, 2)"></pre>
    <br/>
    <!-- /debugging -->

    
    <div>
        <div class="dialogTitleBorder">
            <span class="borderTitleText">Product Details</span>
            <!--<div class="closeIcon" data-bind="click:$parent.removeProduct"></div>-->
            <div class="closeIcon"></div>
        </div>
        <div class="photoContainer leftFloat">
            <img data-bind="visible: photoUri, attr: { src: photoUrl, alt: shortDesc}" class="photoThumbnail"></img>
        </div>
        <div>
            <span>Brand: </span><span data-bind="text: model().brand" class="textValues"></span>
        </div>
        <div>
            <span>Model: </span><span data-bind="text: model().name" class="textValues"></span>
        </div>
        <div>
            <span>Price: </span><span data-bind="text: $root.formatCurrency(salePrice())" class="textValues"></span>
        </div>
        <div>
            <span>Rating: </span><span data-bind="starRating: rating"></span>
        </div>
    </div>
</script>

CSS

body {padding : 10px; }
body, input, select {font: 14px 'Segoe UI', 'SansationRegular', Arial, sans-serif;}
.page {    
}
.showroom {
}
.header 
{
    margin-bottom: 20px;
}
span {
    /*font: 12px 'SansationRegular', 'Segoe UI', Arial, sans-serif;*/
    margin: 0 4px 0 4px;
    color: black;
}
/*
ul li span { 
        float: left;
        width: 40px;
}
*/
.leftFloat {
    float: left;
}
.rightFloat {
    float: right;
}
.alignedCaption {
        float: left;
        width: 40px;
}
/*.text*/
.textValues {
    margin: 0 4px 0 4px;
    color: rgb(47, 123, 163);
}
.caption {
    /*font: 12px 'SansationBold', 'Segoe UI', Arial, sans-serif;*/
    font-weight: bold;
    color: navy;
}
.notes {
    /*font: 12px 'SansationLight', 'Segoe UI', Arial, sans-serif;*/
    color: black;
}
input, select {
    /*font: 12px 'SansationRegular', 'Segoe UI', Arial, sans-serif;*/
    margin: 0 4px 0 4px;
    clear: left;
    color: rgb(47, 123, 163);
}
input[type=text] {
    width: 100px;
}
.integerInput {
    width: 25px;
}
.currencyInput {
    width: 50px;
}
select {
    width: 150px;
}
.productsSelect {
    width: 550px;
}
.negative {
    color: red;
}
.positive {
    color: green;
}
table {
    margin: 8px;
    border-spacing: 0;
}
thead {
    font: 14px 'Segoe UI', 'SansationBold', Arial, sans-serif;
    font-weight: bold;
}
td {
    padding: 8px 0 8px 0;
    border-bottom: 1px solid lightgray;
}
.smallList {
    margin: 0px;
    padding-left: 0em;
    height: 280px;
    width: 240px;
    /*border: gray solid thin;
    overflow:scroll;
    overflow-x: hidden;*/
}
.selectable {
    list-style: none;
    width: 60px;
    height: 60px;
    text-align: center;
    line-height: 30px;
    padding: 4px;
    margin: 4px;
    float: left;
    -o-text-overflow: ellipsis; /* Opera */
    text-overflow: ellipsis; /* IE, Safari (WebKit) */
    overflow: hidden; /* don't show excess chars */
    list-style: none;
    -moz-border-radius: 20px;
    -webkit-border-radius: 20px;
   ...

JavaScript

var my = my || {}; //my namespace

my.dataservice = (function(my) {
    "use strict";
    var getProducts = function() {
        return my.sampleData;
    };
    return {
        getProduct: getProducts
    };
})(my);

my.sampleData = (function(my) {
    "use strict";
    var data = {
        Products: [
            {
            "ModelId": 1,
            "SalePrice": 1649.01,
            "ListPrice": 2199.00,
            "Rating": 5,
            "Photo": "[7].314ce.jpg",
            "CategoryId": 1,
            "ItemNumber": "T314CE",
            "Description": "Taylor 314-CE Left-Handed Grand Auditorium Acoustic-Electric Guitar",
            "Reviews": [{
                "ProductId": 4,
                "ReviewerName": "guitarhero",
                "Description": "This guitar has never let me down. I gig 3-6 nights a week and the 314CE just keeps on ticking. Change the battery and the strings regularly and she sounds like a dream everytime. If you want great sound, playability, dependability and just great playing fun get this guitar. You won\u0027t be sorry.",
                "ReviewDate": "\/Date(1302181440000)\/",
                "Id": 3},
            {
                "ProductId": 4,
                "ReviewerName": "billyjack",
                "Description": "Best guitar ever!",
                "ReviewDate": "\/Date(1302218040000)\/",
                "Id": 4}],
            "Model": {
                "Name": "314ce",
                "Brand": "Taylor",
                "Id": 1
            },
            "Category": {
                "Name": "Acoustic Guitars",
                "Id": 1
            },
            "Id": 4},
        {
            "ModelId": 3,
            "SalePrice": 4775.00,
            "ListPrice": 7199.00,
            "Rating": 5,
            "Photo": "814ce_tobacco_sunburst.jpg",
            "CategoryId": 1,
            "ItemNumber": "T814CE",
            "Description": "Taylor 814-CE Acoustic Electric Guitar in Tobacco Sunburst",
           ...