Added Backbone

This commit is contained in:
Mattias Erming 2014-03-07 22:24:02 +01:00
parent efa3fcd7ab
commit bd963fbd8c
7 changed files with 114 additions and 279 deletions

27
app.js
View file

@ -1,7 +1,4 @@
var commander = require("commander")
var listen = require("./lib/server.js").listen;
var argv = commander
var argv = require("commander")
.option("-p, --port <n>", "port to use", parseInt)
.parse(process.argv);
@ -10,4 +7,24 @@ if (argv.port) {
PORT = argv.port;
}
listen(PORT);
var server =
new (require("./lib/server.js"))()
.listen(PORT);
// Temp
var models = require("./lib/models.js");
var network = new models.Network({host: "irc.network.org"});
server.networks.add(network);
network.get("channels").add(new models.Channel({
name: "#foo",
messages: [
new models.Message({user: "user", text: "Hi!"}),
new models.Message({user: "user", text: ".. Hello?"}),
],
users: [
new models.User({name: "user"}),
new models.User({name: "other_user"}),
]
}));

View file

@ -27,13 +27,13 @@ h2 {
border-right: 1px solid #ccc;
float: left;
height: 100%;
line-height: 36px;
width: 199px;
}
#sidebar .channel {
border-bottom: 1px solid transparent;
color: #f00;
cursor: pointer;
line-height: 1.8em;
padding: 0 12px;
}
#sidebar .channel:first-child {
@ -43,9 +43,16 @@ h2 {
#sidebar .channel:hover {
text-decoration: underline;
}
#sidebar .network:first-child .channel:first-child {
#sidebar .network {
margin-top: 1em;
}
#sidebar .network:first-child {
margin-top: 0;
}
#sidebar .network:first-child .channel {
background: #eaeaea;
border-bottom-color: #e5e5e5;
line-height: 36px;
}
#chat {
bottom: 0;

View file

@ -43,7 +43,7 @@
<script type="text/html" id="users">
{{#users}}
<div class="user" data-id="{{id}}">
{{name}}
{{mode}}{{name}}
</div>
{{/users}}
</script>

View file

@ -1,7 +1,10 @@
$(function() {
var socket = io.connect("");
socket.on("event", function(event) {
render(event);
socket.on("event", function(data) {
render(data);
// Debug
console.log(data);
});
var chat = $("#chat");
@ -13,49 +16,7 @@ $(function() {
var messages = $("#messages").html();
var users = $("#users").html()
function render(event) {
var type = event.type;
var data = event.data;
var action = event.action;
var target = event.target;
if (action == "REMOVE") {
remove(target);
return;
}
if (target != "") {
target = $("[data-id='" + target + "']");
}
switch (type) {
case "NETWORK":
case "CHANNEL":
refresh(data);
break;
case "USER":
target = target.find(".users");
target.html(Mustache.render(users, {users: event.data}));
break;
case "MESSAGE":
var keepAtBottom = target.isScrollBottom();
target = target.find(".messages");
target.append(Mustache.render(messages, {messages: event.data}));
if (keepAtBottom) {
target.scrollToBottom();
}
break;
}
}
function remove(id) {
$("[data-id='" + id + "']").remove();
}
function refresh(data) {
function render(data) {
chat.html("");
var partials = {
users: users,
@ -80,60 +41,6 @@ $(function() {
.focus();
}
var View = {};
View.refresh = function(event) {
var data = event.data;
sidebar.html(
Mustache.render(networks, {
networks: data
})
);
chat.html("");
var partials = {
users: users,
messages: messages
};
data.forEach(function(network) {
chat.append(Mustache.render(channels, network, partials));
});
chat.find(".messages").scrollToBottom();
chat.find(".window")
// Sort windows by `data-id` value.
.sort(function(a, b) { return ($(a).data("id") - $(b).data("id")); })
.last()
.bringToTop()
.find(".input")
.focus();
};
View.add = function(event) {
var target = $("[data-id='" + event.target + "'] ");
switch (event.type) {
case "users":
target = target.find(".users");
target.html(Mustache.render(users, {users: event.data}));
break;
case "messages":
var keepAtBottom = target.isScrollBottom();
target = target.find(".messages");
target.append(Mustache.render(messages, {messages: event.data}));
if (keepAtBottom) {
target.scrollToBottom();
}
break;
}
};
View.remove = function(event) {
$("[data-id='" + event.target + "']").remove();
};
chat.on("submit", "form", function() {
var input = $(this).find(".input");
var text = input.val();

View file

@ -1,66 +1,67 @@
var _ = require("lodash");
var Backbone = require("backbone");
var moment = require("moment");
var models = exports;
var models =
module.exports =
{};
var id = 1;
models.Network = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
id: id++,
address: "",
nick: "",
channels: []
}));
};
models.User = Backbone.Model.extend({
defaults: {
mode: "",
name: "user"
}
});
models.Network.prototype.toJSON = function() {
return _.omit(this, "client");
};
models.Message = Backbone.Model.extend({
defaults: {
time: moment().format("HH:mm"),
user: "user",
text: "text"
}
});
models.Channel = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
id: id++,
name: "",
models.Channel = Backbone.Model.extend({
defaults: {
type: "channel",
name: "",
topic: "",
users: [],
messages: []
}));
};
},
initialize: function() {
this.set({
id: id++
});
}
});
models.User = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
id: id++,
name: ""
}));
};
models.ChannelCollection = Backbone.Collection.extend({
model: models.Channel
});
models.Message = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
time: moment().format("HH:mm"),
user: "",
text: ""
}));
};
models.Network = Backbone.Model.extend({
defaults: {
host: "",
},
initialize: function() {
this.set({
id: id++,
channels: new models.ChannelCollection()
});
this.get("channels").add(new models.Channel({
type: "network",
name: this.get("host")
}));
}
});
models.Event = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
action: "",
data: "",
target: "",
type: ""
}));
};
models.Target = function(attr) {
attr = attr || {};
_.extend(this, _.defaults(attr, {
network: "",
channel: ""
}));
};
models.NetworkCollection = Backbone.Collection.extend({
model: models.Network,
initialize: function() {
this.add(new models.Network({
host: "Lobby"
}));
}
});

