Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
The Rendering Revolution: Running Apps in the B...
Search
Trek Glowacki
October 24, 2013
Technology
2
420
The Rendering Revolution: Running Apps in the Browser with Ember.js
Trek Glowacki
October 24, 2013
Tweet
Share
More Decks by Trek Glowacki
See All by Trek Glowacki
Documents are not the web
trek
1
200
Beyond Front-end Developer
trek
1
460
UI Patterns and Reuse ~ or ~ Why I Hope We Never Need an Ember.js Widget Library
trek
10
5.9k
applications: a series of states
trek
19
2k
Cargo Cults
trek
0
310
Other Decks in Technology
See All in Technology
ついに出た!OpenAIの最新モデル「o1」って何がすごいの?
minorun365
PRO
3
1.2k
開発者の定量・定性データを組み合わせて開発者体験を把握するための取り組み
ham0215
1
140
Privacy Sandbox on Android / DroidKaigi 2024
7pairs
1
270
『GRANBLUE FANTASY Relink』キャラクターの魅力を支えるリグ・シミュレーション制作事例
cygames
0
120
再考 アクターモデル/ reconsider actor model
ytake
0
360
株式会社EventHub・エンジニア採用資料
eventhub
0
3k
JTCや セキュリティチェックリストが夢の跡
nikinusu
1
710
Creative UIs with Compose: DroidKaigi 2024
chrishorner
1
590
フルカイテン株式会社 採用資料
fullkaiten
0
32k
2024年のナビゲーション・フォーカス対応:Composeでキーボード・ナビゲーションをサポートしよう
tahia910
0
110
PDF Viewer作成の今までとこれから
hunachi
0
480
不動産tech Product Night#2_AIことはじめ_GA橋本
takehikohashimoto
0
190
Featured
See All Featured
What’s in a name? Adding method to the madness
productmarketing
PRO
21
3k
Ruby is Unlike a Banana
tanoku
96
11k
Thoughts on Productivity
jonyablonski
66
4.2k
The Power of CSS Pseudo Elements
geoffreycrofte
71
5.3k
A Modern Web Designer's Workflow
chriscoyier
692
190k
Teambox: Starting and Learning
jrom
131
8.7k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
25
3.9k
Why You Should Never Use an ORM
jnunemaker
PRO
53
8.9k
Atom: Resistance is Futile
akmur
261
25k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
28
1.6k
Optimising Largest Contentful Paint
csswizardry
31
2.8k
Optimizing for Happiness
mojombo
375
69k
Transcript
@trek
None
None
None
IE 5 IE 8 IE 7
None
None
None
None
None
None
None
None
None
2003 2005 2009
None
None
None
None
None
None
Why?
None
None
None
None
None
None
None
screen rendering display screen state AFK behavior persistence
screen rendering display screen state AFK behavior persistence client server
screen rendering display screen state AFK behavior persistence client server
APIs Node, Rails
APIs
screen rendering display screen state AFK behavior persistence client server
screen rendering display screen state AFK behavior persistence client server
None
Mobile Cocoa Touch Android SDK Desktop Cocoa .NET Web ?
Mobile Cocoa Touch Android SDK Desktop Cocoa .NET Web
None
None
Router Route Controller View/Template Model/Data
Router Route Controller View/Template Model/Data what is the current context?
how does this encode to a URL?
Router Route Controller View/Template Model/Data What data should I fetch?
What template should I show?
Router Route Controller View/Template Model/Data how do I translate user
interaction in this context into intent (e.g. a "click" into "show me more")? how do I present the data for this context?
Router Route Controller View/Template Model/Data how do I paint to
the screen?
Router Route Controller View/Template Model/Data what is the structure of
my data
Router Route Controller View/Template Model/Data
App = Ember.Application.create(); <!-- application.hbs --> <h1>Welcome to Ember.js</h1> Router
Route Controller View/Template Model/Data
None
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav> <!-- favorites.hbs --> <h2>Favorites<h2> <ul> <li>...</li> <li>...</li> </ul> <!-- about.hbs --> <h2>About<h2>
None
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav> <!-- favorites.hbs --> <h2>Favorites<h2> <ul> <li>...</li> <li>...</li> </ul> <!-- about.hbs --> <h2>About<h2>
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); App.AboutRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: '/api/currentUser/profile' }); } });
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); App.AboutRoute = Ember.Route.extend({ model: function(){ var self = this; $('#a-loader).show(); $.ajax({ url: '/api/currentUser/profile', success: function(response){ $('#a-loader).hide(); self.renderWithSomeData(response); } }); } });
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); App.AboutRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: '/api/currentUser/profile' }); } }); { name: 'trek', bio: 'Much shorter than you expect' }
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- favorites.hbs --> <h2>Favorites<h2> <ul> <li>...</li> <li>...</li> </ul> <!-- about.hbs --> <h2>About<h2> <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav>
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- favorites.hbs --> <h2>Favorites<h2> <ul> <li>...</li> <li>...</li> </ul> <!-- about.hbs --> <h1>About<h1> <h2>{{name}}<h2> <div class='bio'> {{bio}} </div> <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav>
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); App.FavoritesRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: '/api/currentUser/favorites' }); } }); [ {"id": 1, "title": "Hoverbike Captains of the SS"}, {"id": 2, "title": "The Terrifying Madness That Lies Beyond"} ]
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- favorites.hbs --> <h2>Favorites<h2> <ul> <li>...</li> <li>...</li> </ul> <!-- about.hbs --> <h1>About<h1> <h2>{{name}}<h2> <div class='bio'> {{bio}} </div> <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav>
App = Ember.Application.create(); App.Router.map(function(){ this.route("about"); this.route("favorites", { path: "/favs" });
}); <!-- favorites.hbs --> <h2>Favorites<h2> <ul> {{#each}} <li> {{title}} </li> {{/each}} </ul> <!-- about.hbs --> <h1>About<h1> <h2>{{name}}<h2> <div class='bio'> {{bio}} </div> <!-- application.hbs --> <h1>Welcome to Ember.js</h1> <nav> {{#link-to 'about'}}About{{/link-to}} {{#link-to 'favorites'}}Favorites{{/link-to}} {{outlet}}<!-- filled with child template when you navigate into route --> </nav>
None
None
None
var Rdio = Ember.Application.create(); Rdio.Router.map(function(){}); Rdio.ApplicationRoute = Ember.Route.extend({ model: function(){
return $.ajax({ url: "/api/authenticate" }) } }); <!-- application.hbs --> {{outlet}} <!-- loading.hbs --> <div class="loading-container"> <span class="icon-loading spinner"/> </div>
None
{ username: 'trek', messageCount: 4, playlists: [ {id: 981, title:
"Everyday I'm shufflin'"}, {id: 191, title: "RUNNIN"} ] }
None
<div class='navigation'> <ul> <h3>Browse</h3> <li>{{#link-to "heavyRotation"}}Heavy Rotation{{/link-to}}</li> <li>{{#link-to "recentActivity"}}Recent Activity{{/link-to}}</li>
<li>{{#link-to "topCharts"}}Top Charts{{/link-to}}</li> <li>{{#link-to "newReleases"}}New Releases{{/link-to}}</li> <li>{{#link-to "stations"}}Stations{{/link-to}}</li> </ul>
<ul> <h3>Playlists</h3> <ul> {{#each playlists}} {{#link-to "playlist" this}} {{name}} {{/link-to}}
{{/each}} </ul> </ul>
<ul> <h3>Playlists</h3> <ul> {{#each playlists}} {{#link-to "playlist" this}} {{name}} {{/link-to}}
{{/each}} </ul> </ul> { username: 'trek', messageCount: 4, playlists: [ {id: 981, title: "Everyday I'm shufflin'"}, {id: 191, title: "RUNNIN"} ] }
<div class='top-bar'> <ul> <li>{{#link-to "profile"}}{{username}}{{/link-to}}</li> <li>{{#link-to "alets"}}{{messageCount}}{{/link-to}}</li> </ul>
<div class='top-bar'> <ul> <li>{{#link-to "profile"}}{{username}}{{/link-to}}</li> <li>{{#link-to "alets"}}{{messageCount}}{{/link-to}}</li> </ul> { username:
'trek', messageCount: 4, playlists: [ {id: 981, title: " {id: 191, title: " ] }
{{outlet}}
None
None
var Rdio = Ember.Application.create(); Rdio.Router.map(function(){}); Rdio.ApplicationRoute = Ember.Route.extend({ model: function(){
return $.ajax({ url: "/api/authenticate" }) } });
var Rdio = Ember.Application.create(); Rdio.Router.map(function(){ this.route("heavyRotation") }); Rdio.ApplicationRoute = Ember.Route.extend({
model: function(){ return $.ajax({ url: "/api/authenticate" }) } }); Rdio.HeavyRotationRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: "/api/heavyRotation" }) } });
None
[ { title: "The Speed of Things", artistName: "Dale Earnhardt
Jr. Jr.", songsCount: 13, isExplicit: false, imageUrl: "/images/c10efa31.png" }, { title: "I Love You", artistName: "The Neighbourhood", songsCount: 11, isExplicit: true, imageUrl: "/images/9ec1ce1.png" } {...}, {...} ]
None
<!-- heavyRotation.hbs --> <h3>Heavy Rotation</h3> {{#each}} {{link-to "album" this}} <div
class="album-"> </div> {{title}} {{artistName}} {{songsCount}} songs {{#if isExplicit}} EXPLICIT {{/if}} {{/link-to}} {{/each}}
<!-- heavyRotation.hbs --> <h3>Heavy Rotation</h3> {{#each}} {{link-to "album" this}} <div
class="album-"> </div> {{title}} {{artistName}} {{songsCount}} songs {{#if isExplicit}} EXPLICIT {{/if}} {{/link-to}} {{/each}} [ { title: "I Love You", artistName: "The Neighbourhood", songsCount: 11, isExplicit: true, imageUrl: "/images/9ec1ce1.png" } ]
None
None
None
Rdio.Router.map(function(){ this.route("heavyRotation"); this.route("album", {path: "album/:album_id"}); }); Rdio.AlbumRoute = Ember.Route.extend({ model:
function(params){ return $.ajax({ url: "/api/album/" + params.album_id }); } })
None
{ title: "The Speed of Things", artistName: "Dale Earnhardt Jr.
Jr.", songsCount: 13, isExplicit: false, imageUrl: "/images/c10efa31.png", playCount: 32694, songs: [ {trackNumber: 1, title: "Beautiful Dream"}, {trackNumber: 2, title: "Run"} ] }
None
None
None
None
None
Rdio.Router.map(function(){ this.resource("artist", {path: "artist/:artist_id"}, function(){ this.route("albums", {path: '/'}); this.route("songs"); })
}); Rdio.ArtistRoute = Ember.Route.extend({ model: function(params){ return $.ajax({ url: "/api/artist/" + params.artist_id }); } }); Rdio.ArtistAlbumsRoute = Ember.Route.extend({ model: function(parmas, transition){ return $.ajax({ url: "/api/artist/" + transition.params.artist_id + "/albums" }); } });
Rdio.Router.map(function(){ this.resource("artist", {path: "artist/:artist_id"}, function(){ this.route("albums", {path: '/'}); this.route("songs"); })
}); Rdio.ArtistRoute = Ember.Route.extend({ model: function(params){ return $.ajax({ url: "/api/artist/" + params.artist_id }); } }); Rdio.ArtistSongsRoute = Ember.Route.extend({ model: function(parmas, transition){ return $.ajax({ url: "/api/artist/" + transition.params.artist_id + "/songs" }); } });
None
None
None
None
None
None
None
None
None
None
None
<!-- application.hbs --> {{outlet}} {{outlet "playbar"}}
<!-- application.hbs --> {{outlet}} {{outlet "playbar"}}
Rdio.ApplicationRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: "/api/authenticate" })
} });
Rdio.ApplicationRoute = Ember.Route.extend({ model: function(){ return $.ajax({ url: "/api/authenticate" })
}, renderTemplate: function(){ this._super(); this.render('playbar', { into: 'application', outlet: 'playbar' }); } });
None
None
{{#each tracks}} <ul> <li> {{trackNumber}} {{name}} </li> </ul> {{/each}}
{{#each tracks}} <ul> <li {{action "play" this}}> {{trackNumber}} {{name}} </li>
</ul> {{/each}}
current controller current route {{#each tracks}} <ul> <li {{action "play"
this}}> {{trackNumber}} {{name}} </li> </ul> {{/each}} parent route application route ...
Rdio.ApplicationRoute = Ember.Route.extend({ actions: { play: function(song){ this.controllerFor('playbar').send('play', song); }
} });
Rdio.ApplicationRoute = Ember.Route.extend({ actions: { play: function(song){ this.controllerFor('playbar').send('play', song); }
} }); Rdio.PlaybarController = Ember.Controller.extend({ actions: { play: function(song){ ... } } });
None