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
Architectural Extensions
denyspoltorak
0
280
AIエージェント、”どう作るか”で差は出るか? / AI Agents: Does the "How" Make a Difference?
rkaga
4
2k
Package Management Learnings from Homebrew
mikemcquaid
0
210
Data-Centric Kaggle
isax1015
2
760
「ブロックテーマでは再現できない」は本当か?
inc2734
0
710
Amazon Bedrockを活用したRAGの品質管理パイプライン構築
tosuri13
4
250
AtCoder Conference 2025
shindannin
0
1k
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
640
Implementation Patterns
denyspoltorak
0
280
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.5k
Rust 製のコードエディタ “Zed” を使ってみた
nearme_tech
PRO
0
150
AI時代の認知負荷との向き合い方
optfit
0
150
Featured
See All Featured
The AI Revolution Will Not Be Monopolized: How open-source beats economies of scale, even for LLMs
inesmontani
PRO
3
3k
Faster Mobile Websites
deanohume
310
31k
Making Projects Easy
brettharned
120
6.6k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
730
The #1 spot is gone: here's how to win anyway
tamaranovitovic
2
930
Scaling GitHub
holman
464
140k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
51k
Practical Orchestrator
shlominoach
191
11k
Ecommerce SEO: The Keys for Success Now & Beyond - #SERPConf2024
aleyda
1
1.8k
The Cost Of JavaScript in 2023
addyosmani
55
9.5k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
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