1
0
Fork 0
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

452 lines
11 KiB

/*jslint laxbreak:true */
/*jslint laxcomma:true */
/*jslint loopfunc:true */
/*jslint strict:true */
/*jslint browser:true */
/*jslint devel:true */
// Filename: app.js
define([
"underscore"
, "async"
, "backbone"
, "jquery"
, "bootstrap"
, "config"
, "views/app"
, "views/footer"
, "views/sidebar"
, "views/player"
, "views/main"
, "models/client"
// , "models/dmap"
, "collections/server"
, "collections/playlist"
, "views/client"
, "views/list"
, "text!../templates/app/modal-loading.html"
, "text!../templates/app/modal-login.html"
, "text!../templates/app/modal-about.html"
],
function(
_
, async
, Backbone
, $
, Bootstrap
, Config
, AppView
, FooterView
, SideBarView
, PlayerView
, MainView
, ClientModel
//, DMAPModel
, ServerCollection
, PlaylistCollection
, ClientView
, ListView
, tmplModalLoading
, tmplModalLogin
, tmplModalAbout
) {
"use strict";
var App = Backbone.Router.extend({
routes: {
"about": "_routerActionAbout"
, "playlist": "_routerActionPlaylist"
, "servers/:server": "_routerActionClient"
, "playlist/:item": "_routerActionPlaylistItem"
, ":server/items/:item": "_routerActionServerItem"
, "*actions": "_routerDefaultAction" // matches http://example.com/#anything-here
}
, historyStart: window.history.length
, playlist: null
, servers: null
, initialize: function() {
_.bindAll(this
, "_serversInited"
, "_routerActionAbout"
, "_routerActionPlaylist"
, "_routerActionClient"
, "_routerActionItem"
, "_routerActionServerItem"
, "_routerDefaultAction"
, "_serverInit"
, "__showModalAbout"
);
var that = this
;
console.log("app.js::init()");
// Setup underscore templates with mustache styles
_.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
this.servers = new ServerCollection();
this.playlist = new PlaylistCollection();
var serverLength = 0
, serverCbInit = function (server) {
if (serverLength > 1) {
--serverLength;
} else {
that._serversInited();
}
};
async.waterfall([
function __asyncAppFetchServerCollection(callback) {
that.servers.fetch({
success: function __fnApEventServersFetched(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) {
serverLength = servers.length;
async.forEach(that.servers.models, function __fnAppCbServerInit(server) {
that._serverInit(server, serverCbInit);
});
that.servers.on("add", function __fnAppCbServerAdded(server) {
server.save();
that._serverInit(server);
});
callback(null, servers);
}
]
, function __asyncAppDependenciesReady(err, result) {
that.Views = {};
that.Views.App = new AppView();
that.Views.SideBar = new SideBarView({
el: that.Views.App.Layout.panes.west
, servers: that.servers
});
that.Views.Player = new PlayerView({
el: that.Views.App.Layout.panes.north
, servers: that.servers
});
that.Views.Footer = new FooterView({
el: that.Views.App.Layout.panes.south
});
that.Views.Main = new MainView({
el: that.Views.App.Layout.panes.center
});
that.Views.Playlist = new ListView({
collection: that.playlist
, type: "playlist"
});
that.Views.Main.setView("playlist", that.Views.Playlist);
that.Views.Main.on("action:item", function __fnAppEventMainViewActionItem (event) {
});
that.Views.Main.on("action:playorder", function __fnAppEventMainViewActionItem (event) {
that.Views.Player.setPlayIndex(event);
});
that.Views.Footer.on("toggle:sidebar", function __fnAppEventTogglerSiderBar (event) {
that.Views.App.toggleSideBar();
that.Views.Main.resizeView();
});
that.Views.Footer.on("toggle:random", function __fnAppEventTogglerRandom (event) {
that.Views.Player.setRandomState(event);
});
that.Views.Footer.on("toggle:repeat", function __fnAppEventTogglerRepeater (event) {
that.Views.Player.setRepeatState(event);
});
that.Views.Footer.on("show:about", that.__showModalAbout);
that.Views.SideBar.on("add:playlist-item", function __fnAppEventPlaylistAddItem (event) {
var listItem = that.servers.get(event.hostname).client.collections.databases[event.dbId].get("dmap_listing").get(event.item).attributes
;
delete listItem._id;
listItem.id = event.hostname + ":" + event.dbId + ":" + event.item;
listItem = _.extend({}, listItem, {
server: event.hostname
, database: event.dbId
, order: new Date().toString()
});
that.playlist.on("add", function __fnAppSavePlaylistModel (model) {
model.save();
});
that.playlist.add(listItem);
});
that.Views.App.$el.delegate("div.modal", "hidden", function __fnAppEventRemoveModals (event) {
$(event.target).remove();
});
Backbone.history.start({
pushState: true
, root: Config.docRoot
});
// For now let's reset the state when we start up
//that.navigate("", false);
App.__super__.initialize.apply(that, that.routes);
});
return this;
}
, _serversInited: function () {
var that = this
;
console.debug("All Base Servers Inited!");
that.Views.Player.init();
that.Views.Player.playAtIndex(0);//Math.floor(Math.random() * that.Views.Player._playIndex.length));
}
, _routerDefaultAction: function () {
var that = this
;
if (!that.servers || that.servers.length === 0) {
Backbone.Router.prototype.navigate("about", true);
} else {
Backbone.Router.prototype.navigate("playlist", true);
}
}
, _routerActionAbout: function () {
var that = this
;
that.__showModalAbout();
}
, _routerActionPlaylist: function () {
var that = this
;
that.Views.SideBar.select("> ul > li:first");
that.Views.Main.showView("playlist");
}
, _routerActionClient: function (hostname) {
var that = this
, server = this.servers.get(hostname)
, client = server && server.client || undefined
;
if (server && client) {
that.Views.SideBar.select(server);
// FIXME: This needs to take client states into account
var __fnAppEventClientLoaded = function () {
if (!that.Views.Main.getView(server.get("hostname"))) {
that.Views.Main.setView(server.client.attributes.hostname, new ClientView({
/*el: that.Views.App.Layout.panes.center
, */server: server
, appendEl: that.Views.App.Layout.panes.center
}));
}
that.Views.Main.showView(server.get("hostname"));
}
, __fnAppEventClientInitited = function () {
client.fetchDatabases(function __fnAppCbFetchDatabases() {
client.fetchDatabase(function __fnAppCbFetchDatabase() {
client.fetchGenres(function __fnAppCbFetchGenres() {
client.fetchArtists(function __fnAppCbFetchArtists() {
client.fetchAlbums(function __fnAppCbFetchAlbums() {
__fnAppEventClientLoaded();
});
});
});
});
});
};
if (client.state < 4) {
client.on("inited", __fnAppEventClientInitited);
if (client.state <= 0) {
client.init();
}
} else if (client.state === 4) {
__fnAppEventClientInitited();
} else if (client.state > 4) {
__fnAppEventClientLoaded();
}
}
}
, _routerActionPlaylistItem: function (item) {
var that = this
;
that.Views.SideBar.select("> ul > li:first");
}
, _routerActionServerItem: function (server, item) {
var that = this
;
that.Views.SideBar.select(server);
that.Views.Main.showView(server.get("hostname"));
}
, _serverInit: function(server, cbInit) {
var that = this
;
that.loadingStates = 0;
that.loadingModal = $(tmplModalLoading);
that.loadingTimeout = null;
server.client.off("all");
server.client.on("inited", function __fnAppEventClientInited(client) {
cbInit(null, client);
});
server.client.on("state", function __fnAppEventClientStateChange(client, 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);
if (that.loadingModal.modal) {
that.loadingModal.modal("hide");
}
}
}
});
server.client.on("unauthorized", function __fnAppEventClientUnauthorized(client, xhr) {
var tmplHtml = _.template(tmplModalLogin)({ dmap_itemname: client.url() })
, serverModel = that.servers.get(client.attributes.hostname)
;
that._modalLogin = $(tmplHtml);
that._modalLogin.find("form").on("submit", function __fnAppEventModalLogin(event) {
var username = $(event.target).find("input[type='text']").val()
, password = $(event.target).find("input[type='password']").val()
, saveCredentials = $(event.target).find("input[type='checkbox']").is(':checked')
;
client.setAuth(username, password);
if (saveCredentials) {
var newModel = (_.clone({}, serverModel.attributes, {username: username, password: password}));
serverModel.set("username", username, {silent: true});
serverModel.set("password", password, {silent: true});
serverModel.save(newModel, {silence: true});
}
that._modalLogin.modal("hide");
setTimeout(client.init, 250);
event.preventDefault();
});
that._modalLogin.delegate("input[type='checkbox']", "click", function __fnEventModalRemember(event) {
if (event.target.checked === true) {
if (!confirm("Using this feature will save the login and password locally in clear text, are you sure?")) {
event.target.checked = false;
event.preventDefault();
}
}
});
setTimeout(function __fnEventAppUnauthorizedDisplayModal() {
that._modalLogin.modal();
}, 50);
});
server.client.init();
}
, __showModalAbout: function () {
var that = this
;
that._modalAbout = $(tmplModalAbout);
that._modalAbout.on("hidden", function __fnEventAppModalAboutClosed(event) {
// FIXME: Doesn't seem to work after 50 >_<
if (window.history.length === 50) {
window.history.length = 0;
that.historyStart = 1;
}
console.log(window.history.length, that.historyStart);
if (window.history.length === that.historyStart) {
that.navigate("", false);
} else {
window.history.back();
}
});
that._modalAbout.modal();
}
});
return App;
});