diff --git a/chat/css/global.css b/chat/css/global.css index eff916f..4e648e7 100644 --- a/chat/css/global.css +++ b/chat/css/global.css @@ -67,6 +67,9 @@ bottom:150px; overflow:auto; } +#content.logs #chatList { + right:20px; +} #content #inputFieldContainer { position:absolute; left:20px; @@ -259,7 +262,7 @@ #content img { border:none; } -#content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, +#content #chatList, #content #onlineListContainer, #content #helpContainer, #content #settingsContainer, #content #colorCodesContainer, #content #colorCodesContainer a, #content textarea { border-width:1px; border-style:solid; diff --git a/chat/js/chat.js b/chat/js/chat.js index b5165dd..bc6cc36 100644 --- a/chat/js/chat.js +++ b/chat/js/chat.js @@ -4,10 +4,10 @@ * @copyright (c) Sebastian Tschan * @license Modified MIT License * @link https://blueimp.net/ajax/ - * + * * The SELFHTML documentation has been used throughout this project: * http://selfhtml.org - * + * * Stylesheet and cookie methods have been inspired by Paul Sowden (A List Apart): * http://www.alistapart.com/stories/alternate/ */ @@ -22,7 +22,11 @@ var ajaxChat = { loginChannelID: null, loginChannelName: null, timerRate: null, + inactiveRate: null, + inactivePeriod: null, + actualRate: null, timer: null, + inactivityTimer: null, ajaxURL: null, baseURL: null, regExpMediaUrl: null, @@ -89,17 +93,18 @@ var ajaxChat = { DOMbuffering: null, DOMbuffer: null, DOMbufferRowClass: 'rowOdd', - - init: function(config, lang, initSettings, initStyle, initialize, initializeFunction, finalizeFunction) { + debug: false, + + init: function(config, lang, initSettings, initStyle, initialize, initializeFunction, finalizeFunction) { this.httpRequest = {}; this.usersList = []; this.userNamesList = []; this.userMenuCounter = 0; this.lastID = 0; this.localID = 0; - this.lang = lang; + this.lang = lang; this.initConfig(config); - this.initDirectories(); + this.initDirectories(); if(initSettings) { this.initSettings(); } @@ -112,11 +117,21 @@ var ajaxChat = { this.setLoadHandler(); } }, - + initConfig: function(config) { this.loginChannelID = config['loginChannelID']; - this.loginChannelName = config['loginChannelName']; - this.timerRate = config['timerRate']; + this.loginChannelName = config['loginChannelName']; + this.timerRate = this.actualRate = config['timerRate']; + this.inactiveRate = config['inactiveRate']; + if (!this.inactiveRate) { + this.inactiveRate = this.timeRate*5; + } + this.inactivePeriod = config['inactivePeriod']; + if (!this.inactivePeriod) { + this.inactivePeriod = 5*60*1000; + } else { + this.inactivePeriod = this.inactivePeriod*1000; + } this.ajaxURL = config['ajaxURL']; this.baseURL = config['baseURL']; this.regExpMediaUrl = config['regExpMediaUrl']; @@ -137,7 +152,7 @@ var ajaxChat = { this.chatBotName = config['chatBotName']; this.chatBotID = config['chatBotID']; this.allowUserMessageDelete = config['allowUserMessageDelete']; - this.inactiveTimeout = config['inactiveTimeout']; + this.inactiveTimeout = Math.max(config['inactiveTimeout'],2); this.privateChannelDiff = config['privateChannelDiff']; this.privateMessageDiff = config['privateMessageDiff']; this.showChannelMessages = config['showChannelMessages']; @@ -146,9 +161,25 @@ var ajaxChat = { this.socketServerHost = config['socketServerHost']; this.socketServerPort = config['socketServerPort']; this.socketServerChatID = config['socketServerChatID']; + this.debug = config['debug']; this.DOMbuffering = false; this.DOMbuffer = ""; + /** + * The calculation below looks incorrect - inactiveTimeout is in minutes, timerRate is in ms. this.retryTimerDelay = (this.inactiveTimeout*6000 - this.timerRate)/4 + this.timerRate; + * So I think inactiveTimeout should be multiplied by 60000 not 6000. + * With original calc and inactive timeout = the minimum of 2 mins and timerRate of 2s, this would result in + * an ajax retry delay of 4.5secs which is unreasonable on a slow connection. + * With corrected calc and inactive timeout = the minimum of 2 mins and timerRate of 2s, this would result in + * an ajax retry delay of 31.5secs which is about the maximum we should allow. + * With original calc and inactive timeout = 15 mins and timerRate of 2s, this would result in + * an ajax retry delay of 24secs which is reasonable. + * With corrected calc and inactive timeout = 15 mins and timerRate of 2s, this would result in + * an ajax retry delay of 226secs which is 3 mins and is unreasonable. + * Calc looks to allow at least 4 retries before user becomes inactive which seems reasonable. + * However with large inactiveTimeouts, the retry period should be limited. + **/ + this.retryTimerDelay = Math.min(this.inactiveTimeout*60*1000/4, 60000); }, initDirectories: function() { @@ -157,7 +188,7 @@ var ajaxChat = { this.dirs['sounds'] = this.baseURL+'sounds/'; this.dirs['flash'] = this.baseURL+'flash/'; }, - + initSettings: function() { var cookie = this.readCookie(this.sessionName + '_settings'), i, settingsArray, setting, key, value, number; @@ -209,21 +240,21 @@ var ajaxChat = { if(this.inArray(this.nonPersistentSettings, property)) { if(this.unusedSettings && this.unusedSettings[property]) { // Store the unusedSetting previously stored: - this.settings[property] = this.unusedSettings[property]; + this.settings[property] = this.unusedSettings[property]; } else { continue; } } settingsArray.push(property + '=' + this.encodeText(this.settings[property])); } - this.createCookie(this.sessionName + '_settings', settingsArray.join('&'), this.cookieExpiration); + this.createCookie(this.sessionName + '_settings', settingsArray.join('&'), this.cookieExpiration); } }, - + getSettings: function() { return this.settings; }, - + getSetting: function(key) { // Only return null if setting is null or undefined, not if it is false: for(var property in this.settings) { @@ -233,11 +264,11 @@ var ajaxChat = { } return null; }, - + setSetting: function(key, value) { this.settings[key] = value; }, - + initializeSettings: function() { if(this.settings['persistFontColor'] && this.settings['fontColor']) { // Set the inputField font color to the font color: @@ -246,17 +277,17 @@ var ajaxChat = { } } }, - - initialize: function() { + + initialize: function() { this.setUnloadHandler(); this.initializeDocumentNodes(); this.loadPageAttributes(); this.initEmoticons(); this.initColorCodes(); - this.initializeSettings(); + this.initializeSettings(); this.setSelectedStyle(); this.customInitialize(); - //preload the Alert icon (it can't display if there's no connection unless it's cached!) + // preload the Alert icon (it can't display if there's no connection unless it's cached!) this.setStatus('retrying'); if(typeof this.initializeFunction === 'function') { this.initializeFunction(); @@ -283,17 +314,17 @@ var ajaxChat = { } this.updateChat(params); }, - + setStartChatHandler: function() { if(this.dom['inputField']) { this.dom['inputField'].onfocus = function() { ajaxChat.startChat(); // Reset the onfocus event on first call: ajaxChat.dom['inputField'].onfocus = ''; - }; + }; } }, - + startChat: function() { this.chatStarted = true; if(this.dom['inputField'] && this.settings['autoFocus']) { @@ -306,7 +337,7 @@ var ajaxChat = { loadPageAttributes: function() { var htmlTag = document.getElementsByTagName('html')[0]; this.langCode = htmlTag.getAttribute('lang') ? htmlTag.getAttribute('lang') : 'en'; - this.baseDirection = htmlTag.getAttribute('dir') ? htmlTag.getAttribute('dir') : 'ltr'; + this.baseDirection = htmlTag.getAttribute('dir') ? htmlTag.getAttribute('dir') : 'ltr'; }, setLoadHandler: function() { @@ -321,9 +352,9 @@ var ajaxChat = { onload(); ajaxChat.initialize(); }; - } + } }, - + setUnloadHandler: function() { // Make sure finalize() is called on page unload: var onunload = window.onunload; @@ -359,7 +390,7 @@ var ajaxChat = { this.updateChatlistView(); } }, - + initializeDocumentNodes: function() { this.dom = {}; for(var key in this.domIDs) { @@ -389,7 +420,7 @@ var ajaxChat = { } this.DOMbuffer = ""; }, - + initColorCodes: function() { if(this.dom['colorCodesContainer']) { this.DOMbuffer = ""; @@ -422,9 +453,10 @@ var ajaxChat = { } else if(this.loginChannelName !== null) { params += '&channelName='+this.encodeText(this.loginChannelName); } + this.resetInactivityTimer(); this.updateChat(params); }, - + updateChat: function(paramString) { var requestUrl = this.ajaxURL + '&lastID=' @@ -434,7 +466,7 @@ var ajaxChat = { } this.makeRequest(requestUrl,'GET',null); }, - + loadFlashInterface: function() { if(this.dom['flashInterfaceContainer']) { this.updateDOM( @@ -456,7 +488,7 @@ var ajaxChat = { FABridge.addInitializationCallback('ajaxChat', this.flashInterfaceLoadCompleteHandler); } }, - + flashInterfaceLoadCompleteHandler: function() { ajaxChat.initializeFlashInterface(); }, @@ -483,13 +515,13 @@ var ajaxChat = { } this.socket.connect(this.socketServerHost, this.socketServerPort); } catch(e) { - //alert(e); + this.debugMessage('socketConnect', e); } } clearTimeout(this.socketReconnectTimer); this.socketReconnectTimer = null; }, - + socketConnectHandler: function(event) { ajaxChat.socketIsConnected = true; // setTimeout is needed to avoid calling the flash interface recursively: @@ -503,7 +535,7 @@ var ajaxChat = { ajaxChat.updateChat(null); } }, - + socketDataHandler: function(event) { ajaxChat.socketUpdate(event.getData()); }, @@ -533,11 +565,11 @@ var ajaxChat = { +'"/>' ); } catch(e) { - //alert(e); + this.debugMessage('socketRegister', e); } } }, - + loadXML: function(str) { if(!arguments.callee.parser) { try { @@ -552,7 +584,7 @@ var ajaxChat = { arguments.callee.XMLDOM = new ActiveXObject('Microsoft.XMLDOM'); } arguments.callee.XMLDOM.loadXML(str); - return arguments.callee.XMLDOM; + return arguments.callee.XMLDOM; }; } else { // Safari, Konqueror: @@ -574,7 +606,7 @@ var ajaxChat = { } return arguments.callee.parser.parseFromString(str, 'text/xml'); }, - + socketUpdate: function(data) { var xmlDoc = this.loadXML(data); if(xmlDoc) { @@ -602,15 +634,15 @@ var ajaxChat = { this.settings['audioVolume'] = volume; try { if(!this.soundTransform) { - this.soundTransform = FABridge.ajaxChat.create('flash.media.SoundTransform'); + this.soundTransform = FABridge.ajaxChat.create('flash.media.SoundTransform'); } this.soundTransform.setVolume(volume); } catch(e) { - //alert(e); + this.debugMessage('setAudioVolume', e); } } }, - + loadSounds: function() { try { this.setAudioVolume(this.settings['audioVolume']); @@ -625,10 +657,10 @@ var ajaxChat = { sound.load(urlRequest); } } catch(e) { - alert(e); + this.debugMessage('loadSounds', e); } }, - + soundLoadCompleteHandler: function(event) { var sound = event.getTarget(); for(var key in ajaxChat.soundFiles) { @@ -645,7 +677,7 @@ var ajaxChat = { setTimeout(function() { ajaxChat.addChatBotMessageToChatList('/error SoundIO'); }, 0); setTimeout(ajaxChat.updateChatlistView, 1); }, - + soundPlayCompleteHandler: function(event) { // soundChannel event 'soundComplete' }, @@ -659,12 +691,12 @@ var ajaxChat = { // sndTransform:SoundTransform (default = null) return this.sounds[soundID].play(0, 0, this.soundTransform); } catch(e) { - //alert(e); + this.debugMessage('playSound', e); } } return null; }, - + playSoundOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { if(this.settings['audio'] && this.sounds && this.lastID && !this.channelSwitch) { switch(userID) { @@ -722,7 +754,7 @@ var ajaxChat = { if (this.requestStatus !== 'retrying' || newStatus === 'ok') { this.requestStatus = newStatus; } - + var statusIcon = document.getElementById('statusIconContainer'); if (statusIcon) { @@ -739,12 +771,12 @@ var ajaxChat = { } } }, - + forceNewRequest: function() { - ajaxChat.updateChat(null); + ajaxChat.updateChat(null); ajaxChat.setStatus('retrying'); }, - + getHttpRequest: function(identifier) { if(!this.httpRequest[identifier]) { if (window.XMLHttpRequest) { @@ -769,7 +801,7 @@ var ajaxChat = { makeRequest: function(url, method, data) { var identifier; this.setStatus('waiting'); - + try { if(data) { // Create up to 50 HTTPRequest objects: @@ -784,7 +816,7 @@ var ajaxChat = { } //if the response takes longer than retryTimerDelay to give an OK status, abort the connection and start again. this.retryTimer = setTimeout(ajaxChat.forceNewRequest, ajaxChat.retryTimerDelay); - + this.getHttpRequest(identifier).open(method, url, true); this.getHttpRequest(identifier).onreadystatechange = function() { try { @@ -793,7 +825,7 @@ var ajaxChat = { try { clearTimeout(ajaxChat.timer); } catch(e) { - //alert(e); + this.debugMessage('makeRequest::clearTimeout', e); } try { if(data) { @@ -802,12 +834,12 @@ var ajaxChat = { ajaxChat.updateChatlistView(); } } catch(e) { - //alert(e); + this.debugMessage('makeRequest::ConnectionTimeout', e); } - try { - ajaxChat.timer = setTimeout(function() { ajaxChat.updateChat(null); }, ajaxChat.timerRate); + try { + ajaxChat.timer = setTimeout(function() { ajaxChat.updateChat(null); }, ajaxChat.actualRate); } catch(e) { - //alert(e); + this.debugMessage('makeRequest::setTimeout', e); } } }; @@ -822,10 +854,10 @@ var ajaxChat = { ajaxChat.setStatus('retrying'); this.updateChatlistView(); } - this.timer = setTimeout(function() { ajaxChat.updateChat(null); }, this.timerRate); + this.timer = setTimeout(function() { ajaxChat.updateChat(null); }, this.actualRate); } }, - + handleResponse: function(identifier) { var xmlDoc; if (this.getHttpRequest(identifier).readyState === 4) { @@ -842,7 +874,7 @@ var ajaxChat = { } else { this.addChatBotMessageToChatList('/error ConnectionStatus '+this.getHttpRequest(identifier).status); this.setStatus('retrying'); - this.updateChatlistView(); + this.updateChatlistView(); return false; } } @@ -853,7 +885,7 @@ var ajaxChat = { this.handleXML(xmlDoc); return true; }, - + handleXML: function(xmlDoc) { this.handleInfoMessages(xmlDoc.getElementsByTagName('info')); this.handleOnlineUsers(xmlDoc.getElementsByTagName('user')); @@ -869,16 +901,16 @@ var ajaxChat = { if(this.socketIsConnected) { timeout = this.socketTimerRate; } else { - timeout = this.timerRate; + timeout = this.actualRate; if(this.socketServerEnabled && !this.socketReconnectTimer) { // If the socket connection fails try to reconnect once in a minute: this.socketReconnectTimer = setTimeout(ajaxChat.socketConnect, 60000); } } - this.timer = setTimeout(function() {ajaxChat.updateChat(null);}, timeout); + this.timer = setTimeout(function() {ajaxChat.updateChat(null);}, timeout); } }, - + handleInfoMessages: function(infoNodes) { var infoType, infoData; for(var i=0; i= 0 ) { isInline = true; @@ -1090,7 +1122,7 @@ var ajaxChat = { this.showHide(menuID); this.dom['chatList'].scrollTop = this.dom['chatList'].scrollHeight; }, - + getUserNodeStringItems: function(encodedUserName, userID, isInline) { var menu; if(encodedUserName !== this.encodedUserName) { @@ -1182,10 +1214,10 @@ var ajaxChat = { menu += this.getCustomUserMenuItems(encodedUserName, userID); return menu; }, - + setOnlineListRowClasses: function() { if(this.dom['onlineList']) { - var node = this.dom['onlineList'].firstChild; + var node = this.dom['onlineList'].firstChild; var rowEven = false; while(node) { this.setClass(node, (rowEven ? 'rowEven' : 'rowOdd')); @@ -1194,7 +1226,7 @@ var ajaxChat = { } } }, - + clearChatList: function() { while(this.dom['chatList'].hasChildNodes()) { this.dom['chatList'].removeChild(this.dom['chatList'].firstChild); @@ -1217,7 +1249,7 @@ var ajaxChat = { } return arguments.callee.encodedChatBotName; }, - + addChatBotMessageToChatList: function(messageText) { this.addMessageToChatList( new Date(), @@ -1229,17 +1261,17 @@ var ajaxChat = { null ); }, - + addMessageToChatList: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { // Prevent adding the same message twice: if(this.getMessageNode(messageID)) { return; - } + } if(!this.onNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) { return; } this.DOMbufferRowClass = this.DOMbufferRowClass === 'rowEven' ? 'rowOdd' : 'rowEven'; - this.DOMbuffer = this.DOMbuffer + + this.DOMbuffer = this.DOMbuffer + this.getChatListMessageString( dateObject, userID, userName, userRole, messageID, messageText, channelID, ip ); @@ -1281,23 +1313,23 @@ var ajaxChat = { + this.replaceText(messageText) + ''; }, - + getChatListUserNameTitle: function(userID, userName, userRole, ip) { - return (ip !== null) ? ' title="IP: ' + ip + '"' : ''; + return (ip !== null) ? ' title="IP: ' + ip + '"' : ''; }, - + getMessageDocumentID: function(messageID) { return ((messageID === null) ? 'ajaxChat_lm_'+(this.localID++) : 'ajaxChat_m_'+messageID); }, - + getMessageNode: function(messageID) { return ((messageID === null) ? null : document.getElementById(this.getMessageDocumentID(messageID))); }, - + getUserDocumentID: function(userID) { return 'ajaxChat_u_'+userID; }, - + getUserNode: function(userID) { return document.getElementById(this.getUserDocumentID(userID)); }, @@ -1305,11 +1337,11 @@ var ajaxChat = { getUserMenuDocumentID: function(userID) { return 'ajaxChat_um_'+userID; }, - + getInlineUserMenuDocumentID: function(menuID, index) { return 'ajaxChat_ium_'+menuID+'_'+index; }, - + getDeletionLink: function(messageID, userID, userRole, channelID) { if(messageID !== null && this.isAllowedToDeleteMessage(messageID, userID, userRole, channelID)) { if(!arguments.callee.deleteMessage) { @@ -1323,7 +1355,7 @@ var ajaxChat = { } return ''; }, - + isAllowedToDeleteMessage: function(messageID, userID, userRole, channelID) { if((((this.userRole === '1' && this.allowUserMessageDelete && (userID === this.userID || parseInt(channelID) === parseInt(this.userID)+this.privateMessageDiff || @@ -1333,7 +1365,7 @@ var ajaxChat = { } return false; }, - + onNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { if(!this.customOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) { return false; @@ -1367,7 +1399,7 @@ var ajaxChat = { } return false; }, - + blinkOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { if(this.settings['blink'] && this.lastID && !this.channelSwitch && userID !== this.userID) { clearInterval(this.blinkInterval); @@ -1377,7 +1409,7 @@ var ajaxChat = { ); } }, - + blinkUpdate: function(blinkStr) { if(!this.originalDocumentTitle) { this.originalDocumentTitle = document.title; @@ -1398,19 +1430,19 @@ var ajaxChat = { arguments.callee.blink++; } }, - - updateChatlistView: function() { + + updateChatlistView: function() { if(this.dom['chatList'].childNodes && this.settings['maxMessages']) { while(this.dom['chatList'].childNodes.length > this.settings['maxMessages']) { this.dom['chatList'].removeChild(this.dom['chatList'].firstChild); } } - + if(this.settings['autoScroll']) { this.dom['chatList'].scrollTop = this.dom['chatList'].scrollHeight; } }, - + encodeText: function(text) { return encodeURIComponent(text); }, @@ -1466,7 +1498,7 @@ var ajaxChat = { this.encodeSpecialCharsCallback ); }, - + encodeSpecialCharsCallback: function(str) { switch(str) { case '&': @@ -1487,13 +1519,13 @@ var ajaxChat = { decodeSpecialChars: function(text) { var regExp = new RegExp('(&)|(<)|(>)|(')|(")', 'g'); - + return text.replace( regExp, this.decodeSpecialCharsCallback ); }, - + decodeSpecialCharsCallback: function(str) { switch(str) { case '&': @@ -1510,7 +1542,7 @@ var ajaxChat = { return str; } }, - + inArray: function(haystack, needle) { var i = haystack.length; while(i--) { @@ -1535,7 +1567,7 @@ var ajaxChat = { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('<\\/?[^>]+?>', 'g'); } - + return str.replace(arguments.callee.regExp, ''); }, @@ -1543,9 +1575,9 @@ var ajaxChat = { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('\\[\\/?[^\\]]+?\\]', 'g'); } - + return str.replace(arguments.callee.regExp, ''); - }, + }, escapeRegExp: function(text) { if (!arguments.callee.regExp) { @@ -1559,7 +1591,7 @@ var ajaxChat = { } return text.replace(arguments.callee.regExp, '\\$1'); }, - + addSlashes: function(text) { // Adding slashes in front of apostrophs and backslashes to ensure a valid JavaScript expression: return text.replace(/\\/g, '\\\\').replace(/\'/g, '\\\''); @@ -1572,7 +1604,7 @@ var ajaxChat = { formatDate: function(format, date) { date = (date == null) ? new date() : date; - + return format .replace(/%Y/g, date.getFullYear()) .replace(/%m/g, this.addLeadingZero(date.getMonth()+1)) @@ -1581,7 +1613,7 @@ var ajaxChat = { .replace(/%i/g, this.addLeadingZero(date.getMinutes())) .replace(/%s/g, this.addLeadingZero(date.getSeconds())); }, - + addLeadingZero: function(number) { number = number.toString(); if(number.length < 2) { @@ -1622,7 +1654,7 @@ var ajaxChat = { return 'default'; } }, - + handleInputFieldKeyPress: function(event) { if(event.keyCode === 13 && !event.shiftKey) { this.sendMessage(); @@ -1639,7 +1671,7 @@ var ajaxChat = { handleInputFieldKeyUp: function(event) { this.updateMessageLengthCounter(); }, - + updateMessageLengthCounter: function() { if(this.dom['messageLengthCounter']) { this.updateDOM( @@ -1650,7 +1682,7 @@ var ajaxChat = { ); } }, - + sendMessage: function(text) { text = text ? text : this.dom['inputField'].value; if(!text) { @@ -1659,17 +1691,24 @@ var ajaxChat = { text = this.parseInputMessage(text); if(text) { clearTimeout(this.timer); + this.resetInactivityTimer(); var message = 'lastID=' + this.lastID + '&text=' - + this.encodeText(text); + + this.encodeText(text); this.makeRequest(this.ajaxURL,'POST',message); } this.dom['inputField'].value = ''; this.dom['inputField'].focus(); this.updateMessageLengthCounter(); }, - + + resetInactivityTimer: function() { + clearTimeout(this.inactivityTimer); + this.actualRate = this.timerRate; + this.inactivityTimer = setTimeout(function() { this.actualRate = this.inactiveRate;}.bind(this), this.inactivePeriod); + }, + parseInputMessage: function(text) { var textParts; if(text.charAt(0) === '/') { @@ -1696,7 +1735,7 @@ var ajaxChat = { } return text; }, - + assignFontColorToMessage: function(text) { return '[color='+this.settings['fontColor']+']'+text+'[/color]'; }, @@ -1724,7 +1763,7 @@ var ajaxChat = { } return text; }, - + parseIgnoreInputCommand: function(text, textParts) { var userName, ignoredUserNames = this.getIgnoredUserNames(), i; if(textParts.length > 1) { @@ -1772,12 +1811,12 @@ var ajaxChat = { } return this.ignoredUserNames; }, - + setIgnoredUserNames: function(ignoredUserNames) { this.ignoredUserNames = ignoredUserNames; this.setSetting('ignoredUserNames', ignoredUserNames.join(' ')); }, - + ignoreMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { var textParts; if(userID === this.chatBotID && messageText.charAt(0) === '/') { @@ -1789,7 +1828,7 @@ var ajaxChat = { case '/roll': userName = textParts[1]; break; - } + } } } if(this.inArray(this.getIgnoredUserNames(), userName)) { @@ -1835,7 +1874,7 @@ var ajaxChat = { } } }, - + getClass: function(node) { if(typeof node.className !== 'undefined') { return node.className; // IE @@ -1843,7 +1882,7 @@ var ajaxChat = { return node.getAttribute('class'); } }, - + setClass: function(node, className) { if(typeof node.className !== 'undefined') { node.className = className; // IE @@ -1855,7 +1894,7 @@ var ajaxChat = { scriptLinkEncode: function(text) { return this.encodeText(this.addSlashes(this.decodeSpecialChars(text))); }, - + scriptLinkDecode: function(text) { return this.encodeSpecialChars(this.removeSlashes(this.decodeText(text))); }, @@ -1872,9 +1911,9 @@ var ajaxChat = { default: arguments.callee.utf8Decode = false; return value; - } + } } else if(arguments.callee.utf8Decode) { - return this.utf8Decode(value); + return this.utf8Decode(value); } else { return value; } @@ -1887,7 +1926,7 @@ var ajaxChat = { insertMessageWrapper: function(text) { this.insertText(this.getScriptLinkValue(text), true); }, - + switchChannel: function(channel) { if(!this.chatStarted) { this.clearChatList(); @@ -1897,11 +1936,11 @@ var ajaxChat = { this.requestTeaserContent(); return; } - clearTimeout(this.timer); + clearTimeout(this.timer); var message = 'lastID=' + this.lastID + '&channelName=' - + this.encodeText(channel); + + this.encodeText(channel); this.makeRequest(this.ajaxURL,'POST',message); if(this.dom['inputField'] && this.settings['autoFocus']) { this.dom['inputField'].focus(); @@ -1913,7 +1952,7 @@ var ajaxChat = { var message = 'logout=true'; this.makeRequest(this.ajaxURL,'POST',message); }, - + handleLogout: function(url) { window.location.href = url; }, @@ -1931,7 +1970,7 @@ var ajaxChat = { this.setClass(node, (this.getSetting(setting) ? 'button' : 'button off')); } }, - + showHide: function(id, styleDisplay, displayInline) { var node = document.getElementById(id); if(node) { @@ -1939,16 +1978,16 @@ var ajaxChat = { node.style.display = styleDisplay; } else { if(node.style.display === 'none') { - node.style.display = (displayInline ? 'inline' : 'block'); + node.style.display = (displayInline ? 'inline' : 'block'); } else { node.style.display = 'none'; } - } + } } }, setPersistFontColor: function(bool) { - this.settings['persistFontColor'] = bool; + this.settings['persistFontColor'] = bool; if(!this.settings['persistFontColor']) { this.settings['fontColor'] = null; if(this.dom['inputField']) { @@ -1973,16 +2012,16 @@ var ajaxChat = { this.insert('[color=' + color + ']', '[/color]'); } }, - + insertText: function(text, clearInputField) { if(clearInputField) { this.dom['inputField'].value = ''; } this.insert(text, ''); }, - + insertBBCode: function(bbCode) { - switch(bbCode) { + switch(bbCode) { case 'url': var url = prompt(this.lang['urlDialog'], 'http://'); if(url) @@ -1991,7 +2030,7 @@ var ajaxChat = { this.dom['inputField'].focus(); break; default: - this.insert('[' + bbCode + ']', '[/' + bbCode + ']'); + this.insert('[' + bbCode + ']', '[/' + bbCode + ']'); } }, @@ -2008,7 +2047,7 @@ var ajaxChat = { if (insText.length === 0) { range.move('character', -endTag.length); } else { - range.moveStart('character', startTag.length + insText.length + endTag.length); + range.moveStart('character', startTag.length + insText.length + endTag.length); } range.select(); } @@ -2042,7 +2081,7 @@ var ajaxChat = { + this.dom['inputField'].value.substr(pos); } }, - + replaceText: function(text) { try{ text = this.replaceLineBreaks(text); @@ -2053,20 +2092,20 @@ var ajaxChat = { text = this.replaceHyperLinks(text); text = this.replaceEmoticons(text); } - text = this.breakLongWords(text); + text = this.breakLongWords(text); text = this.replaceCustomText(text); } catch(e){ - //alert(e); + this.debugMessage('replaceText', e); } return text; }, - + replaceCommands: function(text) { try { if(text.charAt(0) !== '/') { return text; } - var textParts = text.split(' '); + var textParts = text.split(' '); switch(textParts[0]) { case '/login': return this.replaceCommandLogin(textParts); @@ -2137,7 +2176,7 @@ var ajaxChat = { return this.replaceCustomCommands(text, textParts); } } catch(e) { - //alert(e); + this.debugMessage('replaceCommands', e); } return text; }, @@ -2145,7 +2184,7 @@ var ajaxChat = { replaceCommandLogin: function(textParts) { return '' + this.lang['login'].replace(/%s/, textParts[1]) - + ''; + + ''; }, replaceCommandLogout: function(textParts) { @@ -2154,21 +2193,21 @@ var ajaxChat = { type = textParts[2]; return '' + this.lang['logout' + type].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandChannelEnter: function(textParts) { return '' + this.lang['channelEnter'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandChannelLeave: function(textParts) { return '' + this.lang['channelLeave'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandPrivMsg: function(textParts) { var privMsgText = textParts.slice(1).join(' '); privMsgText = this.replaceBBCode(privMsgText); @@ -2179,7 +2218,7 @@ var ajaxChat = { + ' ' + privMsgText; }, - + replaceCommandPrivMsgTo: function(textParts) { var privMsgText = textParts.slice(2).join(' '); privMsgText = this.replaceBBCode(privMsgText); @@ -2190,7 +2229,7 @@ var ajaxChat = { + ' ' + privMsgText; }, - + replaceCommandPrivAction: function(textParts) { var privActionText = textParts.slice(1).join(' '); privActionText = this.replaceBBCode(privActionText); @@ -2202,7 +2241,7 @@ var ajaxChat = { + this.lang['privmsg'] + ' '; }, - + replaceCommandPrivActionTo: function(textParts) { var privActionText = textParts.slice(2).join(' '); privActionText = this.replaceBBCode(privActionText); @@ -2212,9 +2251,9 @@ var ajaxChat = { + privActionText + ' ' + this.lang['privmsgto'].replace(/%s/, textParts[1]) - + ' '; + + ' '; }, - + replaceCommandAction: function(textParts) { var actionText = textParts.slice(1).join(' '); actionText = this.replaceBBCode(actionText); @@ -2222,9 +2261,9 @@ var ajaxChat = { actionText = this.replaceEmoticons(actionText); return '' + actionText - + ''; + + ''; }, - + replaceCommandInvite: function(textParts) { var inviteText = this.lang['invite'] .replace(/%s/, textParts[1]) @@ -2240,99 +2279,99 @@ var ajaxChat = { ); return '' + inviteText - + ''; + + ''; }, - + replaceCommandInviteTo: function(textParts) { var inviteText = this.lang['inviteto'] .replace(/%s/, textParts[1]) .replace(/%s/, textParts[2]); return '' + inviteText - + ''; + + ''; }, - + replaceCommandUninvite: function(textParts) { var uninviteText = this.lang['uninvite'] .replace(/%s/, textParts[1]) .replace(/%s/, textParts[2]); return '' + uninviteText - + ''; + + ''; }, - + replaceCommandUninviteTo: function(textParts) { var uninviteText = this.lang['uninviteto'] .replace(/%s/, textParts[1]) .replace(/%s/, textParts[2]); return '' + uninviteText - + ''; + + ''; }, - + replaceCommandQueryOpen: function(textParts) { return '' + this.lang['queryOpen'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandQueryClose: function(textParts) { return '' + this.lang['queryClose'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandIgnoreAdded: function(textParts) { return '' + this.lang['ignoreAdded'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandIgnoreRemoved: function(textParts) { return '' + this.lang['ignoreRemoved'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandIgnoreList: function(textParts) { return '' + this.lang['ignoreList'] + ' ' + this.getInlineUserMenu(textParts.slice(1)) - + ''; + + ''; }, - + replaceCommandIgnoreListEmpty: function(textParts) { return '' + this.lang['ignoreListEmpty'] - + ''; + + ''; }, - + replaceCommandKick: function(textParts) { return '' + this.lang['logoutKicked'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandWho: function(textParts) { return '' + this.lang['who'] + ' ' + this.getInlineUserMenu(textParts.slice(1)) - + ''; + + ''; }, replaceCommandWhoChannel: function(textParts) { return '' + this.lang['whoChannel'].replace(/%s/, textParts[1]) + ' ' + this.getInlineUserMenu(textParts.slice(2)) - + ''; + + ''; }, - + replaceCommandWhoEmpty: function(textParts) { return '' + this.lang['whoEmpty'] - + ''; + + ''; }, - + replaceCommandList: function(textParts) { var channels = textParts.slice(1); var listChannels = []; @@ -2352,9 +2391,9 @@ var ajaxChat = { return '' + this.lang['list'] + ' ' + listChannels.join(', ') - + ''; + + ''; }, - + replaceCommandBans: function(textParts) { var users = textParts.slice(1); var listUsers = []; @@ -2372,26 +2411,26 @@ var ajaxChat = { return '' + this.lang['bans'] + ' ' + listUsers.join(', ') - + ''; + + ''; }, - + replaceCommandBansEmpty: function(textParts) { return '' + this.lang['bansEmpty'] - + ''; + + ''; }, - + replaceCommandUnban: function(textParts) { return '' + this.lang['unban'].replace(/%s/, textParts[1]) - + ''; + + ''; }, - + replaceCommandWhois: function(textParts) { return '' + this.lang['whois'].replace(/%s/, textParts[1]) + ' ' + textParts[2] - + ''; + + ''; }, replaceCommandWhereis: function(textParts) { @@ -2406,24 +2445,24 @@ var ajaxChat = { + textParts[2] + '' ) - + ''; + + ''; }, - + replaceCommandRoll: function(textParts) { var rollText = this.lang['roll'].replace(/%s/, textParts[1]); rollText = rollText.replace(/%s/, textParts[2]); rollText = rollText.replace(/%s/, textParts[3]); return '' + rollText - + ''; + + ''; }, - + replaceCommandNick: function(textParts) { return '' + this.lang['nick'].replace(/%s/, textParts[1]).replace(/%s/, textParts[2]) - + ''; + + ''; }, - + replaceCommandError: function(textParts) { var errorMessage = this.lang['error'+textParts[1]]; if(!errorMessage) { @@ -2433,7 +2472,7 @@ var ajaxChat = { } return '' + errorMessage - + ''; + + ''; }, getInlineUserMenu: function(users) { @@ -2466,7 +2505,7 @@ var ajaxChat = { var openTags, closeTags, regExpOpenTags = /<[^>\/]+?>/gm, regExpCloseTags = /<\/[^>]+?>/gm; - + openTags = str.match(regExpOpenTags); closeTags = str.match(regExpCloseTags); // Return true if the number of tags doesn't match: @@ -2477,32 +2516,32 @@ var ajaxChat = { } return false; }, - + breakLongWords: function(text) { var newText, charCounter, currentChar, withinTag, withinEntity, i; - + if(!this.settings['wordWrap']) return text; - + newText = ''; charCounter = 0; - + for(i=0; i): if(i>5 && text.substr(i-5,4) === '
0 && text.charAt(i-1) === '>') { withinTag = false; // Reset the charCounter after newline tags (
): if(i>4 && text.substr(i-5,4) === '
0 && text.charAt(i-1) === ';') { @@ -2510,7 +2549,7 @@ var ajaxChat = { // We only increase the charCounter once for the whole entiy: charCounter++; } - + if(!withinTag && !withinEntity) { // Reset the charCounter if we encounter a word boundary: if(currentChar === ' ' || currentChar === '\n' || currentChar === '\t') { @@ -2524,14 +2563,14 @@ var ajaxChat = { newText += '​'; charCounter = 0; } - } + } // Add the current char to the text: newText += currentChar; } - + return newText; }, - + replaceBBCode: function(text) { if(!this.settings['bbCode']) { // If BBCode is disabled, just strip the text from BBCode tags: @@ -2539,11 +2578,11 @@ var ajaxChat = { } // Remove the BBCode tags: return text.replace( - /\[(\w+)(?:=([^<>]*?))?\](.+?)\[\/\1\]/gm, + /\[(\w+)(?:=([^<>]*?))?\](.+?)\[\/\1\]/gm, this.replaceBBCodeCallback ); }, - + replaceBBCodeCallback: function(str, p1, p2, p3) { // Only replace predefined BBCode tags: if(!ajaxChat.inArray(ajaxChat.bbCodeTags, p1)) { @@ -2552,7 +2591,7 @@ var ajaxChat = { // Avoid invalid XHTML (unclosed tags): if(ajaxChat.containsUnclosedTags(p3)) { return str; - } + } switch(p1) { case 'color': return ajaxChat.replaceBBCodeColor(p3, p2); @@ -2575,7 +2614,7 @@ var ajaxChat = { if(this.settings['bbCodeColors']) { // Only allow predefined color codes: if(!attribute || !this.inArray(ajaxChat.colorCodes, attribute)) - return content; + return content; return '' + this.replaceBBCode(content) @@ -2583,7 +2622,7 @@ var ajaxChat = { } return content; }, - + replaceBBCodeUrl: function(content, attribute) { var url, regExpUrl; if(attribute) @@ -2602,7 +2641,7 @@ var ajaxChat = { + this.replaceBBCode(content) + ''; }, - + replaceBBCodeImage: function(url) { var regExpUrl, maxWidth, maxHeight; if(this.settings['bbCodeImages']) { @@ -2647,13 +2686,13 @@ var ajaxChat = { + this.replaceBBCode(content.replace(/\t|(?: )/gm, '  ')) + ''; }, - + replaceBBCodeUnderline: function(content) { return '' + this.replaceBBCode(content) + ''; }, - + replaceHyperLinks: function(text) { var regExp; if(!this.settings['hyperLinks']) { @@ -2706,11 +2745,11 @@ var ajaxChat = { arguments.callee.regExp = new RegExp(regExpStr, 'gm'); } return text.replace( - arguments.callee.regExp, + arguments.callee.regExp, this.replaceEmoticonsCallback ); }, - + replaceEmoticonsCallback: function(str, p1, p2, p3) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('(="[^"]*$)|(&[^;]*$)', ''); @@ -2718,9 +2757,9 @@ var ajaxChat = { // Avoid replacing emoticons in tag attributes or XHTML entities: if(p1.match(arguments.callee.regExp)) { return str; - } + } if(p2) { - var index = ajaxChat.arraySearch(p2, ajaxChat.emoticonCodes); + var index = ajaxChat.arraySearch(p2, ajaxChat.emoticonCodes); return ajaxChat.replaceEmoticons(p1) + ' +

[LANG]title[/LANG]

- + -
+
@@ -391,4 +391,4 @@

[LANG]settings[/LANG]

- + \ No newline at end of file diff --git a/chat/lib/template/logs.html b/chat/lib/template/logs.html index 073ae2b..492aef2 100644 --- a/chat/lib/template/logs.html +++ b/chat/lib/template/logs.html @@ -24,13 +24,13 @@ -
+

[LANG]logsTitle[/LANG]

@@ -133,7 +132,8 @@

[LANG]logsTitle[/LANG]

-
+
+
@@ -148,10 +148,10 @@

[LANG]logsTitle[/LANG]

- -