$(function() { var commands = [ "/connect", "/deop", "/devoice", "/disconnect", "/join", "/kick", "/leave", "/mode", "/nick", "/op", "/part", "/query", "/quit", "/server", "/topic", "/voice", "/whois", ]; var socket = io.connect(""); $.each(["network", "channel", "message", "user"], function(i, type) { socket.on(type, function(json) { event(type, json); }); }); var chat = $("#chat"); var sidebar = $("#sidebar"); var tpl = []; function render(id, json, partials) { tpl[id] = tpl[id] || $(id).html(); if (!json) { // If no data is supplied, return the template instead. // Handy when fetching partials. return tpl[id]; } return Mustache.render( tpl[id], json, partials || {} ); } function event(type, json) { switch (type) { case "network": var html = ""; var partials = { users: render("#user"), messages: render("#message"), }; json.forEach(function(network) { html += render("#window", network, partials); }); $("#windows")[0].innerHTML = html; sidebar.find("#list").html( render("#network", {networks: json}, {channels: render("#channel")}) ).find(".channel") .first() .addClass("active"); chat.find(".messages").scrollGlue({animate: 400}).scrollToBottom(); chat.find(".window") .find("input") .tabComplete(commands, {appendSpace: true}) .end() .first() .bringToTop() .end(); break; case "channel": var id = json.data.id; if (json.action == "remove") { $("#channel-" + id + ", #window-" + id).remove(); return; } sidebar.find(".channel").removeClass("active"); $("#network-" + json.target).append( render("#channel", {channels: json.data}) ).find(".channel") .last() .addClass("active"); $("#windows").append( render("#window", {channels: json.data}) ).find(".window") .last() .find("input") .tabComplete(commands, {appendSpace: true}) .end() .bringToTop() .find(".messages") .scrollGlue({animate: 400}) .end(); break; case "user": var target = chat.find("#window-" + json.target); if (target.size() == 0) { return; } target = target.find(".users"); target.html(render("#user", {users: json.data})); break; case "message": var target = $("#window-" + json.target); if (target.size() == 0) { return; } var message = json.data; if (message.type == "error") { target = target.parent().find(".active"); } target = target.find(".messages"); target.append(render("#message", {messages: message})); break; } } sidebar.on("click", ".channel", function(e) { e.preventDefault(); sidebar.find("#list .active").removeClass("active"); $("#viewport").removeClass(); var item = $(this) .addClass("active") .find(".badge") .html("") .end(); $("#window-" + item.attr("id").replace("channel-", "")) .bringToTop(); }); sidebar.find("input[type=checkbox]").each(function() { var input = $(this); var value = input.val(); var checked = true; if (($.cookie("hidden") || []).indexOf(value) !== -1) { checked = false; } input.prop("checked", checked) .wrap("