Promise Routing

Demo of promise routing

by krisselden

HTML

<script src="http://cloud.github.com/downloads/wycats/handlebars.js/handlebars-1.0.0.beta.6.js"></script>
<script src="http://cloud.github.com/downloads/emberjs/ember.js/ember-latest.js"></script>
<script type="text/x-handlebars" data-template-name="application">
    <h1>Routing Test</h1>
    <p>Demo of promise routing problem if you don't add loading states along side nested routes.</p>
    <ol>
        <li>
            Click 'Show' for Demo.<br>
            Click 'Show' for Schedule.<br>
            Click 'Next Page' for Schedule.<br>
            Use browser back.
        </li>
        <li>
            Click 'Show' for Demo.<br>
            Click 'Show' for Schedule.<br>
            Click 'Show' for Breakfast.<br>
            Click 'Back To Page'.<br>
            Use browser back.
        </li>
    </ol>
    
    {{outlet}}
</script>

<script type="text/x-handlebars" data-template-name="yapps">
    <h2>Yapps:</h2>
    <ul>
    {{#each this}}
        <li>{{title}} <button {{action show this}}>Show</button></li>
    {{/each}}
    </ul>
</script>

<script type="text/x-handlebars" data-template-name="yapp">
    <button {{action back}}>Back To Home</button>
    <h2>Yapp: {{title}}</h2>
    <h3>Pages:</h3>
    <ul>
    {{#each pages}}
        <li>{{title}} <button {{action show this}}>Show</button></li>
    {{/each}}
    </ul>
</script>

<script type="text/x-handlebars" data-template-name="page">
    <button {{action back}}>Back To Yapp</button>
    {{#if hasNext}}
        <button {{action next}}>Next Page</button>
    {{/if}}
    <h2>Page: {{title}}</h2>
    <h3>Subpages:</h3>
    <ul>
    {{#each subpages}}
        <li>{{title}} <button {{action show this}}>Show</button></li>
    {{/each}}
    </ul>
</script>

<script type="text/x-handlebars" data-template-name="subpage">
    <button {{action back}}>Back To Page</button>
    <h2>Subpage: {{title}}</h2>
</script>

JavaScript

var USE_PROMISE = true;

function promise(model) {
    if (!model.then && USE_PROMISE) {
        var deferred = $.Deferred();
        setTimeout(function() {
            deferred.resolve(model);
        }, 100);
        return deferred.promise(model);
    } else {
        return model;
    }
}

App = Ember.Application.create({
    autoinit:false   
});

App.ApplicationController = Em.Controller.extend();
App.YappsController = Em.ArrayController.extend();
App.YappController = Em.ObjectController.extend();
App.PageController = Em.ObjectController.extend({
    yappController: null,
    hasNext: function() {
        return this.get('yappController.pages.length') > 1;
    }.property('yappController.pages.length'),
    next: function() {
        var pages = this.get('yappController.pages'),
            page = this.get('content'),
            index = pages.indexOf(page);
        if (index === -1) {
            return null;
        }
        if (index === pages.length - 1) {
            return pages[0];
        }
        return pages[index + 1];
    }.property('yappController.pages.[]', 'content')
});
App.SubpageController = Em.ObjectController.extend();

App.ApplicationView = Em.View.extend({
    templateName: 'application'
});
App.LoadingView = Em.View.extend({
    template: function() {
        return 'Loading…';
    }
});
App.YappsView = Em.View.extend({
    templateName: 'yapps'
});
App.YappView = Em.View.extend({
    templateName: 'yapp'
});
App.PageView = Em.View.extend({
    templateName: 'page'
});
App.SubpageView = Em.View.extend({
    templateName: 'subpage'
});

App.Yapp = Em.Object.extend();
App.Yapp.id = 1;
App.Yapp.store = {};
App.Yapp.findAll = function() {
    var store = App.Yapp.store, yapps = [], id;
    for (id in store) {
        if (store.hasOwnProperty(id)) {
            yapps.push(store[id]);
        }
    }
    return yapps;
};
App.Yapp.find = function(id) {
    return promise(App.Yapp.store[id]);
};

App.Page = Em.Object.extend();
App.Page.id =...