summaryrefslogtreecommitdiff
path: root/static/js/pichat.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/js/pichat.js')
-rwxr-xr-xstatic/js/pichat.js244
1 files changed, 244 insertions, 0 deletions
diff --git a/static/js/pichat.js b/static/js/pichat.js
new file mode 100755
index 0000000..559e775
--- /dev/null
+++ b/static/js/pichat.js
@@ -0,0 +1,244 @@
+function escapeHtml(txt) {
+ if (!txt) { return ""; }
+ else { return $("<span>").text(txt).html(); }
+}
+
+// http://stackoverflow.com/questions/37684/replace-url-with-html-links-javascript
+function linkify(text) {
+ var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi;
+ return text.replace(exp,"<a href='$1'>$1</a>");
+}
+
+// http://snippets.dzone.com/posts/show/6995
+var URLRegex = /^((http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/i
+var PicRegex = /\.(jpg|jpeg|png|gif|bmp)$/i;
+
+function isImage(content) {
+ var match = URLRegex.exec(content);
+ sansParams = match && match[0].replace(/\?.*$/i, "");
+ return sansParams && PicRegex.test(sansParams);
+}
+
+function buildMsgContent(content) {
+ if (isImage(content)) {
+ return '<a href="' + content + '" target="_blank">'
+ + '<img src="'+ content + '" /></a>';
+ } else {
+ return linkify(escapeHtml(content));
+ }
+}
+
+function buildMessageDiv(msg) {
+ var nick = escapeHtml(msg.nick);
+ return '<div class="msgDiv"><b><a href="/u/' + nick + ' ">' + nick + '</a>: </b>'
+ + buildMsgContent(msg.content) + '</div>';
+}
+
+function buildGrowlDataAndPopDatShit(msg) {
+ var nick = escapeHtml(msg.nick);
+ nick = '<a href="/u/' + nick + ' " style="color:pink">' + nick + '</a>:'
+ var msg = buildMsgContent(msg.content)
+ growl(nick, msg)
+}
+
+function buildUserDiv(user) {
+ if (user.avatar) {
+ return '<div class="username"><a href="/u/' + escapeHtml(user.nick) + '">' +
+ '<img src="' + user.avatar + '" width="50" height="50">' +
+ escapeHtml(user.nick) + '</a></div>';
+ } else {
+ return '<div class="username"><a href="/u/' + escapeHtml(user.nick) + '">' +
+ escapeHtml(user.nick) + '</a></div>';
+ }
+}
+
+function handleMsgError(resp) {
+ var respText = resp.responseText ? resp.responseText.trim() : false;
+ if (respText == 'MUST_LOGIN') {
+ alert("Can't send message! Please login.");
+ } else if (respText) {
+ alert("Can't send message! (" + respText + ")");
+ } else {
+ alert("Can't send message!");
+ }
+}
+
+function submitMessage() {
+ var content = $.trim($('#msgInput').val());
+ if (content == '') { return; }
+ PostedMessages.push(content);
+ $('#msgInput').val('');
+
+ updateUI([{ 'nick': Nick, 'content': content}], null);
+
+ var onSuccess = function(json) {};
+ var onError = function(resp, textStatus, errorThrown) {
+ $('#msgInput, #msgSubmit').removeAttr('disabled');
+ handleMsgError(resp);
+ };
+
+ $.ajax({
+ type: 'GET',
+ timeout: 5000,
+ url: '/msg',
+ data: { 'room': Room, 'content': content },
+ cache: false,
+ dataType: 'json',
+ success: onSuccess,
+ error: onError
+ });
+}
+
+function ifEnter(fn) {
+ return function(e) {
+ if (e.keyCode == 13) { fn(); }
+ };
+}
+
+function isScrolledToBottom(div) {
+ return Math.abs(div.scrollTop - (div.scrollHeight - div.offsetHeight)) <= 3;
+}
+
+function scrollToBottom(div) {
+ div.scrollTop = div.scrollHeight;
+}
+
+// Give images time to start loading before scrolling.
+// Needed until server knows size of images.
+function delayedScrollToBottom(delay) {
+ setTimeout(scrollToBottom, delay, $('#messageList')[0]);
+}
+
+function updateUI(msgs, users) {
+ if (window['growlize'] && msgs !== null) {
+ $.map(msgs, buildGrowlDataAndPopDatShit)
+ }
+ else if (msgs !== null) {
+ var msgStr = $.map(msgs, buildMessageDiv).join('');
+ var wasScrolledToBottom = isScrolledToBottom($('#messageList')[0]);
+ $('#messageList').append(msgStr);
+
+ if (wasScrolledToBottom) {
+ delayedScrollToBottom(500);
+ }
+ }
+ if (users !== null) {
+ $("#userList").html($.map(users, buildUserDiv).join(''));
+ }
+}
+
+// A duplicate message is a message that was likely to have
+// originated from this browser.
+function isDuplicateMessage(m) {
+ if (m.nick != Nick || $.inArray(m.content, PostedMessages) == -1) {
+ return false;
+ }
+ var now = new Date().getTime();
+ return m.created_on - now < 5000;
+}
+
+function refresh() {
+ var onSuccess = function(json) {
+ try {
+ Timestamp = json.timestamp;
+ var messages = $.grep(
+ json.messages,
+ function(m) { return !isDuplicateMessage(m) });
+ updateUI(messages, json.users);
+ if (typeof UnseenMsgCounter !== 'undefined') {
+ UnseenMsgCounter += messages.length;
+ }
+ } catch(e) {
+ if (IsAdmin) {
+ alert("Exception in refresh");
+ console.log(e);
+ }
+ }
+ setTimeout(refresh, 1000);
+ };
+ var onError = function(resp, textStatus, errorThrown) {
+ if (IsAdmin) {
+ console.log(resp, textStatus, errorThrown);
+ }
+ setTimeout(refresh, 1000);
+ };
+
+ $.ajax({
+ type: 'GET',
+ timeout: 5000,
+ url: '/refresh',
+ data: { 'room': Room, 'since': Timestamp },
+ cache: false,
+ dataType: 'json',
+ success: onSuccess,
+ error: onError
+ });
+}
+
+function initChat() {
+ $('.msgDiv .content').each(function() {
+ var t = $(this);
+ t.html(buildMsgContent(t.text()));
+ });
+
+ $('#msgInput').keyup(ifEnter(submitMessage));
+ $('#msgSubmit').click(submitMessage);
+
+ delayedScrollToBottom(500);
+ setTimeout(refresh, 1000);
+}
+
+function initProfile() {
+ $('.logged-dump .content').each(function() {
+ var t = $(this);
+ t.html(buildMsgContent(t.text()));
+ });
+
+ var onSubmit = function(original_element, edit, old) {
+ edit = $.trim(edit);
+ if (edit == old) { return old };
+ // TODO: Prevent entering script tags
+ if (original_element == 'avatar' && edit.indexOf("<") != -1) {
+ return old;
+ }
+ $.ajax({
+ type: "GET",
+ timeout: 5000,
+ url: "/update-profile",
+ data: { 'attr': original_element, 'val': edit }
+ });
+ if (original_element == 'avatar') {
+ var s = '<img id="avatarPic" src="' + edit + '" width="150" />';
+ $('#avatarPic').replaceWith(s);
+ }
+ return escapeHtml(edit);
+ };
+
+ var opt = { 'default_text': 'Enter here!',
+ 'callback': onSubmit,
+ 'field_type': 'text',
+ 'callbackShowErrors': false };
+ $('#avatar.editable').editInPlace(opt);
+
+
+ opt['field_type'] = 'textarea';
+ $('#contact.editable, #bio.editable').editInPlace(opt);
+
+};
+
+function initLog() {
+ $('.logged-dump .content').each(function() {
+ var t = $(this);
+ t.html(buildMsgContent(t.text()));
+ });
+
+}
+
+function growl(user, msg) {
+ $.gritter.add({
+ // (string | mandatory) the heading of the notification
+ title: user,
+ // (string | mandatory) the text inside the notification
+ text: msg
+ });
+}