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
AIで開発はどれくらい加速したのか?AIエージェントによるコード生成を、現場の評価と研究開発の評価の両面からdeep diveしてみる
daisuketakeda
1
2k
AIによる開発の民主化を支える コンテキスト管理のこれまでとこれから
mulyu
3
130
IFSによる形状設計/デモシーンの魅力 @ 慶應大学SFC
gam0022
1
300
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
190
0→1 フロントエンド開発 Tips🚀 #レバテックMeetup
bengo4com
0
550
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
200
なるべく楽してバックエンドに型をつけたい!(楽とは言ってない)
hibiki_cube
0
140
余白を設計しフロントエンド開発を 加速させる
tsukuha
7
2.1k
AI & Enginnering
codelynx
0
110
コントリビューターによるDenoのすゝめ / Deno Recommendations by a Contributor
petamoriken
0
200
Grafana:建立系統全知視角的捷徑
blueswen
0
330
KIKI_MBSD Cybersecurity Challenges 2025
ikema
0
1.3k
Featured
See All Featured
Darren the Foodie - Storyboard
khoart
PRO
2
2.4k
Heart Work Chapter 1 - Part 1
lfama
PRO
5
35k
Mind Mapping
helmedeiros
PRO
0
78
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
110
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
46
2.7k
Statistics for Hackers
jakevdp
799
230k
Google's AI Overviews - The New Search
badams
0
900
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
240
Leo the Paperboy
mayatellez
4
1.4k
The browser strikes back
jonoalderson
0
360
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
77
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