/***************************************** * * FUNCTION AND VAR DECLARATIONS * ******************************************/ //DEBUG STUFF var triggerError = attachErrorHandler('chatDebug', true); var escaper = encodeURIComponent || escape; var decoder = decodeURIComponent || unescape; window.onerror = function(msg, url, line, col, error) { if (document.location.href.indexOf("proc=debug") <= 0) { var extra = !col ? '' : ' | column: ' + col; extra += !error ? '' : ' | error: ' + error; extra += !navigator.userAgent ? '' : ' | user agent: ' + navigator.userAgent; var debugLine = 'Error: ' + msg + ' | url: ' + url + ' | line: ' + line + extra; window.location = '?_src_=chat&proc=debug¶m[error]='+escaper(debugLine); } return true; }; //Globals window.status = 'Output'; var $messages, $subOptions, $subAudio, $selectedSub, $contextMenu, $filterMessages, $last_message; var opts = { //General 'messageCount': 0, //A count...of messages... 'messageLimit': 2053, //A limit...for the messages... 'scrollSnapTolerance': 10, //If within x pixels of bottom 'clickTolerance': 10, //Keep focus if outside x pixels of mousedown position on mouseup 'imageRetryDelay': 50, //how long between attempts to reload images (in ms) 'imageRetryLimit': 50, //how many attempts should we make? 'popups': 0, //Amount of popups opened ever 'wasd': false, //Is the user in wasd mode? 'priorChatHeight': 0, //Thing for height-resizing detection 'restarting': false, //Is the round restarting? //Options menu 'selectedSubLoop': null, //Contains the interval loop for closing the selected sub menu 'suppressSubClose': false, //Whether or not we should be hiding the selected sub menu 'highlightTerms': [], 'highlightLimit': 5, 'highlightColor': '#FFFF00', //The color of the highlighted message 'pingDisabled': false, //Has the user disabled the ping counter //Ping display 'lastPang': 0, //Timestamp of the last response from the server. 'pangLimit': 35000, 'pingTime': 0, //Timestamp of when ping sent 'pongTime': 0, //Timestamp of when ping received 'noResponse': false, //Tracks the state of the previous ping request 'noResponseCount': 0, //How many failed pings? //Clicks 'mouseDownX': null, 'mouseDownY': null, 'preventFocus': false, //Prevents switching focus to the game window //Client Connection Data 'clientDataLimit': 5, 'clientData': [], //Admin music volume update 'volumeUpdateDelay': 5000, //Time from when the volume updates to data being sent to the server 'volumeUpdating': false, //True if volume update function set to fire 'updatedVolume': 0, //The volume level that is sent to the server 'defaultMusicVolume': 25, 'messageCombining': true, }; function clamp(val, min, max) { return Math.max(min, Math.min(val, max)) } function outerHTML(el) { var wrap = document.createElement('div'); wrap.appendChild(el.cloneNode(true)); return wrap.innerHTML; } //Polyfill for fucking date now because of course IE8 and below don't support it if (!Date.now) { Date.now = function now() { return new Date().getTime(); }; } //Polyfill for trim() (IE8 and below) if (typeof String.prototype.trim !== 'function') { String.prototype.trim = function () { return this.replace(/^\s+|\s+$/g, ''); }; } //Shit fucking piece of crap that doesn't work god fuckin damn it function linkify(text) { var rex = /((?:'+$0+''; } else { return $1 ? $0: ''+$0+''; } }); } function byondDecode(message) { // Basically we url_encode twice server side so we can manually read the encoded version and actually do UTF-8. // The replace for + is because FOR SOME REASON, BYOND replaces spaces with a + instead of %20, and a plus with %2b. // Marvelous. message = message.replace(/\+/g, "%20"); message = decoder(message); return message; } //Actually turns the highlight term match into appropriate html function addHighlightMarkup(match) { var extra = ''; if (opts.highlightColor) { extra += ' style="background-color: '+opts.highlightColor+'"'; } return ''+match+''; } //Highlights words based on user settings function highlightTerms(el) { if (el.children.length > 0) { for(var h = 0; h < el.children.length; h++){ highlightTerms(el.children[h]); } } var hasTextNode = false; for (var node = 0; node < el.childNodes.length; node++) { if (el.childNodes[node].nodeType === 3) { hasTextNode = true; break; } } if (hasTextNode) { //If element actually has text var newText = ''; for (var c = 0; c < el.childNodes.length; c++) { //Each child element if (el.childNodes[c].nodeType === 3) { //Is it text only? var words = el.childNodes[c].data.split(' '); for (var w = 0; w < words.length; w++) { //Each word in the text var newWord = null; for (var i = 0; i < opts.highlightTerms.length; i++) { //Each highlight term if (opts.highlightTerms[i] && words[w].toLowerCase().indexOf(opts.highlightTerms[i].toLowerCase()) > -1) { //If a match is found newWord = words[w].replace("<", "<").replace(new RegExp(opts.highlightTerms[i], 'gi'), addHighlightMarkup); break; } if (window.console) console.log(newWord) } newText += newWord || words[w].replace("<", "<"); newText += w >= words.length ? '' : ' '; } } else { //Every other type of element newText += outerHTML(el.childNodes[c]); } } el.innerHTML = newText; } } function iconError(E) { var that = this; setTimeout(function() { var attempts = $(that).data('reload_attempts'); if (typeof attempts === 'undefined' || !attempts) { attempts = 1; } if (attempts > opts.imageRetryLimit) return; var src = that.src; that.src = null; that.src = src+'#'+attempts; $(that).data('reload_attempts', ++attempts); }, opts.imageRetryDelay); } //Send a message to the client function output(message, flag) { if (typeof message === 'undefined') { return; } if (typeof flag === 'undefined') { flag = ''; } if (flag !== 'internal') opts.lastPang = Date.now(); message = byondDecode(message) //The behemoth of filter-code (for Admin message filters) //Note: This is proooobably hella inefficient var filteredOut = false; if (opts.hasOwnProperty('showMessagesFilters') && !opts.showMessagesFilters['All'].show) { //Get this filter type (defined by class on message) var messageHtml = $.parseHTML(message), messageClasses; if (opts.hasOwnProperty('filterHideAll') && opts.filterHideAll) { var internal = false; messageClasses = (!!$(messageHtml).attr('class') ? $(messageHtml).attr('class').split(/\s+/) : false); if (messageClasses) { for (var i = 0; i < messageClasses.length; i++) { //Every class if (messageClasses[i] == 'internal') { internal = true; break; } } } if (!internal) { filteredOut = 'All'; } } else { //If the element or it's child have any classes if (!!$(messageHtml).attr('class') || !!$(messageHtml).children().attr('class')) { messageClasses = $(messageHtml).attr('class').split(/\s+/); if (!!$(messageHtml).children().attr('class')) { messageClasses = messageClasses.concat($(messageHtml).children().attr('class').split(/\s+/)); } var tempCount = 0; for (var i = 0; i < messageClasses.length; i++) { //Every class var thisClass = messageClasses[i]; $.each(opts.showMessagesFilters, function(key, val) { //Every filter if (key !== 'All' && val.show === false && typeof val.match != 'undefined') { for (var i = 0; i < val.match.length; i++) { var matchClass = val.match[i]; if (matchClass == thisClass) { filteredOut = key; break; } } } if (filteredOut) return false; }); if (filteredOut) break; tempCount++; } } else { if (!opts.showMessagesFilters['Misc'].show) { filteredOut = 'Misc'; } } } } //Stuff we do along with appending a message var atBottom = false; if (!filteredOut) { var bodyHeight = $('body').height(); var messagesHeight = $messages.outerHeight(); var scrollPos = $('body,html').scrollTop(); //Should we snap the output to the bottom? if (bodyHeight + scrollPos >= messagesHeight - opts.scrollSnapTolerance) { atBottom = true; if ($('#newMessages').length) { $('#newMessages').remove(); } //If not, put the new messages box in } else { if ($('#newMessages').length) { var messages = $('#newMessages .number').text(); messages = parseInt(messages); messages++; $('#newMessages .number').text(messages); if (messages == 2) { $('#newMessages .messageWord').append('s'); } } else { $messages.after('1 new message '); } } } //Url stuff if (message.length && flag != 'preventLink') { message = linkify(message); } opts.messageCount++; //Pop the top message off if history limit reached if (opts.messageCount >= opts.messageLimit) { $messages.children('div.entry:first-child').remove(); opts.messageCount--; //I guess the count should only ever equal the limit } var handled = false; var trimmed_message = message.trim() var lastmessages = $messages.children('div.entry:last-child'); if (opts.messageCombining && lastmessages.length && $last_message) { if($last_message == trimmed_message) { if(lastmessages.children('span.r').length) { var current_value = parseInt(lastmessages.children('span.r').text()) lastmessages.children('span.r').text(current_value+1) } else { lastmessages.append($('', { 'class': 'r', 'text': 2})); } var insertedBadge = $(lastmessages).find('.r'); insertedBadge.animate({ "font-size": "0.9em" }, 100, function() { insertedBadge.animate({ "font-size": "0.7em" }, 100); }); opts.messageCount--; handled = true; } } if(!handled) { //Actually append the message var entry = document.createElement('div'); entry.className = 'entry'; if (filteredOut) { entry.className += ' hidden'; entry.setAttribute('data-filter', filteredOut); } $last_message = trimmed_message; entry.innerHTML = trimmed_message; $messages[0].appendChild(entry); $(entry).find("img.icon").error(iconError); //Actually do the snap //Stuff we can do after the message shows can go here, in the interests of responsiveness if (opts.highlightTerms && opts.highlightTerms.length > 0) { highlightTerms(entry); } } if (!filteredOut && atBottom) { $('body,html').scrollTop($messages.outerHeight()); } } function internalOutput(message, flag) { output(escaper(message), flag) } //Runs a route within byond, client or server side. Consider this "ehjax" for byond. function runByond(uri) { window.location = uri; } function setCookie(cname, cvalue, exdays) { cvalue = escaper(cvalue); var d = new Date(); d.setTime(d.getTime() + (exdays*24*60*60*1000)); var expires = 'expires='+d.toUTCString(); document.cookie = cname + '=' + cvalue + '; ' + expires; } function getCookie(cname) { var name = cname + '='; var ca = document.cookie.split(';'); for(var i=0; i < ca.length; i++) { var c = ca[i]; while (c.charAt(0)==' ') c = c.substring(1); if (c.indexOf(name) === 0) { return decoder(c.substring(name.length,c.length)); } } return ''; } function rgbToHex(R,G,B) {return toHex(R)+toHex(G)+toHex(B);} function toHex(n) { n = parseInt(n,10); if (isNaN(n)) return "00"; n = Math.max(0,Math.min(n,255)); return "0123456789ABCDEF".charAt((n-n%16)/16) + "0123456789ABCDEF".charAt(n%16); } function handleClientData(ckey, ip, compid) { //byond sends player info to here var currentData = {'ckey': ckey, 'ip': ip, 'compid': compid}; if (opts.clientData && !$.isEmptyObject(opts.clientData)) { runByond('?_src_=chat&proc=analyzeClientData¶m[cookie]='+JSON.stringify({'connData': opts.clientData})); for (var i = 0; i < opts.clientData.length; i++) { var saved = opts.clientData[i]; if (currentData.ckey == saved.ckey && currentData.ip == saved.ip && currentData.compid == saved.compid) { return; //Record already exists } } if (opts.clientData.length >= opts.clientDataLimit) { opts.clientData.shift(); } } else { runByond('?_src_=chat&proc=analyzeClientData¶m[cookie]=none'); } //Update the cookie with current details opts.clientData.push(currentData); setCookie('connData', JSON.stringify(opts.clientData), 365); } //Server calls this on ehjax response //Or, y'know, whenever really function ehjaxCallback(data) { opts.lastPang = Date.now(); if (data == 'softPang') { return; } else if (data == 'pang') { opts.pingCounter = 0; //reset opts.pingTime = Date.now(); runByond('?_src_=chat&proc=ping'); } else if (data == 'pong') { if (opts.pingDisabled) {return;} opts.pongTime = Date.now(); var pingDuration = Math.ceil((opts.pongTime - opts.pingTime) / 2); $('#pingMs').text(pingDuration+'ms'); pingDuration = Math.min(pingDuration, 255); var red = pingDuration; var green = 255 - pingDuration; var blue = 0; var hex = rgbToHex(red, green, blue); $('#pingDot').css('color', '#'+hex); } else if (data == 'roundrestart') { opts.restarting = true; internalOutput('
The connection has been closed because the server is restarting. Please wait while you automatically reconnect.
', 'internal'); } else { //Oh we're actually being sent data instead of an instruction var dataJ; try { dataJ = $.parseJSON(data); } catch (e) { //But...incorrect :sadtrombone: window.onerror('JSON: '+e+'. '+data, 'browserOutput.html', 327); return; } data = dataJ; if (data.clientData) { if (opts.restarting) { opts.restarting = false; $('.connectionClosed.restarting:not(.restored)').addClass('restored').text('The round restarted and you successfully reconnected!'); } if (!data.clientData.ckey && !data.clientData.ip && !data.clientData.compid) { //TODO: Call shutdown perhaps return; } else { handleClientData(data.clientData.ckey, data.clientData.ip, data.clientData.compid); } sendVolumeUpdate(); } else if (data.firebug) { if (data.trigger) { internalOutput('Loading firebug console, triggered by '+data.trigger+'...', 'internal'); } else { internalOutput('Loading firebug console...', 'internal'); } var firebugEl = document.createElement('script'); firebugEl.src = 'https://getfirebug.com/firebug-lite-debug.js'; document.body.appendChild(firebugEl); } else if (data.adminMusic) { if (typeof data.adminMusic === 'string') { var adminMusic = byondDecode(data.adminMusic); adminMusic = adminMusic.match(/https?:\/\/\S+/) || ''; if (data.musicRate) { var newRate = Number(data.musicRate); if(newRate) { $('#adminMusic').prop('defaultPlaybackRate', newRate); } } else { $('#adminMusic').prop('defaultPlaybackRate', 1.0); } $('#adminMusic').prop('src', adminMusic); $('#adminMusic').trigger("play"); } } } } function createPopup(contents, width) { opts.popups++; $('body').append(''); //Attach close popup event var $popup = $('#popup'+opts.popups); var height = $popup.outerHeight(); $popup.css({'height': height+'px', 'margin': '-'+(height/2)+'px 0 0 -'+(width/2)+'px'}); $popup.on('click', '.close', function(e) { e.preventDefault(); $popup.remove(); }); } function toggleWasd(state) { opts.wasd = (state == 'on' ? true : false); } function sendVolumeUpdate() { opts.volumeUpdating = false; if(opts.updatedVolume) { runByond('?_src_=chat&proc=setMusicVolume¶m[volume]='+opts.updatedVolume); } } function subSlideUp() { $(this).removeClass('scroll'); $(this).css('height', ''); } function startSubLoop() { if (opts.selectedSubLoop) { clearInterval(opts.selectedSubLoop); } return setInterval(function() { if (!opts.suppressSubClose && $selectedSub.is(':visible')) { $selectedSub.slideUp('fast', subSlideUp); clearInterval(opts.selectedSubLoop); } }, 5000); //every 5 seconds } function handleToggleClick($sub, $toggle) { if ($selectedSub !== $sub && $selectedSub.is(':visible')) { $selectedSub.slideUp('fast', subSlideUp); } $selectedSub = $sub if ($selectedSub.is(':visible')) { $selectedSub.slideUp('fast', subSlideUp); clearInterval(opts.selectedSubLoop); } else { $selectedSub.slideDown('fast', function() { var windowHeight = $(window).height(); var toggleHeight = $toggle.outerHeight(); var priorSubHeight = $selectedSub.outerHeight(); var newSubHeight = windowHeight - toggleHeight; $(this).height(newSubHeight); if (priorSubHeight > (windowHeight - toggleHeight)) { $(this).addClass('scroll'); } }); opts.selectedSubLoop = startSubLoop(); } } /***************************************** * * DOM READY * ******************************************/ if (typeof $ === 'undefined') { var div = document.getElementById('loading').childNodes[1]; div += '

ERROR: Jquery did not load.'; } $(function() { $messages = $('#messages'); $subOptions = $('#subOptions'); $subAudio = $('#subAudio'); $selectedSub = $subOptions; //Hey look it's a controller loop! setInterval(function() { if (opts.lastPang + opts.pangLimit < Date.now() && !opts.restarting) { //Every pingLimit if (!opts.noResponse) { //Only actually append a message if the previous ping didn't also fail (to prevent spam) opts.noResponse = true; opts.noResponseCount++; internalOutput('
You are either AFK, experiencing lag or the connection has closed.
', 'internal'); } } else if (opts.noResponse) { //Previous ping attempt failed ohno $('.connectionClosed[data-count="'+opts.noResponseCount+'"]:not(.restored)').addClass('restored').text('Your connection has been restored (probably)!'); opts.noResponse = false; } }, 2000); //2 seconds /***************************************** * * LOAD SAVED CONFIG * ******************************************/ var savedConfig = { 'sfontSize': getCookie('fontsize'), 'slineHeight': getCookie('lineheight'), 'spingDisabled': getCookie('pingdisabled'), 'shighlightTerms': getCookie('highlightterms'), 'shighlightColor': getCookie('highlightcolor'), 'smusicVolume': getCookie('musicVolume'), 'smessagecombining': getCookie('messagecombining'), }; if (savedConfig.sfontSize) { $messages.css('font-size', savedConfig.sfontSize); internalOutput('Loaded font size setting of: '+savedConfig.sfontSize+'', 'internal'); } if (savedConfig.slineHeight) { $("body").css('line-height', savedConfig.slineHeight); internalOutput('Loaded line height setting of: '+savedConfig.slineHeight+'', 'internal'); } if (savedConfig.spingDisabled) { if (savedConfig.spingDisabled == 'true') { opts.pingDisabled = true; $('#ping').hide(); } internalOutput('Loaded ping display of: '+(opts.pingDisabled ? 'hidden' : 'visible')+'', 'internal'); } if (savedConfig.shighlightTerms) { var savedTerms = $.parseJSON(savedConfig.shighlightTerms); var actualTerms = ''; for (var i = 0; i < savedTerms.length; i++) { if (savedTerms[i]) { actualTerms += savedTerms[i] + ', '; } } if (actualTerms) { actualTerms = actualTerms.substring(0, actualTerms.length - 2); internalOutput('Loaded highlight strings of: ' + actualTerms+'', 'internal'); opts.highlightTerms = savedTerms; } } if (savedConfig.shighlightColor) { opts.highlightColor = savedConfig.shighlightColor; internalOutput('Loaded highlight color of: '+savedConfig.shighlightColor+'', 'internal'); } if (savedConfig.smusicVolume) { var newVolume = clamp(savedConfig.smusicVolume, 0, 100); $('#adminMusic').prop('volume', newVolume / 100); $('#musicVolume').val(newVolume); opts.updatedVolume = newVolume; sendVolumeUpdate(); internalOutput('Loaded music volume of: '+savedConfig.smusicVolume+'', 'internal'); } else{ $('#adminMusic').prop('volume', opts.defaultMusicVolume / 100); } if (savedConfig.smessagecombining) { if (savedConfig.smessagecombining == 'false') { opts.messageCombining = false; } else { opts.messageCombining = true; } } (function() { var dataCookie = getCookie('connData'); if (dataCookie) { var dataJ; try { dataJ = $.parseJSON(dataCookie); } catch (e) { window.onerror('JSON '+e+'. '+dataCookie, 'browserOutput.html', 434); return; } opts.clientData = dataJ; } })(); /***************************************** * * BASE CHAT OUTPUT EVENTS * ******************************************/ $('body').on('click', 'a', function(e) { e.preventDefault(); }); $('body').on('mousedown', function(e) { var $target = $(e.target); if ($contextMenu && opts.hasOwnProperty('contextMenuTarget') && opts.contextMenuTarget) { hideContextMenu(); return false; } if ($target.is('a') || $target.parent('a').length || $target.is('input') || $target.is('textarea')) { opts.preventFocus = true; } else { opts.preventFocus = false; opts.mouseDownX = e.pageX; opts.mouseDownY = e.pageY; } }); $messages.on('mousedown', function(e) { if ($selectedSub && $selectedSub.is(':visible')) { $selectedSub.slideUp('fast', subSlideUp); clearInterval(opts.selectedSubLoop); } }); $('body').on('mouseup', function(e) { if (!opts.preventFocus && (e.pageX >= opts.mouseDownX - opts.clickTolerance && e.pageX <= opts.mouseDownX + opts.clickTolerance) && (e.pageY >= opts.mouseDownY - opts.clickTolerance && e.pageY <= opts.mouseDownY + opts.clickTolerance) ) { opts.mouseDownX = null; opts.mouseDownY = null; runByond('byond://winset?mapwindow.map.focus=true'); } }); $messages.on('click', 'a', function(e) { var href = $(this).attr('href'); $(this).addClass('visited'); if (href[0] == '?' || (href.length >= 8 && href.substring(0,8) == 'byond://')) { runByond(href); } else { href = escaper(href); runByond('?action=openLink&link='+href); } }); //Fuck everything about this event. Will look into alternatives. $('body').on('keydown', function(e) { if (e.target.nodeName == 'INPUT' || e.target.nodeName == 'TEXTAREA') { return; } if (e.ctrlKey || e.altKey || e.shiftKey) { //Band-aid "fix" for allowing ctrl+c copy paste etc. Needs a proper fix. return; } e.preventDefault() var k = e.which; // Hardcoded because else there would be no feedback message. if (k == 113) { // F2 runByond('byond://winset?screenshot=auto'); internalOutput('Screenshot taken', 'internal'); } var c = ""; switch (k) { case 8: c = 'BACK'; case 9: c = 'TAB'; case 13: c = 'ENTER'; case 19: c = 'PAUSE'; case 27: c = 'ESCAPE'; case 33: // Page up c = 'NORTHEAST'; case 34: // Page down c = 'SOUTHEAST'; case 35: // End c = 'SOUTHWEST'; case 36: // Home c = 'NORTHWEST'; case 37: c = 'WEST'; case 38: c = 'NORTH'; case 39: c = 'EAST'; case 40: c = 'SOUTH'; case 45: c = 'INSERT'; case 46: c = 'DELETE'; case 93: // That weird thing to the right of alt gr. c = 'APPS'; default: c = String.fromCharCode(k); } if (c.length == 0) { if (!e.shiftKey) { c = c.toLowerCase(); } runByond('byond://winset?mapwindow.map.focus=true;mainwindow.input.text='+c); return false; } else { runByond('byond://winset?mapwindow.map.focus=true'); return false; } }); //Mildly hacky fix for scroll issues on mob change (interface gets resized sometimes, messing up snap-scroll) $(window).on('resize', function(e) { if ($(this).height() !== opts.priorChatHeight) { $('body,html').scrollTop($messages.outerHeight()); opts.priorChatHeight = $(this).height(); } }); /***************************************** * * OPTIONS INTERFACE EVENTS * ******************************************/ $('body').on('click', '#newMessages', function(e) { var messagesHeight = $messages.outerHeight(); $('body,html').scrollTop(messagesHeight); $('#newMessages').remove(); runByond('byond://winset?mapwindow.map.focus=true'); }); $('#toggleOptions').click(function(e) { handleToggleClick($subOptions, $(this)); }); $('#toggleAudio').click(function(e) { handleToggleClick($subAudio, $(this)); }); $('.sub, .toggle').mouseenter(function() { opts.suppressSubClose = true; }); $('.sub, .toggle').mouseleave(function() { opts.suppressSubClose = false; }); $('#decreaseFont').click(function(e) { var fontSize = parseInt($messages.css('font-size')); fontSize = fontSize - 1 + 'px'; $messages.css({'font-size': fontSize}); setCookie('fontsize', fontSize, 365); internalOutput('Font size set to '+fontSize+'', 'internal'); }); $('#increaseFont').click(function(e) { var fontSize = parseInt($messages.css('font-size')); fontSize = fontSize + 1 + 'px'; $messages.css({'font-size': fontSize}); setCookie('fontsize', fontSize, 365); internalOutput('Font size set to '+fontSize+'', 'internal'); }); $('#decreaseLineHeight').click(function(e) { var Heightline = parseFloat($("body").css('line-height')); var Sizefont = parseFloat($("body").css('font-size')); var lineheightvar = Heightline / Sizefont lineheightvar -= 0.1; lineheightvar = lineheightvar.toFixed(1) $("body").css({'line-height': lineheightvar}); setCookie('lineheight', lineheightvar, 365); internalOutput('Line height set to '+lineheightvar+'', 'internal'); }); $('#increaseLineHeight').click(function(e) { var Heightline = parseFloat($("body").css('line-height')); var Sizefont = parseFloat($("body").css('font-size')); var lineheightvar = Heightline / Sizefont lineheightvar += 0.1; lineheightvar = lineheightvar.toFixed(1) $("body").css({'line-height': lineheightvar}); setCookie('lineheight', lineheightvar, 365); internalOutput('Line height set to '+lineheightvar+'', 'internal'); }); $('#togglePing').click(function(e) { if (opts.pingDisabled) { $('#ping').slideDown('fast'); opts.pingDisabled = false; } else { $('#ping').slideUp('fast'); opts.pingDisabled = true; } setCookie('pingdisabled', (opts.pingDisabled ? 'true' : 'false'), 365); }); $('#saveLog').click(function(e) { $.ajax({ type: 'GET', url: 'browserOutput.css', success: function(styleData) { var win; try { win = window.open('', 'Chat Log', 'toolbar=no, location=no, directories=no, status=no, menubar=yes, scrollbars=yes, resizable=yes, width=780, height=600, top=' + (screen.height/2 - 635/2) + ', left=' + (screen.width/2 - 780/2)); } catch (e) { return; } if (win) { win.document.head.innerHTML = 'Chat Log'; win.document.head.innerHTML += ''; win.document.body.innerHTML = $messages.html(); } } }); }); $('#highlightTerm').click(function(e) { if ($('.popup .highlightTerm').is(':visible')) {return;} var termInputs = ''; for (var i = 0; i < opts.highlightLimit; i++) { termInputs += '
'; } var popupContent = '
String Highlighting
' + '
' + '
Choose up to '+opts.highlightLimit+' strings that will highlight the line when they appear in chat.
' + '
' + termInputs + '
' + '
' + '
' + '
'; createPopup(popupContent, 250); }); $('body').on('keyup', '#highlightColor', function() { var color = $('#highlightColor').val(); color = color.trim(); if (!color || color.charAt(0) != '#') return; $('#highlightColor').css('background-color', color); }); $('body').on('submit', '#highlightTermForm', function(e) { e.preventDefault(); var count = 0; while (count < opts.highlightLimit) { var term = $('#highlightTermInput'+count).val(); if (term) { term = term.trim(); if (term === '') { opts.highlightTerms[count] = null; } else { opts.highlightTerms[count] = term.toLowerCase(); } } else { opts.highlightTerms[count] = null; } count++; } var color = $('#highlightColor').val(); color = color.trim(); if (color == '' || color.charAt(0) != '#') { opts.highlightColor = '#FFFF00'; } else { opts.highlightColor = color; } var $popup = $('#highlightPopup').closest('.popup'); $popup.remove(); setCookie('highlightterms', JSON.stringify(opts.highlightTerms), 365); setCookie('highlightcolor', opts.highlightColor, 365); }); $('#clearMessages').click(function() { $messages.empty(); opts.messageCount = 0; }); $('#musicVolumeSpan').hover(function() { $('#musicVolumeText').addClass('hidden'); $('#musicVolume').removeClass('hidden'); }, function() { $('#musicVolume').addClass('hidden'); $('#musicVolumeText').removeClass('hidden'); }); $('#musicVolume').change(function() { var newVolume = $('#musicVolume').val(); newVolume = clamp(newVolume, 0, 100); $('#adminMusic').prop('volume', newVolume / 100); setCookie('musicVolume', newVolume, 365); opts.updatedVolume = newVolume; if(!opts.volumeUpdating) { setTimeout(sendVolumeUpdate, opts.volumeUpdateDelay); opts.volumeUpdating = true; } }); $('#toggleCombine').click(function(e) { opts.messageCombining = !opts.messageCombining; setCookie('messagecombining', (opts.messageCombining ? 'true' : 'false'), 365); }); $('img.icon').error(iconError); /***************************************** * * KICK EVERYTHING OFF * ******************************************/ runByond('?_src_=chat&proc=doneLoading'); if ($('#loading').is(':visible')) { $('#loading').remove(); } $('#userBar').show(); opts.priorChatHeight = $(window).height(); });