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.

296 lines
7.3 KiB

/*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/layout.html"
, "text!../../templates/sidebar/server-list-item.html"
, "text!../../templates/sidebar/modal-new-server.html"
// Plugins
, "jquery-ui"
]
, function (
_
, $
, Backbone
, Bootstrap
, async
, Config
, ServerCollection
, tmplSideBarLayout
, 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"
, "changeServerItemState"
, "_addServerItem"
, "_routerActionPlaylist"
, "_routerActionClient"
, "_addPlaylistItem"
);
var that = this
, serverModel = null
;
SideBar.__super__.initialize.apply(that, arguments);
this.servers = options.servers;
that.$el.html(tmplSideBarLayout);
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);
});
this.$el.find("> ul > li:first > span").droppable({
activeClass: "droppable"
, hoverClass: "droppable-hover"
, scope: "list-item"
, tolerance: "touch" // We really need this cause our items
// are much bigger than the droppable
, drop: that._addPlaylistItem
});
}
, 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();
});
}
, _addPlaylistItem: function (event, ui) {
var that = this
, dropData = $(ui.draggable[0]).data()
, item = _.clone(dropData)
;
if (item.draggable) {
delete item.draggable;
delete item.uiDraggable;
}
that.trigger("add:playlist-item", item);
}
, 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();
return false;
};
}(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;
});