Improved the event/render flow
This commit is contained in:
parent
acfeac27f4
commit
efa3fcd7ab
|
@ -36,10 +36,6 @@ h2 {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
}
|
}
|
||||||
#sidebar .channel[data-id='0'] {
|
|
||||||
background: #eaeaea;
|
|
||||||
border-bottom-color: #e5e5e5;
|
|
||||||
}
|
|
||||||
#sidebar .channel:first-child {
|
#sidebar .channel:first-child {
|
||||||
color: #333;
|
color: #333;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -47,6 +43,10 @@ h2 {
|
||||||
#sidebar .channel:hover {
|
#sidebar .channel:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
#sidebar .network:first-child .channel:first-child {
|
||||||
|
background: #eaeaea;
|
||||||
|
border-bottom-color: #e5e5e5;
|
||||||
|
}
|
||||||
#chat {
|
#chat {
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 200px;
|
left: 200px;
|
||||||
|
|
|
@ -1,12 +1,8 @@
|
||||||
$(function() {
|
$(function() {
|
||||||
var socket = io.connect("");
|
var socket = io.connect("");
|
||||||
socket.on(
|
socket.on("event", function(event) {
|
||||||
"event",
|
render(event);
|
||||||
function(event) {
|
});
|
||||||
console.log(event);
|
|
||||||
View[event.action](event);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
var chat = $("#chat");
|
var chat = $("#chat");
|
||||||
var sidebar = $("#sidebar");
|
var sidebar = $("#sidebar");
|
||||||
|
@ -17,11 +13,77 @@ $(function() {
|
||||||
var messages = $("#messages").html();
|
var messages = $("#messages").html();
|
||||||
var users = $("#users").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) {
|
||||||
|
chat.html("");
|
||||||
|
var partials = {
|
||||||
|
users: users,
|
||||||
|
messages: messages
|
||||||
|
};
|
||||||
|
data.forEach(function(network) {
|
||||||
|
chat.append(Mustache.render(channels, network, partials));
|
||||||
|
});
|
||||||
|
sidebar.html(
|
||||||
|
Mustache.render(networks, {
|
||||||
|
networks: data
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
var View = {};
|
var View = {};
|
||||||
|
|
||||||
View.refresh = function(event) {
|
View.refresh = function(event) {
|
||||||
var data = event.data;
|
var data = event.data;
|
||||||
|
|
||||||
sidebar.html(
|
sidebar.html(
|
||||||
Mustache.render(networks, {
|
Mustache.render(networks, {
|
||||||
networks: data
|
networks: data
|
||||||
|
@ -48,32 +110,23 @@ $(function() {
|
||||||
};
|
};
|
||||||
|
|
||||||
View.add = function(event) {
|
View.add = function(event) {
|
||||||
var target = "";
|
var target = $("[data-id='" + event.target + "'] ");
|
||||||
var render = "";
|
|
||||||
|
|
||||||
switch (event.type) {
|
switch (event.type) {
|
||||||
case "user":
|
|
||||||
target = ".users";
|
case "users":
|
||||||
render = Mustache.render(
|
target = target.find(".users");
|
||||||
users, {users: event.data}
|
target.html(Mustache.render(users, {users: event.data}));
|
||||||
);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "message":
|
case "messages":
|
||||||
target = ".messages";
|
|
||||||
render = Mustache.render(
|
|
||||||
messages, {messages: event.data}
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target != "") {
|
|
||||||
target = $("[data-id='" + event.target + "'] " + target);
|
|
||||||
var keepAtBottom = target.isScrollBottom();
|
var keepAtBottom = target.isScrollBottom();
|
||||||
target.append(render);
|
target = target.find(".messages");
|
||||||
|
target.append(Mustache.render(messages, {messages: event.data}));
|
||||||
if (keepAtBottom) {
|
if (keepAtBottom) {
|
||||||
target.scrollToBottom();
|
target.scrollToBottom();
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,10 +134,6 @@ $(function() {
|
||||||
$("[data-id='" + event.target + "']").remove();
|
$("[data-id='" + event.target + "']").remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
View.change = function(event) {
|
|
||||||
// ..
|
|
||||||
};
|
|
||||||
|
|
||||||
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,7 +156,10 @@ $(function() {
|
||||||
(function() {
|
(function() {
|
||||||
var highest = 1;
|
var highest = 1;
|
||||||
$.fn.bringToTop = function() {
|
$.fn.bringToTop = function() {
|
||||||
return this.css('z-index', highest++);
|
return this
|
||||||
|
.css('z-index', highest++)
|
||||||
|
.find("input")
|
||||||
|
.focus();
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.scrollToBottom = function() {
|
$.fn.scrollToBottom = function() {
|
||||||
|
|
|
@ -2,7 +2,7 @@ var _ = require("lodash");
|
||||||
var moment = require("moment");
|
var moment = require("moment");
|
||||||
|
|
||||||
var models = exports;
|
var models = exports;
|
||||||
var id = 0;
|
var id = 1;
|
||||||
|
|
||||||
models.Network = function(attr) {
|
models.Network = function(attr) {
|
||||||
attr = attr || {};
|
attr = attr || {};
|
||||||
|
@ -56,3 +56,11 @@ models.Event = function(attr) {
|
||||||
type: ""
|
type: ""
|
||||||
}));
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
models.Target = function(attr) {
|
||||||
|
attr = attr || {};
|
||||||
|
_.extend(this, _.defaults(attr, {
|
||||||
|
network: "",
|
||||||
|
channel: ""
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
207
lib/server.js
207
lib/server.js
|
@ -1,149 +1,130 @@
|
||||||
var _ = require("lodash");
|
|
||||||
var connect = require("connect");
|
var connect = require("connect");
|
||||||
|
var models = require("./models.js");
|
||||||
|
var _ = require("lodash");
|
||||||
var irc = require("irc");
|
var irc = require("irc");
|
||||||
var io = require("socket.io");
|
var io = require("socket.io");
|
||||||
var models = require("./models.js");
|
|
||||||
|
|
||||||
exports.listen = listen;
|
exports.listen = listen;
|
||||||
|
|
||||||
var sockets;
|
var sockets = false;;
|
||||||
var networks = [];
|
var networks = [];
|
||||||
|
|
||||||
addNetwork("Lobby", false);
|
addToServer(
|
||||||
|
"NETWORK",
|
||||||
|
new models.Network({address: "Start"})
|
||||||
|
);
|
||||||
|
|
||||||
function listen(port) {
|
function listen(port) {
|
||||||
var http = connect()
|
var http = connect()
|
||||||
.use(connect.static("client"))
|
.use(connect.static("client"))
|
||||||
.listen(port);
|
.listen(port);
|
||||||
sockets = io.listen(http).sockets;
|
sockets = io
|
||||||
sockets.on("connection", function(socket) {
|
.listen(http)
|
||||||
init(socket);
|
.on("connection", initSocket)
|
||||||
});
|
.sockets;
|
||||||
}
|
}
|
||||||
|
|
||||||
function init(socket) {
|
function initSocket(socket) {
|
||||||
|
socket.on("input", handleUserInput);
|
||||||
refresh();
|
refresh();
|
||||||
socket.on(
|
}
|
||||||
"input",
|
|
||||||
function(input) {
|
function sendEvent(params) {
|
||||||
handleUserInput(input)
|
if (sockets) {
|
||||||
}
|
sockets.emit("event", new models.Event(params));
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (typeof sockets === "undefined") {
|
sendEvent({action: "RENDER", type: "NETWORK", data: networks});
|
||||||
return;
|
|
||||||
}
|
|
||||||
sockets.emit("event", new models.Event({
|
|
||||||
action: "refresh",
|
|
||||||
data: networks
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleUserInput(input) {
|
function addToServer(type, model, target) {
|
||||||
var text = input.text;
|
switch (type) {
|
||||||
var target = getChannel(input.id);
|
|
||||||
|
|
||||||
if (text.charAt(0) != "/") {
|
case "NETWORK":
|
||||||
return addMessage(target, text);
|
var channel = new models.Channel({
|
||||||
}
|
name: model.address,
|
||||||
|
type: "network"
|
||||||
|
});
|
||||||
|
|
||||||
var args = text.substr(1).split(" ");
|
model.channels.push(channel);
|
||||||
var cmd = args[0].toUpperCase();
|
networks.push(model);
|
||||||
|
|
||||||
switch (cmd) {
|
refresh();
|
||||||
|
|
||||||
case "SERVER":
|
|
||||||
case "CONNECT":
|
|
||||||
if (args[1]) {
|
|
||||||
addNetwork(args[1], true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "JOIN":
|
|
||||||
if (args[1]) {
|
|
||||||
target.network.channels.push(
|
|
||||||
new models.Channel({
|
|
||||||
name: args[1]
|
|
||||||
})
|
|
||||||
);
|
|
||||||
refresh();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "PART":
|
case "CHANNEL":
|
||||||
target.network.channels =
|
target.network.channels.push(model);
|
||||||
_.without(target.network.channels, target.channel);
|
|
||||||
refresh();
|
refresh();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
case "MESSAGE":
|
||||||
addMessage(
|
target.channel.messages
|
||||||
target,
|
.push(model);
|
||||||
"Command '/" + args[0] + "' does not exist."
|
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;
|
break;
|
||||||
|
|
||||||
}
|
case "JOIN":
|
||||||
}
|
addToServer(
|
||||||
|
"CHANNEL",
|
||||||
function addNetwork(addr, bool) {
|
new models.Channel({name: args[1]}),
|
||||||
bool = bool || false;
|
target
|
||||||
|
|
||||||
var chan = new models.Channel({
|
|
||||||
name: addr,
|
|
||||||
type: "network"
|
|
||||||
});
|
|
||||||
var network = new models.Network({
|
|
||||||
channels: [chan]
|
|
||||||
});
|
|
||||||
|
|
||||||
networks.push(network);
|
|
||||||
refresh();
|
|
||||||
|
|
||||||
if (addr == "Lobby") {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
network.client = new irc.Client(addr, "default_user");
|
|
||||||
network.client.addListener("raw", function() {
|
|
||||||
handleEvent(
|
|
||||||
network, arguments
|
|
||||||
);
|
);
|
||||||
});
|
break;
|
||||||
}
|
|
||||||
|
case "PART":
|
||||||
|
target.network.channels = _.reject(target.network.channels, {id: id});
|
||||||
|
refresh();
|
||||||
|
break;
|
||||||
|
|
||||||
function handleEvent(network) {
|
case "MESSAGE":
|
||||||
var args = arguments;
|
addToServer(
|
||||||
var target = {
|
"MESSAGE",
|
||||||
network: network,
|
new models.Message({text: input.text}),
|
||||||
channel: network.channels[0]
|
getTarget(id)
|
||||||
};
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
console.log(args[1]);
|
}
|
||||||
addMessage(target, args[1][0].args);
|
}
|
||||||
}
|
|
||||||
|
function getTarget(id) {
|
||||||
function addMessage(target, text) {
|
var find;
|
||||||
var message = _.extend(new models.Message, {text: text});
|
_.each(networks, function(n) {
|
||||||
target.channel.messages.push(message);
|
find = {network: n, channel: _.findWhere(n.channels, {id: id})};
|
||||||
sockets.emit("event", new models.Event({
|
if (find.channel)
|
||||||
action: "add",
|
return;
|
||||||
type: "message",
|
});
|
||||||
target: target.channel.id,
|
if (find.channel) {
|
||||||
data: message
|
return new models.Target(find);
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
function getChannel(id) {
|
|
||||||
for (var i = 0; i < networks.length; i++) {
|
|
||||||
var find = {
|
|
||||||
network: networks[i],
|
|
||||||
channel: _.findWhere(networks[i].channels, {id: id})
|
|
||||||
};
|
|
||||||
if (typeof find.channel !== "undefined") {
|
|
||||||
return find;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue