Find file
Fetching contributors…
Cannot retrieve contributors at this time
473 lines (371 sloc) 19.2 KB
<!DOCTYPE html><html><head><title>jsla.md</title><meta http-equiv="Content-Type" content="text/html" charset="UTF-8"><link rel="stylesheet" media="all" href="./docco.css"></head><body><div id="container"><div id="jump_to">Jump To &hellip;<div id="jump_wrapper"><div id="jump_page"><a href="./index.html" class="source"><span class="file_name">README</span></a><a href="./apps/jukebox/web/moment.min.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">moment.min.js</span></a><a href="./apps/jukebox/web/backbone.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">backbone.js</span></a><a href="./apps/jukebox/web/chat.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">chat.js</span></a><a href="./apps/jukebox/web/d3.v2.min.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">d3.v2.min.js</span></a><a href="./apps/jukebox/web/mp3.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">mp3.js</span></a><a href="./apps/jukebox/web/jsmad.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">jsmad.js</span></a><a href="./apps/jukebox/web/require.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">require.js</span></a><a href="./apps/jukebox/web/houseChat.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">houseChat.js</span></a><a href="./apps/jukebox/web/houseAuth.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">houseAuth.js</span></a><a href="./apps/jukebox/web/jukebox.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">jukebox.js</span></a><a href="./apps/jukebox/web/dancer.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">dancer.js</span></a><a href="./apps/jukebox/web/jquery.idle-timer.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">jquery.idle-timer.js</span></a><a href="./apps/jukebox/web/aac.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">aac.js</span></a><a href="./apps/jukebox/web/aurora.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">aurora.js</span></a><a href="./apps/jukebox/web/jquery.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">jquery.js</span></a><a href="./apps/jukebox/web/houseSongs.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">houseSongs.js</span></a><a href="./apps/jukebox/web/jquery.ui.min.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">jquery.ui.min.js</span></a><a href="./apps/jukebox/web/chart.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">chart.js</span></a><a href="./apps/jukebox/web/backbone-house.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">backbone-house.js</span></a><a href="./apps/jukebox/web/alac.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">alac.js</span></a><a href="./apps/jukebox/web/underscore.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">underscore.js</span></a><a href="./apps/jukebox/web/pitch.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">pitch.js</span></a><a href="./apps/jukebox/web/flac.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">flac.js</span></a><a href="./apps/jukebox/web/id3v2.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">id3v2.js</span></a><a href="./apps/jukebox/web/index.js.html" class="source "><span class="base_path">apps / jukebox / web / </span><span class="file_name">index.js</span></a><a href="./apps/jukebox/config/config.js.html" class="source "><span class="base_path">apps / jukebox / config / </span><span class="file_name">config.js</span></a><a href="./apps/jukebox/index.js.html" class="source "><span class="base_path">apps / jukebox / </span><span class="file_name">index.js</span></a><a href="./endPoints/songs/index.js.html" class="source "><span class="base_path">endPoints / songs / </span><span class="file_name">index.js</span></a><a href="./endPoints/apps/index.js.html" class="source "><span class="base_path">endPoints / apps / </span><span class="file_name">index.js</span></a><a href="./endPoints/files/index.js.html" class="source "><span class="base_path">endPoints / files / </span><span class="file_name">index.js</span></a><a href="./endPoints/auth/index.js.html" class="source "><span class="base_path">endPoints / auth / </span><span class="file_name">index.js</span></a><a href="./endPoints/users/index.js.html" class="source "><span class="base_path">endPoints / users / </span><span class="file_name">index.js</span></a><a href="./endPoints/collections/index.js.html" class="source "><span class="base_path">endPoints / collections / </span><span class="file_name">index.js</span></a><a href="./endPoints/chat/index.js.html" class="source "><span class="base_path">endPoints / chat / </span><span class="file_name">index.js</span></a><a href="./endPoints/songr/index.js.html" class="source "><span class="base_path">endPoints / songr / </span><span class="file_name">index.js</span></a><a href="./endPoints/fs/index.js.html" class="source "><span class="base_path">endPoints / fs / </span><span class="file_name">index.js</span></a><a href="./endPoints/songq/index.js.html" class="source "><span class="base_path">endPoints / songq / </span><span class="file_name">index.js</span></a><a href="./endPoints/artists/index.js.html" class="source "><span class="base_path">endPoints / artists / </span><span class="file_name">index.js</span></a><a href="./endPoints/albums/index.js.html" class="source "><span class="base_path">endPoints / albums / </span><span class="file_name">index.js</span></a><a href="./endPoints/songp/index.js.html" class="source "><span class="base_path">endPoints / songp / </span><span class="file_name">index.js</span></a><a href="./endPoints/index.js.html" class="source "><span class="base_path">endPoints / </span><span class="file_name">index.js</span></a></div></div></div><div id="page"><div id="content"><h1>JS.LA</h1>
<p><a href="http://JukeboxJs.com/">Jukebox Home</a>
<a href="http://JukeboxJs.com/jukebox/">Jukebox Demo</a>
<a href="https://github.com/comster/jukebox/">Jukebox on Github</a>
<a href="https://www.jeffpelton.com/">About Me</a></p>
<p><img src="jukebox_jsla.png" alt="JSLA" title="" /></p>
<h1>Contents</h1>
<ul>
<li>App Requirements</li>
<li>Technology Strategy</li>
<li>HTML5 App Features &amp; Limitations</li>
<li>System Architecture</li>
<li>RESTful server, socketio, and static files</li>
<li>Backbone Client App</li>
<li>Organizing a backbone project</li>
<li>Chat &amp; sockets</li>
<li>Audio in the browser using aurora.js</li>
<li>Metadata from audio, album art</li>
<li>HTML sliders and progress bars, drag and drop</li>
<li>Uploading with xhr2</li>
<li>Vizualizing audio using dancer.js &amp; d3</li>
<li>Mobile approach using media queries and user agent</li>
<li>Where to go from here?</li>
</ul>
<h2>App Requirements</h2>
<ul>
<li>HTML5 Web App</li>
<li>Audio Playback without Flash</li>
<li>Chat Rooms via Sockets</li>
<li>User Authentication</li>
<li>Media Server</li>
<li>Library Data</li>
<li>Queue Data</li>
</ul>
<h2>Technology Strategy</h2>
<p><em>Open Source</em>. Not targeting massive deployment to production. Experimenting with the technology.</p>
<ul>
<li><a href="http://www.mongodb.org/">mongodb</a></li>
<li><a href="http://nodejs.org/">node.js</a></li>
<li><a href="https://github.com/comster/house">house.js</a></li>
<li><a href="http://socket.io">socket.io.js</a></li>
<li><a href="http://jquery.com/">jquery.js</a></li>
<li><a href="http://documentcloud.github.com/underscore/">underscore.js</a></li>
<li><a href="http://backbonejs.org/">backbone.js</a></li>
<li><a href="https://github.com/ofmlabs/aurora.js/">aurora.js</a></li>
<li><a href="http://jsantell.github.com/dancer.js/">dancer.js</a></li>
<li><a href="http://d3js.org/">d3.js</a></li>
</ul>
<h2>HTML5 App Features &amp; Limitations</h2>
<p>Applications targeting the browser. HTML5, JS &amp; CSS.</p>
<ul>
<li>Browser compatability</li>
<li>URLs &amp; SEO</li>
<li>App Stores</li>
<li>Device screen resolutions</li>
<li>Network connection, Offline &amp; Caching</li>
</ul>
<p>Resources</p>
<ul>
<li><a href="http://www.html5rocks.com/">HTML5rocks.com</a></li>
<li><a href="http://caniuse.com/">Can I Use.com</a></li>
<li><a href="http://todomvc.com/">TodoMVC: JS framework list</a></li>
</ul>
<h2>System Architecture</h2>
<h3>Server</h3>
<ul>
<li>House on Node.js
<ul><li>Users &amp; Auth</li>
<li>Media Uploads</li>
<li>Library Data &amp; Queue</li>
<li>Chat Room Sockets</li></ul></li>
</ul>
<h3>Client</h3>
<ul>
<li>Backbone App View
<ul><li>Nav View</li>
<li>Media Player View
<ul><li>Player Controls</li>
<li>Player Information</li>
<li>Player Visualization</li></ul></li>
<li>Library View
<ul><li>Song List
<ul><li>Song Row</li></ul></li>
<li>Song Upload</li>
<li>Song Search</li></ul></li>
<li>Queue View
<ul><li>Song Queue List</li>
<li>Song Played List</li></ul></li>
<li>Chat View
<ul><li>Room List
<ul><li>New Room Form</li></ul></li>
<li>Open Room
<ul><li>Member List</li>
<li>Message List</li>
<li>Message Row
<ul><li>User Avatar &amp; Name</li>
<li>Msg Txt</li></ul></li>
<li>New Message Form</li></ul></li></ul></li></ul></li>
</ul>
<h2>RESTful server, socketio, and static files</h2>
<p>Backbone friendly REST endpoints:</p>
<ul>
<li><a href="endPoints/auth/index.js.html">Authentication</a></li>
<li><a href="endPoints/files/index.js.html">Media Files</a></li>
<li><a href="endPoints/songs/index.js.html">Song Library</a></li>
<li><a href="endPoints/songq/index.js.html">Song Queue</a></li>
<li><a href="endPoints/songp/index.js.html">Songs Played</a></li>
<li><a href="endPoints/chat/index.js.html">Chat Rooms</a> REST &amp; socket server</li>
</ul>
<p>Backbone application static files served from apps/jukebox/web to /jukebox</p>
<h2>Backbone Client App</h2>
<p>Organizing a backbone project</p>
<ul>
<li><a href="http://requirejs.org/">Require.js</a> &amp; <a href="http://requirejs.org/docs/whyamd.html">Why AMD?</a></li>
</ul>
<p>Example Bootstrap:</p>
<pre><code>&lt;html&gt;
&lt;body&gt;
&lt;div id="jukebox"&gt;&lt;/div&gt;
&lt;script src="require.js"&gt;&lt;/script&gt;
&lt;script&gt;
require(['jquery.js'], function(){
require(['index.js'], function(webApp){
webApp.init(function(jukebox){
jukebox.setEl($('#jukebox'));
});
});
});
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
// index.js
(function(){
var app = {};
app.init = function($el, callback) {
require(['underscore.js'], function(){
require(['backbone.js'], function(){
require(['jukebox.js'], function(jukebox) {
if(callback) callback(jukebox);
});
});
});
}
// use require module pattern
if(define) {
define(function () {
return app;
});
}
})();
</code></pre>
<h2>Backbone Components</h2>
<p>Understand how Views, Models and Collections work together:</p>
<ul>
<li>Views have a var $el, a render() function and can listen to dom events</li>
<li>Views often reference a Collection or Model. ex. ListView (has col) and RowView (has model).</li>
<li>Collections contain Models</li>
</ul>
<p>Example:</p>
<pre><code>var MyListView = Backbone.View.extend({
initialize: function() {
this.collection = new MyCollection();
// listen for new documents to add to the list
this.collection.on('add', function(doc){
self.$el.append(doc.getView().el);
});
// load initial data from the server
this.collection.fetch();
},
render: function() {
this.$el.html('&lt;ul&gt;&lt;/ul&gt;');
return this;
},
events: {
"click": "alert"
},
alert: function() {
alert('you clicked on the view el');
}
});
var view = new MyView({el: $('#div-id')});
view.render();
</code></pre>
<h2>Chat &amp; sockets</h2>
<p><a href="endPoints/chat/index.js.html">Chat Server</a></p>
<pre><code>var io = house.io.of('/socket.io/chat');
// user connection to chat
io.on('connection', function (socket) {
// Ask for the room status
socket.on('info', function(room_id, callback) {
callback(roomInfo[room_id]);
});
// Manually advance the queue for a room
socket.on('skip', function(data) {
advanceRoomSongQ(data.roomId, true);
});
// Request to join a room
socket.on('join', function(roomId) {
// subscribe this socket (user) to this room
socket.join(roomId);
// tell the others in the room
io.in(roomId).emit('entered', {room_id: roomId, user: roomUsers[roomId][socket.handshake.session.id]});
socket.on('disconnect', function () {
io.in(roomId).emit('exited', {room_id: roomId, user: roomUsers[roomId][socket.handshake.session.id]});
socket.leave(roomId);
});
});
});
// example of saving a message on the server and emitting it to the chat room
var newMsg = {room_id, msg, user, at};
insertMessage(newMsg, function(err, data) {
io.in(room_id).emit('message', newMsg);
});
</code></pre>
<p><a href="apps/jukebox/web/houseChat.js.html">Chat Client</a></p>
<pre><code>// Backbone listens for messages
chat.MessageListView = Backbone.View.extend({
initialize: function() {
this.collection.on('add', function(doc, col) {
$ul.append(doc.getView().render().el);
});
}
});
var socket = io.connect('http://localhost/socket.io/chat');
// join a room
socket.emit('join', room.get('id'));
// listen for messages
socket.on('message', function (data) {
self.rooms[data.room_id].messageCollection.add(data);
});
</code></pre>
<h2>Audio in the browser using aurora.js</h2>
<ul>
<li><a href="http://caniuse.com/#feat=audio-api">Can I Use?: Audio API</a></li>
<li><a href="https://github.com/ofmlabs/aurora.js">Aurora on github</a></li>
<li>mp3, flac, alac, m4a, aac, ogg</li>
</ul>
<p>Example:</p>
<pre><code>var player = Player.fromURL('http://mysite.com/audio.wav');
var player = Player.fromFile(file);
player.play();
player.on('format', function(format){
/*
bitrate: 320000
channelsPerFrame: 2
formatID: "mp3"
sampleRate: 44100
*/
});
player.on('duration', function(msecs){
// update current song time
});
</code></pre>
<h2>Metadata from audio, album art</h2>
<p>Metadata from aurora:</p>
<pre><code>player.on('metadata', function(metadata){
/*
album
artist
genre
title
trackNumber
year
*/
var src = window.URL.createObjectURL(metadata.cover.toBlob());
$('.coverArt').append('&lt;img src="' + src + '" /&gt;');
});
</code></pre>
<h2>Uploading with xhr2</h2>
<ul>
<li><a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/">XMLHttpRequest Level 2</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/file/xhr2/">HTML5rocks.com/en/tutorials/file/xhr2/</a></li>
<li><a href="http://caniuse.com/#feat=xhr2">Can I Use?: XHR2</a></li>
</ul>
<p>Example:</p>
<pre><code>var formData = new FormData();
var xhr = new XMLHttpRequest();
formData.append('files', blobOrFile);
xhr.open('POST', '/api/files', true);
// Listen to the upload progress.
var progressBar = $row.find('progress');
xhr.upload.onprogress = function(e) {
if (e.lengthComputable) {
progressBar.val((e.loaded / e.total) * 100);
progressBar.textContent = progressBar.value; // Fallback for unsupported browsers.
}
};
xhr.onload = function(e) {
console.log('upload complete');
var data = JSON.parse(e.target.response);
};
xhr.send(formData);
</code></pre>
<h2>HTML sliders and progress bars, drag and drop</h2>
<ul>
<li><a href="http://caniuse.com/#feat=input-range">Can I Use?: Input range</a></li>
<li><a href="http://caniuse.com/#feat=progressmeter">Can I Use?: Progress Meter</a></li>
<li><a href="http://caniuse.com/#feat=dragndrop">Can I Use?: DragnDrop</a></li>
<li><a href="http://www.html5rocks.com/en/tutorials/file/dndfiles/#toc-selecting-files-dnd">http://www.html5rocks.com/en/tutorials/file/dndfiles/#toc-selecting-files-dnd</a></li>
</ul>
<p>Example:</p>
<pre><code>&lt;input class="rating" type="range" min="0" max="100" title="Rating" value="50"&gt;
&lt;meter min="0.0" max="100.0" value="33.33"&gt;&lt;/meter&gt;
</code></pre>
<p>Result:</p>
<p><input class="rating" type="range" min="0" max="100" title="Rating" value="50"></p>
<p><meter min="0.0" max="100.0" value="33.33"></meter></p>
<h2>Vizualizing audio using dancer.js &amp; d3</h2>
<ul>
<li><a href="http://jsantell.github.com/dancer.js/">Dancer API</a></li>
<li>Dancer <a href="https://github.com/comster/dancer.js/commit/1b369a78dce26829b495b86d4aa0f5fddfeded1f">patch</a> to work with Aurora <a href="https://github.com/comster/dancer.js">forked on github</a></li>
<li><a href="http://bl.ocks.org/1062544">Basic D3 Sample</a></li>
<li><a href="http://comster.github.com/dancer.js/examples/aurora/">Dancer.js &amp; Aurora Example</a></li>
</ul>
<p>Example:</p>
<pre><code>var dancer = new Dancer();
var kick = dancer.createKick({
onKick: function ( mag ) {
console.log('Kick!');
drawRadParticles(mag);
},
offKick: function ( mag ) {
console.log('no kick :(');
drawSadParticles(mag);
}
}).on();
</code></pre>
<h2>Mobile approach using media queries and user agent</h2>
<ul>
<li>Target screen sizes using css media queries</li>
<li>Use browser user agent to determain iphone for limiting visualization</li>
<li>Not currently targeting network connection for media format &amp; compression</li>
</ul>
<p>Example of css media query to format app for smaller screens:</p>
<pre><code>@media only screen and (min-width: 767px) {
nav li:hover {
color: green;
}
}
</code></pre>
<p>Example:</p>
<pre><code>if(window.navigator.userAgent.indexOf('iPhone') !== -1) {
pageSize = 100;
} else {
pageSize = 10; // load less on iphone
}
</code></pre>
<h2>Where to go from here?</h2>
<p>Other cool HTML5</p>
<ul>
<li>Routing URLs</li>
<li><a href="http://caniuse.com/#feat=history">Can I Use?: History</a></li>
<li>Web Workers</li>
</ul>
<p>TODO</p>
<ul>
<li>Visualizations as plug-ins</li>
<li>Skins</li>
<li>Podcast player</li>
<li>Drag and drop images to chat</li>
<li>DJ more than the audio (visual, skin, etc)</li>
<li>Drag and drop queue</li>
<li>Round Robin Queue</li>
<li>Compress HTML app css &amp; js.</li>
<li>Reference files remotely, without CORS</li>
<li>Youtube API</li>
<li>Last.fm</li>
</ul>
<h2>Thank you</h2>
<p>Tell me what you think @comster and git the code at https://github.com/comster</p>
</div></div><div id="projectname"><a href="./index.html">JukeboxJS</a></div></div></body></html>