Added window management
This commit is contained in:
parent
a1d5f52875
commit
cb663777b4
|
@ -0,0 +1,117 @@
|
||||||
|
/*!
|
||||||
|
* jQuery Cookie Plugin v1.4.1
|
||||||
|
* https://github.com/carhartl/jquery-cookie
|
||||||
|
*
|
||||||
|
* Copyright 2013 Klaus Hartl
|
||||||
|
* Released under the MIT license
|
||||||
|
*/
|
||||||
|
(function (factory) {
|
||||||
|
if (typeof define === 'function' && define.amd) {
|
||||||
|
// AMD
|
||||||
|
define(['jquery'], factory);
|
||||||
|
} else if (typeof exports === 'object') {
|
||||||
|
// CommonJS
|
||||||
|
factory(require('jquery'));
|
||||||
|
} else {
|
||||||
|
// Browser globals
|
||||||
|
factory(jQuery);
|
||||||
|
}
|
||||||
|
}(function ($) {
|
||||||
|
|
||||||
|
var pluses = /\+/g;
|
||||||
|
|
||||||
|
function encode(s) {
|
||||||
|
return config.raw ? s : encodeURIComponent(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function decode(s) {
|
||||||
|
return config.raw ? s : decodeURIComponent(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
function stringifyCookieValue(value) {
|
||||||
|
return encode(config.json ? JSON.stringify(value) : String(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseCookieValue(s) {
|
||||||
|
if (s.indexOf('"') === 0) {
|
||||||
|
// This is a quoted cookie as according to RFC2068, unescape...
|
||||||
|
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Replace server-side written pluses with spaces.
|
||||||
|
// If we can't decode the cookie, ignore it, it's unusable.
|
||||||
|
// If we can't parse the cookie, ignore it, it's unusable.
|
||||||
|
s = decodeURIComponent(s.replace(pluses, ' '));
|
||||||
|
return config.json ? JSON.parse(s) : s;
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function read(s, converter) {
|
||||||
|
var value = config.raw ? s : parseCookieValue(s);
|
||||||
|
return $.isFunction(converter) ? converter(value) : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = $.cookie = function (key, value, options) {
|
||||||
|
|
||||||
|
// Write
|
||||||
|
|
||||||
|
if (value !== undefined && !$.isFunction(value)) {
|
||||||
|
options = $.extend({}, config.defaults, options);
|
||||||
|
|
||||||
|
if (typeof options.expires === 'number') {
|
||||||
|
var days = options.expires, t = options.expires = new Date();
|
||||||
|
t.setTime(+t + days * 864e+5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (document.cookie = [
|
||||||
|
encode(key), '=', stringifyCookieValue(value),
|
||||||
|
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
|
||||||
|
options.path ? '; path=' + options.path : '',
|
||||||
|
options.domain ? '; domain=' + options.domain : '',
|
||||||
|
options.secure ? '; secure' : ''
|
||||||
|
].join(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read
|
||||||
|
|
||||||
|
var result = key ? undefined : {};
|
||||||
|
|
||||||
|
// To prevent the for loop in the first place assign an empty array
|
||||||
|
// in case there are no cookies at all. Also prevents odd result when
|
||||||
|
// calling $.cookie().
|
||||||
|
var cookies = document.cookie ? document.cookie.split('; ') : [];
|
||||||
|
|
||||||
|
for (var i = 0, l = cookies.length; i < l; i++) {
|
||||||
|
var parts = cookies[i].split('=');
|
||||||
|
var name = decode(parts.shift());
|
||||||
|
var cookie = parts.join('=');
|
||||||
|
|
||||||
|
if (key && key === name) {
|
||||||
|
// If second argument (value) is a function it's a converter...
|
||||||
|
result = read(cookie, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent storing a cookie that we couldn't decode.
|
||||||
|
if (!key && (cookie = read(cookie)) !== undefined) {
|
||||||
|
result[name] = cookie;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
config.defaults = {};
|
||||||
|
|
||||||
|
$.removeCookie = function (key, options) {
|
||||||
|
if ($.cookie(key) === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must not alter options, thus extending a fresh object...
|
||||||
|
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
|
||||||
|
return !$.cookie(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
}));
|
|
@ -29,6 +29,10 @@ 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;
|
||||||
|
@ -36,12 +40,20 @@ button {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
.container {
|
||||||
|
margin: 10% auto;
|
||||||
|
max-width: 480px;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
padding: 0 30px;
|
||||||
|
}
|
||||||
#sidebar {
|
#sidebar {
|
||||||
background: #262c36;
|
background: #262c36;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
overflow: auto;
|
overflow: hidden;
|
||||||
overflow-x: hidden;
|
overflow-y: auto;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@ -64,6 +76,7 @@ button {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
#networks {
|
#networks {
|
||||||
|
display: none;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
padding: 30px 40px 80px;
|
padding: 30px 40px 80px;
|
||||||
}
|
}
|
||||||
|
@ -109,10 +122,10 @@ button {
|
||||||
font: 18px Octicons;
|
font: 18px Octicons;
|
||||||
padding: 8px 12px;
|
padding: 8px 12px;
|
||||||
}
|
}
|
||||||
#connect:before {
|
#footer #btn-1:before {
|
||||||
content: "\f085";
|
content: "\f085";
|
||||||
}
|
}
|
||||||
#settings:before {
|
#footer #btn-2:before {
|
||||||
content: "\f02f";
|
content: "\f02f";
|
||||||
}
|
}
|
||||||
#main {
|
#main {
|
||||||
|
@ -157,11 +170,15 @@ button {
|
||||||
content: "\f05e";
|
content: "\f05e";
|
||||||
}
|
}
|
||||||
#windows {
|
#windows {
|
||||||
bottom: 0;
|
bottom: 40px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
overflow: auto;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
#windows > div {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
#chat {
|
#chat {
|
||||||
font: 13px Consolas, monospace;
|
font: 13px Consolas, monospace;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -172,7 +189,7 @@ button {
|
||||||
opacity: .6;
|
opacity: .6;
|
||||||
}
|
}
|
||||||
#chat .window {
|
#chat .window {
|
||||||
bottom: 40px;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
@ -193,6 +210,7 @@ button {
|
||||||
}
|
}
|
||||||
#messages {
|
#messages {
|
||||||
display: table;
|
display: table;
|
||||||
|
table-layout: fixed;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -226,6 +244,7 @@ button {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
width: 134px;
|
width: 134px;
|
||||||
}
|
}
|
||||||
|
#messages a,
|
||||||
#messages .from button {
|
#messages .from button {
|
||||||
color: #33b0f7;
|
color: #33b0f7;
|
||||||
}
|
}
|
||||||
|
@ -312,7 +331,7 @@ button {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
left: 0;
|
left: 0;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 180px;
|
right: 0px;
|
||||||
}
|
}
|
||||||
#form input {
|
#form input {
|
||||||
border: 0;
|
border: 0;
|
||||||
|
@ -323,9 +342,11 @@ button {
|
||||||
padding: 0 12px;
|
padding: 0 12px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
#submit {
|
#form #submit {
|
||||||
margin-left: -999px;
|
height: 0;
|
||||||
|
margin-left: -9999px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 767px) {
|
@media (max-width: 767px) {
|
||||||
|
|
|
@ -20,8 +20,8 @@
|
||||||
<aside id="sidebar">
|
<aside id="sidebar">
|
||||||
<div id="networks"></div>
|
<div id="networks"></div>
|
||||||
<footer id="footer">
|
<footer id="footer">
|
||||||
<button id="connect" class="active"></button>
|
<button id="btn-1" data-target="#connect"></button>
|
||||||
<button id="settings"></button>
|
<button id="btn-2" data-target="#settings"></button>
|
||||||
</footer>
|
</footer>
|
||||||
</aside>
|
</aside>
|
||||||
<div id="main">
|
<div id="main">
|
||||||
|
@ -32,17 +32,31 @@
|
||||||
</header>
|
</header>
|
||||||
<div id="windows">
|
<div id="windows">
|
||||||
<div id="chat"></div>
|
<div id="chat"></div>
|
||||||
<form id="form" action="">
|
<div id="connect" class="container">
|
||||||
<input id="submit" tabindex="-1" type="submit">
|
<div class="row">
|
||||||
<input id="input">
|
<div class="col-sm-12">
|
||||||
</form>
|
<h1>Connect</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="settings" class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-12">
|
||||||
|
<h1>Settings</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<form id="form" action="">
|
||||||
|
<input id="submit" tabindex="-1" type="submit">
|
||||||
|
<input id="input">
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="templates">
|
<div id="templates">
|
||||||
<script type="text/html" class="networks">
|
<script type="text/html" class="networks">
|
||||||
{{#each networks}}
|
{{#each networks}}
|
||||||
<section class="network" data-id="{{id}}">
|
<section id="network-{{id}}" class="network">
|
||||||
{{partial "channels"}}
|
{{partial "channels"}}
|
||||||
</section>
|
</section>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -50,7 +64,7 @@
|
||||||
|
|
||||||
<script type="text/html" class="channels">
|
<script type="text/html" class="channels">
|
||||||
{{#each channels}}
|
{{#each channels}}
|
||||||
<button class="chan" data-id="{{id}}" data-type="{{type}}">
|
<button id="chan-{{id}}" class="chan" data-type="{{type}}">
|
||||||
<span class="badge"></span>
|
<span class="badge"></span>
|
||||||
{{name}}
|
{{name}}
|
||||||
</button>
|
</button>
|
||||||
|
@ -82,7 +96,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div id="users">
|
<div id="users">
|
||||||
{{#each users}}
|
{{#each users}}
|
||||||
<button>{{mode}}{{name}}</button>
|
<button class="user">{{mode}}{{name}}</button>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</script>
|
</script>
|
||||||
|
@ -95,7 +109,7 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="from">
|
<span class="from">
|
||||||
{{#if from}}
|
{{#if from}}
|
||||||
<button>{{from}}</button>
|
<button class="user">{{from}}</button>
|
||||||
{{else}}
|
{{else}}
|
||||||
//
|
//
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -31,11 +31,12 @@ $(function() {
|
||||||
"/whois"
|
"/whois"
|
||||||
];
|
];
|
||||||
|
|
||||||
|
var sidebar = $("#sidebar");
|
||||||
var chat = $("#chat");
|
var chat = $("#chat");
|
||||||
var networks = $("#networks");
|
|
||||||
|
|
||||||
|
var networks = $("#networks");
|
||||||
var channels = [];
|
var channels = [];
|
||||||
var activeChannel = null;
|
var active = null;
|
||||||
|
|
||||||
var tpl = [];
|
var tpl = [];
|
||||||
function render(name, data) {
|
function render(name, data) {
|
||||||
|
@ -56,16 +57,19 @@ $(function() {
|
||||||
render("networks", {
|
render("networks", {
|
||||||
networks: data.networks
|
networks: data.networks
|
||||||
})
|
})
|
||||||
);
|
).fadeIn();
|
||||||
networks.find(".chan")
|
var active = $($.cookie("active"));
|
||||||
.eq(0)
|
if (active.length === 0) {
|
||||||
.trigger("click");
|
active = networks.find(".chan").eq(0);
|
||||||
|
}
|
||||||
|
active.trigger("click");
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("join", function(data) {
|
socket.on("join", function(data) {
|
||||||
channels.push(data.chan);
|
channels.push(data.chan);
|
||||||
|
var id = data.network;
|
||||||
var network = networks
|
var network = networks
|
||||||
.find(".network[data-id='" + data.network + "']")
|
.find("#network-" + id)
|
||||||
.eq(0);
|
.eq(0);
|
||||||
network.append(
|
network.append(
|
||||||
render("channels", {
|
render("channels", {
|
||||||
|
@ -83,9 +87,7 @@ $(function() {
|
||||||
chan.messages.push(data.msg);
|
chan.messages.push(data.msg);
|
||||||
if (isActive(chan)) {
|
if (isActive(chan)) {
|
||||||
chat.find("#messages").append(
|
chat.find("#messages").append(
|
||||||
render("messages", {
|
render("messages", {messages: [data.msg]})
|
||||||
messages: [data.msg]
|
|
||||||
})
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,6 +101,9 @@ $(function() {
|
||||||
networks: [data.network]
|
networks: [data.network]
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
networks.find(".chan")
|
||||||
|
.last()
|
||||||
|
.trigger("click");
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("nick", function(data) {
|
socket.on("nick", function(data) {
|
||||||
|
@ -106,7 +111,8 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("part", function(data) {
|
socket.on("part", function(data) {
|
||||||
networks.find(".chan[data-id='" + data.chan + "']")
|
var id = data.chan;
|
||||||
|
networks.find("#chan-" + id)
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.find(".chan")
|
.find(".chan")
|
||||||
|
@ -115,7 +121,8 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on("quit", function(data) {
|
socket.on("quit", function(data) {
|
||||||
networks.find(".network[data-id='" + data.network + "']")
|
var id = data.network;
|
||||||
|
networks.find("#network-" + id)
|
||||||
.remove()
|
.remove()
|
||||||
.end()
|
.end()
|
||||||
.find(".chan")
|
.find(".chan")
|
||||||
|
@ -128,8 +135,7 @@ $(function() {
|
||||||
if (typeof chan !== "undefined") {
|
if (typeof chan !== "undefined") {
|
||||||
chan.users = data.users;
|
chan.users = data.users;
|
||||||
if (isActive(chan)) {
|
if (isActive(chan)) {
|
||||||
chat.find(".sidebar")
|
chat.find(".sidebar").html(render("users", chan));
|
||||||
.html(render("users", chan));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -143,29 +149,39 @@ $(function() {
|
||||||
var value = input.val();
|
var value = input.val();
|
||||||
input.val("");
|
input.val("");
|
||||||
socket.emit("input", {
|
socket.emit("input", {
|
||||||
target: chat.data("target"),
|
target: active.id || -1,
|
||||||
text: value
|
text: value
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
networks.on("click", ".chan", function() {
|
sidebar.on("click", "button:not(.active)", function() {
|
||||||
var self = $(this);
|
var btn = $(this);
|
||||||
var id = self.data("id");
|
var id = "#" + btn.attr("id");
|
||||||
if (self.hasClass("active")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chat.data("target", id);
|
$.cookie("active", id);
|
||||||
networks.find(".active").removeClass("active");
|
|
||||||
self.addClass("active");
|
|
||||||
|
|
||||||
var chan = find(id);
|
sidebar.find(".active").removeClass("active");
|
||||||
if (typeof chan !== "undefined") {
|
btn.addClass("active");
|
||||||
activeChannel = chan;
|
|
||||||
chat.html(render("chat", chan));
|
active = null;
|
||||||
chat.find(".window")
|
if (btn.hasClass("chan")) {
|
||||||
.sticky()
|
var chan = find(id.replace("#chan-", ""));
|
||||||
.scrollBottom();
|
if (typeof chan !== "undefined") {
|
||||||
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -181,8 +197,19 @@ $(function() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
chat.on("click", ".user", function() {
|
||||||
|
var user = $(this).text();
|
||||||
|
if (user.indexOf("#") !== -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
socket.emit("input", {
|
||||||
|
target: active.id || -1,
|
||||||
|
text: "/whois " + user
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
function isActive(chan) {
|
function isActive(chan) {
|
||||||
return activeChannel !== null && chan == activeChannel;
|
return active !== null && chan == active;
|
||||||
}
|
}
|
||||||
|
|
||||||
function find(id) {
|
function find(id) {
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1,10 +1,20 @@
|
||||||
|
var _ = require("lodash");
|
||||||
|
|
||||||
module.exports = function(network, chan, cmd, args) {
|
module.exports = function(network, chan, cmd, args) {
|
||||||
if (cmd != "part") {
|
if (cmd != "part" && cmd != "leave" && cmd != "close") {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var irc = network.irc;
|
var client = this;
|
||||||
if (args.length === 0) {
|
if (chan.type == "query") {
|
||||||
args.push(chan.name);
|
network.channels = _.without(network.channels, chan);
|
||||||
|
client.emit("part", {
|
||||||
|
chan: chan.id
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var irc = network.irc;
|
||||||
|
if (args.length === 0) {
|
||||||
|
args.push(chan.name);
|
||||||
|
}
|
||||||
|
irc.part(args);
|
||||||
}
|
}
|
||||||
irc.part(args);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,10 +4,11 @@ var Msg = require("../../models/msg");
|
||||||
|
|
||||||
module.exports = function(irc, network) {
|
module.exports = function(irc, network) {
|
||||||
var client = this;
|
var client = this;
|
||||||
irc.on("whois", function(data) {
|
irc.on("whois", function(err, data) {
|
||||||
if (!data) {
|
if (data === null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var chan = _.findWhere(network.channels, {name: data.nickname});
|
var chan = _.findWhere(network.channels, {name: data.nickname});
|
||||||
if (typeof chan === "undefined") {
|
if (typeof chan === "undefined") {
|
||||||
chan = new Chan({
|
chan = new Chan({
|
||||||
|
@ -20,6 +21,7 @@ module.exports = function(irc, network) {
|
||||||
chan: chan
|
chan: chan
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefix = {
|
var prefix = {
|
||||||
hostname: "from",
|
hostname: "from",
|
||||||
realname: "is",
|
realname: "is",
|
||||||
|
|
|
@ -89,6 +89,7 @@ function input(client, data) {
|
||||||
args
|
args
|
||||||
]);
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
console.log(err.stack);
|
||||||
// ..
|
// ..
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue