Shuo/client/js/chat.js

257 lines
5.4 KiB
JavaScript
Raw Normal View History

2014-03-06 15:11:25 +00:00
$(function() {
var socket = io.connect("");
2014-03-12 13:10:53 +00:00
$.each([
2014-03-14 21:57:54 +00:00
"NETWORKS",
"CHANNELS",
"MESSAGES",
"USERS"
2014-03-12 13:10:53 +00:00
], function(i, type) {
socket.on(type, function(data) {
2014-03-17 16:24:32 +00:00
console.log(data);
2014-03-12 13:10:53 +00:00
render(type, data);
});
2014-03-07 03:18:53 +00:00
});
2014-03-06 15:11:25 +00:00
var chat = $("#chat");
var sidebar = $("#sidebar");
2014-03-14 19:21:00 +00:00
2014-03-06 15:11:25 +00:00
// Templates
2014-03-17 16:24:32 +00:00
var network_tpl = $("#network").html();
var channel_tpl = $("#channel").html();
var window_tpl = $("#window").html();
var message_tpl = $("#message").html();
var user_tpl = $("#user").html()
2014-03-06 15:11:25 +00:00
2014-03-12 13:10:53 +00:00
function render(type, data) {
switch (type) {
2014-03-17 16:24:32 +00:00
2014-03-14 21:57:54 +00:00
case "NETWORKS":
2014-03-17 00:54:58 +00:00
var windows = chat
.find("#windows")
.html("");
2014-03-12 13:10:53 +00:00
data.forEach(function(network) {
2014-03-17 16:24:32 +00:00
windows.append(Mustache.render(window_tpl, network, {
users: user_tpl,
messages: message_tpl
}));
2014-03-12 13:10:53 +00:00
});
2014-03-16 20:07:27 +00:00
sidebar.find("#list").html(
2014-03-17 16:24:32 +00:00
Mustache.render(network_tpl, {networks: data}, {
channels: channel_tpl
2014-03-12 13:10:53 +00:00
})
2014-03-17 16:24:32 +00:00
).find(".channel")
.first()
2014-03-14 19:21:00 +00:00
.addClass("active");
2014-03-12 13:10:53 +00:00
chat.find(".messages").sticky().scrollToBottom();
chat.find(".window")
2014-03-17 16:24:32 +00:00
.first()
2014-03-14 19:21:00 +00:00
.bringToTop();
2014-03-12 13:10:53 +00:00
break;
2014-03-17 16:24:32 +00:00
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;
2014-03-14 21:57:54 +00:00
case "USERS":
2014-03-17 16:24:32 +00:00
var target;
if (typeof data.target !== "undefined") {
target = chat.find(".window[data-id='" + data.target + "']");
}
2014-03-12 13:10:53 +00:00
target = target.find(".users");
2014-03-17 16:24:32 +00:00
target.html(Mustache.render(user_tpl, {users: data.data}));
2014-03-12 13:10:53 +00:00
break;
2014-03-14 21:57:54 +00:00
case "MESSAGES":
2014-03-17 16:24:32 +00:00
var target;
if (typeof data.target !== "undefined") {
target = chat.find(".window[data-id='" + data.target + "']");
}
2014-03-15 16:14:05 +00:00
var message = data.data;
2014-03-17 16:24:32 +00:00
if (message.type == "error") {
2014-03-15 16:14:05 +00:00
target = target.parent().find(".active");
}
2014-03-17 16:24:32 +00:00
2014-03-12 13:10:53 +00:00
target = target.find(".messages");
2014-03-17 16:24:32 +00:00
target.append(Mustache.render(message_tpl, {messages: message}));
2014-03-12 13:10:53 +00:00
break;
2014-03-17 16:24:32 +00:00
2014-03-12 13:10:53 +00:00
}
2014-03-07 03:18:53 +00:00
}
2014-03-15 15:51:21 +00:00
sidebar.on("click", ".channel", function(e) {
e.preventDefault();
2014-03-16 20:07:27 +00:00
sidebar.find("#list .active").removeClass("active");
2014-03-17 00:54:58 +00:00
$("#viewport").removeClass();
2014-03-15 15:51:21 +00:00
var item = $(this)
.addClass("active")
.find(".badge")
.html("")
.end();
var id = item.data("id");
chat.find(".window[data-id='" + id + "']")
.bringToTop();
});
2014-03-17 00:54:58 +00:00
2014-03-16 20:07:27 +00:00
sidebar.find("input[type=checkbox]").each(function() {
var input = $(this);
var value = input.val();
input.prop("checked", true).wrap("<label>").parent().append(value);
input.on("change", function() {
chat.toggleClass(
"hide-" + value,
!input.prop("checked")
);
});
});
2014-03-17 00:54:58 +00:00
chat.on("click touchstart", ".toggle a", function(e) {
e.preventDefault();
$("#viewport").toggleClass($(this).attr("class"));
});
2014-03-06 15:11:25 +00:00
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
});
}
});
2014-03-15 15:51:21 +00:00
2014-03-14 21:57:54 +00:00
chat.on("click", ".close", function() {
var btn = $(this);
btn.prop("disabled", true);
socket.emit("input", {
id: btn.closest(".window").data("id"),
2014-03-15 15:51:21 +00:00
text: "/LEAVE"
2014-03-14 21:57:54 +00:00
});
});
2014-03-15 15:51:21 +00:00
2014-03-15 15:07:49 +00:00
chat.on("append", ".window", function() {
var id = $(this).data("id");
var badge = sidebar.find(".channel[data-id='" + id + "']:not(.active) .badge");
badge.html((parseInt(badge.html()) + 1) || "1");
});
2014-03-15 15:51:21 +00:00
chat.on("click", ".user", function(e) {
2014-03-14 21:57:54 +00:00
e.preventDefault();
2014-03-15 15:51:21 +00:00
});
chat.on("dblclick", ".user", function() {
var user = $(this);
var id = user.closest(".window").data("id");
var name = user.attr("href");
var channel = sidebar
.find(".channel[data-id='" + id + "']")
.siblings(".channel[data-name='" + name + "']");
if (channel.size() != 0) {
channel.trigger("click");
return;
}
socket.emit("input", {
id: id,
text: "/QUERY " + name
});
2014-03-06 15:11:25 +00:00
});
});
2014-03-09 18:39:25 +00:00
(function($) {
2014-03-06 15:11:25 +00:00
var highest = 1;
$.fn.bringToTop = function() {
2014-03-14 19:21:00 +00:00
return this.css('z-index', highest++)
.addClass("active")
.find(".input")
.end()
.siblings()
.removeClass("active")
.end();
2014-03-06 15:11:25 +00:00
};
2014-03-09 18:39:25 +00:00
})(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();
});
}
2014-03-14 02:00:01 +00:00
var timer;
var resizing = false;
$(window).on("resize", function() {
// This will prevent the scroll event from triggering
// while resizing the window.
resizing = true;
clearTimeout(timer);
timer = setTimeout(function() {
resizing = false;
}, 100);
if (sticky) {
self.scrollToBottom();
}
});
2014-03-09 18:39:25 +00:00
var sticky = false;
self.on("scroll", function() {
2014-03-14 02:00:01 +00:00
if (!resizing) {
sticky = self.isScrollAtBottom();
}
2014-03-09 18:39:25 +00:00
});
self.trigger("scroll");
self.on("append", function() {
if (sticky) {
self.scrollToBottom();
}
});
return this;
};
2014-03-06 18:53:02 +00:00
$.fn.scrollToBottom = function() {
2014-03-16 19:00:57 +00:00
return this.each(function() {
this.scrollTop = this.scrollHeight;
});
2014-03-06 18:53:02 +00:00
};
2014-03-09 18:39:25 +00:00
$.fn.isScrollAtBottom = function() {
2014-03-16 19:00:57 +00:00
if ((this.scrollTop() + this.outerHeight() + 1) >= this.prop("scrollHeight")) {
2014-03-06 18:53:02 +00:00
return true;
}
};
2014-03-16 19:00:57 +00:00
})(jQuery);