diff --git a/index.html b/index.html
index cd85f0c..c4e3926 100644
--- a/index.html
+++ b/index.html
@@ -6,8 +6,8 @@ com.podnoms.settings = {
REALTIME_HOST: 'www.deepsouthsounds.com:8081',
REALTIME_PORT: 'www.deepsouthsounds.com:8081',
urlRoot: '/api/v1/',
- liveStreamRoot: 'http://radio.deepsouthsounds.com:8000/mp3',
- streamInfoUrl: 'http://radio.deepsouthsounds.com:8000/mp3',
+ liveStreamRoot: 'http://rad.deepsouthsounds.com:8000/dss_320_mp3',
+ streamInfoUrl: 'http://rad.deepsouthsounds.com:8000/dss_320_mp3',
volume: '50',
smDebugMode: false,
isDebug: false,
diff --git a/manage.py b/manage.py
old mode 100755
new mode 100644
diff --git a/static/css/bootstrap-player.css b/static/css/bootstrap-player.css
new file mode 100644
index 0000000..a3e4c48
--- /dev/null
+++ b/static/css/bootstrap-player.css
@@ -0,0 +1,69 @@
+.playa input[type=range] {
+ -webkit-appearance:none;
+ -moz-apperance:none;
+ background-color:#ddd;
+ border: 1px solid #bbb;
+ height:.5em;
+ border-radius:.5em;
+ width:100%;
+ margin:-2px;
+ padding:0 !important;
+ line-height:0;
+}
+.playa input[type=range]::-webkit-slider-thumb {
+ -webkit-appearance:none;
+ -moz-apperance:none;
+ z-index:3;
+ height:1em;
+ width:1em;
+ border-radius:1em;
+ border:1px solid #aaa;
+ background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fefefe), color-stop(0.49, #dddddd), color-stop(0.51, #d1d1d1), color-stop(1, #a1a1a1));
+}
+
+.playa {
+ /*margin:0;*/
+}
+
+.playa .thumbnail {
+ width:96%;
+ padding:1.5%;
+}
+
+.playa .btn-group {
+ text-align:center;
+}
+
+@media (max-width: 979px) and (min-width: 768px){
+ .span4 .playa, .playa.span4{
+ padding:0;
+ }
+}
+@media (min-width: 768px){
+ .playa .btn-group .btn {
+ padding:4px 3px;
+ margin:auto;
+ display:inline-block;
+ float:none;
+ }
+ .playa .btn-group .span1 {
+ width:8%;
+ }
+ .playa .btn-group .span2 {
+ width:16%;
+ }
+ .playa .btn-group .span3 {
+ width:25%;
+ }
+ .playa .btn-group .span4{
+ width:33%;
+ }
+ .playa.span2 .btn-group .btn, .playa.span1 .btn-group .btn, .span2 .playa .btn-group .btn, .span1 .playa .btn-group .btn{
+ width:100%;
+ display:block;
+ }
+ .span4.playa, .span3 .playa, .span2 .playa, .span1 .playa, .playa.span4, .playa.span3, .playa.span2, .playa.span1{
+ padding:0;
+ overflow:hidden;
+ }
+}
diff --git a/static/img/radio.jpg b/static/img/radio.jpg
new file mode 100644
index 0000000..b42a9df
Binary files /dev/null and b/static/img/radio.jpg differ
diff --git a/static/js/app/lib/audioController.coffee b/static/js/app/lib/audioController.coffee
index 08834fd..75bfb87 100644
--- a/static/js/app/lib/audioController.coffee
+++ b/static/js/app/lib/audioController.coffee
@@ -7,6 +7,8 @@ define ['app', 'marionette', 'vent', 'utils'],
@listenTo(vent, 'mix:init', @mixInit)
@listenTo(vent, 'mix:pause', @mixPause)
@listenTo(vent, 'mix:play', @mixPlay)
+ @listenTo(vent, 'live:play', @livePlay)
+ @listenTo(vent, 'live:pause', @livePause)
mixInit: (model) =>
console.log "AudioController: mixInit"
@@ -32,5 +34,13 @@ define ['app', 'marionette', 'vent', 'utils'],
mixPause: (model) ->
console.log("AudioController: mixPause")
com.podnoms.player.pause();
+
+ livePlay: ->
+ console.log("AudioController: livePlay")
+ com.podnoms.player.playLive
+ success: ->
+ console.log("Live stream started")
+ vent.trigger('live:started')
+
AudioController
diff --git a/static/js/app/lib/audioController.js b/static/js/app/lib/audioController.js
index 60e33b9..4af7cc7 100644
--- a/static/js/app/lib/audioController.js
+++ b/static/js/app/lib/audioController.js
@@ -1,30 +1,33 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['app', 'marionette', 'vent', 'utils'], function(App, Marionette, vent, utils) {
- var AudioController;
- AudioController = (function(_super) {
+ var AudioController, _ref;
+ AudioController = (function(_super) {
__extends(AudioController, _super);
function AudioController() {
- this.mixInit = __bind(this.mixInit, this);
- return AudioController.__super__.constructor.apply(this, arguments);
+ this.mixInit = __bind(this.mixInit, this); _ref = AudioController.__super__.constructor.apply(this, arguments);
+ return _ref;
}
AudioController.prototype.initialize = function(options) {
console.log("AudioController: initialize");
this.listenTo(vent, 'mix:init', this.mixInit);
this.listenTo(vent, 'mix:pause', this.mixPause);
- return this.listenTo(vent, 'mix:play', this.mixPlay);
+ this.listenTo(vent, 'mix:play', this.mixPlay);
+ this.listenTo(vent, 'live:play', this.livePlay);
+ return this.listenTo(vent, 'live:pause', this.livePause);
};
AudioController.prototype.mixInit = function(model) {
var id,
_this = this;
+
console.log("AudioController: mixInit");
id = model.get('id');
com.podnoms.player.stopPlaying();
@@ -53,6 +56,16 @@
return com.podnoms.player.pause();
};
+ AudioController.prototype.livePlay = function() {
+ console.log("AudioController: livePlay");
+ return com.podnoms.player.playLive({
+ success: function() {
+ console.log("Live stream started");
+ return vent.trigger('live:started');
+ }
+ });
+ };
+
return AudioController;
})(Marionette.Controller);
diff --git a/static/js/app/lib/panningRegion.js b/static/js/app/lib/panningRegion.js
index 5638e1d..febb8de 100644
--- a/static/js/app/lib/panningRegion.js
+++ b/static/js/app/lib/panningRegion.js
@@ -1,12 +1,14 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette'], function(Marionette) {
- var PanningRegion, getPrefixedCssProp;
+ var PanningRegion, getPrefixedCssProp, _ref;
+
getPrefixedCssProp = function(baseProp) {
var str;
+
str = Modernizr.prefixed(baseProp);
str = str.replace(/([A-Z])/g, function(str, m1) {
return "-" + m1.toLowerCase();
@@ -14,17 +16,18 @@
return str;
};
PanningRegion = (function(_super) {
-
__extends(PanningRegion, _super);
function PanningRegion() {
- return PanningRegion.__super__.constructor.apply(this, arguments);
+ _ref = PanningRegion.__super__.constructor.apply(this, arguments);
+ return _ref;
}
PanningRegion.prototype.el = "#content";
PanningRegion.prototype.initialize = function() {
var transEndEventNames;
+
transEndEventNames = {
WebkitTransition: "webkitTransitionEnd",
MozTransition: "transitionend",
@@ -40,6 +43,7 @@
PanningRegion.prototype.transitionToView = function(newView, type) {
var self, view;
+
self = this;
view = this.currentView;
if (!view || view.isClosed) {
@@ -49,6 +53,7 @@
Marionette.triggerMethod.call(this, "willTransition", view);
newView.on("render", function() {
var $background, newViewMatrix, translation, worldBgMatrix, worldContentMatrix;
+
self.$el.off(self.transEndEventName);
translation = void 0;
if (type === "slide") {
diff --git a/static/js/app/lib/utils.js b/static/js/app/lib/utils.js
index 4933f18..8e11d57 100644
--- a/static/js/app/lib/utils.js
+++ b/static/js/app/lib/utils.js
@@ -1,8 +1,8 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
-
define(['jquery', 'bootstrap', 'toastr'], function($, bootstrap, toastr) {
var _this = this;
+
return {
modal: function(url) {
if (url) {
@@ -24,6 +24,7 @@
},
checkPlayCount: function() {
var _this = this;
+
if (document.cookie.indexOf("sessionId")) {
$.getJSON("/ajax/session_play_count", function(data) {
console.log("utils: got playcount");
diff --git a/static/js/app/views/activity/activityItemView.js b/static/js/app/views/activity/activityItemView.js
index 2ac89e6..ad3f7ce 100644
--- a/static/js/app/views/activity/activityItemView.js
+++ b/static/js/app/views/activity/activityItemView.js
@@ -1,16 +1,17 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'text!/tpl/ActivityListItemView'], function(Marionette, Template) {
- var ActivityItemView;
- return ActivityItemView = (function(_super) {
+ var ActivityItemView, _ref;
+ return ActivityItemView = (function(_super) {
__extends(ActivityItemView, _super);
function ActivityItemView() {
- return ActivityItemView.__super__.constructor.apply(this, arguments);
+ _ref = ActivityItemView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
ActivityItemView.prototype.template = _.template(Template);
diff --git a/static/js/app/views/activity/activityListView.js b/static/js/app/views/activity/activityListView.js
index 8ac3c67..cfdeef6 100644
--- a/static/js/app/views/activity/activityListView.js
+++ b/static/js/app/views/activity/activityListView.js
@@ -1,16 +1,17 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'models/activity/activityCollection', 'views/activity/activityItemView', 'text!/tpl/ActivityListView'], function(Marionette, ActivityCollection, ActivityItemView, Template) {
- var ActivityListView;
- ActivityListView = (function(_super) {
+ var ActivityListView, _ref;
+ ActivityListView = (function(_super) {
__extends(ActivityListView, _super);
function ActivityListView() {
- return ActivityListView.__super__.constructor.apply(this, arguments);
+ _ref = ActivityListView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
ActivityListView.prototype.template = _.template(Template);
@@ -25,6 +26,7 @@
ActivityListView.prototype.initialize = function() {
var _this = this;
+
console.log("ActivityListView: initialize");
this.collection = new ActivityCollection;
this.collection.fetch({
diff --git a/static/js/app/views/comment/commentItemView.js b/static/js/app/views/comment/commentItemView.js
index c61b6d9..8b47684 100644
--- a/static/js/app/views/comment/commentItemView.js
+++ b/static/js/app/views/comment/commentItemView.js
@@ -1,16 +1,17 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'text!/tpl/CommentItemView'], function(Marionette, Template) {
- var CommentItemView;
- CommentItemView = (function(_super) {
+ var CommentItemView, _ref;
+ CommentItemView = (function(_super) {
__extends(CommentItemView, _super);
function CommentItemView() {
- return CommentItemView.__super__.constructor.apply(this, arguments);
+ _ref = CommentItemView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
CommentItemView.prototype.template = _.template(Template);
diff --git a/static/js/app/views/header.coffee b/static/js/app/views/header.coffee
index 00e3cf5..aad60a7 100644
--- a/static/js/app/views/header.coffee
+++ b/static/js/app/views/header.coffee
@@ -6,7 +6,8 @@
Copyright (c) 2012, Fergal Moran. All rights reserved.
Code provided under the BSD License:
###
-define ["underscore", "backbone", "vent", "utils", "text!/tpl/HeaderView"], (_, Backbone, vent, utils, Template) ->
+define ["underscore", "backbone", "vent", "utils", "text!/tpl/HeaderView"],
+(_, Backbone, vent, utils, Template) ->
class HeaderView extends Backbone.View
template: _.template(Template)
events:
@@ -42,15 +43,7 @@ define ["underscore", "backbone", "vent", "utils", "text!/tpl/HeaderView"], (_,
this
playLive: ->
- ref = this
- dssSoundHandler.playLive()
- _eventAggregator.trigger "track_playing"
- button = $(@el).find("#header-play-pause-button")
- button.data "mode", "pause"
- $.getJSON "ajax/live_now_playing/", (data) ->
- alert data.title
- $(ref.el).find("#live-now-playing").text data.title
-
+ vent.trigger('live:play')
togglePlayState: ->
button = $(@el).find("#header-play-pause-button")
diff --git a/static/js/app/views/header.js b/static/js/app/views/header.js
index 08314cb..d694ae4 100644
--- a/static/js/app/views/header.js
+++ b/static/js/app/views/header.js
@@ -1,5 +1,4 @@
-// Generated by CoffeeScript 1.3.3
-
+// Generated by CoffeeScript 1.6.2
/*
@license
@@ -15,13 +14,14 @@ Code provided under the BSD License:
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(["underscore", "backbone", "vent", "utils", "text!/tpl/HeaderView"], function(_, Backbone, vent, utils, Template) {
- var HeaderView;
- HeaderView = (function(_super) {
+ var HeaderView, _ref;
+ HeaderView = (function(_super) {
__extends(HeaderView, _super);
function HeaderView() {
- return HeaderView.__super__.constructor.apply(this, arguments);
+ _ref = HeaderView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
HeaderView.prototype.template = _.template(Template);
@@ -67,20 +67,12 @@ Code provided under the BSD License:
};
HeaderView.prototype.playLive = function() {
- var button, ref;
- ref = this;
- dssSoundHandler.playLive();
- _eventAggregator.trigger("track_playing");
- button = $(this.el).find("#header-play-pause-button");
- button.data("mode", "pause");
- return $.getJSON("ajax/live_now_playing/", function(data) {
- alert(data.title);
- return $(ref.el).find("#live-now-playing").text(data.title);
- });
+ return vent.trigger('live:play');
};
HeaderView.prototype.togglePlayState = function() {
var button, mode;
+
button = $(this.el).find("#header-play-pause-button");
mode = button.data("mode");
if (mode === "play") {
diff --git a/static/js/app/views/mix/mixItemView.js b/static/js/app/views/mix/mixItemView.js
index 2f504e7..31a85a1 100644
--- a/static/js/app/views/mix/mixItemView.js
+++ b/static/js/app/views/mix/mixItemView.js
@@ -1,26 +1,22 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['moment', 'app', 'vent', 'marionette', 'models/comment/commentCollection', 'views/comment/commentListView', 'text!/tpl/MixListItemView'], function(moment, App, vent, Marionette, CommentsCollection, CommentsListView, Template) {
- var MixItemView;
- MixItemView = (function(_super) {
+ var MixItemView, _ref;
+ MixItemView = (function(_super) {
__extends(MixItemView, _super);
function MixItemView() {
this.doStart = __bind(this.doStart, this);
-
this.renderComments = __bind(this.renderComments, this);
-
this.renderGenres = __bind(this.renderGenres, this);
-
this.onRender = __bind(this.onRender, this);
-
- this.initialize = __bind(this.initialize, this);
- return MixItemView.__super__.constructor.apply(this, arguments);
+ this.initialize = __bind(this.initialize, this); _ref = MixItemView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
MixItemView.prototype.template = _.template(Template);
@@ -54,6 +50,7 @@
MixItemView.prototype.onRender = function() {
var id, totalDuration, totalDurationText;
+
id = this.model.get('id');
if (this.model.get('duration')) {
totalDuration = moment.duration(this.model.get('duration'), "seconds");
@@ -73,6 +70,7 @@
MixItemView.prototype.renderGenres = function() {
var el;
+
el = this.el;
$.each(this.model.get("genre-list"), function(data) {
$("#genre-list", el).append('' + this.text + '');
@@ -83,6 +81,7 @@
MixItemView.prototype.renderComments = function() {
var comments;
+
comments = new CommentsCollection();
comments.url = this.model.get("resource_uri") + "comments/";
comments.mix_id = this.model.id;
@@ -90,6 +89,7 @@
comments.fetch({
success: function(data) {
var content;
+
console.log(data);
content = new CommentsListView({
collection: comments
@@ -133,6 +133,7 @@
MixItemView.prototype.mixFavourite = function() {
var app;
+
console.log("MixItemView: favouriteMix");
app = require('app');
app.vent.trigger("mix:favourite", this.model);
@@ -141,6 +142,7 @@
MixItemView.prototype.mixLike = function() {
var app;
+
console.log("MixItemView: likeMix");
app = require('app');
app.vent.trigger("mix:like", this.model);
@@ -149,6 +151,7 @@
MixItemView.prototype.mixShare = function(e) {
var app, mode;
+
console.log("MixItemView: shareMix");
mode = $(e.currentTarget).data("mode");
console.log("MixItemView: " + mode);
diff --git a/static/js/app/views/mix/mixListView.js b/static/js/app/views/mix/mixListView.js
index 5df61f7..448c7c2 100644
--- a/static/js/app/views/mix/mixListView.js
+++ b/static/js/app/views/mix/mixListView.js
@@ -1,19 +1,20 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'vent', 'models/mix/mixCollection', 'views/mix/mixItemView', 'text!/tpl/MixListView'], function(Marionette, vent, MixCollection, MixItemView, Template) {
- var MixListView;
+ var MixListView, _ref;
+
MixListView = (function(_super) {
var currentMix;
__extends(MixListView, _super);
function MixListView() {
- this.initialize = __bind(this.initialize, this);
- return MixListView.__super__.constructor.apply(this, arguments);
+ this.initialize = __bind(this.initialize, this); _ref = MixListView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
MixListView.prototype.template = _.template(Template);
@@ -28,6 +29,7 @@
MixListView.prototype.initialize = function() {
var _this = this;
+
console.log("MixListView: initialize");
this.collection = new MixCollection();
this.collection.fetch({
@@ -43,6 +45,7 @@
MixListView.prototype.mixPlay = function(model) {
var v;
+
console.log("MixListView: mixPlay");
if (currentMix !== -1) {
v = this.children.findByModelCid(currentMix);
diff --git a/static/js/app/views/sidebar/sidebarView.coffee b/static/js/app/views/sidebar/sidebarView.coffee
index ef09405..908cfe4 100644
--- a/static/js/app/views/sidebar/sidebarView.coffee
+++ b/static/js/app/views/sidebar/sidebarView.coffee
@@ -13,6 +13,7 @@ define ['underscore', 'backbone', 'marionette', 'vent', 'views/activity/activity
this.listenTo(vent, 'mix:init', @mixInit)
this.listenTo(vent, 'mix:play', @mixPlay)
this.listenTo(vent, 'mix:pause', @mixPause)
+ this.listenTo(vent, 'live:started', @liveStarted)
return
onRender: ->
@@ -38,5 +39,20 @@ define ['underscore', 'backbone', 'marionette', 'vent', 'views/activity/activity
$(@topRegion.el).show()
@topRegion.show(new NowPlayingView({model: model}))
+ liveStarted: ->
+ console.log "SidebarView: livePlay"
+ $.getJSON "ajax/live_now_playing/", (data) =>
+ $(@topRegion.el).show()
+ @topRegion.show(new NowPlayingView({
+ model: new Backbone.Model({
+ mix_image: "/static/img/radio.jpg",
+ item_url: "",
+ title: data.Description,
+ user_profile_url: "",
+ user_name: "Deep South Sounds Radio"
+ })
+ }))
+ true
+
SidebarView
diff --git a/static/js/app/views/sidebar/sidebarView.js b/static/js/app/views/sidebar/sidebarView.js
index 1c76f73..b03d197 100644
--- a/static/js/app/views/sidebar/sidebarView.js
+++ b/static/js/app/views/sidebar/sidebarView.js
@@ -1,16 +1,17 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['underscore', 'backbone', 'marionette', 'vent', 'views/activity/activityListView', 'views/widgets/nowPlayingView', 'text!/tpl/SidebarView'], function(_, Backbone, Marionette, vent, ActivityListView, NowPlayingView, Template) {
- var SidebarView;
- SidebarView = (function(_super) {
+ var SidebarView, _ref;
+ SidebarView = (function(_super) {
__extends(SidebarView, _super);
function SidebarView() {
- return SidebarView.__super__.constructor.apply(this, arguments);
+ _ref = SidebarView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
SidebarView.prototype.template = _.template(Template);
@@ -25,6 +26,7 @@
this.listenTo(vent, 'mix:init', this.mixInit);
this.listenTo(vent, 'mix:play', this.mixPlay);
this.listenTo(vent, 'mix:pause', this.mixPause);
+ this.listenTo(vent, 'live:started', this.liveStarted);
};
SidebarView.prototype.onRender = function() {
@@ -36,7 +38,6 @@
this.streamRegion.show(new ActivityListView());
$(this.topRegion.el).hide();
"@topRegion.show(\n new NowPlayingView(\n model: new Backbone.Model({\n item_url: \"fdskjfhdsk\", title: \"Argle bargle\", user_profile_url: \"/\", user_name: \"Foo Ferra\"\n })\n ))";
-
};
SidebarView.prototype.mixInit = function(model) {
@@ -47,6 +48,25 @@
}));
};
+ SidebarView.prototype.liveStarted = function() {
+ var _this = this;
+
+ console.log("SidebarView: livePlay");
+ $.getJSON("ajax/live_now_playing/", function(data) {
+ $(_this.topRegion.el).show();
+ return _this.topRegion.show(new NowPlayingView({
+ model: new Backbone.Model({
+ mix_image: "/static/img/radio.jpg",
+ item_url: "",
+ title: data.Description,
+ user_profile_url: "",
+ user_name: "Deep South Sounds Radio"
+ })
+ }));
+ });
+ return true;
+ };
+
return SidebarView;
})(Marionette.Layout);
diff --git a/static/js/app/views/user/userListView.js b/static/js/app/views/user/userListView.js
index 83c4475..db84b7f 100644
--- a/static/js/app/views/user/userListView.js
+++ b/static/js/app/views/user/userListView.js
@@ -1,18 +1,18 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
__hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['jquery', 'marionette', 'models/user/userCollection', 'views/user/userItemView', 'text!/tpl/UserListView', 'libs/bootstrap/bootpag'], function($, Marionette, UserCollection, UserItemView, Template) {
- var UserListView;
- UserListView = (function(_super) {
+ var UserListView, _ref;
+ UserListView = (function(_super) {
__extends(UserListView, _super);
function UserListView() {
- this.initialize = __bind(this.initialize, this);
- return UserListView.__super__.constructor.apply(this, arguments);
+ this.initialize = __bind(this.initialize, this); _ref = UserListView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
UserListView.prototype.template = _.template(Template);
@@ -23,6 +23,7 @@
UserListView.prototype.initialize = function() {
var _this = this;
+
console.log("UserListView: initialize");
this.collection = new UserCollection();
this.collection.fetch({
diff --git a/static/js/app/views/widgets/nowPlayingView.js b/static/js/app/views/widgets/nowPlayingView.js
index e4e8640..53c0212 100644
--- a/static/js/app/views/widgets/nowPlayingView.js
+++ b/static/js/app/views/widgets/nowPlayingView.js
@@ -1,16 +1,17 @@
-// Generated by CoffeeScript 1.3.3
+// Generated by CoffeeScript 1.6.2
(function() {
var __hasProp = {}.hasOwnProperty,
__extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
define(['marionette', 'vent', 'text!/tpl/NowPlayingView'], function(Marionette, vent, Template) {
- var NowPlayingView;
- NowPlayingView = (function(_super) {
+ var NowPlayingView, _ref;
+ NowPlayingView = (function(_super) {
__extends(NowPlayingView, _super);
function NowPlayingView() {
- return NowPlayingView.__super__.constructor.apply(this, arguments);
+ _ref = NowPlayingView.__super__.constructor.apply(this, arguments);
+ return _ref;
}
NowPlayingView.prototype.template = _.template(Template);
diff --git a/static/js/libs/bootstrap/bootstrap-player.js b/static/js/libs/bootstrap/bootstrap-player.js
new file mode 100644
index 0000000..b781f3b
--- /dev/null
+++ b/static/js/libs/bootstrap/bootstrap-player.js
@@ -0,0 +1,313 @@
+(function($) {
+ 'use strict';
+ $('audio[controls]').before(function(){
+ var song = this;
+ song.controls=false;
+ var player_box = document.createElement('div');
+ $(player_box).addClass($(song).attr('class') + ' well container-fluid playa');
+ var data_sec = document.createElement('section');
+ $(data_sec).addClass('collapse');
+ var toggle_holder = document.createElement('div');
+ $(toggle_holder).addClass('btn-group row-fluid');
+ var data_toggle = document.createElement('a');
+ $(data_toggle).html('');
+ $(data_toggle).addClass('btn btn-block');
+ $(data_toggle).attr('style', 'opacity:0.3');
+ $(data_toggle).click(function (){$(data_sec).collapse('toggle');});
+ $(data_toggle).attr('title', 'Details');
+ $(data_toggle).tooltip({'container': 'body', 'placement': 'top', 'html': true});
+ $(toggle_holder).append(data_toggle);
+ var data_table = document.createElement('table');
+ $(data_table).addClass('table table-condensed');
+ var player = document.createElement('section');
+ $(player).addClass('btn-group row-fluid');
+ var load_error = function(){
+ console.log('error');
+ $(player_box).find('.btn').addClass('disabled');
+ $(player_box).find('input[type="range"]').hide();
+ $(player_box).find('.icon-spin').text('Error');
+ $(player_box).find('.icon-spin').parent().attr('title', 'There was an error loading the audio.');
+ $(player_box).find('.icon-spin').parent().tooltip('fixTitle');
+ $(player_box).find('.icon-spin').removeClass('icon-spinner icon-spin');
+ };
+ var addPlay = function() {
+ var play = document.createElement('button');
+ $(play).addClass('btn disabled span1');
+ play.setPlayState = function(toggle){
+ $(play).removeClass('disabled');
+ if (toggle === 'play') {
+ $(play).html('');
+ $(play).click(function () {
+ song.play();
+ });
+ }
+ if (toggle === 'pause') {
+ $(play).html('');
+ $(play).click(function () {
+ song.pause();
+ });
+ }
+ };
+ $(song).on('play', function(){play.setPlayState('pause');});
+ $(song).on('canplay', function(){play.setPlayState('play');});
+ $(song).on('pause', function(){play.setPlayState('play');});
+ var timeout = 0;
+ var loadCheck = setInterval(function() {
+ if(isNaN(song.duration) === false){
+ play.setPlayState('play');
+ clearInterval(loadCheck);
+ return true;
+ }
+ if(song.networkState === 3 || timeout === 75){
+ load_error();
+ clearInterval(loadCheck);
+ return false;
+ }
+ timeout++;
+ }, 50);
+
+ $(player).append(play);
+ };
+ var addSeek = function() {
+ var seek = document.createElement('input');
+ $(seek).attr({
+ 'type': 'range',
+ 'min': 0,
+ 'value': 0,
+ 'class': 'seek'
+ });
+ seek.progress = function () {
+ var bg = 'rgba(223, 240, 216, 1) 0%';
+ bg += ', rgba(223, 240, 216, 1) ' + ((song.currentTime/song.duration) * 100) + '%';
+ bg += ', rgba(223, 240, 216, 0) ' + ((song.currentTime/song.duration) * 100) + '%';
+ for (var i=0; i song.currentTime && isNaN(song.buffered.end(i)) === false && isNaN(song.buffered.start(i)) === false){
+ var bufferedstart;
+ var bufferedend;
+ if (song.buffered.end(i) < song.duration) {
+ bufferedend = ((song.buffered.end(i)/song.duration) * 100);
+ }
+ else {
+ bufferedend = 100;
+ }
+ if (song.buffered.start(i) > song.currentTime){
+ bufferedstart = ((song.buffered.start(i)/song.duration) * 100);
+ }
+ else {
+ bufferedstart = ((song.currentTime/song.duration) * 100);
+ }
+ bg += ', rgba(217, 237, 247, 0) ' + bufferedstart + '%';
+ bg += ', rgba(217, 237, 247, 1) ' + bufferedstart + '%';
+ bg += ', rgba(217, 237, 247, 1) ' + bufferedend + '%';
+ bg += ', rgba(217, 237, 247, 0) ' + bufferedend + '%';
+ }
+ }
+ $(seek).css('background', '-webkit-linear-gradient(left, ' + bg + ')');
+ //These may be re-enabled when/if other browsers support the background like webkit
+ //$(seek).css('background','-o-linear-gradient(left, ' + bg + ')');
+ //$(seek).css('background','-moz-linear-gradient(left, ' + bg + ')');
+ //$(seek).css('background','-ms-linear-gradient(left, ' + bg + ')');
+ //$(seek).css('background','linear-gradient(to right, ' + bg + ')');
+ $(seek).css('background-color', '#ddd');
+ };
+ seek.set = function () {
+ $(seek).val(song.currentTime);
+ seek.progress();
+ };
+ seek.slide = function () {
+ song.currentTime = $(seek).val();
+ seek.progress();
+ };
+ seek.init = function () {
+ $(seek).attr({
+ 'max': song.duration,
+ 'step': song.duration / 100
+ });
+ seek.set();
+ };
+ seek.reset = function () {
+ $(seek).val(0);
+ song.currentTime = $(seek).val();
+ if(!song.loop){song.pause();}
+ else {song.play();}
+ };
+ var seek_wrapper = document.createElement('div');
+ $(seek_wrapper).addClass('btn disabled span4');
+
+ $(seek_wrapper).append(seek);
+ $(seek).on('change', seek.slide);
+ $(song).on('timeupdate', seek.init);
+ $(song).on('loadedmetadata', seek.init);
+ $(song).on('loadeddata', seek.init);
+ $(song).on('progress', seek.init);
+ $(song).on('canplay', seek.init);
+ $(song).on('canplaythrough', seek.init);
+ $(song).on('ended', seek.reset);
+ if(song.readyState > 0){
+ seek.init();
+ }
+ $(player).append(seek_wrapper);
+ };
+ var addTime = function() {
+ var time = document.createElement('a');
+ $(time).addClass('btn span3');
+ $(time).tooltip({'container': 'body', 'placement': 'right', 'html': true});
+ time.twodigit = function (myNum) {
+ return ("0" + myNum).slice(-2);
+ };
+ time.timesplit = function (a) {
+ if (isNaN(a)){return '';}
+ var hours = Math.floor(a / 3600);
+ var minutes = Math.floor(a / 60) - (hours * 60);
+ var seconds = Math.floor(a) - (hours * 3600) - (minutes * 60);
+ var timeStr = time.twodigit(minutes) + ':' + time.twodigit(seconds);
+ if (hours > 0) {
+ timeStr = hours + ':' + timeStr;
+ }
+ return timeStr;
+ };
+ time.showtime = function () {
+ $(time).html(time.timesplit(song.duration));
+ $(time).attr({'title': 'Click to Reset
Position: ' + (time.timesplit(song.currentTime))});
+ if (!song.paused){
+ $(time).html(time.timesplit(song.currentTime));
+ $(time).attr({'title': 'Click to Reset
Length: ' + (time.timesplit(song.duration))});
+ }
+ $(time).tooltip('fixTitle');
+ };
+ $(time).click(function () {
+ song.pause();
+ song.currentTime = 0;
+ time.showtime();
+ $(time).tooltip('fixTitle');
+ $(time).tooltip('show');
+ });
+ $(time).tooltip('show');
+ $(song).on('loadedmetadata', time.showtime);
+ $(song).on('loadeddata', time.showtime);
+ $(song).on('progress', time.showtime);
+ $(song).on('canplay', time.showtime);
+ $(song).on('canplaythrough', time.showtime);
+ $(song).on('timeupdate', time.showtime);
+ if(song.readyState > 0){
+ time.showtime();
+ }
+ else {
+ $(time).html('');
+ }
+ $(player).append(time);
+ };
+ var addMute = function() {
+ var mute = document.createElement('button');
+ $(mute).addClass('btn span1');
+ mute.checkVolume = function () {
+ if (song.volume > 0.5 && !song.muted) {
+ $(mute).html('');
+ } else if (song.volume < 0.5 && song.volume > 0 && !song.muted) {
+ $(mute).html('');
+ } else {
+ $(mute).html('');
+ }
+ };
+ $(mute).click(function () {
+ if (song.muted) {
+ song.muted = false;
+ song.volume = song.oldvolume;
+ } else {
+ song.muted = true;
+ song.oldvolume = song.volume;
+ song.volume = 0;
+ }
+ mute.checkVolume();
+ });
+ mute.checkVolume();
+ $(song).on('volumechange', mute.checkVolume);
+ $(player).append(mute);
+ };
+ var addVolume = function() {
+ var volume = document.createElement('input');
+ $(volume).attr({
+ 'type': 'range',
+ 'min': 0,
+ 'max': 1,
+ 'step': 1 / 100,
+ 'value': 1
+ });
+ volume.slide = function () {
+ song.muted = false;
+ song.volume = $(volume).val();
+ };
+ volume.set = function () {
+ $(volume).val(song.volume);
+ };
+ var vol_wrapper = document.createElement('div');
+ $(vol_wrapper).addClass('btn disabled span3');
+ $(vol_wrapper).append(volume);
+ $(volume).on("change", volume.slide);
+ $(song).on('volumechange', volume.set);
+ $(player).append(vol_wrapper);
+ };
+ var addAlbumArt = function() {
+ var albumArt = document.createElement('img');
+ $(albumArt).addClass('thumbnail');
+ $(albumArt).attr('src', $(song).data('infoAlbumArt'));
+ $(data_sec).append(albumArt);
+ };
+ var addInfo = function(title, dataId) {
+ var row = document.createElement('tr');
+ var head = document.createElement('th');
+ var data = document.createElement('td');
+ $(head).html(title);
+ $(data).html($(song).data(dataId));
+ $(row).append(head);
+ $(row).append(data);
+ $(data_table).append(row);
+ };
+ var addData = function() {
+ if (typeof($(song).data('infoAlbumArt')) !== 'undefined'){ addAlbumArt();}
+ if (typeof($(song).data('infoArtist')) !== 'undefined'){ addInfo('Artist', 'infoArtist');}
+ if (typeof($(song).data('infoTitle')) !== 'undefined'){ addInfo('Title', 'infoTitle');}
+ if (typeof($(song).data('infoAlbumTitle')) !== 'undefined'){ addInfo('Album', 'infoAlbumTitle');}
+ if (typeof($(song).data('infoLabel')) !== 'undefined'){ addInfo('Label', 'infoLabel');}
+ if (typeof($(song).data('infoYear')) !== 'undefined'){ addInfo('Year', 'infoYear');}
+ if ($(data_table).html() !== ""){
+ $(data_sec).append(data_table);
+ $(player_box).append(toggle_holder);
+ $(player_box).append(data_sec);
+ }
+ };
+ var addPlayer = function() {
+ if ($(song).data('play') !== 'off'){ addPlay();}
+ if ($(song).data('seek') !== 'off'){ addSeek();}
+ if ($(song).data('time') !== 'off'){ addTime();}
+ if ($(song).data('mute') !== 'off'){ addMute();}
+ if ($(song).data('volume') !== 'off'){ addVolume();}
+ $(player_box).append(player);
+ };
+ var addAttribution = function() {
+ var attribution = document.createElement('small');
+ $(attribution).addClass('pull-right muted');
+ if (typeof($(song).data('infoAttLink')) !== 'undefined'){
+ var attribution_link = document.createElement('a');
+ $(attribution_link).addClass('muted');
+ $(attribution_link).attr('href', $(song).data('infoAttLink'));
+ $(attribution_link).html($(song).data('infoAtt'));
+ $(attribution).append(attribution_link);
+ }
+ else {
+ $(attribution).html($(song).data('infoAtt'));
+ }
+ $(player_box).append(attribution);
+ };
+ var fillPlayerBox = function() {
+ addData();
+ addPlayer();
+ if (typeof($(song).data('infoAtt')) !== 'undefined'){ addAttribution();}
+ };
+ fillPlayerBox();
+ $(song).on('error', function(){
+ load_error();
+ });
+ return player_box;
+ });
+})(jQuery)
\ No newline at end of file
diff --git a/static/js/libs/bootstrap/html5slider.js b/static/js/libs/bootstrap/html5slider.js
new file mode 100644
index 0000000..f9ff25a
--- /dev/null
+++ b/static/js/libs/bootstrap/html5slider.js
@@ -0,0 +1,284 @@
+/*
+ html5slider - a JS implementation of for Firefox 16 and up
+ https://github.com/fryn/html5slider
+
+ Copyright (c) 2010-2012 Frank Yan,
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+(function () {
+
+// test for native support
+ var test = document.createElement('input');
+ try {
+ test.type = 'range';
+ if (test.type == 'range')
+ return;
+ } catch (e) {
+ return;
+ }
+
+// test for required property support
+ test.style.background = 'linear-gradient(red, red)';
+ if (!test.style.backgroundImage || !('MozAppearance' in test.style) || !document.mozSetImageElement || !this.MutationObserver)
+ return;
+
+ var scale;
+ var isMac = navigator.platform == 'MacIntel';
+ var thumb = {
+ radius: isMac ? 9 : 6,
+ width: isMac ? 22 : 12,
+ height: isMac ? 16 : 20
+ };
+ var track = 'linear-gradient(transparent ' + (isMac ?
+ '6px, #999 6px, #999 7px, #ccc 8px, #bbb 9px, #bbb 10px, transparent 10px' :
+ '9px, #999 9px, #bbb 10px, #fff 11px, transparent 11px') +
+ ', transparent)';
+ var styles = {
+ 'min-width': thumb.width + 'px',
+ 'min-height': thumb.height + 'px',
+ 'max-height': thumb.height + 'px',
+ padding: '0 0 ' + (isMac ? '2px' : '1px'),
+ border: 0,
+ 'border-radius': 0,
+ cursor: 'default',
+ 'text-indent': '-999999px' // -moz-user-select: none; breaks mouse capture
+ };
+ var options = {
+ attributes: true,
+ attributeFilter: ['min', 'max', 'step', 'value']
+ };
+ var forEach = Array.prototype.forEach;
+ var onChange = document.createEvent('HTMLEvents');
+ onChange.initEvent('change', true, false);
+
+ if (document.readyState == 'loading')
+ document.addEventListener('DOMContentLoaded', initialize, true);
+ else
+ initialize();
+
+ function initialize() {
+ // create initial sliders
+ forEach.call(document.querySelectorAll('input[type=range]'), transform);
+ // create sliders on-the-fly
+ new MutationObserver(function (mutations) {
+ mutations.forEach(function (mutation) {
+ if (mutation.addedNodes)
+ forEach.call(mutation.addedNodes, function (node) {
+ check(node);
+ if (node.childElementCount)
+ forEach.call(node.querySelectorAll('input'), check);
+ });
+ });
+ }).observe(document, { childList: true, subtree: true });
+ }
+
+ function check(input) {
+ if (input.localName == 'input' && input.type != 'range' &&
+ input.getAttribute('type') == 'range')
+ transform(input);
+ }
+
+ function transform(slider) {
+
+ var isValueSet, areAttrsSet, isChanged, isClick, prevValue, rawValue, prevX;
+ var min, max, step, range, value = slider.value;
+
+ // lazily create shared slider affordance
+ if (!scale) {
+ scale = document.body.appendChild(document.createElement('hr'));
+ style(scale, {
+ '-moz-appearance': isMac ? 'scale-horizontal' : 'scalethumb-horizontal',
+ display: 'block',
+ visibility: 'visible',
+ opacity: 1,
+ position: 'fixed',
+ top: '-999999px'
+ });
+ document.mozSetImageElement('__sliderthumb__', scale);
+ }
+
+ // reimplement value and type properties
+ var getValue = function () {
+ return '' + value;
+ };
+ var setValue = function setValue(val) {
+ value = '' + val;
+ isValueSet = true;
+ draw();
+ delete slider.value;
+ slider.value = value;
+ slider.__defineGetter__('value', getValue);
+ slider.__defineSetter__('value', setValue);
+ };
+ slider.__defineGetter__('value', getValue);
+ slider.__defineSetter__('value', setValue);
+ slider.__defineGetter__('type', function () {
+ return 'range';
+ });
+
+ // sync properties with attributes
+ ['min', 'max', 'step'].forEach(function (prop) {
+ if (slider.hasAttribute(prop))
+ areAttrsSet = true;
+ slider.__defineGetter__(prop, function () {
+ return this.hasAttribute(prop) ? this.getAttribute(prop) : '';
+ });
+ slider.__defineSetter__(prop, function (val) {
+ val === null ? this.removeAttribute(prop) : this.setAttribute(prop, val);
+ });
+ });
+
+ // initialize slider
+ slider.readOnly = true;
+ style(slider, styles);
+ update();
+
+ new MutationObserver(function (mutations) {
+ mutations.forEach(function (mutation) {
+ if (mutation.attributeName != 'value') {
+ update();
+ areAttrsSet = true;
+ }
+ // note that value attribute only sets initial value
+ else if (!isValueSet) {
+ value = slider.getAttribute('value');
+ draw();
+ }
+ });
+ }).observe(slider, options);
+
+ slider.addEventListener('mousedown', onDragStart, true);
+ slider.addEventListener('keydown', onKeyDown, true);
+ slider.addEventListener('focus', onFocus, true);
+ slider.addEventListener('blur', onBlur, true);
+
+ function onDragStart(e) {
+ isClick = true;
+ setTimeout(function () {
+ isClick = false;
+ }, 0);
+ if (e.button || !range)
+ return;
+ var width = parseFloat(getComputedStyle(this, 0).width);
+ var multiplier = (width - thumb.width) / range;
+ if (!multiplier)
+ return;
+ // distance between click and center of thumb
+ var dev = e.clientX - this.getBoundingClientRect().left - thumb.width / 2 -
+ (value - min) * multiplier;
+ // if click was not on thumb, move thumb to click location
+ if (Math.abs(dev) > thumb.radius) {
+ isChanged = true;
+ this.value -= -dev / multiplier;
+ }
+ rawValue = value;
+ prevX = e.clientX;
+ this.addEventListener('mousemove', onDrag, true);
+ this.addEventListener('mouseup', onDragEnd, true);
+ }
+
+ function onDrag(e) {
+ var width = parseFloat(getComputedStyle(this, 0).width);
+ var multiplier = (width - thumb.width) / range;
+ if (!multiplier)
+ return;
+ rawValue += (e.clientX - prevX) / multiplier;
+ prevX = e.clientX;
+ isChanged = true;
+ this.value = rawValue;
+ }
+
+ function onDragEnd() {
+ this.removeEventListener('mousemove', onDrag, true);
+ this.removeEventListener('mouseup', onDragEnd, true);
+ }
+
+ function onKeyDown(e) {
+ if (e.keyCode > 36 && e.keyCode < 41) { // 37-40: left, up, right, down
+ onFocus.call(this);
+ isChanged = true;
+ this.value = value + (e.keyCode == 38 || e.keyCode == 39 ? step : -step);
+ }
+ }
+
+ function onFocus() {
+ if (!isClick)
+ this.style.boxShadow = !isMac ? '0 0 0 2px #fb0' :
+ 'inset 0 0 20px rgba(0,127,255,.1), 0 0 1px rgba(0,127,255,.4)';
+ }
+
+ function onBlur() {
+ this.style.boxShadow = '';
+ }
+
+ // determines whether value is valid number in attribute form
+ function isAttrNum(value) {
+ return !isNaN(value) && +value == parseFloat(value);
+ }
+
+ // validates min, max, and step attributes and redraws
+ function update() {
+ min = isAttrNum(slider.min) ? +slider.min : 0;
+ max = isAttrNum(slider.max) ? +slider.max : 100;
+ if (max < min)
+ max = min > 100 ? min : 100;
+ step = isAttrNum(slider.step) && slider.step > 0 ? +slider.step : 1;
+ range = max - min;
+ draw(true);
+ }
+
+ // recalculates value property
+ function calc() {
+ if (!isValueSet && !areAttrsSet)
+ value = slider.getAttribute('value');
+ if (!isAttrNum(value))
+ value = (min + max) / 2;
+ ;
+ // snap to step intervals (WebKit sometimes does not - bug?)
+ value = Math.round((value - min) / step) * step + min;
+ if (value < min)
+ value = min;
+ else if (value > max)
+ value = min + ~~(range / step) * step;
+ }
+
+ // renders slider using CSS background ;)
+ function draw(attrsModified) {
+ calc();
+ if (isChanged && value != prevValue)
+ slider.dispatchEvent(onChange);
+ isChanged = false;
+ if (!attrsModified && value == prevValue)
+ return;
+ prevValue = value;
+ var position = range ? (value - min) / range * 100 : 0;
+ var bg = '-moz-element(#__sliderthumb__) ' + position + '% no-repeat, ';
+ style(slider, { background: bg + track });
+ }
+
+ }
+
+ function style(element, styles) {
+ for (var prop in styles)
+ element.style.setProperty(prop, styles[prop], 'important');
+ }
+
+})();
\ No newline at end of file
diff --git a/templates/base.html b/templates/base.html
index 0824b54..a0e2116 100644
--- a/templates/base.html
+++ b/templates/base.html
@@ -9,6 +9,7 @@
{% compress css %}
+
@@ -57,6 +58,7 @@
+
diff --git a/templates/views/HeaderView.html b/templates/views/HeaderView.html
index 08d78af..ce09f10 100644
--- a/templates/views/HeaderView.html
+++ b/templates/views/HeaderView.html
@@ -34,6 +34,9 @@
{% endif %}
+
{% if user.is_authenticated %}
Upload
diff --git a/templates/views/NowPlayingView.html b/templates/views/NowPlayingView.html
index 7d12a82..d87b153 100644
--- a/templates/views/NowPlayingView.html
+++ b/templates/views/NowPlayingView.html
@@ -2,7 +2,7 @@
-