Improved rendering

This commit is contained in:
Mattias Erming 2014-03-17 17:24:32 +01:00
parent bb090ef331
commit a8ad02b738
5 changed files with 97 additions and 68 deletions

View File

@ -153,7 +153,7 @@ h2 {
#chat .users { #chat .users {
background: #fff; background: #fff;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
bottom: 0; bottom: 30px;
overflow-y: auto; overflow-y: auto;
padding: 4px 0; padding: 4px 0;
position: absolute; position: absolute;
@ -255,6 +255,7 @@ h2 {
display: none; display: none;
} }
#chat .users { #chat .users {
bottom: 0;
right: -160px; right: -160px;
} }
#chat .users a { #chat .users a {

View File

@ -55,20 +55,24 @@
<div id="scripts"> <div id="scripts">
<script type="text/html" id="networks"> <script type="text/html" id="network">
{{#networks}} {{#networks}}
<div class="network list-group" data-id="{{id}}"> <div class="network list-group" data-id="{{id}}">
{{> channels}}
</div>
{{/networks}}
</script>
<script type="text/html" id="channel">
{{#channels}} {{#channels}}
<a href="{{name}}" class="channel list-group-item" data-id="{{id}}" data-name="{{name}}"> <a href="{{name}}" class="channel list-group-item" data-id="{{id}}" data-name="{{name}}">
<span class="badge pull-right"></span> <span class="badge pull-right"></span>
{{name}} {{name}}
</a> </a>
{{/channels}} {{/channels}}
</div>
{{/networks}}
</script> </script>
<script type="text/html" id="channels"> <script type="text/html" id="window">
{{#channels}} {{#channels}}
<div class="window {{type}}" data-id="{{id}}"> <div class="window {{type}}" data-id="{{id}}">
<div class="toggle"> <div class="toggle">
@ -93,7 +97,7 @@
{{/channels}} {{/channels}}
</script> </script>
<script type="text/html" id="users"> <script type="text/html" id="user">
{{#users}} {{#users}}
<a href="{{name}}" class="user"> <a href="{{name}}" class="user">
{{mode}}{{name}} {{mode}}{{name}}
@ -101,7 +105,7 @@
{{/users}} {{/users}}
</script> </script>
<script type="text/html" id="messages"> <script type="text/html" id="message">
{{#messages}} {{#messages}}
<div class="message {{type}}"> <div class="message {{type}}">
<span class="time">{{time}}</span> <span class="time">{{time}}</span>

View File

@ -8,6 +8,7 @@ $(function() {
"USERS" "USERS"
], function(i, type) { ], function(i, type) {
socket.on(type, function(data) { socket.on(type, function(data) {
console.log(data);
render(type, data); render(type, data);
}); });
}); });
@ -16,59 +17,84 @@ $(function() {
var sidebar = $("#sidebar"); var sidebar = $("#sidebar");
// Templates // Templates
var networks = $("#networks").html(); var network_tpl = $("#network").html();
var channels = $("#channels").html(); var channel_tpl = $("#channel").html();
var messages = $("#messages").html(); var window_tpl = $("#window").html();
var users = $("#users").html() var message_tpl = $("#message").html();
var user_tpl = $("#user").html()
function render(type, data) { function render(type, data) {
var target;
if (typeof data.target !== "undefined") {
target = $(".window[data-id='" + data.target + "']");
}
switch (type) { switch (type) {
case "NETWORKS": case "NETWORKS":
var partials = {
users: users,
messages: messages
};
var windows = chat var windows = chat
.find("#windows") .find("#windows")
.html(""); .html("");
data.forEach(function(network) { data.forEach(function(network) {
windows.append(Mustache.render(channels, network, partials)); windows.append(Mustache.render(window_tpl, network, {
users: user_tpl,
messages: message_tpl
}));
}); });
sidebar.find("#list").html( sidebar.find("#list").html(
Mustache.render(networks, { Mustache.render(network_tpl, {networks: data}, {
networks: data channels: channel_tpl
}) })
); ).find(".channel")
sidebar.find(".channel") .first()
.last()
.addClass("active"); .addClass("active");
chat.find(".messages").sticky().scrollToBottom(); chat.find(".messages").sticky().scrollToBottom();
chat.find(".window") chat.find(".window")
// Sort windows by `data-id` value. .first()
.sort(function(a, b) { return ($(a).data("id") - $(b).data("id")); })
.last()
.bringToTop(); .bringToTop();
break; break;
case "CHANNELS":
if (data.action == "remove") {
chat.find(".window[data-id='" + data.data.id + "']").remove();
sidebar.find(".channel[data-id='" + data.data.id + "']").remove();
return;
}
sidebar.find(".network[data-id='" + data.target + "']").append(
Mustache.render(channel_tpl, {channels: data.data}, {
channels: channel_tpl
})
);
chat.find("#windows").append(
Mustache.render(window_tpl, {channels: data.data}, {
users: user_tpl,
messages: message_tpl
})
);
break;
case "USERS": case "USERS":
var target;
if (typeof data.target !== "undefined") {
target = chat.find(".window[data-id='" + data.target + "']");
}
target = target.find(".users"); target = target.find(".users");
target.html(Mustache.render(users, {users: data.data})); target.html(Mustache.render(user_tpl, {users: data.data}));
break; break;
case "MESSAGES": case "MESSAGES":
var target;
if (typeof data.target !== "undefined") {
target = chat.find(".window[data-id='" + data.target + "']");
}
var message = data.data; var message = data.data;
if (message.type == "error" || message.type == "notice") { if (message.type == "error") {
target = target.parent().find(".active"); target = target.parent().find(".active");
} }
target = target.find(".messages"); target = target.find(".messages");
target.append(Mustache.render(messages, {messages: message})); target.append(Mustache.render(message_tpl, {messages: message}));
break; break;
} }
} }
@ -124,10 +150,6 @@ $(function() {
}); });
}); });
chat.on("click", ".messages", function() {
$(this).next("form").find("input:first").focus();
});
chat.on("append", ".window", function() { chat.on("append", ".window", function() {
var id = $(this).data("id"); var id = $(this).data("id");
var badge = sidebar.find(".channel[data-id='" + id + "']:not(.active) .badge"); var badge = sidebar.find(".channel[data-id='" + id + "']:not(.active) .badge");

View File

@ -70,18 +70,22 @@ models.Channel = Backbone.Model.extend({
}); });
this.set("messages", new models.MessageCollection()); this.set("messages", new models.MessageCollection());
this.get("messages").on("all", function() { this.get("messages").on("all", function(action, data) {
this.trigger("MESSAGES", { this.trigger("MESSAGES", {
target: this.get("id"), target: this.get("id"),
data: this.get("messages").last() type: "message",
data: data,
action: action
}); });
}, this); }, this);
this.set("users", new models.UserCollection()); this.set("users", new models.UserCollection());
this.get("users").on("all", function() { this.get("users").on("all", function(action) {
this.trigger("USERS", { this.trigger("USERS", {
target: this.get("id"), target: this.get("id"),
data: this.get("users") type: "user",
data: this.get("users"),
action: action
}); });
}, this); }, this);
} }
@ -102,13 +106,19 @@ models.Network = Backbone.Model.extend({
}); });
this.set("channels", new models.ChannelCollection()); this.set("channels", new models.ChannelCollection());
this.get("channels").on("all", function(type, data) { this.get("channels").on("all", function(action, data) {
if (type == "USERS" || type == "MESSAGES") { if (action == "USERS" || action == "MESSAGES") {
this.trigger(type, data); this.trigger(action, data);
} else { } else {
this.trigger("CHANNELS"); this.trigger("CHANNELS", {
target: this.get("id"),
type: "channel",
data: data,
action: action
});
} }
}, this); }, this);
this.get("channels").add(new models.Channel({ this.get("channels").add(new models.Channel({
type: "network", type: "network",
name: this.get("host") name: this.get("host")

View File

@ -18,28 +18,14 @@ Server.prototype.listen = function(port) {
.use(connect.static("client")) .use(connect.static("client"))
.listen(port); .listen(port);
this.networks.on("all", function(type, data) { this.networks.on("all", function(action, data) {
if (type == "USERS" || type == "MESSAGES") { this.sockets.emit(action, data);
this.sockets.emit(type, data);
} else {
// Force a refresh on network and channel events.
this.sockets.emit(
"NETWORKS", self.networks
);
}
}, this); }, this);
this.sockets = io.listen(http, {log: false}).sockets; this.sockets = io.listen(http, {log: false}).sockets;
this.sockets.on("connection", function(socket) { this.sockets.on("connection", function(socket) {
socket.emit( socket.emit("NETWORKS", self.networks);
"NETWORKS", self.networks socket.on("input", function(input) { handleInput.call(self, input); });
);
socket.on(
"input",
function(input) {
handleInput.call(self, input);
}
);
}); });
if (config.autoConnect) { if (config.autoConnect) {
@ -53,7 +39,13 @@ Server.prototype.connect = function(host, channels) {
var network = new models.Network({ var network = new models.Network({
host: host host: host
}); });
this.networks.add(network);
this.networks.add(network, {silent: true});
this.networks.trigger(
"NETWORKS",
this.networks
);
network.connect(channels).addListener("raw", function() { network.connect(channels).addListener("raw", function() {
handleEvent.apply(network, arguments); handleEvent.apply(network, arguments);
}); });
@ -482,7 +474,7 @@ function handleEvent(argv) {
} }
if (typeof rpl_namreply === "undefined") { if (typeof rpl_namreply === "undefined") {
channel.get("users").reset({silent: true}); channel.get("users").reset(undefined, {silent: true});
} }
// This variable is global but will be deleted when // This variable is global but will be deleted when