TomsterMail

The latest build of Ember.

by alexspeller

HTML

<script src="http://ember.alexspeller.com/handlebars-1.0.0.js"></script>
<script src="http://ember.alexspeller.com/ember-latest.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.1.0/moment.min.js"></script>
<script type="text/x-handlebars" data-template-name="application">
    <div class='url'>URL: {{target.url}}</div>
    <aside>
        
        <ul>
            <li><h2>Mailboxes</h2></li>
            {{#each}}
                <li>
                    {{#linkTo 'mailbox' this}}
                        <span class="count">
                            {{messages.length}}
                        </span>
                        {{name}}
                    {{/linkTo}}
                </li>
            {{/each}}
        </ul>
    </aside>
    
    <section class='main'>
        {{outlet}}
    </section>
</script>

<script type="text/x-handlebars" data-template-name="index">
    <section class="index">
        <h1>TomsterMail</h1>
        <span class='tomster'></span>    
    </section>
</script>


<script type="text/x-handlebars" data-template-name="mailbox">
    <table>
        <tr>
            <th>Date</th>
            <th>Subject</th>
            <th>From</th>
            <th>To</th>
        </tr>
            
        {{#each messages}}
            {{#linkTo 'mail' this tagName=tr}}
                <td>{{date date}}</td>
                <td>{{view.isActive}}{{subject}}</td>
                <td>{{from}}</td>
                <td>{{to}}</td>
            {{/linkTo}}
        {{/each}}
    </table>
    
    {{outlet}}

</script>

<script type="text/x-handlebars" data-template-name="mailbox/index">
    <section class="mailbox-index">
        Select an email        
    </section>
</script>

<script type="text/x-handlebars" data-template-name="mail">
    <section class="mail">
        <dl>
            <dt>From</dt>
            <dd>{{from}}</dd>
            <dt>To</dt>
            <dd>{{to}}</dd>
            <dt>Date</dt>
            <dd>{{date...

CSS

body {
    font-family: sans-serif;
    color: #333;
}

h1 {
    font-size: 2em;
    margin-bottom: 1em;
}

h2 {
    margin-bottom: 1em;
}

h4 {
    font-size: 1.5em;
    margin-bottom: 1em;
    font-weight: bold;
}

.loading {
    position: absolute;
    top: 50%;
    bottom: 50%;
    left: 50%;
    right: 50%;
    
    width: 100px;
    height: 50px;
    
    color: white;
    background-color: rgba(0,0,0,0.5);
    
    margin-left: -50px;
    margin-top: -25px;
    
    border-radius: 10px;
    text-align: center;
    line-height: 50px;
    
}

aside {
    float: left;
    background-color: #9cb5d1;
    width: 180px;
    height: 430px;
    border: 1px solid #ccc;
    border-right-color: #333;
}

aside h2 {
    text-transform: uppercase;
    font-size: 0.7em;
    font-weight: bold;
    letter-spacing: 0.2em;
    text-shadow: 1px 1px 0px #eee;
    padding: 15px;
    margin-bottom: 0;
}

aside a {
    color: #333;
    text-decoration: none;
    display: block;
    padding: 15px;
}

aside a.active {
    background: linear-gradient(to bottom, #7db9e8 0%,#267dc9 99%);
    color: white;
    text-shadow: 1px 1px 0px #666;
}

span.count {
    float: right;
    background-color: #505f71;
    color: white;
    padding: 0.5em 1em;
    border-radius: 40%;
    font-size: 0.6em;
    position: relative;
    top: -3px;
    font-weight: bold;
}

section.main {
    height: 430px;
    border: 1px solid #ccc;
    margin-left: 180px;
}

section .index {
    padding-top: 5em;
    text-align: center;
    height: 100%;
}

table {
    width: 99%;
    border-bottom: 1px solid #999;
    border-collapse: collapse;
}

td, th {
    padding: 0.5em;
}

th {
    font-weight: bold;
    font-size: 0.8em;
}

tr {
    border-bottom: 1px solid #ccc;
    cursor: pointer;
}

td a {
    text-decoration: none;
    color: #333;
}

tr.active {
    background: linear-gradient(to bottom, #7db9e8 0%,#267dc9 99%);
    color: white;
    text-shadow: 1px 1px 0px #666;
}

section .mailbox-index {
   ...

CoffeeScript

window.App = Ember.Application.create
  LOG_TRANSITIONS: true

#############
# Route Map #
#############

App.Router.map ->
  @resource 'mailbox', path: '/:id', ->
    @resource 'mail', path: '/:index'

#####################
# Route definitions #
#####################

App.ApplicationRoute = Em.Route.extend
  model: ->
    Mailbox.find()
    
App.MailboxRoute = Em.Route.extend
  model: (params) ->
    Mailbox.find params.id

  serialize: (mailbox) ->
    id: mailbox.id

App.MailRoute = Em.Route.extend
  model: (params) ->
    @modelFor('mailbox').messages[params.index]

  serialize: (mail) ->
    index: @modelFor('mailbox').messages.indexOf(mail)

# Just defining a route called LoadingRoute is enough to make ember
# enter this route when a promise is returned from any routes 'model'
# hook. The 'loading' template will be rendered in the application
# outlet with the LoadingView view #by default, although this can
# be overriden with the renderTemplate hook if desired
App.LoadingRoute = Em.Route.extend()

###########
# Helpers #
###########

# Register a date helper that formats dates using
# the moment.js library
Ember.Handlebars.registerBoundHelper 'date', (date) ->
  moment(date).format 'MMM Do'
  
#########
# Model #
#########

# this is just a basic filler for the model.
# Normally you would load data from the server using
# ajax or a library like Ember Data or Ember Model

Mailbox =
  find: (name) ->
    result = if name?
        Mailbox.DATA.findProperty 'id', name
    else
        Mailbox.DATA
    # Return a promise that resolves in 1 second
    # to simulate loading
    new Em.RSVP.Promise (resolve) ->
      Em.run.later @, resolve, result, 1000

Mailbox.DATA = [
    name: "Inbox"
    id: "inbox"
    messages: [
       subject: "Welcome to Ember"
       from: "[email protected]"
       to: "[email protected]"
       date: new Date()
       body: "Welcome to Ember. We hope you enjoy your stay"
    ,
       subject: "Great Ember Resources"
       from:...