learn.knockoutjs.com - single page applications

http://learn.knockoutjs.com/#/?tutorial=webmail

by gurkavcu

HTML

<script src="http://learn.knockoutjs.com/Scripts/Lib/jquery.tmpl.js"></script>
<script src="http://learn.knockoutjs.com/Scripts/Lib/jquery.address.js"></script>
<script src="http://learn.knockoutjs.com/Scripts/Lib/knockout-1.3.0.latest.js"></script>
<link rel="stylesheet" href="http://learn.knockoutjs.com/Content/App/coderunner.css">
<script src="http://learn.knockoutjs.com/scripts/lib/knockout.address.js"></script>
<link rel="stylesheet" href="http://learn.knockoutjs.com/Content/TutorialSpecific/webmail.css">
<body>
    <!-- Folders -->
    <ul class="folders" data-bind="template: { name: 'folderTemplate', foreach: folders }"></ul>
    <script type="text/html" id="folderTemplate">
        <li data-bind="css: { selected: $data == mailViewModel.selectedFolder() },
        click: function() { mailViewModel.selectFolder($data) }">
            ${$data}
        </li>    
    </script>
    
    <!-- Mails grid -->
    <table class="mails" data-bind="visible: !selectedMail()">
        <thead><tr><th>From</th><th>To</th><th>Subject</th><th>Date</th></tr></thead>
        <tbody data-bind="template: { name: 'mailsGridRow', foreach: currentPageMails }"></tbody>
    </table>
    <script type="text/html" id="mailsGridRow">
        <tr data-bind="click: function() { mailViewModel.selectedMailId(id) }">
            <td>${from}</td>
            <td>${to}</td>
            <td>${subject}</td>
            <td>${date}</td>
        </tr>      
    </script>
    
    <!-- Selected mail -->
    <div class="viewMail" data-bind="template: { name: 'mailTemplate', data: selectedMail }"></div>
    <script type="text/html" id="mailTemplate">    
        <div class="mailInfo">
            <h1>${subject}</h1>
            <p><label>From</label>: ${from}</p>
            <p><label>To</label>: ${to}</p>
            <p><label>Date</label>: ${date}</p>
        </div>
        <p class="message" data-bind="html: messageContent" />
    </script>
</body>

JavaScript

$(function() {
    var viewModel = {
        // Data
        folders: ['Inbox', 'Archive', 'Sent', 'Spam'],
        selectedFolder: ko.observable('Inbox'),
        selectedMailId: ko.observable(),
        currentPageMails: ko.observableArray([]),
    
        // Behaviours
        selectFolder: function(folder) {
            this.selectedMailId(null);
            this.selectedFolder(folder);
        }
    };
        
    viewModel.selectedMail = ko.dependentObservable(function() {
        var mailIdToFind = this.selectedMailId();
        return ko.utils.arrayFirst(viewModel.currentPageMails(), function(item) {
            return item.id == mailIdToFind
        });
    }, viewModel);
    
    window.mailViewModel = viewModel;
    ko.applyBindings(viewModel);
    
    ko.linkObservableToUrl(viewModel.selectedFolder, "folder" /* hash param name */ , "Inbox" /* default value */ );
    ko.linkObservableToUrl(viewModel.selectedMailId, "mailId" /* hash param name */ );
    
    ko.dependentObservable(function() {
        if (this.lastMailRequest) this.lastMailRequest.abort(); // Prevent concurrent requests
        // Get folder data from JSON web service and feed output into currentPageMails
        //this.lastMailRequest = $.get("/mail/foldercontents", {
        //    folder: this.selectedFolder()
        //}, this.currentPageMails);
        this.lastMailRequest = $.ajax({
            type: 'POST',
            url: '/echo/json/',
            data: {
                json: JSON.stringify({ folder: this.selectedFolder() }),
                delay: 0
            },
            context: this,
            success: function(data) {
                this.currentPageMails(fakeData[data.folder]);
            }
        });
        
    }, viewModel);
});







//Fake data for jsFiddle echo AJAX requests
var fakeData = {};

fakeData.Inbox = 
[{"id":1,"from":"Abbot \[email protected]\u003e","to":"[email protected]","date":"May 25, 2011","subject":"Booking confirmation...