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 argv = require("commander")
|
||||||
var listen = require("./lib/server.js").listen;
|
|
||||||
|
|
||||||
var argv = commander
|
|
||||||
.option("-p, --port <n>", "port to use", parseInt)
|
.option("-p, --port <n>", "port to use", parseInt)
|
||||||
.parse(process.argv);
|
.parse(process.argv);
|
||||||
|
|
||||||
@ -10,4 +7,24 @@ if (argv.port) {
|
|||||||
PORT = 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;
|
border-right: 1px solid #ccc;
|
||||||
float: left;
|
float: left;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
line-height: 36px;
|
|
||||||
width: 199px;
|
width: 199px;
|
||||||
}
|
}
|
||||||
#sidebar .channel {
|
#sidebar .channel {
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
color: #f00;
|
color: #f00;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
line-height: 1.8em;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
}
|
}
|
||||||
#sidebar .channel:first-child {
|
#sidebar .channel:first-child {
|
||||||
@ -43,9 +43,16 @@ h2 {
|
|||||||
#sidebar .channel:hover {
|
#sidebar .channel:hover {
|
||||||
text-decoration: underline;
|
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;
|
background: #eaeaea;
|
||||||
border-bottom-color: #e5e5e5;
|
border-bottom-color: #e5e5e5;
|
||||||
|
line-height: 36px;
|
||||||
}
|
}
|
||||||
#chat {
|
#chat {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
<script type="text/html" id="users">
|
<script type="text/html" id="users">
|
||||||
{{#users}}
|
{{#users}}
|
||||||
<div class="user" data-id="{{id}}">
|
<div class="user" data-id="{{id}}">
|
||||||
{{name}}
|
{{mode}}{{name}}
|
||||||
</div>
|
</div>
|
||||||
{{/users}}
|
{{/users}}
|
||||||
</script>
|
</script>
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
$(function() {
|
$(function() {
|
||||||
var socket = io.connect("");
|
var socket = io.connect("");
|
||||||
socket.on("event", function(event) {
|
socket.on("event", function(data) {
|
||||||
render(event);
|
render(data);
|
||||||
|
|
||||||
|
// Debug
|
||||||
|
console.log(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
var chat = $("#chat");
|
var chat = $("#chat");
|
||||||
@ -13,49 +16,7 @@ $(function() {
|
|||||||
var messages = $("#messages").html();
|
var messages = $("#messages").html();
|
||||||
var users = $("#users").html()
|
var users = $("#users").html()
|
||||||
|
|
||||||
function render(event) {
|
function render(data) {
|
||||||
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) {
|
|
||||||
chat.html("");
|
chat.html("");
|
||||||
var partials = {
|
var partials = {
|
||||||
users: users,
|
users: users,
|
||||||
@ -80,60 +41,6 @@ $(function() {
|
|||||||
.focus();
|
.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() {
|
chat.on("submit", "form", function() {
|
||||||
var input = $(this).find(".input");
|
var input = $(this).find(".input");
|
||||||
var text = input.val();
|
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 moment = require("moment");
|
||||||
|
|
||||||
var models = exports;
|
var models =
|
||||||
|
module.exports =
|
||||||
|
{};
|
||||||
|
|
||||||
var id = 1;
|
var id = 1;
|
||||||
|
|
||||||
models.Network = function(attr) {
|
models.User = Backbone.Model.extend({
|
||||||
attr = attr || {};
|
defaults: {
|
||||||
_.extend(this, _.defaults(attr, {
|
mode: "",
|
||||||
id: id++,
|
name: "user"
|
||||||
address: "",
|
}
|
||||||
nick: "",
|
});
|
||||||
channels: []
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
models.Network.prototype.toJSON = function() {
|
models.Message = Backbone.Model.extend({
|
||||||
return _.omit(this, "client");
|
defaults: {
|
||||||
};
|
time: moment().format("HH:mm"),
|
||||||
|
user: "user",
|
||||||
|
text: "text"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
models.Channel = function(attr) {
|
models.Channel = Backbone.Model.extend({
|
||||||
attr = attr || {};
|
defaults: {
|
||||||
_.extend(this, _.defaults(attr, {
|
|
||||||
id: id++,
|
|
||||||
name: "",
|
|
||||||
type: "channel",
|
type: "channel",
|
||||||
|
name: "",
|
||||||
topic: "",
|
topic: "",
|
||||||
users: [],
|
users: [],
|
||||||
messages: []
|
messages: []
|
||||||
}));
|
},
|
||||||
};
|
initialize: function() {
|
||||||
|
this.set({
|
||||||
|
id: id++
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
models.User = function(attr) {
|
models.ChannelCollection = Backbone.Collection.extend({
|
||||||
attr = attr || {};
|
model: models.Channel
|
||||||
_.extend(this, _.defaults(attr, {
|
});
|
||||||
id: id++,
|
|
||||||
name: ""
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
models.Message = function(attr) {
|
models.Network = Backbone.Model.extend({
|
||||||
attr = attr || {};
|
defaults: {
|
||||||
_.extend(this, _.defaults(attr, {
|
host: "",
|
||||||
time: moment().format("HH:mm"),
|
},
|
||||||
user: "",
|
initialize: function() {
|
||||||
text: ""
|
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) {
|
models.NetworkCollection = Backbone.Collection.extend({
|
||||||
attr = attr || {};
|
model: models.Network,
|
||||||
_.extend(this, _.defaults(attr, {
|
initialize: function() {
|
||||||
action: "",
|
this.add(new models.Network({
|
||||||
data: "",
|
host: "Lobby"
|
||||||
target: "",
|
}));
|
||||||
type: ""
|
}
|
||||||
}));
|
});
|
||||||
};
|
|
||||||
|
|
||||||
models.Target = function(attr) {
|
|
||||||
attr = attr || {};
|
|
||||||
_.extend(this, _.defaults(attr, {
|
|
||||||
network: "",
|
|
||||||
channel: ""
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
139
lib/server.js
139
lib/server.js
@ -1,130 +1,33 @@
|
|||||||
var connect = require("connect");
|
var connect = require("connect");
|
||||||
var models = require("./models.js");
|
|
||||||
var _ = require("lodash");
|
|
||||||
var irc = require("irc");
|
|
||||||
var io = require("socket.io");
|
var io = require("socket.io");
|
||||||
|
|
||||||
exports.listen = listen;
|
// Local library
|
||||||
|
var models = require("./models.js");
|
||||||
|
|
||||||
var sockets = false;;
|
module.exports = Server;
|
||||||
var networks = [];
|
|
||||||
|
|
||||||
addToServer(
|
function Server() {
|
||||||
"NETWORK",
|
this.sockets = false;
|
||||||
new models.Network({address: "Start"})
|
this.networks = new models.NetworkCollection;
|
||||||
);
|
}
|
||||||
|
|
||||||
function listen(port) {
|
Server.prototype.listen = function(port) {
|
||||||
|
var self = this;
|
||||||
var http = connect()
|
var http = connect()
|
||||||
.use(connect.static("client"))
|
.use(connect.static("client"))
|
||||||
.listen(port);
|
.listen(port);
|
||||||
sockets = io
|
|
||||||
.listen(http)
|
|
||||||
.on("connection", initSocket)
|
|
||||||
.sockets;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initSocket(socket) {
|
this.sockets = io.listen(http).sockets;
|
||||||
socket.on("input", handleUserInput);
|
this.sockets.on("connection", function(socket) {
|
||||||
refresh();
|
init.call(self, socket);
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
});
|
});
|
||||||
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"
|
"email": "mattias@mattiaserming.com"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"backbone": "1.1.2",
|
||||||
"commander": "2.1.0",
|
"commander": "2.1.0",
|
||||||
"connect": "2.13.0",
|
"connect": "2.13.0",
|
||||||
"irc": "0.3.6",
|
"irc": "0.3.6",
|
||||||
"lodash": "2.4.1",
|
|
||||||
"moment": "2.5.1",
|
"moment": "2.5.1",
|
||||||
"socket.io": "0.9.16"
|
"socket.io": "0.9.16"
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user