1
0
Fork 0

Moar, always moar commit messages... I'm sorry

master
Matthieu Lalonde 12 years ago committed by xSmurf
parent edd00380cf
commit f3146522fc

@ -17,8 +17,8 @@
@import "/resources/css/player.css"; @import "/resources/css/player.css";
</style> </style>
<script src="resources/js/libs/utils.js">/**/</script> <script src="/resources/js/libs/utils.js">/**/</script>
<script data-main="resources/js/main" src="resources/vendors/require/require.min.js">/**/</script> <script data-main="/resources/js/main" src="/resources/vendors/require/require.min.js">/**/</script>
</head> </head>
<body> <body>
<div class="ui-layout-north" id="wrapperPlayer"> <div class="ui-layout-north" id="wrapperPlayer">
@ -104,7 +104,7 @@
<div class="ui-layout-south row-fluid" id="wrapperFooter"> <div class="ui-layout-south row-fluid" id="wrapperFooter">
<div id="wrapperFooterLeft" class="span4 row-fluid"> <div id="wrapperFooterLeft" class="span4 row-fluid">
<div class="span2"> <div class="span2">
<button class="btn btn-mini btn-inverse" type="button" data-toggle="side-bar"><i class="icon-chevron-right icon-white"></i></button> <button class="btn btn-mini btn-inverse" type="button" data-toggle="side-bar"><i class="icon-chevron-left icon-white"></i></button>
</div> </div>
<button class="btn btn-mini btn-inverse" type="button" data-toggle="button"><i class="icon-random icon-white"></i></button> <button class="btn btn-mini btn-inverse" type="button" data-toggle="button"><i class="icon-random icon-white"></i></button>
<button class="btn btn-mini btn-inverse" type="button" data-toggle="button"><i class="icon-retweet icon-white"></i></button> <button class="btn btn-mini btn-inverse" type="button" data-toggle="button"><i class="icon-retweet icon-white"></i></button>
@ -195,34 +195,6 @@
</div> </div>
</script> </script>
<script type="text/html" id="_tmplModalAboutDaapr">
<div id="modalAboutDaapr" data-closable="true">
<div class="overlay"></div>
<div class="modal" data-show="true" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-header">
<h3 id="myModalLabel">About DAAPr<sup>3</sup></h3>
</div>
<div class="modal-body" style="font-size: 1.2em">
<p>
<b>DAAPr</b>, in its cubic iteration, is a web client for the
<a href="http://en.wikipedia.org/wiki/Digital_Audio_Access_Protocol" title="Digital Audio Access Protocol">DAAP</a> media sharing protocol.
It is 100% client side javascript built using <a href="http://backbonejs.org" title="Backbone.js">Backbone.js</a>,
<a href="http://jquery.com">jQuery</a> and <a href="http://twitter.github.com/bootstrap/" title="Twitter Bootstrap">Bootstrap</a>.
</p>
<p>
<a href="https://matth.lalonde.me/contact/">Feedback</a> is appreciated.
</p>
<p>
This software is <a href="http://en.wikipedia.org/wiki/Copyleft">Copyleft</a> 2012 <a href="https://matth.lalonde.me">Matthieu Lalonde</a> under <a href="http://www.gnu.org/copyleft/lesser.html">LGPL</a>, no guarantees whatsoever.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-mini btn-primary" data-dismiss="modal" aria-hidden="true"><i class="icon-remove"></i>&nbsp;Close</button>
</div>
</div>
</div>
</script>
<script type="text/html" id="_tmplModalFatal"> <script type="text/html" id="_tmplModalFatal">
<div id="modalFatal"> <div id="modalFatal">
<div class="overlay"></div> <div class="overlay"></div>

