Added Backbone
This commit is contained in:
parent
efa3fcd7ab
commit
bd963fbd8c
27
app.js
27
app.js
|
@ -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"}),
|
||||
]
|
||||
}));
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<script type="text/html" id="users">
|
||||
{{#users}}
|
||||
<div class="user" data-id="{{id}}">
|
||||
{{name}}
|
||||
{{mode}}{{name}}
|
||||
</div>
|
||||
{{/users}}
|
||||
</script>
|
||||
|
|
|
@ -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();
|
||||
|
|
107
lib/models.js
107
lib/models.js
|
@ -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"
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
|
139
lib/server.js
139
lib/server.js
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue