Partial rendering

This commit is contained in:
Mattias Erming 2014-03-12 14:10:53 +01:00
parent f13a6aa308
commit f57d994c5c
6 changed files with 218 additions and 38 deletions

View file

@ -1,10 +1,15 @@
$(function() {
var socket = io.connect("");
socket.on("event", function(data) {
render(data);
// Debug
console.log(data);
$.each([
"networks",
"channels",
"user",
"messages"
], function(i, type) {
socket.on(type, function(data) {
render(type, data);
});
});
var chat = $("#chat");
@ -16,29 +21,48 @@ $(function() {
var messages = $("#messages").html();
var users = $("#users").html()
function render(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
})
);
function render(type, data) {
var target;
if (typeof data.target !== "undefined") {
target = $(".window[data-id='" + data.target + "']");
}
chat.find(".messages").sticky().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();
switch (type) {
case "networks":
var partials = {
users: users,
messages: messages
};
chat.html("");
data.forEach(function(network) {
chat.append(Mustache.render(channels, network, partials));
});
sidebar.html(
Mustache.render(networks, {
networks: data
})
);
chat.find(".messages").sticky().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();
break;
case "users":
target = target.find(".users");
target.html(Mustache.render(users, {users: data.data}));
break;
case "messages":
target = target.find(".messages");
target.append(Mustache.render(messages, {messages: data.data}));
break;
}
}
chat.on("submit", "form", function() {

112
js/chat.js Normal file
View file

@ -0,0 +1,112 @@
$(function() {
var socket = io.connect("");
socket.on("event", function(data) {
render(data);
// Debug
console.log(data);
});
var chat = $("#chat");
var sidebar = $("#sidebar");
// Templates
var networks = $("#networks").html();
var channels = $("#channels").html();
var messages = $("#messages").html();
var users = $("#users").html()
function render(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").sticky().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();
}
chat.on("submit", "form", function() {
var input = $(this).find(".input");
var text = input.val();
if (text != "") {
input.val("");
socket.emit("input", {
id: input.data("target"),
text: text
});
}
});
sidebar.on("click", ".channel", function() {
chat.find(".window[data-id='" + $(this).data("id") + "']")
.bringToTop();
});
});
(function($) {
var highest = 1;
$.fn.bringToTop = function() {
return this
.css('z-index', highest++)
.find("input")
.focus();
};
})(jQuery);
// Sticky plugin
// https://github.com/erming/sticky
(function($) {
var append = $.fn.append;
$.fn.append = function() {
return append.apply(this, arguments).trigger("append");
};
$.fn.sticky = function() {
var self = this;
if (self.size() > 1) {
return self.each(function() {
$(this).sticky();
});
}
var sticky = false;
self.on("scroll", function() {
sticky = self.isScrollAtBottom();
});
self.trigger("scroll");
self.on("append", function() {
if (sticky) {
self.scrollToBottom();
}
});
return this;
};
$.fn.scrollToBottom = function() {
this.scrollTop(1e10);
};
$.fn.isScrollAtBottom = function() {
if ((this.scrollTop() + this.outerHeight()) >= this.prop("scrollHeight")) {
return true;
}
};
})(jQuery);

4
js/lib/jquery-2.1.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1
js/lib/mustache.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -45,9 +45,14 @@ models.Channel = Backbone.Model.extend({
this.set("users", new models.UserCollection());
this.get("users").on(
"all",
function(e) {
function(type, model) {
// Bubble event
this.trigger("user", this);
this.trigger(
"users", {
target: this.get("id"),
data: model
}
);
},
this
);
@ -55,9 +60,14 @@ models.Channel = Backbone.Model.extend({
this.set("messages", new models.MessageCollection());
this.get("messages").on(
"add",
function() {
function(type, model) {
// Bubble event
this.trigger("message", this);
this.trigger(
"messages", {
target: this.get("id"),
data: model.last()
}
);
},
this
);
@ -82,9 +92,21 @@ models.Network = Backbone.Model.extend({
this.set("channels", new models.ChannelCollection());
this.get("channels").on(
"all",
function(type) {
// Bubble event
this.trigger(type == "user" || type == "message" ? type : "channel", this);
function(type, model) {
if ([
"users",
"messages"
].indexOf(type) != -1) {
this.trigger(type, model);
} else {
// Bubble event
this.trigger(
"channels", {
target: this.get("id"),
data: model
}
);
}
},
this
);

View file

@ -19,18 +19,25 @@ Server.prototype.listen = function(port) {
this.networks.on(
"all",
function(type) {
self.sockets.emit("event", self.networks);
function(type, data) {
if ([
"users",
"messages"
].indexOf(type) != -1) {
self.sockets.emit(type, data);
} else {
self.sockets.emit("networks", self.networks);
}
// Debug
console.log(type);
console.log(type + ": " + data);
}
);
this.sockets = io.listen(http, {log: false}).sockets;
this.sockets.on("connection", function(socket) {
socket.emit(
"event",
"networks",
self.networks
);
socket.on(
@ -61,6 +68,16 @@ function handleInput(input) {
);
break;
case "JOIN":
if (!argv[1]) {
return;
}
var channels = this.networks.at(0).get("channels");
channels.add(new models.Channel({
name: argv[1]
}));
break;
case "CONNECT":
if (!argv[1]) {
return;