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
Flowfeeds
Search
Benjamin Rhodes
May 22, 2013
Programming
6
5.9k
Flowfeeds
Presentation about flowfeeds.com for the southern California ember.js group.
Benjamin Rhodes
May 22, 2013
Tweet
Share
Other Decks in Programming
See All in Programming
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
2
670
その面倒な作業、「Dart」にやらせませんか? Flutter開発者のための業務効率化
yordgenome03
1
140
Claude CodeによるAI駆動開発の実践 〜そこから見えてきたこれからのプログラミング〜
iriikeita
0
320
「ちょっと古いから」って避けてた技術書、今だからこそ読もう
mottyzzz
11
7.1k
monorepo の Go テストをはやくした〜い!~最小の依存解決への道のり~ / faster-testing-of-monorepos
convto
2
520
EMこそClaude Codeでコード調査しよう
shibayu36
0
330
One Enishi After Another
snoozer05
PRO
0
150
組込みだけじゃない!TinyGo で始める無料クラウド開発入門
otakakot
2
360
Flutterで分数(Fraction)を表示する方法
koukimiura
0
140
Range on Rails ―「多重範囲型」という新たな選択肢が、複雑ロジックを劇的にシンプルにしたワケ
rizap_tech
0
6.7k
CSC509 Lecture 06
javiergs
PRO
0
260
3年ぶりにコードを書いた元CTOが Claude Codeと30分でMVPを作った話
maikokojima
0
620
Featured
See All Featured
Statistics for Hackers
jakevdp
799
220k
Writing Fast Ruby
sferik
629
62k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.5k
Building Better People: How to give real-time feedback that sticks.
wjessup
369
20k
Documentation Writing (for coders)
carmenintech
75
5.1k
A designer walks into a library…
pauljervisheath
209
24k
Practical Orchestrator
shlominoach
190
11k
The Straight Up "How To Draw Better" Workshop
denniskardys
238
140k
Facilitating Awesome Meetings
lara
57
6.6k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Building a Modern Day E-commerce SEO Strategy
aleyda
44
7.8k
BBQ
matthewcrist
89
9.8k
Transcript
Wednesday, May 22, 13
Wednesday, May 22, 13
Why? • To Many RSS feeds :( • Video Playlists
• New music everyday Wednesday, May 22, 13
flowfeeds.com • Stack • Ember.js & Rails 4 • Features
• Audio & Video Player • Drag & Drop Sorting • Infinite Scroll Wednesday, May 22, 13
Audio & Video • Libraries • Video: YouTube JS API
• Audio: SoundManager2 Wednesday, May 22, 13
Flowfeeds.PlayableController = Ember.ObjectController.extend({ bytesLoaded: 0, bytesTotal: 0, duration: 0, isPlaying:
false, position: 0, setup: Ember.K, play: Ember.K, pause: Ember.K, jump: Ember.K, stop: Ember.K }); Wednesday, May 22, 13
Flowfeeds.VideoController = Flowfeeds.PlayableController.extend({ setup: function(model) { this.set('content', model); this.setupAndPlayVideo(); },
// implementation details }); Flowfeeds.AudioController = Flowfeeds.PlayableController.extend({ setup: function(model) { this.set('content', model); this.setupAndPlayAudio(); }, // implementation details }); Wednesday, May 22, 13
PlayerView Wednesday, May 22, 13
Model Attributes {{ artist.name }} {{ title }} <img {{
bindAttr src="thumb" }} /> Wednesday, May 22, 13
Time {{ formatTime position }} {{ formatTime duration }} Wednesday,
May 22, 13
Ember.Handlebars.registerBoundHelper('formatTime', function(ms) { var x = ms / 1000, seconds
= x % 60 >> 0, minutes = x / 60 % 60 >> 0, hours = x / 3600 % 60 >> 0; if(seconds < 10) seconds = "0" + seconds; if(minutes < 10) minutes = "0" + minutes; if(hours === 0) { hours = ""; } else { hours = hours + ":"; } return hours + minutes + ":" + seconds; }); Wednesday, May 22, 13
ProgressView {{ render 'progress' controller }} Wednesday, May 22, 13
progess.hbs <div class="bar loading" {{bindAttr style="view.loadingBarStyle"}}> <div class="bar progress" {{bindAttr
style="view.progressBarStyle"}}> Wednesday, May 22, 13
Flowfeeds.ProgressView = Ember.View.extend({ progressBarStyle: function() { return 'width: ' +
this.get('controller.percentComplete') + '%;'; }.property('controller.percentComplete'), loadingBarStyle: function() { return 'width: ' + this.get('controller.percentLoaded') + '%;'; }.property('controller.percentLoaded'), Wednesday, May 22, 13
Flowfeeds.ProgressController = Ember.ObjectController.extend percentComplete: function() { var duration = this.get('duration');
if(duration === 0) return 0; return 100 * (this.get('position') / duration); }.property('position', 'duration'), percentLoaded: function() { var total = this.get('bytesTotal'); if(total === 0) return 0; return 100 * (this.get('bytesLoaded') / total); }.property('bytesLoaded', 'bytesTotal') }); Wednesday, May 22, 13
Flowfeeds.ProgressView = Ember.View.extend({ click: function(event) { this.jumpEvent(event); }, jumpEvent: function(event)
{ var pos = this.getX(event) / this.$().width(); this.get('controller').send('jump', pos); }, getX: function(event) { return event.pageX - $(event.currentTarget).offset().left; }, Wednesday, May 22, 13
mouseDown: function(event) { event.preventDefault(); this.scrubbing = true; }, mouseMove: function(event)
{ if(this.scrubbing) this.jumpEvent(event); }, mouseUp: function() { this.scrubbing = false; }, mouseLeave: function() { this.scrubbing = false; }, Wednesday, May 22, 13
Play / Next / Prev <button {{action next}}> Wednesday, May
22, 13
Flowfeeds.ApplicationRoute = Ember.Route.extend({ events: { play: function(playable, controller) { this.skipable
= controller.get('target'); this.controllerFor('player').play(playable); }, previous: function() { if(this.skipable) this.skipable.send('previous'); }, next: function() { if(this.skipable) this.skipable.send('next'); }, Wednesday, May 22, 13
Wednesday, May 22, 13
Sortable Wednesday, May 22, 13
Sortable • Libraries: • jQuery UI Sortable Wednesday, May 22,
13
<div class="playables"> {{#each controller}} <div class="playable" {{bindAttr data-id="id"}}> </div> {{/each}}
</div> Wednesday, May 22, 13
Flowfeeds.SortablePlaylistView = Ember.View.extend({ didInsertElement: function() { var controller = this.get('controller');
$('.playables').sortable({ update: function(event, ui) { var indexes = {}; $(this).find('.playable').each(function(index) { indexes[$(this).data('id').toString()] = index; }); $(this).sortable('cancel'); controller.updateSortOrder(indexes); } }); } }); Wednesday, May 22, 13
FlowFeeds.ItemsController = Ember.ArrayController.extend({ sortProperties: ['idx'], updateSortOrder: function(indexes) { this.forEach(function(item) {
var index = indexes[item.get('id')]; item.set('idx', index); }); } }); Wednesday, May 22, 13
Infinite Scroll Wednesday, May 22, 13
{{#view Flowfeeds.InfiniteScrollView}} {{ render 'videos' model }} {{/view}} Wednesday, May
22, 13
Flowfeeds.InfiniteScrollView = Ember.View.extend({ elementId: 'infinite', layout: Ember.Handlebars.compile( "{{ yield }}{{
partial loader }}" ), didInsertElement: function() { var view = this; $('#main').on('scroll', function(){ if(view.isScrolledToBottom()) view.get('controller').send('more'); }); }, willDestroyElement: function() { $('#main').off('scroll'); } }); Wednesday, May 22, 13
Flowfeeds.FeedRoute = Ember.Route.extend({ events: { more: function() { this.modelFor('feed').loadNextPageOfTracks(); }
} }); Wednesday, May 22, 13
Overview • Inheritance • Helpers • Sliders • Sortable •
Infinite Scroll Wednesday, May 22, 13
Questions? • Source: • github.com/nerdyworm/flowfeeds • Contact •
[email protected]
Wednesday,
May 22, 13