@ -8,6 +8,11 @@
// Filename: app.js // Filename: app.js
define([ define([
"underscore" "underscore"
, "jquery"
, "backbone"
, "async"
, "config"
, "views/app" , "views/app"
, "views/footer" , "views/footer"
@ -15,11 +20,21 @@ define([
, "views/player" , "views/player"
, "views/main" , "views/main"
// , "models/client" , "models/client"
, "models/dmap" // , "models/dmap"
, "collections/server"
, "text!../templates/app/modal-loading.html"
, "text!../templates/app/modal-login.html"
], ],
function( function(
_ _
, $
, Backbone
, async
, Config
, AppView , AppView
, FooterView , FooterView
@ -27,47 +42,164 @@ _
, PlayerView , PlayerView
, MainView , MainView
//, ClientModel , ClientModel
, DMAPModel //, DMAPModel
, ServerCollection
, tmplModalLoading
, tmplModalLogin
) { ) {
"use strict"; "use strict";
var init = function() { return {
init: function() {
_.bindAll(this
, "_serverInit"
);
var that = this
;
console.log("app.js::init()"); console.log("app.js::init()");
// Setup underscore templates with mustache styles // Setup underscore templates with mustache styles
_.templateSettings.interpolate = /\{\{(.+?)\}\}/g; _.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
this.Views = {}; var Router = Backbone.Router.extend({
routes: {
this.Views.SideBar = new SideBarView(); "playlist": "_routerActionPlaylist"
this.Views.Player = new PlayerView(); , "servers": "_routerActionClient"
this.Views.Main = new MainView(); , "items/:id": "_routerActionItem"
this.Views.App = new AppView(); , ":server/items/:id": "_routerActionServerItem"
this.Views.Footer = new FooterView(this.Views.App); //"*actions": "defaultRoute" // matches http://example.com/#anything-here
/* }
var client = new ClientModel({ });
hostname: "daap.localhost"
, protocol: "http" this.Router = new Router();
, port: 80
, password: "lawl" Backbone.history.start({
pushState: true
, root: "/"
}); });
client.on("unauthorized", function __client_unauthorized() { this.servers = new ServerCollection();
this.servers.on("add", function (server) {
server.save();
});
this.servers.on("client:unauthorized", function __fnAppEventClientUnauthorized(event) {
var client = event.shift()
;
console.log(arguments); console.log(arguments);
}); });
client.on("inited", function (collections) { this.loadingStates = 0;
console.log(client.url(), arguments); this.loadingModal = $(tmplModalLoading);
this.loadingTimeout = null;
async.waterfall([
function __asyncAppFetchServerCollection(callback) {
that.servers.fetch({
success: function (collection, modelsAttributes) {
if (modelsAttributes.length === 0) {
console.info("Adding default daap server");
collection.add(Config.daap);
}
callback(null, collection);
}
, error: callback
});
}
, function __asyncAppAttachStateEvents(servers, callback) {
async.forEach(that.servers.models, function (server) {
that._serverInit(server);
});
that.servers.on("add", function (server) {
that._serverInit(server);
});
callback(null, servers);
}
]
, function __asyncAppDependenciesReady(err, result) {
that.Views = {};
that.Views.SideBar = new SideBarView(that.servers);
that.Views.Player = new PlayerView();
that.Views.Main = new MainView();
that.Views.App = new AppView();
that.Views.Footer = new FooterView();
that.Views.Footer.on("toggle:sidebar", function __fnAppEventTogglerSiderBar() {
that.Views.App.toggleSideBar();
});
that.Views.App.$el.delegate("div.modal", "hidden", function __fnAppEventRemoveModals(event) {
$(event.target).remove();
});
var item = collections.databases[collections.databasesInfo.get("dmap_listing").at(0).id].get("dmap_listing").get(107);
console.log(item, item.toJSON(), collections.databases[collections.databasesInfo.get("dmap_listing").at(0).id].get("dmap_listing").toJSON());
}); });
*/
//client.init();
return this; return this;
}
, _routerActionPlaylist: function () {
}
, _routerActionClient: function (hostname) {
}
, _routerActionItem: function (item) {
}
, _routerActionServerItem: function (server, item) {
}
, _serverInit: function(server) {
var that = this
;
server.client.on("state", function __fnAppEventClientStateChange(client, state) {
console.log(state);
if (state === ClientModel.defaults._states.loading) {
if (that.loadingStates === 0) {
that.loadingTimeout = setTimeout(function __fnAppTimeoutLoadingStat() {
that.loadingModal.modal();
that.loadingTimeout = null;
}, 800);
}
that.loadingStates++;
} else if (state === ClientModel.defaults._states.loaded) {
that.loadingStates--;
if (that.loadingStates === 0) {
clearTimeout(that.loadingTimeout);
that.loadingModal.modal("hide");
}
}
});
server.client.on("unauthorized", function __fnAppEventClientUnauthorized(client, xhr) {
var tmplHtml = _.template(tmplModalLogin)({ dmap_itemname: client.url() })
, $tmpl = $(tmplHtml)
;
$tmpl.modal();
});
server.client.init();
}
}; };
return { init: init };
}); });

@ -15,14 +15,29 @@ define([
, function (_, Backbone, ServerModel) { , function (_, Backbone, ServerModel) {
"use strict"; "use strict";
return Backbone.Collection.extend({ var Server = Backbone.Collection.extend({
model: ServerModel model: ServerModel
, localStorage: new Backbone.LocalStorage("daap-servers") , localStorage: new Backbone.LocalStorage("daap-servers")
/*
, initialize: function () { , initialize: function () {
return this.__super__.initialize.call(this, arguments); _.bindAll(this, "relayClientTrigger");
//this.on("all", this.relayClientTrigger);
return Server.__super__.initialize.call(this, arguments);
} }
*/ /*
, relayClientTrigger: function() {
var eventName = arguments[0]
;
console.log(eventName);
if (eventName.indexOf("client") === 0) {
delete arguments[0];
//this.trigger(eventName, _.values(arguments));
}
}*/
}); });
return Server;
}); });

@ -71,7 +71,7 @@ require.config({
//, "config": "config" //, "config": "config"
} }
, baseUrl: "./resources/js" , baseUrl: "/resources/js"
, urlArgs: "v=0.3.2" , urlArgs: "v=0.3.2"
}); });

@ -227,8 +227,9 @@ define([
callback(null, this.response); callback(null, this.response);
} else if (this.status === 401) { } else if (this.status === 401) {
that.setState("unauthorized"); that.setState("unauthorized");
that.trigger("unauthorized", [this, e]); that.trigger("unauthorized", that, [this, e]);
} else { } else {
that.setState("failed");
callback(e.status); callback(e.status);
} }
}; };
@ -297,7 +298,12 @@ define([
var that = this var that = this
; ;
this.setState("loading");
that.fetchXHR("/databases", function __fetchDatabasesCallback(content) { that.fetchXHR("/databases", function __fetchDatabasesCallback(content) {
that.setState("loaded");
that.collections.databasesInfo = new DMAPModel(content, { that.collections.databasesInfo = new DMAPModel(content, {
contentCodes: that.collections.contentCodes contentCodes: that.collections.contentCodes
}); });
@ -316,7 +322,12 @@ define([
dbId = 1; dbId = 1;
} }
this.setState("loading");
that.fetchXHR("/databases/" + dbId + "/items", function __fetchDatabaseCallback(content) { that.fetchXHR("/databases/" + dbId + "/items", function __fetchDatabaseCallback(content) {
that.setState("loaded");
that.collections.databases[dbId] = new DMAPModel(content, { that.collections.databases[dbId] = new DMAPModel(content, {
contentCodes: that.collections.contentCodes contentCodes: that.collections.contentCodes
}); });
@ -335,7 +346,12 @@ define([
dbId = 1; dbId = 1;
} }
this.setState("loading");
that.fetchXHR("/databases/" + dbId + "/containers", function __fetchPlaylistsCallback(content) { that.fetchXHR("/databases/" + dbId + "/containers", function __fetchPlaylistsCallback(content) {
that.setState("loaded");
that.collections.playlistsInfo = new DMAPModel(content, { that.collections.playlistsInfo = new DMAPModel(content, {
contentCodes: that.collections.contentCodes contentCodes: that.collections.contentCodes
}); });
@ -367,7 +383,12 @@ define([
requestUri += "/items"; requestUri += "/items";
requestUri += "?meta=dmap.itemid,dmap.persistentid,dmap.containeritemid"; requestUri += "?meta=dmap.itemid,dmap.persistentid,dmap.containeritemid";
this.setState("loading");
that.fetchXHR(requestUri, function __fetchPlaylistCallback(content) { that.fetchXHR(requestUri, function __fetchPlaylistCallback(content) {
that.setState("loaded");
if (!_.isArray(that.collections.playlists[dbId])) { if (!_.isArray(that.collections.playlists[dbId])) {
that.collections.playlists[dbId] = []; that.collections.playlists[dbId] = [];
} }
@ -400,7 +421,11 @@ define([
requestUri += "?meta=dmap.itemid,dmap.persistentid,dmap.containeritemid"; requestUri += "?meta=dmap.itemid,dmap.persistentid,dmap.containeritemid";
this.setState("loading");
that.fetchXHR(requestUri, function __fetchBrowseCallback(content) { that.fetchXHR(requestUri, function __fetchBrowseCallback(content) {
that.setState("loaded");
that.collections.browser[type][dbId] = new DMAPModel(content, { that.collections.browser[type][dbId] = new DMAPModel(content, {
contentCodes: that.collections.contentCodes contentCodes: that.collections.contentCodes
}); });
@ -458,7 +483,8 @@ define([
, state: 0 , state: 0
, _states: { , _states: {
disconnected: 0 failed: -1
, disconnected: 0
, timedout: 1 , timedout: 1
, connecting: 2 , connecting: 2
, unauthorized: 3 , unauthorized: 3

@ -16,6 +16,7 @@ define([
var Model = Backbone.Model.extend({ var Model = Backbone.Model.extend({
client: null client: null
, idAttribute: "hostname"
, initialize: function (attributes, options) { , initialize: function (attributes, options) {
_.bindAll(this, "destroy", "getName", "relayEvent"); _.bindAll(this, "destroy", "getName", "relayEvent");
@ -30,21 +31,23 @@ define([
// We could save here, but it is debatable if we want to leep the name attribute locally // We could save here, but it is debatable if we want to leep the name attribute locally
// that.save(); // that.save();
} }
//that.client.fetchDatabases(that.client.fetchDatabase);
}); });
this.client.on("all", this.relayEvent); //this.client.on("all", this.relayEvent);
return Model.__super__.initialize.call(this, arguments); return Model.__super__.initialize.call(this, arguments);
} }
/*
, relayEvent: function () { , relayEvent: function () {
var args = _.values(arguments) var eventName = arguments[0]
, eventName = args.shift()
; ;
delete arguments[0];
this.trigger("client:" + eventName, args); console.log(eventName);
this.trigger("client:" + eventName, _.values(arguments));
} }
*/
, destroy: function () { , destroy: function () {
if (this.client && this.client.deinit) { if (this.client && this.client.deinit) {
this.client.deinit(); this.client.deinit();

@ -6,11 +6,12 @@
/*jslint devel:true */ /*jslint devel:true */
define([ define([
"jquery" "underscore"
, "jquery"
, "backbone" , "backbone"
, "jquery-layout" , "jquery-layout"
] ]
, function ($, Backbone) { , function (_, $, Backbone) {
"use strict"; "use strict";
return Backbone.View.extend({ return Backbone.View.extend({
@ -23,7 +24,7 @@ define([
} }
, initialize: function() { , initialize: function() {
//_.bindAll(this); _.bindAll(this, "toggleSideBar");
var that = this; var that = this;
@ -55,5 +56,9 @@ define([
} }
}); });
} }
, toggleSideBar: function () {
this.layout.toggle("west");
}
}); });
}); });

@ -5,22 +5,29 @@
/*jslint browser:true */ /*jslint browser:true */
/*jslint devel:true */ /*jslint devel:true */
define([ define([
"jquery" "underscore"
, "jquery"
, "backbone" , "backbone"
, "bootstrap" , "bootstrap"
, "text!../../templates/footer/modal-about.html"
] ]
, function ($, Backbone, Bootstrap) { , function (_, $, Backbone, Bootstrap, tmplModalAbout) {
"use strict"; "use strict";
return Backbone.View.extend({ var View = Backbone.View.extend({
el: $("div#wrapperFooter") el: $("div#wrapperFooter")
, initialize: function (AppView) { , events: {
"click button[data-target='modalAboutDaapr']": "_buttonAboutClick"
}
, initialize: function () {
var that = this var that = this
; ;
that.$el.delegate("button[data-toggle='side-bar']", "click", function (event) { that.$el.delegate("button[data-toggle='side-bar']", "click", function (event) {
AppView.layout.toggle("west"); that.trigger("toggle:sidebar");
var $target = $(event.target); var $target = $(event.target);
if (event.target.tagName === "BUTTON") { if (event.target.tagName === "BUTTON") {
@ -30,6 +37,16 @@ define([
$target.toggleClass("icon-chevron-right"); $target.toggleClass("icon-chevron-right");
$target.toggleClass("icon-chevron-left"); $target.toggleClass("icon-chevron-left");
}); });
}
, _buttonAboutClick: function(event) {
var $modal = $(tmplModalAbout)
;
$modal.modal();
} }
}); });
return View;
}); });

@ -0,0 +1,18 @@
/*jslint laxbreak:true */
/*jslint laxcomma:true */
/*jslint loopfunc:true */
/*jslint strict:true */
/*jslint browser:true */
/*jslint devel:true */
define([
"jquery"
, "backbone"
, "bootstrap"
]
, function ($, Backbone, Bootstrap) {
"use strict";
return Backbone.View.extend({
});
});

@ -43,28 +43,29 @@ _
"click > ul > li:last-child > span > a.sidebar-list-action": "_addServerItem" "click > ul > li:last-child > span > a.sidebar-list-action": "_addServerItem"
} }
, initialize: function () { , initialize: function (servers) {
_.bindAll(this, "renderServerItem", "_addServerItem"); _.bindAll(this, "renderServerItem", "_addServerItem");
var that = this var that = this
, serverModel = null , serverModel = null
; ;
this.servers = new ServerCollection(); this.servers = servers;
this.servers.fetch({ async.forEach(this.servers, that.renderServerItem, function __fnSideBarViewCbInitialRender() {
success: function (collection, modelsAttributes) { that.trigger("rendered");
if (modelsAttributes.length === 0) {
console.info("Adding default daap server");
collection.add(Config.daap);
}
async.forEach(collection.models, that.renderServerItem);
}
}); });
this.servers.on("add", function (server) { this.servers.on("add", function (server) {
that.renderServerItem(server); that.renderServerItem(server);
server.save(); });
this.$el.delegate("> ul > li:first-child", "dblclick", function __fnSideBarEventDblclickPlaylist(event) {
Backbone.Router.prototype.navigate("playlist", false);
setTimeout(function __fnSideBarViewTimeoutTogglePlaylistClass() {
that.$el.find("li.selected").removeClass("selected");
$(event.target).parents("ul:first").find("> li:first-child").addClass("selected");
}, 10);
}); });
} }
@ -126,13 +127,11 @@ _
} else { } else {
modalEl.modal("hide"); modalEl.modal("hide");
setTimeout(function __fnSaveServerModel() {
that.servers.add({ that.servers.add({
protocol: protocol protocol: protocol
, port: port , port: port
, hostname: domain , hostname: domain
}); });
}, 10);
} }
return false; return false;
@ -159,12 +158,10 @@ _
} }
}); });
item.on("client:state", function __fnSideBarViewEventClientState(event) { item.client.on("state", function __fnSideBarViewEventClientState(client, state) {
that.changeServerItemState($item.find("span > i:first-child"), event); that.changeServerItemState($item.find("span > i:first-child"), client, state);
}); });
item.client.init();
$item.find("a.sidebar-list-action").on("click", function (model) { $item.find("a.sidebar-list-action").on("click", function (model) {
return function __fnSideBarClickRemoveAction (event) { return function __fnSideBarClickRemoveAction (event) {
var confirmMessage = "Are you sure you want to delete:\n" + item.getName(); var confirmMessage = "Are you sure you want to delete:\n" + item.getName();
@ -179,17 +176,22 @@ _
}; };
}(item)); }(item));
$item.on("dblclick", function (model) { $item.on("dblclick", function __fnSideBarViewEventDblClickItem(event) {
return function __fnSideBarViewEventDblClickItem(event) { that.$el.find("li.selected").removeClass("selected");
$item.addClass("selected");
}; /*
}(item)); if (item.client.state < item.client._states.loaded) {
item.client.fetchDatabases(item.client.fetchDatabase);
} else {
console.log(item.client.collections);
}
*/
Backbone.Router.prototype.navigate("servers/" + item.id, false);
});
} }
, changeServerItemState: function ($glyph, event) { , changeServerItemState: function ($glyph, client, state) {
var newClass = "icon-folder-closed" var newClass = "icon-folder-closed"
, client = event.shift()
, state = event.shift()
; ;
switch (state) { switch (state) {
@ -206,6 +208,9 @@ _
case 6: case 6:
newClass = "icon-folder-open"; newClass = "icon-folder-open";
break; break;
case -1:
newClass = "icon-warning-sign";
break;
default: default:
case 0: case 0:
case 1: case 1:

@ -0,0 +1,14 @@
<div class="modal span4"
data-backdrop="static"
data-keyboard="false"
data-show="true"
tabindex="-1" role="dialog">
<div class="modal-header">
<h4>Loading</h4>
</div>
<div class="modal-body" style="padding: 10px 10px 0 10px;">
<div class="progress progress-striped">
<div class="bar" style="width: 100%;"></div>
</div>
</div>
</div>

@ -0,0 +1,22 @@
<div class="modal" data-show="true" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-body" style="font-size: 1.2em">
<form>
<fieldset>
<legend>{{dmap_itemname}} login</legend>
<p>
<input type="text" class="input-large" placeholder="Login">
</p>
<p>
<input type="password" class="input-large" placeholder="Password">
</p>
<!--label class="checkbox">
<input type="checkbox"> Remember me
</label-->
</fieldset>
</form>
</div>
<div class="modal-footer">
<button class="btn btn-mini" data-dismiss="modal" aria-hidden="true"><i class="icon-remove"></i>&nbsp;Cancel</button>
<button class="btn btn-mini btn-primary" data-dismiss="modal" aria-hidden="true"><i class="icon-ok"></i>&nbsp;Login</button>
</div>
</div>

@ -0,0 +1,26 @@
<div class="modal"
data-backdrop="true"
data-keyboard="true"
data-show="true"
tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-header">
<h3 id="myModalLabel">About DAAPr<sup>3</sup></h3>
</div>
<div class="modal-body" style="font-size: 1.2em">
<p>
<b>DAAPr</b>, in its cubic iteration, is a web client for the
<a href="http://en.wikipedia.org/wiki/Digital_Audio_Access_Protocol" title="Digital Audio Access Protocol">DAAP</a> media sharing protocol.
It is 100% client side javascript built using <a href="http://backbonejs.org" title="Backbone.js">Backbone.js</a>,
<a href="http://jquery.com">jQuery</a> and <a href="http://twitter.github.com/bootstrap/" title="Twitter Bootstrap">Bootstrap</a>.
</p>
<p>
<a href="https://matth.lalonde.me/contact/">Feedback</a> is appreciated.
</p>
<p>
This software is <a href="http://en.wikipedia.org/wiki/Copyleft">Copyleft</a> 2012 <a href="https://matth.lalonde.me">Matthieu Lalonde</a> under <a href="http://www.gnu.org/copyleft/lesser.html">LGPL</a>, no guarantees whatsoever.
</p>
</div>
<div class="modal-footer">
<button class="btn btn-mini btn-primary" data-dismiss="modal" aria-hidden="true"><i class="icon-remove"></i>&nbsp;Close</button>
</div>
</div>
Loading…
Cancel
Save