var cache = {} var PendingMessages = {} var MessageContentCache = {} var RawFavs = {} var InvalidDomains = [ "http://13gb.com", "http://69.42.73.10", "http://amitkulkarni.info", "http://catcatcat.com", "http://celebskin.com", "http://current.com", "http://files.shroomery.org", "http://guides.macrumors.com", "http://henshin.250x.com", "http://i.pbase.com", "http://images.nintendolife.com", "http://img.bettersoft.de", "http://izismile.com", "http://izismile.com", "http://izismile.com/img", "http://mytextgraphics.com", "http://nexus404.com", "http://nintendolife.com", "http://nofatclips.com", "http://portfolio.deeperstudy.com", "http://ru.fishki.net", "http://ski.far.ru", "http://tripod.com", "http://uallknow.com", "http://victoryaworld.com", "http://images.4chan.org", "http://www.4chan.org", "http://www.angelfire.com", "http://www.animation-central.com", "http://www.arrested.com", "http://www.b3tards.com", "http://www.bloody-disgusting.com", "http://www.commenthaven.com", "http://www.coolnotions.com", "http://www.creepygif.com", "http://www.dailymakeover.com", "http://www.fortunecity.com", "http://www.gifbin.com", "http://www.goatse.fr", "http://www.hail-to-the-thief.org", "http://www.knowledgebase-script.com", "http://www.markagame.ru", "http://www.masternewmedia.org", "http://www.mortalkombatonline.com", "http://www.mymodernmagic.com", "http://www.mystkittsdivebuddy.com", "http://www.nudecelebritieshentai.com", "http://www.oldtimestrongman.com", "http://www.popularpages.net", "http://www.retrojunk.com", "http://www.schm032.com", "http://www.sevenoaksart.co.uk", "http://www.suicidekiss.com", "http://www.thecinemasource.com", "http://www.veryboy.fr", "http://www.vintagecomputing.com", "http://www.virtuallandmedia.com", "http://www.whudat.com", "http://www.willrich.supanet.com", "http://www.ysmarko.com", "http://www.3d-onthelevel.com", "http://www.heathersanimations.com", "http://fortunecity.com", "http://geneology2.com", "http://www.geneology2.com", "http://img.waffleimages.com", "http://www.worldofstock.com", "http://aphrodite.cooltext.com", "http://www.onemetal.com", "http://static.funnyjunk.com", "http://www.whimsical-wits.com", "http://madsenworld.dk", "http://www.oafe.net", "http://www.mrbalihai.com", "http://www.digyourowngrave.com", "http://tripod.com", "http://www.kaitaia.com", "http://carsdriveingallery.com", "http://xxxspacegirls.us", "http://www.newlog.com.ar" ]; var MaxImagePosts = 30 // todo: preload these. also, look into image sprites (no go on animating their sizes tho) // css clipping perhaps? Imgs = { "chatThumb": "/static/img/thumbs/smallheartfaved.gif", "chatThumbBig": "/static/img/thumbs/chatheartover.gif", "chatThumbOff": "/static/img/thumbs/smallheart.gif", "chatThumbDot": "/static/img/thumbs/smallheart.gif", "logThumb": "/static/img/thumbs/heartfaved.gif", "logThumbBig": "/static/img/thumbs/heartover.gif", "logThumbOff": "/static/img/thumbs/heart.gif" } Anim = { "chatThumbBig": {"width": "54px", "height": "54px", "right": "0px", "bottom": "2px"}, "chatThumbTiny": {"width": "8px", "height": "8px", "right": "8px", "bottom": "8px"}, "chatThumb": {"width": "16px", "height": "16px", "right": "4px", "bottom": "4px"}, "logThumb": {"width": "27px", "height": "27px", "marginRight": "0px", "marginTop": "0px"}, "logThumbBig": {"width": "64px", "height": "64px", "marginRight": "-2px", "marginTop": "-2px"} } // Utils /*Object.size = function(obj) { var size = 0, key; for (key in obj) { if (obj.hasOwnProperty(key)) size++; } return size; };*/ isEmptyObject = function(obj) { for (key in obj) { if (obj.hasOwnProperty(key)) return false; } return true } function isCSSPropertySupported(prop){ return prop in document.body.style } function escapeHtml(txt) { if (!txt) { return ""; } // txt = annoyingCaps(txt) return $("").text(txt).html() } URLRegex = /((\b(http\:\/\/|https\:\/\/|ftp\:\/\/)|(www\.))+(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?)/gi; PicRegex = /\.(jpg|jpeg|png|gif|bmp|svg|fid)$/i; function getImagesAsArray(text) { var imgs = [] var urls = text.match(URLRegex) if (urls === null) return imgs for (var i = 0; i"; break; case 'youtube': Youtube.startAnimation(); return "" + "" + ""; break; default: return "" + url + ""; } } Youtube = { "timer": 0, "startAnimation": function(){ if (!Youtube.timer) Youtube.timer = setTimeout(Youtube.animate, 1000) }, "animate": function(){ var thumbs = $(".youtube-thumb") thumbs.each(Youtube.nextThumb) if (thumbs.length == 0){ clearTimeout(Youtube.timer) Youtube.timer = 0 } else Youtube.timer = setTimeout(Youtube.animate, 1000); }, "nextThumb": function(){ var img = $(this); // yt thumb url is http://i.ytimg.com/vi/0123456789A/1.jpg var v = img.attr("src").substr(22,11) var num = img.attr("src").charAt(34); img.attr("src", (Youtube.nextThumbUrl(v, num))) }, "nextThumbUrl": function(v, num){ if (!num) num = 0; num = (parseInt(num) % 3) + 1 // cycle over 1,2,3 return "http://i.ytimg.com/vi/" + v + "/" + num + ".jpg" }, } function getUriType(uri){ if (PicRegex.test(uri.file.toLowerCase())) return "image"; if (parseDomain(uri.host) == "youtube.com" && 'v' in uri.queryKey || uri.anchor.indexOf('v') != -1) return "youtube"; return "link"; } function linkifyWithoutImage(text) { LastMsgContainsImage = false return text.replace(URLRegex, linkReplaceWithoutImage); } function linkReplaceWithoutImage(url){ var urlWithoutParams = url.replace(/\?.*$/i, ""); linkUrl = url.indexOf('http://') == 0 ? url : 'http://' + url; return "" + url + "" } // Message Handling var ImageMsgCount = 0 function removeOldMessages(){ // don't count posts that are all text if (LastMsgContainsImage) ImageMsgCount += 1; while (ImageMsgCount > MaxImagePosts) { var imgMsg = $(".contains-image:first") if (imgMsg.length) { imgMsg.prevAll().remove() // remove all text messages before the image message imgMsg.remove() } else break; ImageMsgCount -= 1; } } function buildMsgContent(content) { if (content.substr(0,6) == "") return content.substr(6,content.length - 13) else return linkify(escapeHtml(content)); } // todo: // isLoading doesn't get passed the right thing by $.map in addMessages function buildMessageDiv(msg, isLoading) { removeOldMessages() var nick = escapeHtml(msg.nick); var msgId = ('msg_id' in msg) ? 'id="message-' + msg.msg_id + '"' : ''; var loadingClass = isLoading ? ' loading' : ''; var containsImageClass = LastMsgContainsImage ? ' contains-image' : ''; return '
' + '' + nick + '' + ' ' + '' + '' + buildMsgContent(msg.content) + '' + '
'; } function buildUserDiv(user) { if (user.avatar) { return ''; } else { return ''; } } // Favs function buildFav(f) { var h = '
' + '' + '' + f.from + '' + ' just faved you!' + '
'; return $(h); } function removeFavAndHideBox() { $(this).remove(); if ($('#favbox').children().length == 0) $('#favbox').hide(); } function showFav(f) { $('#favbox').show(); buildFav(f).appendTo('#favbox').fadeOut(5000, removeFavAndHideBox); } function updateFavs(fs) { if (fs.length == 0) return; $('#favbox').show(); $(fs).each(function(i, f) { showFav(f) }); } // Growl function buildGrowlDataAndPopDatShit(msg) { var nick = escapeHtml(msg.nick); nick = '' + nick + ':' var msg = buildMsgContent(msg.content) growl(nick, msg) } function growl(user, msg) { $.gritter.add({title: user, text: msg}); } 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!"); } } // Messages function invalidImageDomain(content) { var words = content.toLowerCase().split(' '); for (var i = 0; i < words.length; i++) { var w = words[i]; if (PicRegex.test(w)) { for (var j = 0; j < InvalidDomains.length; j++) { var d = InvalidDomains[j]; if (w.indexOf(d) != -1) { return d; } } } } } function submitMessage() { var content = $.trim($('#msgInput').val()); var invalidDomain = invalidImageDomain(content); if (invalidDomain) { $('#msgInput').blur(); // Remove focus to prevent FF alert loop alert("Sorry, cannot accept images from " + invalidDomain + ". Maybe host the image elsewhere?"); return; } $('#msgInput').val(''); if (content == '') { return; } if (content.length > 2468) { alert("POST TOO LONG DUDE!"); return; } // this shouldn't just be client side :V PendingMessages[content] = true; var msg = { 'nick': Nick, 'content': content }; var div = addNewMessage(msg, true); var onSuccess = function(json) { if (typeof pageTracker !== 'undefined') { pageTracker._trackEvent('Message', 'Submit', typeof Room !== 'undefined' ? Room : 'UnknownRoom'); } div.attr('id', 'message-' + json) .removeClass('loading').addClass('loaded'); }; var onError = function(resp, textStatus, errorThrown) { div.remove(); handleMsgError(resp); }; $.ajax({ type: 'POST', 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 addNewMessages(msgs) { var msgStr = $.map(msgs, buildMessageDiv).join(''); $('#messageList').append(msgStr); } function addNewMessage(msg, isLoading) { var msgStr = buildMessageDiv(msg, isLoading); var div = $(msgStr).appendTo('#messageList'); return div; } function setUserList(users) { $("#userList").html($.map(users, buildUserDiv).join('')); } function flattenUserJson(users) { var s = ""; $.map(users.sort(), function(user) { s += user.nick + user.avatar; }); return s; } function updateUI(msgs, users, favs) { if (window['growlize'] && msgs && msgs.length > 0) { $.map(msgs, buildGrowlDataAndPopDatShit) } else if (msgs && msgs.length > 0) { addNewMessages(msgs); } if (users !== null) { var flattened = flattenUserJson(users); if (!('userlist' in cache) || flattened != cache.userlist) { $("#userList").html($.map(users.sort(sortUsersByAlpha), buildUserDiv).join('')); } cache.userlist = flattened } updateFavs(favs); } function sortUsersByAlpha(a, b){ var nickA = a.nick.toLowerCase() var nickB = b.nick.toLowerCase() if (nickA > nickB) return 1 else if (nickA < nickB) return -1 return 0 } function isDuplicateMessage(m) { if (m.nick == Nick && m.content in PendingMessages) { delete PendingMessages[m.content]; return true; } else { return false; } } function refresh() { var onSuccess = function(json) { try { if (json.v && (typeof Version == 'undefined' || Version != json.v)) { location.reload(); } Timestamp = json.timestamp; $.map(json.messages, function(msg){ MessageContentCache[msg.msg_id.toString()] = msg.content }) var messages = $.grep( json.messages, function(m) { return !isDuplicateMessage(m) }); updateUI(messages, json.users, json.favs); if (typeof UnseenMsgCounter !== 'undefined' && !HasFocus) { UnseenMsgCounter += messages.length; } } catch(e) { if (IsAdmin && window.console) { console.error(e); } } setTimeout(refresh, 1000); }; var onError = function(resp, textStatus, errorThrown) { var msg = $.trim(resp.responseText); if (msg == "UNKNOWN_ROOM") location.href = "http://dump.fm"; if (IsAdmin && window.console) { console.error(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() { $('.oldmsg').each(function() { var dump = $(this); var content = dump.find(".content") MessageContentCache[dump.attr("id").substr(8)] = content.text() content.html(buildMsgContent(content.text())); }); $('#msgInput').keyup(ifEnter(submitMessage)); $('#msgSubmit').click(submitMessage); $('#palette-button').click(paletteToggle); messageList = $("#messageList")[0] initChatThumb() scrollToEnd() scrollWatcher() // see /static/webcam/webcam.js if ('webcam' in window) webcam.init() setTimeout(refresh, 1000); } function makePlainText() { var j = $(this); j.text(j.text()); } function activateProfileEditable() { var onSubmit = function(attr, newVal, oldVal) { newVal = $.trim(newVal); if (newVal == oldVal) { return oldVal }; $.ajax({ type: "POST", timeout: 5000, url: "/update-profile", data: { 'attr': attr, 'val': newVal } }); if (attr == 'avatar') { if (newVal != "") { var s = ''; $('#avatarPic').replaceWith(s).show(); } else { $('#avatarPic').hide(); } } return escapeHtml(newVal); }; if ($('#avatar-editing').length > 0) setupUploadAvatar('uploadp'); var textareaOpts = { 'default_text': 'Enter here!', 'callback': onSubmit, 'field_type': 'textarea', 'callbackShowErrors': false }; $('#contact.editable, #bio.editable') .editInPlace(textareaOpts) .each(makePlainText); } function enableProfileEdit() { $('img#contact').replaceWith('
'); $('img#bio').replaceWith('
'); $('#contact, #bio, #avatar').addClass('editable'); $('#avatar-editing').show(); var resetPage = function() { location.reload() }; $('#edit-toggle a').text('done editing').click(resetPage); activateProfileEditable(); } function initProfile() { $(".linkify").each(function() { var text = jQuery(this).text(); jQuery(this).html(linkifyWithoutImage(text)); }); $('#edit-toggle').click(enableProfileEdit); activateProfileEditable(); $('.logged-dump .content').each(function() { var t = $(this); t.html(buildMsgContent(t.text())); }); initLogThumb() }; function initLog() { $('.logged-dump .content').each(function() { var t = $(this); t.html(buildMsgContent(t.text())); }); initLogThumb(); } // jesus this logic is ugly function initLogThumb(){ $(".logged-dump .thumb").bind('mouseover mouseout', function(e) { var favorited = $(this).parents(".dump").hasClass("favorite") ? true : false; if (e.type == "mouseover") { if (favorited) { $(this).attr("src", Imgs.logThumbOff); } else { $(this).attr("src", Imgs.logThumbBig); $(this).stop().animate(Anim.logThumbBig, 'fast'); } } else { // mouseout if (favorited) { $(this).attr("src", Imgs.logThumb); $(this).stop().animate(Anim.logThumb, 'fast'); } else { $(this).attr("src", Imgs.logThumbOff); $(this).stop().animate(Anim.logThumb, 'fast'); } } }) } function initChatThumb(){ $(".chat-thumb").live('mouseover mouseout', function(e) { var favorited = $(this).parents(".dump").hasClass("favorite") ? true : false; if (e.type == "mouseover") { if (favorited) { $(this).attr("src", Imgs.chatThumbOff); } else { $(this).attr("src", Imgs.chatThumbBig); $(this).stop().animate(Anim.chatThumbBig, 'fast') } } else { // mouseout if (favorited) { $(this).attr("src", Imgs.chatThumb); $(this).stop().animate(Anim.chatThumb, 'fast'); } else { $(this).stop().animate(Anim.chatThumbTiny, 'fast', 'swing', function(){ $(this).attr("src", Imgs.chatThumbDot) $(this).animate(Anim.chatThumb, 0) }) } } }) } function paletteToChat(img){ var chatText = $("#msgInput").val() if (chatText.length && chatText[chatText.length - 1] != " ") chatText += " " chatText += $(img).attr("src") + " " $("#msgInput").val(chatText) $("#msgInput").focus().val($("#msgInput").val()) //http://stackoverflow.com/questions/1056359/ paletteHide() } paletteImageCache = false function paletteBuildImageThumbs(){ if (paletteImageCache) { var imgs = paletteImageCache } else { var imgs = [] var dupeFilter = {} for(fav in RawFavs){ var parsedImgs = getImagesAsArray(RawFavs[fav]) for (var i=0; i") } } function paletteShow(){ $("#palette").css("display", "block") if (isEmptyObject(RawFavs)) { $('#palette-thumbs').html('
This is where all the stuff you FAV goes!

