nerdyworm

Building an App With Ember.js and Go - Part 2

We left off in part 1 with the ability to list some kittens in the application. Now we are going to add the ability to create new kittens.

Client

First we are going to need a new page to create our kitten from. Let’s add a create route and some navigation to the existing app.

public/js/app.js
1
2
3
App.Router.map(function() {
  this.route('create');
});

This maps a new url create to our app. When the user visits that url Ember.js will automatically render the create template in the application template’s outlet.

public/index.html
1
2
3
4
5
6
7
8
9
<script type="text/x-handlebars">
<div class="container">
  <ul class="nav nav-tabs">
    <li>{{#linkTo index}}Index{{/linkTo}}</li>
    <li>{{#linkTo create}}Create{{/linkTo}}</li>
  </ul>
  {{outlet}}
</div>
</script>

Here we add two links to the top of the page. Ember will wire up proper page links for us when using the linkTo helper.

public/index.html
1
2
3
4
5
6
<script type="text/x-handlebars" data-template-name="create">
<form {{action save on="submit"}} class="form-inline">
  {{input type="text" value=name}}
  <button type="submit" class="btn btn-primary">Save</button>
</form>
</script>

For our create view let’s use a simple form that when submitted it will trigger the save action in a controller.

Using the input helper we create a text field and bind it to the controller’s name property.

public/js/app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
App.CreateController = Ember.Controller.extend({
  name: null,
  save: function() {
    var kitten = App.Kitten.createRecord({
      name: this.get('name')
    });

    kitten.save().then(function() {
      this.transitionToRoute('index');
      this.set('name', '');
    }.bind(this));
  }
});

The CreateController contains the name property and a save function. The name property is bound to the text box in the create view.

The save function will be called once the user submits the form.

To create a new kitten record on the client side we use createRecord.

Ember Data’s save function returns a promise. This promise is resolved when the server responses successfully. When that happens we want to transition to our list of kittens and empty out clear out the fields input.

Server Side

server.go
1
2
3
4
5
6
7
8
9
type Kitten struct {
    Id      int    `json:"id"`
    Name    string `json:"name"`
    Picture string `json:"picture"`
}

type KittenJSON struct {
    Kitten Kitten `json:"kitten"`
}

We need to declare two new types for our server side kittens. The first Kitten is a simple struct that has our three fields: id, name, and picture.

The second structure serves as our external data structure. Ember Data expects single Kittens to be wrapped in a named json object. For example:

single kitten response
1
{ "kitten": { "id": 1, "name": "Ben" } }

Ember will also send Kittens to the server wrapped in this style request.

server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func CreateKittenHandler(w http.ResponseWriter, r *http.Request) {
    // Parse the incoming kitten from the request body
    var kittenJSON KittenJSON
    err := json.NewDecoder(r.Body).Decode(&kittenJSON)
    if err != nil {
        panic(err)
    }

    // Grab the kitten and set some dummy data
    kitten := kittenJSON.Kitten
    kitten.Id = 5
    kitten.Picture = "http://placekitten.com/300/200"

    // Serialize the modified kitten to JSON
    j, err := json.Marshal(KittenJSON{Kitten: kitten})
    if err != nil {
        panic(err)
    }

    // Write the response
    w.Header().Set("Content-Type", "application/json")
    w.Write(j)
}

To create a kitten we need to define a function that will handle the route.

In order to gain access to the incoming json request from Ember Data we need to decode the request’s body. To do this we use a json.Decoder. We new up a decoder and decode the payload into an instance of KittenJSON. The decoder will populate all the data for us according to the struct’s definition.

Because we want to get this example up and running as quickly as possible I am just manually setting an Id and Picture. The Name property will be set from the incoming json.

We then need to return a response to the client so we serialize our kitten back into a KittenJSON type and write it to the response writer.

server.go
1
2
3
4
func main() {
  // ... omited rest of function
  r.HandleFunc("/api/kittens", CreateKittenHandler).Methods("POST")
}

We need to tell the server when to create a kitten. The create behavior for Ember Data is a POST to the index end point. The Gorilla Mux makes this easy by allowing us to specify the method.

All the wiring complete

All the wiring for this evolution of the app is now complete. We can click the create link, fill out the form, and show the user that we created a kitten.

In Memory Storage

Now the we can create kittens let’s rig up an in memory store to make the application feel slightly more complete.

server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
var kittens []Kitten

func CreateKittenHandler(w http.ResponseWriter, r *http.Request) {
    // ...

    kitten := kittenJSON.Kitten
    kitten.Id = len(kittens) + 1
    kitten.Picture = "http://placekitten.com/300/200"

    kittens = append(kittens, kitten)

    // ...
}

We first declare a new slice of kittens. This variable will exist as long as the server is running. Not production ready but it moves our app forward.

To add a new kitten we just append it to the current list of kittens. We also calculate the id of the kitten to be the length of the slice plus one.

server.go
1
2
3
4
5
6
7
8
9
10
11
12
type KittensJSON struct {
    Kittens []Kitten `json:"kittens"`
}

func KittensHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    j, err := json.Marshal(KittensJSON{Kittens: kittens})
    if err != nil {
        panic(err)
    }
    w.Write(j)
}

We can now make our index function dynamic.

Once again Ember Data expects a specific response structure. In this case it is the plural name of the model and an array. For example:

1
{ "kittens": [{"id": 1 ... }] }

Concludes part 2

We created some very simple in memory persistence on the server side. On the client side we demonstrated the typical create redirect work flow.

Next time we will handle delete and update.

Flowfeeds Presentation

I gave a talk about one of my projects to the local ember.js meetup. Honestly that was the absolutly scariest thing I have done in a long time :)

Building an App With Ember.js and Go - Part 1

Today we embark on a magical jounry of Gophers and Tomsters. In open source the projects with the cutest mascots always gain traction!

With the power of the internets cutest mascots combine we will create the most basic crud app to help you hit the ground running with Ember.js and Go.

Up and Running

The first part of any Ember project is to get the basic up and running. Since this is a super basic example we are just going to wire up a Go server to serve our static assets.

directoy layout
1
2
3
├── public
│   └── index.html
└── server.go
server.go
1
2
3
4
5
6
7
8
9
10
package main

import (
  "net/http"
)

func main() {
  http.Handle("/", http.FileServer(http.Dir("./public/")))
  http.ListenAndServe(":8080", nil)
}

We now have two files. An index.html file with hello world in it and a sever.go file that will serve statis assets out of the public directory.

To run this all you need to do is

1
go run server.go

You should be able to visit http://localhost:8080 and see hello world in your browser.

Personally I feel uneasy that we are not giving ourselves some feedback of what the program is doing so let’s add some logging.

server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main

import (
  "net/http"
  "log"
)

func main() {
  log.Println("Starting Server")
  http.Handle("/", http.FileServer(http.Dir("./public/")))

  log.Println("Listening on 8080")
  http.ListenAndServe(":8080", nil)
}

That makes me feel much better.

Setup Ember

Now that we have a basic http server we can setup our Ember environment.

I have included a script that will grab jQuery, Handlebars, and Ember for your. These are all the dependencies that you need to get the project up and running.

Relevant XKCD: Dependencies

script/js_deps.sh
1
2
3
4
5
6
7
8
9
10
#!/bin/bash

set -e

mkdir -p public/js/lib

wget -O public/js/lib/jquery.js http://code.jquery.com/jquery-2.0.0.js
wget -O public/js/lib/handlebars.js https://raw.github.com/wycats/handlebars.js/1.0.0-rc.4/dist/handlebars.js
wget -O public/js/lib/ember.js http://builds.emberjs.com.s3.amazonaws.com/ember-latest.js
wget -O public/js/lib/ember-data.js http://builds.emberjs.com.s3.amazonaws.com/ember-data-latest.js

Now that we have all our dependencies let’s wire them up in the index.html file.

public/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Ember.js + Go == ♥</title>
  <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet">
</head>
<body>
<script src="js/lib/jquery.js"></script>
<script src="js/lib/handlebars.js"></script>
<script src="js/lib/ember.js"></script>
<script src="js/lib/ember-data.js"></script>
</body>
</html>

All we needed to do is add a few script tags and a style sheet. The order of the tags is important since ember depends on handlebars and jQuery.

app.js
1
2
3
4
5
(function() {

  var App = Ember.Application.create();

})();

Now we can actually create our ember application. The canonical example name space is App, but you can use any name that you would like.

This line of code bootstraps your Ember application. It will automatically run once the page is loaded.

Don’t forget to include the new file in our index.html file after all the lib scripts.

1
<script src="js/app.js"></script>

When you view your application in the browser you should see the following output in your developer console. If you do not see this then something is broken. Make sure that all your files are loading correctly and that they are in the correct order.

1
2
3
4
5
DEBUG: -------------------------------
DEBUG: Ember.VERSION : 1.0.0-rc.3
DEBUG: Handlebars.VERSION : 1.0.0-rc.4
DEBUG: jQuery.VERSION : 2.0.0
DEBUG: -------------------------------

And last but not least we need to define our application template. This is easily accomplished by adding the following script tag to the index.html.

There are various ways of dealing with handlebars templates, but to avoid the complexities of build tools we are just going to use this method.

index.html
1
2
3
<script type="text/x-handlebars">
<h1>Hello Ember.js</h1>
</script>

When you open up the page in the browser you should see Hello Ember.js

RESTFull kittens

Let’s create our kittens endpoint.

First we are going use the super excellent Gorilla web toolkit’s mux for routing.

Install the dependency using the go get command.

1
go get github.com/gorilla/mux

The Gorilla mux provides a ton of wonderful functionality that we will take advantage of later. For now a simple GET endpoint is all we need to move this application forward.

server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package main

import (
  "net/http"
  "log"
  "github.com/gorilla/mux"
)

func KittensHandler(w http.ResponseWriter, r *http.Request) {
  w.Header().Set("Content-Type", "application/json")
  w.Write([]byte(`{"kittens": [
    {"id": 1, "name": "Bobby", "picture": "http://placekitten.com/200/200"},
    {"id": 2, "name": "Wally", "picture": "http://placekitten.com/200/200"},
  ]}`))
}

func main() {
  log.Println("Starting Server")

  r := mux.NewRouter()
  r.HandleFunc("/api/kittens", KittensHandler).Methods("GET")
  http.Handle("/api/", r)

  http.Handle("/", http.FileServer(http.Dir("./public/")))

  log.Println("Listening on 8080")
  http.ListenAndServe(":8080", nil)
}

I prefer to have my api endpoint under an /api name space. This is not a requirement, but a personal preference.

Ember Data expects a very particular response. You want to wrap a collection response with the plural of the model name. So in our case the root should be kittens and the value of kittens should be an array of kitten objects.

The spec for this is currently being fleshed out here: http://jsonapi.org/

Display the Kittens

Now that we have some data from the server we can display it in our Ember app.

public/js/app.js
1
2
3
4
5
6
DS.Store.create({
  revision: 12,
  adapter: DS.RESTAdapter.create({
    namespace: 'api'
  })
});

The first thing we need to do is create a data store. We also need to tell the store’s adapter that we want to namespace ajax calls under the api namespace.

public/js/app.js
1
2
3
4
App.Kitten = DS.Model.extend({
  name: DS.attr('string'),
  picture: DS.attr('string')
});

The next thing we can do is define our Kitten model. We extend a DS.Model and define the attributes name and picture.

public/js/app.js
1
2
3
4
5
App.IndexRoute = Ember.Route.extend({
  model: function() {
    return App.Kitten.find();
  }
});

Ember will automatically route to the index route of an application. We can alter the behavior of the index by defining an App.IndexRoute. This is where we can hook into the model function and return our kittens.

public/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<script type="text/x-handlebars">
<div class="container">
  {{outlet}}
</div>
</script>

<script type="text/x-handlebars" data-template-name="index">

<ul class="thumbnails">
{{#each controller}}

  <li class="span3">
    <div class="thumbnail">
      <img {{bindAttr src="picture"}}/>
      <div class="caption">
        <h3>{{name}}</h3>
      </div>
    </div>
  </li>

{{/each}}
</ul>

</script>

We modified the application template and added a new index template.

The application template now has an outlet. This is where ember will insert the index template or any other template defined by the current route.

In the index template we use the each helper to loop over all the kittens and output them with some basic markup.

In order to display the image we need to use the bindAttr helper. This will ensure that the src attribute is bound to the models picture property.

End of part 1

It took a bit of work to get this example up and running, but things assuming you were able to follow along you should have a fully integrated ember.js app with a go back end.

In the next part we will focus on adding new pages and some editing.

Happy Embering and Gophering :)

Full Source

The full source code to this example can be found on my github account.

Sorting a Slice of Structs in Go

Sorting data in Go requires you to implement the sort.Interface. This interface requires three simple methods: Len, Less, and Swap.

1
2
// returns the number of elements in the collection.
Len() int
1
2
3
// returns whether the element with index i should sort before
// the element with index j.
Less(i, j int) bool
1
2
// swaps the elements with indexes i and j.
Swap(i, j int)`

Define the Struct and Collection

1
2
3
4
5
type Country struct {
    Name string
}

type Countries []Country

First we declare our struct. For this example we are using only a single field which is a string. We also need to define our collection type so that we can satisfy the sort.Interface.

Implement the Interface

1
2
3
4
5
6
7
8
9
10
11
func (slice Countries) Len() int {
    return len(slice)
}

func (slice Countries) Less(i, j int) bool {
    return slice[i].Name < slice[j].Name;
}

func (slice Countries) Swap(i, j int) {
    slice[i], slice[j] = slice[j], slice[i]
}

The first method Len needs to return how many elements are in our collection. The built-in len function will work beautifully for this.

The second method is where we need to figure out which element comes before. For this example we just do a basic string comparison which will give us an ascending alphabetical sort order. If we wanted to sort descending we could just flip the < operator to >.

The last method actually performs the work of shuffling elements around. Go’s multiple assignment makes it easy to swap the values without having to explicitly declare a temporary variable.

The Countries type now provides all the methods to satisfy the sort.Interface interface.

Sort All the Things

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func main() {
    countries := Countries{
        {Name: "United States"},
        {Name: "Bahamas"},
        {Name: "Japan"},
    }

    sort.Sort(countries)

    fmt.Println("\nSorted")
    for i, c := range countries {
        fmt.Println(i, c.Name)
    }
}

There you have it. A simple example of sorting a slice of structs in Go.

As always: Full Source

Ember.js and Middleman

Middleman one of my favorite ways to build single page web applications these days. It is a simple static site generator that uses Sprokets. It is a really wonderful way to develop small applications.

This post is going to walk you through the process of setting up all the dependencies of an Ember.js App.

There are some builders and gems floating around these days. For the most part they fall behind Ember.js development too quickly. This ends up meaning that you spend more fixing dependencies than you do developing your app.

1. Install the middleman gem

Terminal
1
gem install middleman

2. Generate a middleman application

Terminal
1
middleman new blog

3. Add handlebars templates to the Gemfile

Gemfile
1
2
3
4
source 'https://rubygems.org'

gem "middleman", "~>3.0.13"
gem "middleman-ember", github: "nerdyworm/middleman-ember"
Terminal
1
bundle install

4. Configure the handlebars templates gem

config.rb
1
2
3
MiddlemanEmber::HandlebarsTemplate.options = {
  template_path: "app/templates"
}

This line of code tells our template compiler to strip out the template path from our file names. So any file with the path app/templates/template.hbs will be converted to template correctly.

5. JavaScript Structure

1
2
3
4
5
6
7
8
9
10
11
source/javascripts
├── app
│   └── templates
│       └── application.hbs
├── app.js
├── vendor
│   ├── ember-data-latest.js
│   ├── ember-latest.js
│   ├── handlebars.js
│   └── jquery.js
└── vendor.js

This is the project layout that I prefer to use. All application code gets tucked away in the app directory and all external libraries gets tucked away in vendor.

Also note that I build these two files separately. This is because the vendor file changes much less frequently than the app.js file. This means that the browser only has to update the vendor.js when we change a dependency, not when we change a line of application code.

6. Grab Dependencies

1
2
3
4
wget -O source/javascripts/vendor/jquery.js http://code.jquery.com/jquery-2.0.0.js
wget -O source/javascripts/vendor/handlebars.js http://builds.emberjs.com.s3.amazonaws.com/handlebars-1.0.0-rc.3.js
wget -O source/javascripts/vendor/ember-latest.js http://builds.emberjs.com.s3.amazonaws.com/ember-latest.js
wget -O source/javascripts/vendor/ember-data-latest.js http://builds.emberjs.com.s3.amazonaws.com/ember-data-latest.js

These four commands will get you the latest and greatest builds of Ember.js.

I personally like to work off the master branch. Bugs are getting fixed quickly these days, so it pays to be up to date.

7. Setup app.js and vendor.js

source/javascripts/app.js
1
2
3
4
//= require_self
//= require_tree ./app/

App = Ember.Application.create();

The require comments are part of sprokets. require_self includes the current file. require_tree includes all the files alphabetically in the directory specified.

source/javascripts/vendor.js
1
2
3
4
5
//= require ./vendor/jquery
//= require ./vendor/handlebars
//= require ./vendor/ember-latest
//= require ./vendor/ember-data-latest
//= require_tree ./vendor/

The vendor code needs to be loaded in a specific order.

8. Update layout.html.erb

source/layouts/layout.erb
1
<%= javascript_include_tag  "vendor", "app" %>

We need to include our vendor.js and app.js on the web page. Middleman makes this pretty easy by providing the javascript_include_tag helper.

9. Clear out index.html.erb

Empty the contents of source/index.htm.erb

10. Handlebars template application.hbs

source/javascripts/app/templates/application.hbs
1
<h1>Hello Ember.js</h1>

You did it! Checkout your masterpiece

Terminal
1
bundle exec middleman server

If you followed all the steps then you should see Hello Ember.js when you view localhost:4567.

When Ember.js has a stable release I will gladly turn this into a more full featured middleman template.

Global Trance Grooves - 10 Year Anniversary

Every single month for the past ten years I have been looking forward to Global Trance Grooves.

For as long as I can remember I have been driving with the windows down or writing code while listening to the monthly show. It is one of my favorite rituals.

I have never been disappointed by the content on John’s show. He has honed the skill of picking the best DJs and producers to highlight and promote. It is not his raw talent that makes this show incredible, it is his tenacious desire to spread the music he loves.

When I talk about trance music, John 00 Flemming is what I am referring to. The style he promotes represents the sound that I love. Deep, dark, and hypnotic.

This April marked the 10 year anniversary of Global Trance Grooves. John celebrated by putting together an absolutely stunning line up of artists.

If you missed the live broadcast you can download all the sets on soundcloud. Also I have included the link for John’s 2010 essential mix. It is a favorite of mine.

I’m really looking forward to another ten years.

Thanks John.

Ember.js Drag and Drop Sorting With jQuery Sortable

Source Code

Drag and drop with ember.js and jQuery sortable is actually pretty easy. However there are a few tricks that I would like to share.

View and Template

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
App.IndexView = Ember.View.extend({
  didInsertElement: function() {
    var controller = this.get('controller');
    this.$(".sortable").sortable({
      update: function(event, ui) {
        var indexes = {};

        $(this).find('.item').each(function(index) {
          indexes[$(this).data('id')] = index;
        });

        $(this).sortable('cancel');

        controller.updateSortOrder(indexes);
      }
    });
  }
});
1
2
3
4
5
6
7
8
<!-- note, I am only using single {} because octopress eats handlebars tags -->
<ul class="sortable">
{#each item in controller}
  <li class="item" data-id="{unbound item.id}">
    <b>{item.idx}</b> {item.id}
  </li>
{/each}
</ul>

In order to bind the sortable plug-in to the DOM we use the didInsertElement function. This function is called when the view’s element is in the DOM and ready to be manipulated.

We call sortable on the list view that has the CSS class .sortable. This will bind jQuery UI’s sortable plug-in to our DOM element.

The only function we have to implement is the update function. This function is called when the sortable plug-in has finished sorting and the DOM is updated.

What we want to do in the update method is create an index of model ids with their new sort position. We can accomplish that by looping over the items in the list, grabbing the data-id and assigning it the value of the index.

Once we have created an index we need to cancel the sort. This is because we are going to update the model to reflect the new sort order.

Update Models

1
2
3
4
5
6
7
8
9
10
App.IndexController = Ember.ArrayController.extend({
  sortProperties: ['idx'],

  updateSortOrder: function(indexes) {
    this.forEach(function(item) {
      var index = indexes[item.get('id')];
      item.set('idx', index);
    }, this);
  }
});

We can simply loop over the items in the array and update their idx. This will cause the list view to rerender with the correct sort order.

Fin

I hope this saves you some hair pulling and a bit of time.

You can see this in action in the playlist section at flowfeeds.com. You will need to sign up for an account to access it though, sorry.

Source Code Link

Source Code

Why I Do Not Php

I was asked the question about why programmers dislike certain languages and frameworks. The question was made after I was finished talking about local opportunities to a new a friend. My comment was that “I would apply to work there, but they are a PHP shop.”

PHP is self is not bad, nor are the things that any skilled programmer can build with it. In fact it is a wonderful tool. It is designed to fit a majority of the web out there. It is battle hardened and delivers on customer value.

The real problem is that as a programmer it is my job to keep my tools sharp, fresh, and organized. Exactly like a chef will maintain their knives and cookbooks.

This entire blog is filled up with code that I have not been paid to write. It is this kind of effort that I am willing to do to maintain and improve my skill set.

Keeping your skill level up as a programmer is a free time endeavor. It is an incredibly rare position where you can freely invest time on the job to learn and fail. If you have one of these mythical super awesome jobs, please do contact me :)

It is that fact is why PHP is not in my skill set. It is not a tool that I am willing to invest my personal time to grow and maintain.

Back to my pretentious sounding comment that started this post. I would have absolutely zero issue working for a shop where php was the primary language.

It would have to be such an incredible opportunity that I am willing to invest 100% of my free time into keeping that skill honed. I’m pretty sure the only opportunity on the planet that meets those requirements is Facebook, with a 6 figure starting salary, and an incredible team.

Even so, I would still give up a chunk of my salary to work with tools that I love.

Ember Modal Example

Modal views seem to be a source of pain in the ember world. Not all applications treat a modal state the same. Some applications consider a modal a new route, others treat it as a non routed state.

For most crud modals I prefer to have them not route based. This is due to the fact that modal edit/create dialogs tend to be a shorter version of the form than their routed counter parts.

Generally this is my short list of requirements for modals.

  1. Server must acknowledge success or failure before the modal can close
  2. Animate open and close

These are the genral requirements that I deal with all the time. Things like jquery ui modals and bootstrap modals are wonderful for most things, but as soon as your need to control the life cycle or change the close triggers they become overly complex.

After all a modal is just a div with a backdrop, it is not rocket surgery.

Let’s dive into how to make this happen with ember.

application_route.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
App.ApplicationRoute = Em.Route.extend({
  events: {
    openModal: function(modal) {
      this.render(modal, {
        into: 'application',
        outlet: 'modal'
      });
    },

    closeModal: function() {
      App.animateModalClose().then(function() {
        this.render('empty', {
          into: 'application',
          outlet: 'modal'
        });
      }.bind(this));
    }
  }
});

We can start by defining how we want to open and close our modal. The openModal function takes the name of a modal view i.e. widgets.modal and renders it into the application’s outlet named modal.

The closeModal function uses a application wide function App.animateModalClose() which returns a promise that is resolved when the modal is finished animating. Then we simply remove the modal from the outlet by rendering an empty template into the outlet.

How do we actually use this?

widgets_route.js
1
2
3
4
5
6
7
8
App.WidgetsRoute = Em.Route.extend({
  events: {
    edit: function(widget) {
      this.controllerFor('widgets.modal').edit(widget);
      this.send('openModal', 'widgets.modal');
    }
  }
});
widgets_modal_controller.js
1
2
3
4
5
6
7
8
9
10
11
12
13
App.WidgetsModalController = Em.ObjectController.extend({
  edit: function(record) {
    record.on('didUpdate', this, function() {
      this.send('closeModal');
    });

    this.set('model', record);
  },

  save: function() {
    this.get('model.transaction').commit();
  }
});

The edit event will be triggered from a handlebars template with a widget argument.

The WidgetsModalController#edit function takes a record and listens for the didUpdate model life cycle event. This event is triggered once the server acknowledges the model was updated. Then we send the closeModal event which will be handled by the ApplicationRoute.

When we send the openModal event the ApplictionRoute will handle the event. Ember will then render the widgets.modal template with the WigetsModelController.

Overall I do like the design of the modal controller. It only knows about the model’s life cycle and that there is something in the application that will handle the closeModal event. This seems like just enough responsibility for a controller to have. A parallel would be a rails controller that updates a modal and sets the flash message.

Animating Open and Close

modal_view.js
1
2
3
4
5
6
7
8
9
App.ModalView = Em.View.extend({
  // the yeild is missing a pair of { }.
  // octpress likes to interpret them as liquid tags :(
  layout: Em.Handlebars.compile("{yield}<div class=modal-backdrop></div>"),

  didInsertElement: function() {
    App.animateModalOpen();
  }
});

This the basic modal view. All it does is set up a layout with the modal backdrop and call our animation method once the element is inserted into the dom.

modal_animation.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
App.animateModalClose = function() {
  var promise = new Ember.RSVP.Promise();

  $('.modal.in').removeClass('in');
  $('.modal-backdrop.in').removeClass('in');

  setTimeout(function() {
    promise.resolve();
  }, App.DEFAULT_CSS_TRANSITION_DURATION_MS);

  return promise;
};

App.animateModalOpen = function() {
  var promise = new Ember.RSVP.Promise();

  $('.modal').addClass('in');
  $('.modal-backdrop').addClass('in');

  setTimeout(function() {
    promise.resolve();
  }, App.DEFAULT_CSS_TRANSITION_DURATION_MS);

  return promise;
};

The animation methods should be asynchronous. To make sure that we know when the modal is done animating we simply resolve a promise after some predefined duration. We could also do the animation via jQuery and not have to change the external interface.

fin

This is one way of handling modal views.

Ember gives you a lot of options. Your going to have to pick the ones that work best for your application.

How are you handling modals in your applications? Can you share a complete example? <3

Programmer’s Headphones

My current set of headphones are a pair of Beyerdynamic DT-880 Pro.

I have been using this set of headphones every single day for around six months. So far the only thing to show any sign of wear are the pillow like velour ear cushions.

The more I use these headphones the more comfortable they become. When I first slipped them on they were a very tight. To solve this problem I left them on a one gallon water jug over night for a week. This loosened up the headphones enough to be comfortable and still fit well.

Overall the sound quality is superb. Which can be unfortunate at times since the majority of my incoming music is 128k mp3s. I quickly noticed how bad some of my favorite tracks sounded.

The output of these headphones is calibrated towards the low end. This is exactly what I was looking for in a set of headphones. They do not artificially amplify the low end frequencies, but rather highlight them in a pleasant way. If your looking for super bass thumpy headphones keep looking, these are not for you.

One very important note: not for the office. The open back design leaks sound so you will annoy your coworkers quickly.

I have not found an overwhelming reason to go out and buy an external amplifier for these cans yet. My MacBook pro powers them quite well. However I mostly listen to electronic music these days so YMMV. If I ever get the chance to borrow one I will certainly follow up on this note.

Headphones are a very important part of my life. I spend a lot of time thinking and coding in the flow of a long trance set. I am very happy with this set. They are comfortable, sound wonderful, and well designed. If these break for any reason what so ever, I would not hesitate to purchase them again.