View file

@ -1,130 +1,33 @@
var connect = require("connect");
var models = require("./models.js");
var _ = require("lodash");
var irc = require("irc");
var io = require("socket.io");
exports.listen = listen;
// Local library
var models = require("./models.js");
var sockets = false;;
var networks = [];
module.exports = Server;
addToServer(
"NETWORK",
new models.Network({address: "Start"})
);
function Server() {
this.sockets = false;
this.networks = new models.NetworkCollection;
}
function listen(port) {
Server.prototype.listen = function(port) {
var self = this;
var http = connect()
.use(connect.static("client"))
.listen(port);
sockets = io
.listen(http)
.on("connection", initSocket)
.sockets;
}
function initSocket(socket) {
socket.on("input", handleUserInput);
refresh();
}
function sendEvent(params) {
if (sockets) {
sockets.emit("event", new models.Event(params));
}
}
function refresh() {
sendEvent({action: "RENDER", type: "NETWORK", data: networks});
}
function addToServer(type, model, target) {
switch (type) {
case "NETWORK":
var channel = new models.Channel({
name: model.address,
type: "network"
});
model.channels.push(channel);
networks.push(model);
refresh();
break;
case "CHANNEL":
target.network.channels.push(model);
refresh();
break;
case "MESSAGE":
target.channel.messages
.push(model);
sendEvent({
action: "RENDER",
type: "MESSAGE",
target: target.channel.id,
data: model
});
break;
}
}
function handleUserInput(input) {
var id = input.id;
var text = input.text;
var args = text.substr(1).split(' ');
var cmd = text.charAt(0) == "/" ? args[0].toUpperCase()
: "MESSAGE";
var target = getTarget(id);
switch (cmd) {
case "SERVER":
case "CONNECT":
addToServer(
"NETWORK",
new models.Network({address: args[1]})
);
break;
case "JOIN":
addToServer(
"CHANNEL",
new models.Channel({name: args[1]}),
target
);
break;
case "PART":
target.network.channels = _.reject(target.network.channels, {id: id});
refresh();
break;
case "MESSAGE":
addToServer(
"MESSAGE",
new models.Message({text: input.text}),
getTarget(id)
);
break;
}
}
function getTarget(id) {
var find;
_.each(networks, function(n) {
find = {network: n, channel: _.findWhere(n.channels, {id: id})};
if (find.channel)
return;
this.sockets = io.listen(http).sockets;
this.sockets.on("connection", function(socket) {
init.call(self, socket);
});
if (find.channel) {
return new models.Target(find);
}
return this;
};
function init(socket) {
socket.emit(
"event",
this.networks
)
}

View file

@ -6,10 +6,10 @@
"email": "mattias@mattiaserming.com"
},
"dependencies": {
"backbone": "1.1.2",
"commander": "2.1.0",
"connect": "2.13.0",
"irc": "0.3.6",
"lodash": "2.4.1",
"moment": "2.5.1",
"socket.io": "0.9.16"
},