To FAV a post click the little heart next to a users name.

Everything you fav gets saved to your profile.. Have fun!
'); } else { paletteBuildImageThumbs(); } } function paletteHide(){ $("#palette").css("display", "none") $("#palette-thumbs").html("") } function paletteToggle(){ if ($("#palette").css("display") == "none") paletteShow() else paletteHide() } function setupUpload(elementId, roomKey) { var onSubmit = function(file, ext) { if (!(ext && /^(jpg|png|jpeg|gif|bmp|svg)$/i.test(ext))) { alert('SORRY, NOT AN IMAGE DUDE... '); return false; } }; var onComplete = function(file, response) { var r = $.trim(response); g = r; if (r.match(/FILE_TOO_BIG/)) { var maxSize = r.split(" ")[1] / 1024; alert("Sorry. Your file is just too fucking big. " + maxSize + "KB or less please."); return; } else if (r.match(/FILE_NOT_IMAGE/)) { alert("What did you upload? Doesn't seem like an image. Sorry."); return; } else if (r.match(/INVALID_RESOLUTION/)) { var maxWidth = r.split(" ")[1]; var maxHeight = r.split(" ")[2]; alert("Sorry, the maximum image resolution is " + maxWidth + "x" + maxHeight); return; } else if (r != "OK") { alert(r); return; } if (typeof pageTracker !== 'undefined') { var r = typeof Room !== 'undefined' ? Room : 'UnknownRoom'; pageTracker._trackEvent('Message', 'Upload', r); } } new AjaxUpload(elementId, { action: '/upload/message', autoSubmit: true, name: 'image', data: { room: roomKey }, onSubmit: onSubmit, onComplete: onComplete }); } function setupUploadAvatar(elementId) { // NOTE: AjaxUpload responses aren't converted from JSON. var onSubmit = function(file, error) { $('#spinner').show(); }; var onComplete = function(file, resp) { $('#spinner').hide(); if (resp == 'INVALID_REQUEST') { location.reload(); } else if (resp == 'NOT_LOGGED_IN') { location.reload(); } else if (resp == 'INVALID_IMAGE') { alert("Sorry, dump.fm can't deal with your image. Pick another :("); return; } var s = ''; $('#avatarPic').replaceWith(s).show(); $('#avatar').text(resp); }; new AjaxUpload(elementId, { action: '/upload/avatar', autoSubmit: true, name: 'image', onSubmit: onSubmit, onComplete: onComplete }); } // scrolling stuff // this code keeps the div scrolled to the bottom, but will also let the user scroll up, without jumping down function isScrolledToBottom(){ var threshold = 15; var containerHeight = messageList.style.pixelHeight || messageList.offsetHeight var currentHeight = (messageList.scrollHeight > 0) ? messageList.scrollHeight : 0 var result = (currentHeight - messageList.scrollTop - containerHeight < threshold); return result; } function scrollIfPossible(){ if (lastScriptedScrolledPosition <= messageList.scrollTop || isScrolledToBottom()) scrollToEnd() } var lastScriptedScrolledPosition = 0 function scrollToEnd(){ messageList.scrollTop = messageList.scrollHeight lastScriptedScrolledPosition = messageList.scrollTop } function scrollWatcher(){ scrollIfPossible() setTimeout(scrollWatcher, 500) } // well fuck webkit for not supporting {text-decoration: blink} function blinkStart(){ blinkTimer = setInterval(function(){ $(".blink").removeClass("blink").addClass("blink-turning-off") $(".blink-off").removeClass("blink-off").addClass("blink") $(".blink-turning-off").removeClass("blink-turning-off").addClass("blink-off") },500); } function blinkStop(){ clearInterval(blinkTimer); } function initDirectory() { $('.linkify').each(function() { var t = $(this); t.html(buildMsgContent(t.text())); }); } //big hand stuff // TODO: replace this with simple pointer-events thing. function initBigHand(id){ var cursorId = "#cursor-big" var cursor = $(cursorId)[0] // jquery's reported element sizes are not exactly the same as the browser's 'mouseover' target sizes // so we'll allow a few pixels extra var fudgeFactor = 2 $(id).addClass("no-cursor") // i have to do this weirdly bc putting the cursor image where the mouse cursor is causes problems with mouse events: // * it stops mousemove events on the image below the mouse cursor // * it fucks up mouseover/out and even mouseenter/leave events, as well as click // so i am doing this: // on mousing over the image: // make cursor visible // find image co-ords // bind a global mousemove func // bind cursor click event // unbind mouseover // mousemove func: // move image to mouse co-ords // if mouse co-ords are outside the image co-ords: // make cursor invisible // unbind mousemove func // unbind cursor click event var mousemove = function(e){ var y = e.pageY, x = e.pageX, coords = initBigHand.coords cursor.style.top = y + "px" cursor.style.left = x - 32 + "px" // 32: (4 pixels * 8 pixels per big pixel) to line up pointy finger with cursor if (y < coords.top || y > coords.bottom || x < coords.left || x > coords.right) { $(cursorId).addClass('invisible') $(cursorId).css({"top": 0, "left": 0 }) $(cursorId).unbind('click', cursorClick) $('logo7').unbind('mousemove', mousemove) $(id).mouseover(imageMouseOver) } } var cursorClick = function(){ $(id).click() } var imageMouseOver = function(){ //console.log("moused over...") initBigHand.coords = { "left": $(id).offset().left - fudgeFactor, "top": $(id).offset().top - fudgeFactor, "right": $(id).offset().left + $(id).width() + fudgeFactor, "bottom": $(id).offset().top + $(id).height() + fudgeFactor } $('body').mousemove(mousemove) $(cursorId).click(cursorClick) $(cursorId).removeClass('invisible') $(id).unbind('mouseover', imageMouseOver) } $(id).mouseover(imageMouseOver) } // grab message id etc from some element e that's inside a dump // (messages have something like id="message-0001" class="dump" ) function getMessageInfo(e){ var message = $(e).parents(".dump") var id = message.attr("id").substr(8) // cut "message-001" to "001" var nick = message.attr("nick") var link = "http://dump.fm/p/" + nick + "/" + id var content = message.find(".linkify") if (!content.length) content = message.find(".content") var rawContent = content.html() var img = content.find("img").attr("src") var via = "via " + nick + " on dump.fm" return {"nick": nick, "id": id, "link": encodeURIComponent(link), "content": rawContent, "img": encodeURIComponent(img), "via": encodeURIComponent(via)} } Share = { "openLink": function(url){ window.open(url, "_blank") }, "facebook": function(button){ var message = getMessageInfo(button) var url = "http://www.facebook.com/share.php?u=" + message.img + "&t=" + message.via Share.openLink(url) }, "tumblr": function(button){ var message = getMessageInfo(button) var url = "http://www.tumblr.com/share?v=3&u=" + message.img + "&t=" + message.via Share.openLink(url) }, "twitter": function(button){ var message = getMessageInfo(button) var url = "http://twitter.com/home?status=" + message.img + encodeURIComponent(" ") + message.via Share.openLink(url) }, "delicious": function(button){ var message = getMessageInfo(button) var url = "http://delicious.com/save?url=" + message.img + "&title=" + message.img + "¬es=" + message.via Share.openLink(url) } } Tag = { "favorite": function(button){ var message = getMessageInfo(button) var favorited = ($(button).parents(".dump").hasClass("favorite")) ? true : false if (favorited) { Tag.rm(message.id, "favorite") $(button).parents(".dump").removeClass("favorite") if (RawFavs[message.id]) { delete RawFavs[message.id] paletteImageCache = false } } else { Tag.add(message.id, "favorite") $(button).parents(".dump").addClass("favorite") if (RawFavs && MessageContentCache[message.id]) { // chat ui stuff if ($("#palette-button").css("display") == "none") paletteButtonShowAnim() RawFavs[message.id] = MessageContentCache[message.id] paletteImageCache = false } } }, "add": function(message_id, tag){ Tag.ajax("/cmd/tag/add", {"message_id": message_id, "tag": tag}) }, "rm": function(message_id, tag){ Tag.ajax("/cmd/tag/rm", {"message_id": message_id, "tag": tag}) }, "ajax": function(url, data) { $.ajax({ "type": 'POST', "timeout": 5000, "url": url, "data": data, "cache": false }); } } // uhhh todo: move preload stuff into js: // var nextImage = new Image(); // nextImage.src = "your-url/newImage.gif"; // mAcRoMeDiA sHiT function MM_swapImgRestore() { //v3.0 var i,x,a=document.MM_sr; for(i=0;a&&i0&&parent.frames.length) { d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);} if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i, MIT License function parseUri (str) { var o = parseUri.options, m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), uri = {}, i = 14; while (i--) uri[o.key[i]] = m[i] || ""; uri[o.q.name] = {}; uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { if ($1) uri[o.q.name][$1] = $2; }); return uri; }; parseUri.options = { strictMode: false, key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"], q: { name: "queryKey", parser: /(?:^|&)([^&=]*)=?([^&]*)/g }, parser: { strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ } }; // end parseUri function parseDomain(host){ return host.toLowerCase().replace(/^www\./, "") } // Away notification var UnseenMsgCounter = 0; var OrigTitle = ""; var HasFocus = true; function onFocus() { HasFocus = true; UnseenMsgCounter = 0; $('title').text(OrigTitle); } function onBlur() { HasFocus = false; } function titleUpdater() { if (HasFocus || UnseenMsgCounter == 0 || $('title').text() != OrigTitle) { $('title').text(OrigTitle); } else { var plural = UnseenMsgCounter > 1 ? 's' : ''; $('title').text(UnseenMsgCounter + ' new dump' + plural + '! | ' + OrigTitle); } setTimeout(titleUpdater, 2000); } function startTitleUpdater() { $(window).blur(onBlur); $(window).focus(onFocus); setTimeout(titleUpdater, 2000); } $(function() { OrigTitle = $('title').text(); }); $('.msgDiv').live('click', function(e) { var tagName = e.target.tagName; if (tagName == 'A' || tagName == 'IMG') { return; } var wasFavorited = $(this).hasClass("favorite"); var button = $(this).find('.chat-thumb'); if (wasFavorited) { $(button).attr("src", Imgs.chatThumbOff); } else { $(button).attr("src", Imgs.chatThumbBig); $(button).stop().animate(Anim.chatThumbBig, 'fast').animate(Anim.chatThumb, 'fast', 'swing'); } Tag.favorite(button); return false; }); // sha1.js /* * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined * in FIPS 180-1 * Version 2.2 Copyright Paul Johnston 2000 - 2009. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for details. */ /* * Configurable variables. You may need to tweak these to be compatible with * the server-side, but the defaults work in most cases. */ var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ /* * These are the functions you'll usually want to call * They take string arguments and return either hex or base-64 encoded strings */ function hex_sha1(s) { return rstr2hex(rstr_sha1(str2rstr_utf8(s))); } function b64_sha1(s) { return rstr2b64(rstr_sha1(str2rstr_utf8(s))); } function any_sha1(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); } function hex_hmac_sha1(k, d) { return rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } function b64_hmac_sha1(k, d) { return rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } function any_hmac_sha1(k, d, e) { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); } /* * Perform a simple self-test to see if the VM is working */ function sha1_vm_test() { return hex_sha1("abc").toLowerCase() == "a9993e364706816aba3e25717850c26c9cd0d89d"; } /* * Calculate the SHA1 of a raw string */ function rstr_sha1(s) { return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8)); } /* * Calculate the HMAC-SHA1 of a key and some data (raw strings) */ function rstr_hmac_sha1(key, data) { var bkey = rstr2binb(key); if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8); return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160)); } /* * Convert a raw string to a hex string */ function rstr2hex(input) { try { hexcase } catch(e) { hexcase=0; } var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var output = ""; var x; for(var i = 0; i < input.length; i++) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt( x & 0x0F); } return output; } /* * Convert a raw string to a base-64 string */ function rstr2b64(input) { try { b64pad } catch(e) { b64pad=''; } var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var output = ""; var len = input.length; for(var i = 0; i < len; i += 3) { var triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i+2) : 0); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > input.length * 8) output += b64pad; else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); } } return output; } /* * Convert a raw string to an arbitrary string encoding */ function rstr2any(input, encoding) { var divisor = encoding.length; var remainders = Array(); var i, q, x, quotient; /* Convert to an array of 16-bit big-endian values, forming the dividend */ var dividend = Array(Math.ceil(input.length / 2)); for(i = 0; i < dividend.length; i++) { dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); } /* * Repeatedly perform a long division. The binary array forms the dividend, * the length of the encoding is the divisor. Once computed, the quotient * forms the dividend for the next step. We stop when the dividend is zero. * All remainders are stored for later use. */ while(dividend.length > 0) { quotient = Array(); x = 0; for(i = 0; i < dividend.length; i++) { x = (x << 16) + dividend[i]; q = Math.floor(x / divisor); x -= q * divisor; if(quotient.length > 0 || q > 0) quotient[quotient.length] = q; } remainders[remainders.length] = x; dividend = quotient; } /* Convert the remainders to the output string */ var output = ""; for(i = remainders.length - 1; i >= 0; i--) output += encoding.charAt(remainders[i]); /* Append leading zero equivalents */ var full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))) for(i = output.length; i < full_length; i++) output = encoding[0] + output; return output; } /* * Encode a string as utf-8. * For efficiency, this assumes the input is valid utf-16. */ function str2rstr_utf8(input) { var output = ""; var i = -1; var x, y; while(++i < input.length) { /* Decode utf-16 surrogate pairs */ x = input.charCodeAt(i); y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } /* Encode output as utf-8 */ if(x <= 0x7F) output += String.fromCharCode(x); else if(x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 0x80 | ( x & 0x3F)); else if(x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); else if(x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); } return output; } /* * Encode a string as utf-16 */ function str2rstr_utf16le(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); return output; } function str2rstr_utf16be(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); return output; } /* * Convert a raw string to an array of big-endian words * Characters >255 have their high-byte silently ignored. */ function rstr2binb(input) { var output = Array(input.length >> 2); for(var i = 0; i < output.length; i++) output[i] = 0; for(var i = 0; i < input.length * 8; i += 8) output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); return output; } /* * Convert an array of big-endian words to a string */ function binb2rstr(input) { var output = ""; for(var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); return output; } /* * Calculate the SHA-1 of an array of big-endian words, and a bit length */ function binb_sha1(x, len) { /* append padding */ x[len >> 5] |= 0x80 << (24 - len % 32); x[((len + 64 >> 9) << 4) + 15] = len; var w = Array(80); var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; var e = -1009589776; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; var olde = e; for(var j = 0; j < 80; j++) { if(j < 16) w[j] = x[i + j]; else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j))); e = d; d = c; c = bit_rol(b, 30); b = a; a = t; } a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); e = safe_add(e, olde); } return Array(a, b, c, d, e); } /* * Perform the appropriate triplet combination function for the current * iteration */ function sha1_ft(t, b, c, d) { if(t < 20) return (b & c) | ((~b) & d); if(t < 40) return b ^ c ^ d; if(t < 60) return (b & c) | (b & d) | (c & d); return b ^ c ^ d; } /* * Determine the appropriate additive constant for the current iteration */ function sha1_kt(t) { return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514; } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); }