|
|
|
/*jslint laxbreak:true */
|
|
|
|
/*jslint laxcomma:true */
|
|
|
|
/*jslint loopfunc:true */
|
|
|
|
/*jslint strict:true */
|
|
|
|
/*jslint browser:true */
|
|
|
|
/*jslint devel:true */
|
|
|
|
|
|
|
|
define([
|
|
|
|
"underscore"
|
|
|
|
, "jquery"
|
|
|
|
, "backbone"
|
|
|
|
, "bootstrap"
|
|
|
|
, "async"
|
|
|
|
|
|
|
|
, "config"
|
|
|
|
|
|
|
|
, "collections/server"
|
|
|
|
|
|
|
|
, "text!../../templates/sidebar/server-list-item.html"
|
|
|
|
, "text!../../templates/sidebar/modal-new-server.html"
|
|
|
|
]
|
|
|
|
, function (
|
|
|
|
_
|
|
|
|
, $
|
|
|
|
, Backbone
|
|
|
|
, Bootstrap
|
|
|
|
, async
|
|
|
|
|
|
|
|
, Config
|
|
|
|
|
|
|
|
, ServerCollection
|
|
|
|
|
|
|
|
, tmplServerListItem
|
|
|
|
, tmplModalNewServer
|
|
|
|
) {
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var SideBar = Backbone.View.extend({
|
|
|
|
events: {
|
|
|
|
"click > ul > li:last-child > span > a.sidebar-list-action": "_addServerItem"
|
|
|
|
}
|
|
|
|
|
|
|
|
, router: null
|
|
|
|
|
|
|
|
, initialize: function (options) {
|
|
|
|
_.bindAll(this, "renderServerItem", "_addServerItem", "_routerActionPlaylist", "_routerActionClient");
|
|
|
|
var that = this
|
|
|
|
, serverModel = null
|
|
|
|
;
|
|
|
|
|
|
|
|
SideBar.__super__.initialize.apply(that, arguments);
|
|
|
|
|
|
|
|
this.servers = options.servers;
|
|
|
|
|
|
|
|
async.forEach(this.servers, that.renderServerItem, function __fnSideBarViewCbInitialRender() {
|
|
|
|
that.trigger("rendered");
|
|
|
|
|
|
|
|
that.router = new Backbone.Router.extend({
|
|
|
|
"playlist": that._routerActionPlaylist
|
|
|
|
, "servers/:server": that._routerActionClient
|
|
|
|
, ":server/items/:item": that._routerActionClient
|
|
|
|
//"*actions": "defaultRoute" // matches http://example.com/#anything-here
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
this.servers.on("add", function (server) {
|
|
|
|
that.renderServerItem(server);
|
|
|
|
});
|
|
|
|
|
|
|
|
this.$el.delegate("> ul > li:first-child", "click", function __fnSideBarEventDblclickPlaylist(event) {
|
|
|
|
Backbone.Router.prototype.navigate("playlist", true);
|
|
|
|
|
|
|
|
setTimeout(function __fnSideBarViewTimeoutTogglePlaylistClass() {
|
|
|
|
that.$el.find("li.selected").removeClass("selected");
|
|
|
|
$(event.target).parents("ul:first").find("> li:first-child").addClass("selected");
|
|
|
|
}, 10);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
, select: function (serverModel) {
|
|
|
|
var that = this
|
|
|
|
, cid = (serverModel.cid && "#" + serverModel.cid) || serverModel
|
|
|
|
, $server = that.$el.find(cid)
|
|
|
|
;
|
|
|
|
|
|
|
|
that.$el.find("li.selected").removeClass("selected");
|
|
|
|
$server.addClass("selected");
|
|
|
|
}
|
|
|
|
|
|
|
|
, _routerActionPlaylist: function (event) {
|
|
|
|
console.log(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
, _routerActionClient: function (event) {
|
|
|
|
console.log(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
, _addServerItem: function(event) {
|
|
|
|
var that = this
|
|
|
|
, modalEl = $(tmplModalNewServer)
|
|
|
|
;
|
|
|
|
|
|
|
|
modalEl.modal();
|
|
|
|
|
|
|
|
modalEl.find("button[data-save='modal']").on("click", function (event) {
|
|
|
|
modalEl.find("form").submit();
|
|
|
|
});
|
|
|
|
|
|
|
|
modalEl.find("form").on("submit", function (event) {
|
|
|
|
var $input = $(event.target).find("input")
|
|
|
|
, value = $input.val()
|
|
|
|
, protocol = "http"
|
|
|
|
, port = 3689
|
|
|
|
, domain = ""
|
|
|
|
, errors = []
|
|
|
|
;
|
|
|
|
|
|
|
|
if (value.substr(-1) === "/") {
|
|
|
|
value = value.substr(0, value.length - 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (/^(?:http|daap)(?:s)?:\/\//.test(value)) {
|
|
|
|
protocol = value.substring(0, value.indexOf(":")).replace("daap", "http");
|
|
|
|
|
|
|
|
value = value.substr(value.indexOf(":") + 3);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (value.indexOf(":") > 0) {
|
|
|
|
port = value.substring(value.indexOf(":") + 1);
|
|
|
|
|
|
|
|
value = value.substring(0, value.indexOf(":"));
|
|
|
|
} else if (protocol === "https") {
|
|
|
|
port = 443;
|
|
|
|
}
|
|
|
|
|
|
|
|
domain = value.toLowerCase();
|
|
|
|
|
|
|
|
if (isNaN((port = parseInt(port, 10)))) {
|
|
|
|
errors.push("Invalid port number: 3689");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (protocol !== "http" && protocol !== "https") {
|
|
|
|
errors.push("Invalid protocol: http(s)");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_.isEmpty(domain)
|
|
|
|
|| /^([a-z0-9]([\-a-z0-9]*[a-z0-9])?\\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/.test(domain)) {
|
|
|
|
errors.push("Invalid server domain");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (errors.length > 0) {
|
|
|
|
alert("Please correct the following errors:\n" + errors.join("\n"));
|
|
|
|
} else {
|
|
|
|
modalEl.modal("hide");
|
|
|
|
|
|
|
|
that.servers.add({
|
|
|
|
protocol: protocol
|
|
|
|
, port: port
|
|
|
|
, hostname: domain
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
});
|
|
|
|
|
|
|
|
modalEl.on("hidden", function (event) {
|
|
|
|
$(event.target).remove();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
, renderServerItem: function (item) {
|
|
|
|
var that = this
|
|
|
|
, itemHtml = _.template(tmplServerListItem, {
|
|
|
|
cid: item.cid
|
|
|
|
, server_name: item.getName()
|
|
|
|
})
|
|
|
|
, $item = $(itemHtml)
|
|
|
|
;
|
|
|
|
|
|
|
|
this.$el.find("ul:first > li > ul.siderbar-server-list").append($item);
|
|
|
|
|
|
|
|
item.on("change", function __fnSideBarViewClientItemChanged(event) {
|
|
|
|
if (event.get("name")) {
|
|
|
|
$item.find("span > span").text(event.getName());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
item.client.on("state", function __fnSideBarViewEventClientState(client, state) {
|
|
|
|
that.changeServerItemState($item.find("span > i:first-child"), client, state);
|
|
|
|
});
|
|
|
|
|
|
|
|
$item.find("a.sidebar-list-action").on("click", function (model) {
|
|
|
|
return function __fnSideBarClickRemoveAction (event) {
|
|
|
|
var confirmMessage = "Are you sure you want to delete:\n" + item.getName();
|
|
|
|
|
|
|
|
if (window.confirm(confirmMessage)) {
|
|
|
|
$(event.target).parents("li:first").fadeOut(300, function() { $(this).remove(); });
|
|
|
|
|
|
|
|
setTimeout(function () {
|
|
|
|
model.destroy();
|
|
|
|
}, 10);
|
|
|
|
}
|
|
|
|
|
|
|
|
event.preventDefault();
|
|
|
|
};
|
|
|
|
}(item));
|
|
|
|
|
|
|
|
$item.on("click", function __fnSideBarViewEventDblClickItem(event) {
|
|
|
|
// FIXME: This needs to check the state of the client and debounce
|
|
|
|
that.$el.find("li.selected").removeClass("selected");
|
|
|
|
$item.addClass("selected");
|
|
|
|
/*
|
|
|
|
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, true);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
, changeServerItemState: function ($glyph, client, state) {
|
|
|
|
var newClass = "icon-folder-closed"
|
|
|
|
;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case 2:
|
|
|
|
case 5:
|
|
|
|
newClass = "icon-loading";
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
newClass = "icon-exclamation-sign";
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
newClass = "icon-ok-sign";
|
|
|
|
break;
|
|
|
|
case 6:
|
|
|
|
newClass = "icon-folder-open";
|
|
|
|
break;
|
|
|
|
case -1:
|
|
|
|
newClass = "icon-warning-sign";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
case 0:
|
|
|
|
case 1:
|
|
|
|
newClass = "icon-folder-closed";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
$glyph.removeClass();
|
|
|
|
$glyph.addClass(newClass);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return SideBar;
|
|
|
|
});
|