Updated chat rendering

This commit is contained in:
Mattias Erming 2014-07-07 14:42:46 +02:00
parent cb663777b4
commit 9c2ffee7d0
5 changed files with 137 additions and 140 deletions

View File

@ -11,14 +11,17 @@
}); });
} }
console.log("YES");
var isBottom = false; var isBottom = false;
var self = this; var self = this;
this.on("beforeAppend", function() { this.unbind(".sticky");
this.on("beforeAppend.sticky", function() {
isBottom = isScrollBottom.call(self); isBottom = isScrollBottom.call(self);
}); });
this.on("afterAppend", function() { this.on("afterAppend.sticky", function() {
if (isBottom) { if (isBottom) {
self.scrollBottom(); self.scrollBottom();
} }
@ -32,6 +35,8 @@
"overflow-y": overflow "overflow-y": overflow
}); });
this.scrollBottom();
return this; return this;
}; };

View File

@ -1,5 +1,5 @@
@import url( @import url(
http://fonts.googleapis.com/css?family=Lato:300,400,700 http://fonts.googleapis.com/css?family=Lato:400,700
); );
@font-face { @font-face {
font-family: "Octicons"; font-family: "Octicons";
@ -29,10 +29,6 @@ h2 {
line-height: inherit; line-height: inherit;
margin: 0; margin: 0;
} }
h1 {
color: #2c3e50;
font: 300 48px Lato, sans-serif;
}
button { button {
background: 0; background: 0;
border: none; border: none;
@ -75,15 +71,14 @@ button {
background: #323841; background: #323841;
color: #fff; color: #fff;
} }
#networks { #sidebar .networks {
display: none;
min-height: 100%; min-height: 100%;
padding: 30px 40px 80px; padding: 30px 40px 80px;
} }
#networks .network + .network { #sidebar .network + .network {
margin-top: 30px; margin-top: 30px;
} }
#networks .chan { #sidebar .chan {
display: block; display: block;
margin: 1px -10px; margin: 1px -10px;
padding: 6px 10px 8px; padding: 6px 10px 8px;
@ -92,12 +87,12 @@ button {
transition: all .2s; transition: all .2s;
width: 160px; width: 160px;
} }
#networks .chan:first-child { #sidebar .chan:first-child {
color: #84d1ff; color: #84d1ff;
font-size: 15px; font-size: 15px;
font-weight: bold; font-weight: bold;
} }
#networks .badge { #sidebar .badge {
background: rgba(255, 255, 255, .06); background: rgba(255, 255, 255, .06);
border-radius: 3px; border-radius: 3px;
color: #afb6c0; color: #afb6c0;
@ -108,7 +103,7 @@ button {
right: 10px; right: 10px;
transition: all .1s; transition: all .1s;
} }
#networks .badge:empty { #sidebar .badge:empty {
display: none; display: none;
} }
#footer { #footer {
@ -176,8 +171,14 @@ button {
top: 0px; top: 0px;
width: 100%; width: 100%;
} }
#windows > div { #windows > div,
display: none; #windows .chan {
background: #fff;
bottom: 0;
left: 0;
position: absolute;
right: 0;
top: 0;
} }
#chat { #chat {
font: 13px Consolas, monospace; font: 13px Consolas, monospace;
@ -188,7 +189,7 @@ button {
#chat button:hover { #chat button:hover {
opacity: .6; opacity: .6;
} }
#chat .window { #chat .chat {
bottom: 0; bottom: 0;
left: 0; left: 0;
overflow: auto; overflow: auto;
@ -206,37 +207,36 @@ button {
right: 0; right: 0;
top: 0; top: 0;
width: 180px; width: 180px;
z-index: 1;
} }
#messages { #chat .messages {
display: table; display: table;
table-layout: fixed; table-layout: fixed;
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
#messages .msg { #chat .msg {
display: table-row; display: table-row;
word-wrap: break-word; word-wrap: break-word;
} }
#messages .msg:last-child { #chat .msg:last-child {
height: 100%; height: 100%;
} }
#messages .msg:last-child .text { #chat .msg:last-child .text {
padding-bottom: 5px; padding-bottom: 5px;
} }
#messages .time, #chat .time,
#messages .from, #chat .from,
#messages .text { #chat .text {
display: table-cell; display: table-cell;
padding: 5px 0 0; padding: 5px 0 0;
} }
#messages .time { #chat .time {
background: #f9f9f9; background: #f9f9f9;
color: #ddd; color: #ddd;
text-align: right; text-align: right;
width: 46px; width: 46px;
} }
#messages .from { #chat .from {
background: #f9f9f9; background: #f9f9f9;
border-right: 1px solid #f4f4f4; border-right: 1px solid #f4f4f4;
color: #ddd; color: #ddd;
@ -244,46 +244,46 @@ button {
text-align: right; text-align: right;
width: 134px; width: 134px;
} }
#messages a, #chat a,
#messages .from button { #chat .from button {
color: #33b0f7; color: #33b0f7;
} }
#messages .text { #chat .text {
padding-left: 10px; padding-left: 10px;
padding-right: 6px; padding-right: 6px;
} }
#messages .text a { #chat .text a {
word-break: break-all; word-break: break-all;
} }
#messages .type { #chat .type {
color: #ccc; color: #ccc;
display: none; display: none;
} }
#messages .join .type, #chat .join .type,
#messages .part .type, #chat .part .type,
#messages .mode .type, #chat .mode .type,
#messages .nick .type, #chat .nick .type,
#messages .kick .type, #chat .kick .type,
#messages .quit .type, #chat .quit .type,
#messages .quit .type, #chat .quit .type,
#messages .notice .type, #chat .notice .type,
#messages .topic .type { #chat .topic .type {
display: inline; display: inline;
} }
#meta { #chat .meta {
height: 80px; height: 80px;
padding: 25px 0 0 20px; padding: 25px 0 0 20px;
} }
#meta h1 { #chat .meta h1 {
color: #222; color: #222;
font-size: 15px; font-size: 15px;
} }
#meta .type { #chat .meta .type {
color: #ccc; color: #ccc;
text-transform: capitalize; text-transform: capitalize;
} }
#count { #chat .count {
background: #f9f9f9; background: #f9f9f9;
border-top: 1px dashed #e9ecef; border-top: 1px dashed #e9ecef;
border-bottom: 1px solid #e9ecef; border-bottom: 1px solid #e9ecef;
@ -293,7 +293,7 @@ button {
right: 0; right: 0;
top: 80px; top: 80px;
} }
#count:before { #chat .count:before {
color: #eee; color: #eee;
font: 16px Octicons; font: 16px Octicons;
content: "\f02e"; content: "\f02e";
@ -301,8 +301,9 @@ button {
right: 18px; right: 18px;
line-height: 40px; line-height: 40px;
transition: color .2s; transition: color .2s;
z-index: -1;
} }
#search { #chat .search {
color: #222; color: #222;
border: 0; border: 0;
background: none; background: none;
@ -311,9 +312,8 @@ button {
padding: 12px 20px; padding: 12px 20px;
position: relative; position: relative;
width: 100%; width: 100%;
z-index: 2;
} }
#users { #chat .names {
bottom: 0; bottom: 0;
overflow: auto; overflow: auto;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
@ -322,7 +322,7 @@ button {
top: 120px; top: 120px;
width: 100%; width: 100%;
} }
#users button { #chat .names button {
display: block; display: block;
line-height: 1.6em; line-height: 1.6em;
} }

