aboutsummaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--client/client.js555
1 files changed, 291 insertions, 264 deletions
diff --git a/client/client.js b/client/client.js
index 254480d..85e3ecb 100644
--- a/client/client.js
+++ b/client/client.js
@@ -26,452 +26,481 @@ var frontpage = [
"",
"Server and web client released under the WTFPL and MIT open source license.",
"No message history is retained on the hack.chat server."
-].join("\n")
+].join("\n");
-function $(query) {return document.querySelector(query)}
+function $(query) {
+ return document.querySelector(query);
+}
function localStorageGet(key) {
try {
return window.localStorage[key]
- }
- catch(e) {}
+ } catch(e) {}
}
function localStorageSet(key, val) {
try {
window.localStorage[key] = val
- }
- catch(e) {}
+ } catch(e) {}
}
-
-var ws
-var myNick = localStorageGet('my-nick')
-var myChannel = window.location.search.replace(/^\?/, '')
-var lastSent = [""]
-var lastSentPos = 0
-
+var ws;
+var myNick = localStorageGet('my-nick');
+var myChannel = window.location.search.replace(/^\?/, '');
+var lastSent = [""];
+var lastSentPos = 0;
// Ping server every 50 seconds to retain WebSocket connection
-window.setInterval(function() {
- send({cmd: 'ping'})
-}, 50000)
-
+window.setInterval(function () {
+ send({ cmd: 'ping' });
+}, 50000);
function join(channel) {
if (document.domain == 'hack.chat') {
// For https://hack.chat/
- ws = new WebSocket('wss://hack.chat/chat-ws')
+ ws = new WebSocket('wss://hack.chat/chat-ws');
} else {
// for local installs
- ws = new WebSocket('ws://' + document.domain + ':6060')
+ ws = new WebSocket('ws://' + document.domain + ':6060');
}
- var wasConnected = false
+ var wasConnected = false;
- ws.onopen = function() {
+ ws.onopen = function () {
if (!wasConnected) {
if (location.hash) {
- myNick = location.hash.substr(1)
- }
- else {
- myNick = prompt('Nickname:', myNick)
+ myNick = location.hash.substr(1);
+ } else {
+ myNick = prompt('Nickname:', myNick);
}
}
+
if (myNick) {
- localStorageSet('my-nick', myNick)
- send({cmd: 'join', channel: channel, nick: myNick})
+ localStorageSet('my-nick', myNick);
+ send({ cmd: 'join', channel: channel, nick: myNick });
}
- wasConnected = true
+
+ wasConnected = true;
}
- ws.onclose = function() {
+ ws.onclose = function () {
if (wasConnected) {
- pushMessage({nick: '!', text: "Server disconnected. Attempting to reconnect..."})
+ pushMessage({ nick: '!', text: "Server disconnected. Attempting to reconnect. . ." });
}
- window.setTimeout(function() {
- join(channel)
- }, 2000)
+
+ window.setTimeout(function () {
+ join(channel);
+ }, 2000);
}
- ws.onmessage = function(message) {
- var args = JSON.parse(message.data)
- var cmd = args.cmd
- var command = COMMANDS[cmd]
- command.call(null, args)
+ ws.onmessage = function (message) {
+ var args = JSON.parse(message.data);
+ var cmd = args.cmd;
+ var command = COMMANDS[cmd];
+ command.call(null, args);
}
}
-
var COMMANDS = {
- chat: function(args) {
+ chat: function (args) {
if (ignoredUsers.indexOf(args.nick) >= 0) {
- return
+ return;
}
- pushMessage(args)
+
+ pushMessage(args);
},
- info: function(args) {
- args.nick = '*'
- pushMessage(args)
+
+ info: function (args) {
+ args.nick = '*';
+
+ pushMessage(args);
},
- warn: function(args) {
- args.nick = '!'
- pushMessage(args)
+
+ warn: function (args) {
+ args.nick = '!';
+
+ pushMessage(args);
},
- onlineSet: function(args) {
- var nicks = args.nicks
- usersClear()
- nicks.forEach(function(nick) {
- userAdd(nick)
- })
- pushMessage({nick: '*', text: "Users online: " + nicks.join(", ")})
+
+ onlineSet: function (args) {
+ var nicks = args.nicks;
+
+ usersClear();
+
+ nicks.forEach(function (nick) {
+ userAdd(nick);
+ });
+
+ pushMessage({ nick: '*', text: "Users online: " + nicks.join(", ") })
},
- onlineAdd: function(args) {
- var nick = args.nick
- userAdd(nick)
+
+ onlineAdd: function (args) {
+ var nick = args.nick;
+
+ userAdd(nick);
+
if ($('#joined-left').checked) {
- pushMessage({nick: '*', text: nick + " joined"})
+ pushMessage({ nick: '*', text: nick + " joined" });
}
},
- onlineRemove: function(args) {
- var nick = args.nick
- userRemove(nick)
+
+ onlineRemove: function (args) {
+ var nick = args.nick;
+
+ userRemove(nick);
+
if ($('#joined-left').checked) {
- pushMessage({nick: '*', text: nick + " left"})
+ pushMessage({ nick: '*', text: nick + " left" });
}
- },
+ }
}
-
function pushMessage(args) {
// Message container
- var messageEl = document.createElement('div')
- messageEl.classList.add('message')
+ var messageEl = document.createElement('div');
+ messageEl.classList.add('message');
if (args.nick == myNick) {
- messageEl.classList.add('me')
- }
- else if (args.nick == '!') {
- messageEl.classList.add('warn')
- }
- else if (args.nick == '*') {
- messageEl.classList.add('info')
- }
- else if (args.admin) {
- messageEl.classList.add('admin')
- }
- else if (args.mod) {
- messageEl.classList.add('mod')
+ messageEl.classList.add('me');
+ } else if (args.nick == '!') {
+ messageEl.classList.add('warn');
+ } else if (args.nick == '*') {
+ messageEl.classList.add('info');
+ } else if (args.admin) {
+ messageEl.classList.add('admin');
+ } else if (args.mod) {
+ messageEl.classList.add('mod');
}
// Nickname
- var nickSpanEl = document.createElement('span')
- nickSpanEl.classList.add('nick')
- messageEl.appendChild(nickSpanEl)
+ var nickSpanEl = document.createElement('span');
+ nickSpanEl.classList.add('nick');
+ messageEl.appendChild(nickSpanEl);
if (args.trip) {
- var tripEl = document.createElement('span')
- tripEl.textContent = args.trip + " "
- tripEl.classList.add('trip')
- nickSpanEl.appendChild(tripEl)
+ var tripEl = document.createElement('span');
+ tripEl.textContent = args.trip + " ";
+ tripEl.classList.add('trip');
+ nickSpanEl.appendChild(tripEl);
}
if (args.nick) {
- var nickLinkEl = document.createElement('a')
- nickLinkEl.textContent = args.nick
- nickLinkEl.onclick = function() {
- insertAtCursor("@" + args.nick + " ")
- $('#chatinput').focus()
+ var nickLinkEl = document.createElement('a');
+ nickLinkEl.textContent = args.nick;
+
+ nickLinkEl.onclick = function () {
+ insertAtCursor("@" + args.nick + " ");
+ $('#chatinput').focus();
}
- var date = new Date(args.time || Date.now())
- nickLinkEl.title = date.toLocaleString()
- nickSpanEl.appendChild(nickLinkEl)
+
+ var date = new Date(args.time || Date.now());
+ nickLinkEl.title = date.toLocaleString();
+ nickSpanEl.appendChild(nickLinkEl);
}
// Text
- var textEl = document.createElement('pre')
- textEl.classList.add('text')
+ var textEl = document.createElement('pre');
+ textEl.classList.add('text');
- textEl.textContent = args.text || ''
- textEl.innerHTML = textEl.innerHTML.replace(/(\?|https?:\/\/)\S+?(?=[,.!?:)]?\s|$)/g, parseLinks)
+ textEl.textContent = args.text || '';
+ textEl.innerHTML = textEl.innerHTML.replace(/(\?|https?:\/\/)\S+?(?=[,.!?:)]?\s|$)/g, parseLinks);
if ($('#parse-latex').checked) {
// Temporary hotfix for \rule spamming, see https://github.com/Khan/KaTeX/issues/109
- textEl.innerHTML = textEl.innerHTML.replace(/\\rule|\\\\\s*\[.*?\]/g, '')
+ textEl.innerHTML = textEl.innerHTML.replace(/\\rule|\\\\\s*\[.*?\]/g, '');
try {
renderMathInElement(textEl, {delimiters: [
- {left: "$$", right: "$$", display: true},
- {left: "$", right: "$", display: false},
+ { left: "$$", right: "$$", display: true },
+ { left: "$", right: "$", display: false },
]})
- }
- catch (e) {
- console.warn(e)
+ } catch (e) {
+ console.warn(e);
}
}
- messageEl.appendChild(textEl)
+ messageEl.appendChild(textEl);
// Scroll to bottom
- var atBottom = isAtBottom()
- $('#messages').appendChild(messageEl)
+ var atBottom = isAtBottom();
+ $('#messages').appendChild(messageEl);
if (atBottom) {
- window.scrollTo(0, document.body.scrollHeight)
+ window.scrollTo(0, document.body.scrollHeight);
}
- unread += 1
- updateTitle()
+ unread += 1;
+ updateTitle();
}
-
function insertAtCursor(text) {
- var input = $('#chatinput')
- var start = input.selectionStart || 0
- var before = input.value.substr(0, start)
- var after = input.value.substr(start)
- before += text
- input.value = before + after
- input.selectionStart = input.selectionEnd = before.length
- updateInputSize()
-}
+ var input = $('#chatinput');
+ var start = input.selectionStart || 0;
+ var before = input.value.substr(0, start);
+ var after = input.value.substr(start);
+ before += text;
+ input.value = before + after;
+ input.selectionStart = input.selectionEnd = before.length;
+
+ updateInputSize();
+}
function send(data) {
if (ws && ws.readyState == ws.OPEN) {
- ws.send(JSON.stringify(data))
+ ws.send(JSON.stringify(data));
}
}
-
function parseLinks(g0) {
- var a = document.createElement('a')
- a.innerHTML = g0
- var url = a.textContent
- a.href = url
- a.target = '_blank'
- return a.outerHTML
+ var a = document.createElement('a');
+
+ a.innerHTML = g0;
+
+ var url = a.textContent;
+
+ a.href = url;
+ a.target = '_blank';
+
+ return a.outerHTML;
}
+var windowActive = true;
+var unread = 0;
-var windowActive = true
-var unread = 0
+window.onfocus = function () {
+ windowActive = true;
-window.onfocus = function() {
- windowActive = true
- updateTitle()
+ updateTitle();
}
-window.onblur = function() {
- windowActive = false
+window.onblur = function () {
+ windowActive = false;
}
-window.onscroll = function() {
+window.onscroll = function () {
if (isAtBottom()) {
- updateTitle()
+ updateTitle();
}
}
function isAtBottom() {
- return (window.innerHeight + window.scrollY) >= (document.body.scrollHeight - 1)
+ return (window.innerHeight + window.scrollY) >= (document.body.scrollHeight - 1);
}
function updateTitle() {
if (windowActive && isAtBottom()) {
- unread = 0
+ unread = 0;
}
- var title
+ var title;
if (myChannel) {
- title = "?" + myChannel
- }
- else {
- title = "hack.chat"
+ title = "?" + myChannel;
+ } else {
+ title = "hack.chat";
}
+
if (unread > 0) {
- title = '(' + unread + ') ' + title
+ title = '(' + unread + ') ' + title;
}
- document.title = title
-}
-/* footer */
+ document.title = title;
+}
-$('#footer').onclick = function() {
- $('#chatinput').focus()
+$('#footer').onclick = function () {
+ $('#chatinput').focus();
}
-$('#chatinput').onkeydown = function(e) {
+$('#chatinput').onkeydown = function (e) {
if (e.keyCode == 13 /* ENTER */ && !e.shiftKey) {
- e.preventDefault()
+ e.preventDefault();
+
// Submit message
if (e.target.value != '') {
- var text = e.target.value
- e.target.value = ''
- send({cmd: 'chat', text: text})
- lastSent[0] = text
- lastSent.unshift("")
- lastSentPos = 0
- updateInputSize()
+ var text = e.target.value;
+ e.target.value = '';
+
+ send({ cmd: 'chat', text: text });
+
+ lastSent[0] = text;
+ lastSent.unshift("");
+ lastSentPos = 0;
+
+ updateInputSize();
}
- }
- else if (e.keyCode == 38 /* UP */) {
+ } else if (e.keyCode == 38 /* UP */) {
// Restore previous sent messages
if (e.target.selectionStart === 0 && lastSentPos < lastSent.length - 1) {
- e.preventDefault()
+ e.preventDefault();
+
if (lastSentPos == 0) {
- lastSent[0] = e.target.value
+ lastSent[0] = e.target.value;
}
- lastSentPos += 1
- e.target.value = lastSent[lastSentPos]
- e.target.selectionStart = e.target.selectionEnd = e.target.value.length
- updateInputSize()
+
+ lastSentPos += 1;
+ e.target.value = lastSent[lastSentPos];
+ e.target.selectionStart = e.target.selectionEnd = e.target.value.length;
+
+ updateInputSize();
}
- }
- else if (e.keyCode == 40 /* DOWN */) {
+ } else if (e.keyCode == 40 /* DOWN */) {
if (e.target.selectionStart === e.target.value.length && lastSentPos > 0) {
- e.preventDefault()
- lastSentPos -= 1
- e.target.value = lastSent[lastSentPos]
- e.target.selectionStart = e.target.selectionEnd = 0
- updateInputSize()
+ e.preventDefault();
+
+ lastSentPos -= 1;
+ e.target.value = lastSent[lastSentPos];
+ e.target.selectionStart = e.target.selectionEnd = 0;
+
+ updateInputSize();
}
- }
- else if (e.keyCode == 27 /* ESC */) {
- e.preventDefault()
+ } else if (e.keyCode == 27 /* ESC */) {
+ e.preventDefault();
+
// Clear input field
- e.target.value = ""
- lastSentPos = 0
- lastSent[lastSentPos] = ""
- updateInputSize()
- }
- else if (e.keyCode == 9 /* TAB */) {
+ e.target.value = "";
+ lastSentPos = 0;
+ lastSent[lastSentPos] = "";
+
+ updateInputSize();
+ } else if (e.keyCode == 9 /* TAB */) {
// Tab complete nicknames starting with @
- e.preventDefault()
- var pos = e.target.selectionStart || 0
- var text = e.target.value
- var index = text.lastIndexOf('@', pos)
+ e.preventDefault();
+
+ var pos = e.target.selectionStart || 0;
+ var text = e.target.value;
+ var index = text.lastIndexOf('@', pos);
+
if (index >= 0) {
- var stub = text.substring(index + 1, pos).toLowerCase()
+ var stub = text.substring(index + 1, pos).toLowerCase();
// Search for nick beginning with stub
- var nicks = onlineUsers.filter(function(nick) {
+ var nicks = onlineUsers.filter(function (nick) {
return nick.toLowerCase().indexOf(stub) == 0
- })
+ });
+
if (nicks.length == 1) {
- insertAtCursor(nicks[0].substr(stub.length) + " ")
+ insertAtCursor(nicks[0].substr(stub.length) + " ");
}
}
}
}
-
function updateInputSize() {
- var atBottom = isAtBottom()
+ var atBottom = isAtBottom();
- var input = $('#chatinput')
- input.style.height = 0
- input.style.height = input.scrollHeight + 'px'
- document.body.style.marginBottom = $('#footer').offsetHeight + 'px'
+ var input = $('#chatinput');
+ input.style.height = 0;
+ input.style.height = input.scrollHeight + 'px';
+ document.body.style.marginBottom = $('#footer').offsetHeight + 'px';
if (atBottom) {
- window.scrollTo(0, document.body.scrollHeight)
+ window.scrollTo(0, document.body.scrollHeight);
}
}
-$('#chatinput').oninput = function() {
- updateInputSize()
+$('#chatinput').oninput = function () {
+ updateInputSize();
}
-updateInputSize()
+updateInputSize();
/* sidebar */
-$('#sidebar').onmouseenter = $('#sidebar').ontouchstart = function(e) {
- $('#sidebar-content').classList.remove('hidden')
- e.stopPropagation()
+$('#sidebar').onmouseenter = $('#sidebar').ontouchstart = function (e) {
+ $('#sidebar-content').classList.remove('hidden');
+ e.stopPropagation();
}
-$('#sidebar').onmouseleave = document.ontouchstart = function() {
+$('#sidebar').onmouseleave = document.ontouchstart = function () {
if (!$('#pin-sidebar').checked) {
- $('#sidebar-content').classList.add('hidden')
+ $('#sidebar-content').classList.add('hidden');
}
}
-$('#clear-messages').onclick = function() {
+$('#clear-messages').onclick = function () {
// Delete children elements
- var messages = $('#messages')
+ var messages = $('#messages');
while (messages.firstChild) {
- messages.removeChild(messages.firstChild)
+ messages.removeChild(messages.firstChild);
}
}
// Restore settings from localStorage
if (localStorageGet('pin-sidebar') == 'true') {
- $('#pin-sidebar').checked = true
- $('#sidebar-content').classList.remove('hidden')
+ $('#pin-sidebar').checked = true;
+ $('#sidebar-content').classList.remove('hidden');
}
+
if (localStorageGet('joined-left') == 'false') {
- $('#joined-left').checked = false
+ $('#joined-left').checked = false;
}
+
if (localStorageGet('parse-latex') == 'false') {
- $('#parse-latex').checked = false
+ $('#parse-latex').checked = false;
}
-$('#pin-sidebar').onchange = function(e) {
- localStorageSet('pin-sidebar', !!e.target.checked)
+$('#pin-sidebar').onchange = function (e) {
+ localStorageSet('pin-sidebar', !!e.target.checked);
}
-$('#joined-left').onchange = function(e) {
- localStorageSet('joined-left', !!e.target.checked)
+
+$('#joined-left').onchange = function (e) {
+ localStorageSet('joined-left', !!e.target.checked);
}
-$('#parse-latex').onchange = function(e) {
- localStorageSet('parse-latex', !!e.target.checked)
+
+$('#parse-latex').onchange = function (e) {
+ localStorageSet('parse-latex', !!e.target.checked);
}
// User list
-
-var onlineUsers = []
-var ignoredUsers = []
+var onlineUsers = [];
+var ignoredUsers = [];
function userAdd(nick) {
- var user = document.createElement('a')
- user.textContent = nick
- user.onclick = function(e) {
+ var user = document.createElement('a');
+ user.textContent = nick;
+
+ user.onclick = function (e) {
userInvite(nick)
}
- var userLi = document.createElement('li')
- userLi.appendChild(user)
- $('#users').appendChild(userLi)
- onlineUsers.push(nick)
+
+ var userLi = document.createElement('li');
+ userLi.appendChild(user);
+ $('#users').appendChild(userLi);
+ onlineUsers.push(nick);
}
function userRemove(nick) {
- var users = $('#users')
- var children = users.children
+ var users = $('#users');
+ var children = users.children;
+
for (var i = 0; i < children.length; i++) {
- var user = children[i]
+ var user = children[i];
if (user.textContent == nick) {
- users.removeChild(user)
+ users.removeChild(user);
}
}
- var index = onlineUsers.indexOf(nick)
+
+ var index = onlineUsers.indexOf(nick);
if (index >= 0) {
- onlineUsers.splice(index, 1)
+ onlineUsers.splice(index, 1);
}
}
function usersClear() {
- var users = $('#users')
+ var users = $('#users');
+
while (users.firstChild) {
- users.removeChild(users.firstChild)
+ users.removeChild(users.firstChild);
}
- onlineUsers.length = 0
+
+ onlineUsers.length = 0;
}
function userInvite(nick) {
- send({cmd: 'invite', nick: nick})
+ send({ cmd: 'invite', nick: nick });
}
function userIgnore(nick) {
- ignoredUsers.push(nick)
+ ignoredUsers.push(nick);
}
/* color scheme switcher */
@@ -495,44 +524,42 @@ var schemes = [
'pop',
'railscasts',
'solarized',
- 'tomorrow',
-]
+ 'tomorrow'
+];
-var currentScheme = 'atelier-dune'
+var currentScheme = 'atelier-dune';
function setScheme(scheme) {
- currentScheme = scheme
- $('#scheme-link').href = "/schemes/" + scheme + ".css"
- localStorageSet('scheme', scheme)
+ currentScheme = scheme;
+ $('#scheme-link').href = "schemes/" + scheme + ".css";
+ localStorageSet('scheme', scheme);
}
// Add scheme options to dropdown selector
-schemes.forEach(function(scheme) {
- var option = document.createElement('option')
- option.textContent = scheme
- option.value = scheme
- $('#scheme-selector').appendChild(option)
-})
+schemes.forEach(function (scheme) {
+ var option = document.createElement('option');
+ option.textContent = scheme;
+ option.value = scheme;
+ $('#scheme-selector').appendChild(option);
+});
-$('#scheme-selector').onchange = function(e) {
- setScheme(e.target.value)
+$('#scheme-selector').onchange = function (e) {
+ setScheme(e.target.value);
}
// Load sidebar configaration values from local storage if available
if (localStorageGet('scheme')) {
- setScheme(localStorageGet('scheme'))
+ setScheme(localStorageGet('scheme'));
}
-$('#scheme-selector').value = currentScheme
-
+$('#scheme-selector').value = currentScheme;
/* main */
if (myChannel == '') {
- pushMessage({text: frontpage})
- $('#footer').classList.add('hidden')
- $('#sidebar').classList.add('hidden')
-}
-else {
- join(myChannel)
+ pushMessage({ text: frontpage });
+ $('#footer').classList.add('hidden');
+ $('#sidebar').classList.add('hidden');
+} else {
+ join(myChannel);
}