View File

@ -18,7 +18,7 @@
<body> <body>
<aside id="sidebar"> <aside id="sidebar">
<div id="networks"></div> <div class="networks"></div>
<footer id="footer"> <footer id="footer">
<button id="btn-1" data-target="#connect"></button> <button id="btn-1" data-target="#connect"></button>
<button id="btn-2" data-target="#settings"></button> <button id="btn-2" data-target="#settings"></button>
@ -32,19 +32,23 @@
</header> </header>
<div id="windows"> <div id="windows">
<div id="chat"></div> <div id="chat"></div>
<div id="connect" class="container"> <div id="connect">
<div class="container">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<h1>Connect</h1> <h1>Connect</h1>
</div> </div>
</div> </div>
</div>
</div> </div>
<div id="settings" class="container"> <div id="settings">
<div class="container">
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<h1>Settings</h1> <h1>Settings</h1>
</div> </div>
</div> </div>
</div>
</div> </div>
</div> </div>
<form id="form" action=""> <form id="form" action="">
@ -64,7 +68,7 @@
<script type="text/html" class="channels"> <script type="text/html" class="channels">
{{#each channels}} {{#each channels}}
<button id="chan-{{id}}" class="chan" data-type="{{type}}"> <button data-id="{{id}}" data-target="#chan-{{id}}" class="chan">
<span class="badge"></span> <span class="badge"></span>
{{name}} {{name}}
</button> </button>
@ -72,29 +76,33 @@
</script> </script>
<script type="text/html" class="chat"> <script type="text/html" class="chat">
<div class="window"> {{#each channels}}
<div id="messages"> <div id="chan-{{id}}" data-type="{{type}}" class="chan">
<div class="chat">
<div class="messages">
{{partial "messages"}} {{partial "messages"}}
</div> </div>
</div> </div>
<aside class="sidebar"> <aside class="sidebar">
{{partial "users"}} <div class="meta">
<h1>{{name}}</h1>
<span class="type">{{type}}</span>
</div>
<div class="users">
{{partial "users"}}
</div>
</aside> </aside>
</div>
{{/each}}
</script> </script>
<script type="text/html" class="users"> <script type="text/html" class="users">
<div id="meta">
<h1>{{name}}</h1>
<span class="type">
{{type}}
</span>
</div>
{{#if users.length}} {{#if users.length}}
<div id="count"> <div class="count">
<input id="search" placeholder="{{users.length}} users"> <input class="search" placeholder="{{users.length}} users">
</div> </div>
{{/if}} {{/if}}
<div id="users"> <div class="names">
{{#each users}} {{#each users}}
<button class="user">{{mode}}{{name}}</button> <button class="user">{{mode}}{{name}}</button>
{{/each}} {{/each}}

View File

@ -34,10 +34,6 @@ $(function() {
var sidebar = $("#sidebar"); var sidebar = $("#sidebar");
var chat = $("#chat"); var chat = $("#chat");
var networks = $("#networks");
var channels = [];
var active = null;
var tpl = []; var tpl = [];
function render(name, data) { function render(name, data) {
tpl[name] = tpl[name] || Handlebars.compile($("#templates ." + name).html()); tpl[name] = tpl[name] || Handlebars.compile($("#templates ." + name).html());
@ -49,59 +45,61 @@ $(function() {
}); });
socket.on("init", function(data) { socket.on("init", function(data) {
networks.empty(); var channels = $.map(data.networks, function(n) {
channels = $.map(data.networks, function(n) {
return n.channels; return n.channels;
}); });
networks.append( sidebar.find(".networks").html(
render("networks", { render("networks", {
networks: data.networks networks: data.networks
}) })
).fadeIn(); );
var active = $($.cookie("active")); chat.html(
if (active.length === 0) { render("chat", {
active = networks.find(".chan").eq(0); channels: channels
})
);
var id = $.cookie("target");
var target = sidebar.find("[data-target=" + id + "]");
if (target.length !== 0) {
target.trigger("click");
} else {
sidebar.find(".chan")
.eq(0)
.trigger("click");
} }
active.trigger("click");
}); });
socket.on("join", function(data) { socket.on("join", function(data) {
channels.push(data.chan);
var id = data.network; var id = data.network;
var network = networks var network = sidebar.find("#network-" + id);
.find("#network-" + id)
.eq(0);
network.append( network.append(
render("channels", { render("channels", {
channels: [data.chan] channels: [data.chan]
}) })
); );
network.find(".chan") chat.append(
render("chat", {
channels: [data.chan]
})
);
sidebar.find(".chan")
.last() .last()
.trigger("click"); .trigger("click");
}); });
socket.on("msg", function(data) { socket.on("msg", function(data) {
var chan = find(data.chan); chat.find("#chan-" + data.chan)
if (typeof chan !== "undefined") { .find(".messages")
chan.messages.push(data.msg); .append(render("messages", {messages: [data.msg]}));
if (isActive(chan)) {
chat.find("#messages").append(
render("messages", {messages: [data.msg]})
);
}
}
}); });
socket.on("network", function(data) { socket.on("network", function(data) {
var lobby = data.network.channels[0]; sidebar.find(".networks").append(
channels.push(lobby);
networks.append(
render("networks", { render("networks", {
networks: [data.network] networks: [data.network]
}) })
); );
networks.find(".chan") sidebar.find(".chan")
.last() .last()
.trigger("click"); .trigger("click");
}); });
@ -112,7 +110,7 @@ $(function() {
socket.on("part", function(data) { socket.on("part", function(data) {
var id = data.chan; var id = data.chan;
networks.find("#chan-" + id) sidebar.find("[data-target=#chan-" + id + "]")
.remove() .remove()
.end() .end()
.find(".chan") .find(".chan")
@ -122,7 +120,7 @@ $(function() {
socket.on("quit", function(data) { socket.on("quit", function(data) {
var id = data.network; var id = data.network;
networks.find("#network-" + id) sidebar.find("#network-" + id)
.remove() .remove()
.end() .end()
.find(".chan") .find(".chan")
@ -131,13 +129,9 @@ $(function() {
}); });
socket.on("users", function(data) { socket.on("users", function(data) {
var chan = find(data.chan); chat.find("#chan-" + data.chan)
if (typeof chan !== "undefined") { .find(".users")
chan.users = data.users; .html(render("users", data));
if (isActive(chan)) {
chat.find(".sidebar").html(render("users", chan));
}
}
}); });
var input = $("#input") var input = $("#input")
@ -149,45 +143,41 @@ $(function() {
var value = input.val(); var value = input.val();
input.val(""); input.val("");
socket.emit("input", { socket.emit("input", {
target: active.id || -1, target: chat.data("id"),
text: value text: value
}); });
}); });
var top = 1;
sidebar.on("click", "button:not(.active)", function() { sidebar.on("click", "button:not(.active)", function() {
var btn = $(this); var self = $(this);
var id = "#" + btn.attr("id"); var target = self.data("target");
if (!target) {
return;
}
$.cookie("active", id); $.cookie("target", target);
chat.data(
"id",
self.data("id")
);
sidebar.find(".active").removeClass("active"); sidebar.find(".active").removeClass("active");
btn.addClass("active"); self.addClass("active")
.find(".badge")
.removeClass("highlight")
.empty();
active = null; var chan = $(target)
if (btn.hasClass("chan")) { .css("z-index", top++)
var chan = find(id.replace("#chan-", "")); .find(".chat")
if (typeof chan !== "undefined") { .sticky();
active = chan;
chat.fadeIn();
chat.siblings().hide();
chat.html(render("chat", chan));
chat.find(".window")
.sticky()
.scrollBottom();
}
} else {
chat.empty();
var target = $(btn.data("target"));
if (target.length !== 0) {
target.fadeIn();
target.siblings().hide();
}
}
}); });
chat.on("input", "#search", function() { chat.on("input", ".search", function() {
var val = $(this).val(); var val = $(this).val();
$("#users").find("button").each(function() { var names = $(this).closest(".users").find(".names");
names.find("button").each(function() {
var btn = $(this); var btn = $(this);
if (btn.text().toLowerCase().indexOf(val) === 0) { if (btn.text().toLowerCase().indexOf(val) === 0) {
btn.show(); btn.show();
@ -203,7 +193,7 @@ $(function() {
return; return;
} }
socket.emit("input", { socket.emit("input", {
target: active.id || -1, target: active,
text: "/whois " + user text: "/whois " + user
}); });
}); });
@ -212,12 +202,6 @@ $(function() {
return active !== null && chan == active; return active !== null && chan == active;
} }
function find(id) {
return $.grep(channels, function(c) {
return c.id == id;
})[0];
}
function complete(word) { function complete(word) {
return $.grep( return $.grep(
commands, commands,

File diff suppressed because one or more lines are too long