/* * @package AJAX_Chat * @author Sebastian Tschan * @copyright (c) Sebastian Tschan * @license GNU Affero General Public 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/ * * Modified for Flashii Chat */ // AJAX Chat client side logic: var ajaxChat = { settingsInitiated: null, styleInitiated: null, initializeFunction: null, finalizeFunction: null, loginChannelID: null, loginChannelName: null, timerRate: null, timer: null, ajaxURL: null, baseURL: null, regExpMediaUrl: null, dirs: null, startChatOnLoad: null, chatStarted: null, domIDs: null, dom: null, settings: null, nonPersistentSettings: null, unusedSettings: null, bbCodeTags: null, colorCodes: null, emoticonCodes: null, emoticonFiles: null, soundFiles: null, sounds: null, soundTransform: null, sessionName: null, cookieExpiration: null, cookiePath: null, cookieDomain: null, cookieSecure: null, chatBotName: null, chatBotID: null, allowUserMessageDelete: null, inactiveTimeout: null, privateChannelDiff: null, privateMessageDiff: null, showChannelMessages: null, messageTextMaxLength: null, socketServerEnabled: null, socketServerHost: null, socketServerPort: null, socketServerChatID: null, socket: null, socketIsConnected: null, socketTimerRate: null, socketReconnectTimer: null, socketRegistrationID: null, userID: null, userName: null, userRole: null, channelID: null, channelName: null, channelSwitch: null, usersList: null, userNamesList: null, userMenuCounter: null, encodedUserName: null, userNodeString: null, ignoredUserNames: null, lastID: null, localID: null, lang: null, langCode: null, baseDirection: null, originalDocumentTitle: null, blinkInterval: null, httpRequest: null, retryTimer:null, retryTimerDelay:null, DOMbuffering: null, DOMbuffer: null, DOMbufferRowClass: 'rowOdd', imageID: 0, init: function(config, lang, initSettings, initStyle, initialize, initializeFunction, finalizeFunction) { this.httpRequest = new Object(); this.usersList = new Array(); this.userNamesList = new Array(); this.userMenuCounter = 0; this.lastID = 0; this.localID = 0; this.lang = lang; this.initConfig(config); this.initDirectories(); if(initSettings) { this.initSettings(); } if(initStyle) { this.initStyle(); } this.initializeFunction = initializeFunction; this.finalizeFunction = finalizeFunction; if(initialize) { this.setLoadHandler(); } }, initConfig: function(config) { this.loginChannelID = config['loginChannelID']; this.loginChannelName = config['loginChannelName']; this.timerRate = config['timerRate']; this.ajaxURL = config['ajaxURL']; this.baseURL = config['baseURL']; this.regExpMediaUrl = config['regExpMediaUrl']; this.startChatOnLoad = config['startChatOnLoad']; this.domIDs = config['domIDs']; this.settings = config['settings']; this.nonPersistentSettings = config['nonPersistentSettings']; this.bbCodeTags = config['bbCodeTags']; this.colorCodes = config['colorCodes']; this.emoticonCodes = config['emoticonCodes']; this.emoticonFiles = config['emoticonFiles']; this.soundFiles = config['soundFiles']; this.sessionName = config['sessionName']; this.cookieExpiration = config['cookieExpiration']; this.cookiePath = config['cookiePath']; this.cookieDomain = config['cookieDomain']; this.cookieSecure = config['cookieSecure']; this.chatBotName = config['chatBotName']; this.chatBotID = config['chatBotID']; this.allowUserMessageDelete = config['allowUserMessageDelete']; this.inactiveTimeout = config['inactiveTimeout']; this.privateChannelDiff = config['privateChannelDiff']; this.privateMessageDiff = config['privateMessageDiff']; this.showChannelMessages = config['showChannelMessages']; this.messageTextMaxLength = config['messageTextMaxLength']; this.socketServerEnabled = config['socketServerEnabled']; this.socketServerHost = config['socketServerHost']; this.socketServerPort = config['socketServerPort']; this.socketServerChatID = config['socketServerChatID']; this.DOMbuffering = false; this.DOMbuffer = ""; this.retryTimerDelay = this.timerRate + (((this.inactiveTimeout*6000) - this.timerRate)/4); }, initDirectories: function() { this.dirs = new Object(); //this.dirs['emoticons'] = 'http://cdn.flashii.net/img/emoticons/'; //this.dirs['sounds'] = 'http://cdn.flashii.net/snd/chat/'; //this.dirs['emoticons'] = 'https://static.flash.moe/emoticons/'; this.dirs['emoticons'] = ''; //this.dirs['sounds'] = 'sounds/'; this.dirs['sounds'] = ''; }, initSettings: function() { this.settingsInitiated = true; this.unusedSettings = new Object(); var cookie = this.readCookie(this.sessionName + '_settings'); if(cookie) { var settingsArray = cookie.split('&'); var setting,key,value,number; for(var i=0; i'
						+ this.emoticonCodes[i]
						+ ''; } if(this.dom['emoticonsContainer']) { this.updateDOM('emoticonsContainer', this.DOMbuffer); } this.DOMbuffer = ""; }, initColorCodes: function() { if(this.dom['colorCodesContainer']) { this.DOMbuffer = ""; for(var i=0; i' + "\r\n" } this.updateDOM('colorCodesContainer', this.DOMbuffer); this.DOMbuffer = ""; } }, setStatus: function(currentStatus) { //Make sure the status container div exists before changing its class. if (document.getElementById('statusIconContainer') != null ) { //currentStatus options are: Off for green, On for orange, and Alert for red. document.getElementById('statusIconContainer').className = 'statusContainer' + currentStatus; } }, startChatUpdate: function() { // Start the chat update and retrieve current user and channel info and set the login channel: var infos = 'userID,userName,userRole,channelID,channelName'; if(this.socketServerEnabled) { infos += ',socketRegistrationID'; } var params = '&getInfos=' + this.encodeText(infos); if(!isNaN(parseInt(this.loginChannelID))) { params += '&channelID='+this.loginChannelID; } else if(this.loginChannelName !== null) { params += '&channelName='+this.encodeText(this.loginChannelName); } this.updateChat(params); }, updateChat: function(paramString) { var requestUrl = this.ajaxURL + '&lastID=' + this.lastID; if(paramString) { requestUrl += paramString; } this.makeRequest(requestUrl,'GET',null); }, loadFlashInterface: function() { if(this.dom['flashInterfaceContainer']) { this.updateDOM( 'flashInterfaceContainer', '' +'' +'' +'' +'' ); FABridge.addInitializationCallback('ajaxChat', this.flashInterfaceLoadCompleteHandler); } }, flashInterfaceLoadCompleteHandler: function() { ajaxChat.initializeFlashInterface(); }, initializeFlashInterface: function() { if(this.socketServerEnabled) { this.socketTimerRate = (this.inactiveTimeout-1)*60*1000; this.socketConnect(); } this.loadSounds(); this.initializeCustomFlashInterface(); }, socketConnect: function() { if(!this.socketIsConnected) { try { if(!this.socket && FABridge.ajaxChat) { this.socket = FABridge.ajaxChat.create('flash.net.XMLSocket'); this.socket.addEventListener('connect', this.socketConnectHandler); this.socket.addEventListener('close', this.socketCloseHandler); this.socket.addEventListener('data', this.socketDataHandler); this.socket.addEventListener('ioError', this.socketIOErrorHandler); this.socket.addEventListener('securityError', this.socketSecurityErrorHandler); } this.socket.connect(this.socketServerHost, this.socketServerPort); } catch(e) { //alert(e); } } clearTimeout(this.socketReconnectTimer); this.socketReconnectTimer = null; }, socketConnectHandler: function(event) { ajaxChat.socketIsConnected = true; // setTimeout is needed to avoid calling the flash interface recursively: setTimeout('ajaxChat.socketRegister()', 0); }, socketCloseHandler: function(event) { ajaxChat.socketIsConnected = false; if(ajaxChat.socket) { clearTimeout(ajaxChat.timer); ajaxChat.updateChat(null); } }, socketDataHandler: function(event) { ajaxChat.socketUpdate(event.getData()); }, socketIOErrorHandler: function(event) { // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages): setTimeout('ajaxChat.addChatBotMessageToChatList(\'/error SocketIO\')', 0); setTimeout('ajaxChat.updateChatlistView()', 1); }, socketSecurityErrorHandler: function(event) { // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages): setTimeout('ajaxChat.addChatBotMessageToChatList(\'/error SocketSecurity\')', 0); setTimeout('ajaxChat.updateChatlistView()', 1); }, socketRegister: function() { if(this.socket && this.socketIsConnected) { try { this.socket.send( '' ); } catch(e) { //alert(e); } } }, loadXML: function(str) { if(!arguments.callee.parser) { try { // DOMParser native implementation (Mozilla, Opera): arguments.callee.parser = new DOMParser(); } catch(e) { var customDOMParser = function() {} if(navigator.appName == 'Microsoft Internet Explorer') { // IE implementation: customDOMParser.prototype.parseFromString = function(str, contentType) { if(!arguments.callee.XMLDOM) { arguments.callee.XMLDOM = new ActiveXObject('Microsoft.XMLDOM'); } arguments.callee.XMLDOM.loadXML(str); return arguments.callee.XMLDOM; } } else { // Safari, Konqueror: customDOMParser.prototype.parseFromString = function(str, contentType) { if(!arguments.callee.httpRequest) { arguments.callee.httpRequest = new XMLHttpRequest(); } arguments.callee.httpRequest.open( 'GET', 'data:text/xml;charset=utf-8,'+encodeURIComponent(str), false ); arguments.callee.httpRequest.send(null); return arguments.callee.httpRequest.responseXML; } } arguments.callee.parser = new customDOMParser(); } } return arguments.callee.parser.parseFromString(str, 'text/xml'); }, socketUpdate: function(data) { var xmlDoc = this.loadXML(data); if(xmlDoc) { this.handleOnlineUsers(xmlDoc.getElementsByTagName('user')); // If the root node has the attribute "mode" set to "1" it is a channel message: if((this.showChannelMessages || xmlDoc.firstChild.getAttribute('mode') != '1') && !this.channelSwitch) { var channelID = xmlDoc.firstChild.getAttribute('channelID'); if(channelID == this.channelID || parseInt(channelID) == parseInt(this.userID)+this.privateMessageDiff ) { this.handleChatMessages(xmlDoc.getElementsByTagName('message')); } } } }, setAudioVolume: function(volume) { volume = parseFloat(volume); if(!isNaN(volume)) { if(volume < 0) { volume = 0.0; } else if(volume > 1) { volume = 1.0; } this.settings['audioVolume'] = volume; try { if(!this.soundTransform) { this.soundTransform = FABridge.ajaxChat.create('flash.media.SoundTransform'); } this.soundTransform.setVolume(volume); } catch(e) { //alert(e); } } return ajaxChat.setHTML5SoundVolume(volume); }, loadSounds: function() { try { this.setAudioVolume(this.settings['audioVolume']); this.sounds = new Object(); var sound,urlRequest; for(var key in this.soundFiles) { sound = FABridge.ajaxChat.create('flash.media.Sound'); sound.addEventListener('complete', this.soundLoadCompleteHandler); sound.addEventListener('ioError', this.soundIOErrorHandler); urlRequest = FABridge.ajaxChat.create('flash.net.URLRequest'); urlRequest.setUrl(this.dirs['sounds']+this.soundFiles[key]); sound.load(urlRequest); } } catch(e) { alert(e); } }, soundLoadCompleteHandler: function(event) { var sound = event.getTarget(); for(var key in ajaxChat.soundFiles) { // Get the sound key by matching the sound URL with the sound filename: if((new RegExp(ajaxChat.soundFiles[key])).test(sound.getUrl())) { // Add the loaded sound to the sounds list: ajaxChat.sounds[key] = sound; } } }, soundIOErrorHandler: function(event) { // setTimeout is needed to avoid calling the flash interface recursively (e.g. sound on new messages): setTimeout('ajaxChat.addChatBotMessageToChatList(\'/error SoundIO\')', 0); setTimeout('ajaxChat.updateChatlistView()', 1); }, soundPlayCompleteHandler: function(event) { // soundChannel event 'soundComplete' }, playSound: function(soundID) { if(this.sounds && this.sounds[soundID]) { try { // play() parameters are // startTime:Number (default = 0), // loops:int (default = 0) and // sndTransform:SoundTransform (default = null) //return this.sounds[soundID].play(0, 0, this.soundTransform); return ajaxChat.playHTML5Sound(soundID,this.sounds[soundID]); } catch(e) { //alert(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) { case this.chatBotID: var messageParts = messageText.split(' ', 1); switch(messageParts[0]) { case '/login': case '/channelEnter': this.playSound(this.settings['soundEnter']); break; case '/logout': case '/channelLeave': case '/kick': this.playSound(this.settings['soundLeave']); break; case '/error': this.playSound(this.settings['soundError']); break; case '/unban': this.playSound(this.settings['soundKick']); break; default: this.playSound(this.settings['soundChatBot']); } break; case this.userID: this.playSound(this.settings['soundSend']); break; default: var messageParts = messageText.split(' ', 1); switch(messageParts[0]) { case '/privmsg': this.playSound(this.settings['soundPrivate']); break; default: this.playSound(this.settings['soundReceive']); } break; } } }, fillSoundSelection: function(selectionID, selectedSound) { var selection = document.getElementById(selectionID); // Skip the first, empty selection: var i = 1; for(var key in this.soundFiles) { selection.options[i] = new Option(key, key); if(key == selectedSound){ selection.options[i].selected = true; } i++; } }, getHttpRequest: function(identifier) { if(!this.httpRequest[identifier]) { if (window.XMLHttpRequest) { this.httpRequest[identifier] = new XMLHttpRequest(); if (this.httpRequest[identifier].overrideMimeType) { this.httpRequest[identifier].overrideMimeType('text/xml'); } } else if (window.ActiveXObject) { try { this.httpRequest[identifier] = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { this.httpRequest[identifier] = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { } } } } return this.httpRequest[identifier]; }, makeRequest: function(url, method, data) { ajaxChat.setStatus('On'); ajaxChat.retryTimer = setTimeout("ajaxChat.updateChat(null); ajaxChat.setStatus('Alert');", this.retryTimerDelay); try { var identifier; if(data) { // Create up to 50 HTTPRequest objects: if(!arguments.callee.identifier || arguments.callee.identifier > 50) { arguments.callee.identifier = 1; } else { arguments.callee.identifier++; } identifier = arguments.callee.identifier; } else { identifier = 0; } this.getHttpRequest(identifier).open(method, url, true); this.getHttpRequest(identifier).onreadystatechange = function() { try { ajaxChat.handleResponse(identifier); } catch(e) { try { clearTimeout(ajaxChat.timer); } catch(e) { //alert(e); } try { if(data) { ajaxChat.addChatBotMessageToChatList('/error ConnectionTimeout'); ajaxChat.setStatus('Alert'); ajaxChat.updateChatlistView(); } } catch(e) { //alert(e); } try { ajaxChat.timer = setTimeout('ajaxChat.updateChat(null);', ajaxChat.timerRate); } catch(e) { //alert(e); } } }; if(method == 'POST') { this.getHttpRequest(identifier).setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); } this.getHttpRequest(identifier).send(data); } catch(e) { clearTimeout(this.timer); if(data) { this.addChatBotMessageToChatList('/error ConnectionTimeout'); ajaxChat.setStatus('Alert'); this.updateChatlistView(); } this.timer = setTimeout('ajaxChat.updateChat(null);', this.timerRate); } }, handleResponse: function(identifier) { if (this.getHttpRequest(identifier).readyState == 4) { if (this.getHttpRequest(identifier).status == 200) { clearTimeout(ajaxChat.retryTimer); var xmlDoc = this.getHttpRequest(identifier).responseXML; ajaxChat.setStatus('Off'); } else { // Connection status 0 can be ignored. if (this.getHttpRequest(identifier).status == 0) { ajaxChat.setStatus('On'); this.updateChatlistView(); return false; } else { this.addChatBotMessageToChatList('/error ConnectionStatus '+this.getHttpRequest(identifier).status); ajaxChat.setStatus('Alert'); this.updateChatlistView(); return false; } } } if(!xmlDoc) { return false; } this.handleXML(xmlDoc); return true; }, handleXML: function(xmlDoc) { this.handleInfoMessages(xmlDoc.getElementsByTagName('info')); this.handleOnlineUsers(xmlDoc.getElementsByTagName('user')); this.handleChatMessages(xmlDoc.getElementsByTagName('message')); this.channelSwitch = null; this.setChatUpdateTimer(); }, setChatUpdateTimer: function() { clearTimeout(this.timer); if(this.chatStarted) { var timeout; if(this.socketIsConnected) { timeout = this.socketTimerRate; } else { timeout = this.timerRate; 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('ajaxChat.updateChat(null);', timeout); } }, handleInfoMessages: function(infoNodes) { var infoType, infoData; for(var i=0; i' + userName + '' + '
    '+this.getUserNodeStringItems(encodedUserName, userID, false) : ' style="display:none;">') + '
' +''; if(userID == this.userID) { this.userNodeString = str; } return str; } }, toggleUserMenu: function(menuID, userName, userID) { // If the menu is empty, fill it with user node menu items before toggling it. var isInline = false; if (menuID.indexOf('ium') >= 0 ) { isInline = true; } if(!document.getElementById(menuID).firstChild) { this.updateDOM( menuID, this.getUserNodeStringItems( this.encodeText(this.addSlashes(this.getScriptLinkValue(userName))), userID, isInline ), false, true ) } this.showHide(menuID); this.dom['chatList'].scrollTop = this.dom['chatList'].scrollHeight; }, getUserNodeStringItems: function(encodedUserName, userID, isInline) { var menu; if(encodedUserName != this.encodedUserName) { menu = '
  • ' + this.lang['userMenuViewProfile'] + '
  • ' + '
  • ' + this.lang['userMenuSendPrivateMessage'] + '
  • ' + '
  • ' + this.lang['userMenuDescribe'] + '
  • ' + '
  • ' + this.lang['userMenuOpenPrivateChannel'] + '
  • ' + '
  • ' + this.lang['userMenuClosePrivateChannel'] + '
  • ' + '
  • ' + this.lang['userMenuIgnore'] + '
  • '; if (isInline) { menu += '
  • ' + this.lang['userMenuInvite'] + '
  • ' + '
  • ' + this.lang['userMenuUninvite'] + '
  • ' + '
  • ' + this.lang['userMenuWhereis'] + '
  • '; } if(this.userRole == 2 || this.userRole == 3 || this.userRole == 6) { menu += '
  • ' + this.lang['userMenuKick'] + '
  • ' + '
  • ' + this.lang['userMenuWhois'] + '
  • '; } } else { menu = '
  • ' + this.lang['userMenuLogout'] + '
  • ' + '
  • ' + this.lang['userMenuWho'] + '
  • ' + '
  • ' + this.lang['userMenuIgnoreList'] + '
  • ' + '
  • ' + this.lang['userMenuList'] + '
  • ' + '
  • ' + this.lang['userMenuAction'] + '
  • ' + '
  • ' + this.lang['userMenuNick'] + '
  • '; if(this.userRole == 2 || this.userRole == 3 || this.userRole == 4 || this.userRole == 6 || this.userRole == 9) { menu += '
  • ' + this.lang['userMenuEnterPrivateRoom'] + '
  • ' + '
  • ' + this.lang['userMenuLogs'] + '
  • '; if(this.userRole == 2 || this.userRole == 3 || this.userRole == 6) { menu += '
  • ' + this.lang['userMenuBans'] + '
  • '; } } } menu += this.getCustomUserMenuItems(encodedUserName, userID); return menu; }, setOnlineListRowClasses: function() { if(this.dom['onlineList']) { var node = this.dom['onlineList'].firstChild; var rowEven = false; while(node) { this.setClass(node, (rowEven ? 'rowEven' : 'rowOdd')) node = node.nextSibling; rowEven = !rowEven; } } }, clearChatList: function() { while(this.dom['chatList'].hasChildNodes()) { this.dom['chatList'].removeChild(this.dom['chatList'].firstChild); } }, clearOnlineUsersList: function() { this.usersList = new Array(); this.userNamesList = new Array(); if(this.dom['onlineList']) { while(this.dom['onlineList'].hasChildNodes()) { this.dom['onlineList'].removeChild(this.dom['onlineList'].firstChild); } } }, getEncodedChatBotName: function() { if(typeof arguments.callee.encodedChatBotName == 'undefined') { arguments.callee.encodedChatBotName = this.encodeSpecialChars(this.chatBotName); } return arguments.callee.encodedChatBotName; }, addChatBotMessageToChatList: function(messageText) { this.addMessageToChatList( new Date(), this.chatBotID, this.getEncodedChatBotName(), 5, null, messageText, 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.getChatListMessageString( dateObject, userID, userName, userRole, messageID, messageText, channelID, ip ); if(!this.DOMbuffering){ this.updateDOM('chatList', this.DOMbuffer) this.DOMbuffer = ""; } }, getChatListMessageString: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { var rowClass = this.DOMbufferRowClass; var userClass = this.getRoleClass(userRole); var colon; if(messageText.indexOf('/action') == 0 || messageText.indexOf('/me') == 0 || messageText.indexOf('/privaction') == 0) { userClass += ' action'; colon = ' '; } else { colon = ': '; } var dateTime = this.settings['dateFormat'] ? '' + this.formatDate(this.settings['dateFormat'], dateObject) + ' ' : ''; return '
    ' + this.getDeletionLink(messageID, userID, userRole, channelID) + dateTime + '' + userName + '' + colon + this.replaceText(messageText) + '
    '; }, getChatListUserNameTitle: function(userID, userName, userRole, 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)); }, 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) { arguments.callee.deleteMessage = this.encodeSpecialChars(this.lang['deleteMessage']); } return ' ' // Adding a space - without any content Opera messes up the chatlist display } return ''; }, isAllowedToDeleteMessage: function(messageID, userID, userRole, channelID) { if((((this.userRole == 1 && this.allowUserMessageDelete && (userID == this.userID || parseInt(channelID) == parseInt(this.userID)+this.privateMessageDiff || parseInt(channelID) == parseInt(this.userID)+this.privateChannelDiff)) || this.userRole == 7 || this.userRole == 5 || this.userRole == 2) && userRole != 3 && userRole != 4) || this.userRole == 3) { return true; } 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; } if(this.ignoreMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip)) { return false; } if(this.parseDeleteMessageCommand(messageText)) { return false; } this.blinkOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip); this.playSoundOnNewMessage(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip); return true; }, parseDeleteMessageCommand: function(messageText) { if(messageText.indexOf('/delete') == 0) { var messageID = messageText.substr(8); var messageNode = this.getMessageNode(messageID); if(messageNode) { var nextSibling = messageNode.nextSibling; try { this.dom['chatList'].removeChild(messageNode); if(nextSibling) { this.updateChatListRowClasses(nextSibling); } } catch(e) { } } return true; } 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); this.blinkInterval = setInterval( 'ajaxChat.blinkUpdate(\''+this.addSlashes(this.decodeSpecialChars(userName))+'\')', this.settings['blinkInterval'] ); } }, blinkUpdate: function(blinkStr) { if(!this.originalDocumentTitle) { this.originalDocumentTitle = document.title; } if(!arguments.callee.blink) { document.title = '[@ ] '+blinkStr+' - '+this.originalDocumentTitle; arguments.callee.blink = 1; } else if(arguments.callee.blink > this.settings['blinkIntervalNumber']) { clearInterval(this.blinkInterval); document.title = this.originalDocumentTitle; arguments.callee.blink = 0; } else { if(arguments.callee.blink % 2 != 0) { document.title = '[@ ] '+blinkStr+' - '+this.originalDocumentTitle; } else { document.title = '[ @] '+blinkStr+' - '+this.originalDocumentTitle; } arguments.callee.blink++; } }, 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); }, decodeText: function(text) { return decodeURIComponent(text); }, utf8Encode: function(plainText) { var utf8Text = ''; for(var i=0; i127) && (c<2048)) { utf8Text += String.fromCharCode((c>>6)|192); utf8Text += String.fromCharCode((c&63)|128); } else { utf8Text += String.fromCharCode((c>>12)|224); utf8Text += String.fromCharCode(((c>>6)&63)|128); utf8Text += String.fromCharCode((c&63)|128); } } return utf8Text; }, utf8Decode: function(utf8Text) { var plainText = ''; var c,c2,c3; var i=0; while(i191) && (c<224)) { c2 = utf8Text.charCodeAt(i+1); plainText += String.fromCharCode(((c&31)<<6) | (c2&63)); i+=2; } else { c2 = utf8Text.charCodeAt(i+1); c3 = utf8Text.charCodeAt(i+2); plainText += String.fromCharCode(((c&15)<<12) | ((c2&63)<<6) | (c3&63)); i+=3; } } return plainText; }, encodeSpecialChars: function(text) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('[&<>\'"]', 'g'); } return text.replace( arguments.callee.regExp, this.encodeSpecialCharsCallback ); }, encodeSpecialCharsCallback: function(str) { switch(str) { case '&': return '&'; case '<': return '<'; case '>': return '>'; case '\'': // As ' is not supported by IE, we use ' as replacement for ('): return '''; case '"': return '"'; default: return str; } }, decodeSpecialChars: function(text) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('(&)|(<)|(>)|(')|(")', 'g'); } return text.replace( arguments.callee.regExp, this.decodeSpecialCharsCallback ); }, decodeSpecialCharsCallback: function(str) { switch(str) { case '&': return '&'; case '<': return '<'; case '>': return '>'; case ''': return '\''; case '"': return '"'; default: return str; } }, inArray: function(haystack, needle) { var i = haystack.length; while(i--) { if(haystack[i] === needle) { return true; } } return false; }, arraySearch: function(needle, haystack) { var i = haystack.length; while(i--) { if(haystack[i] === needle) { return i; } } return false; }, stripTags: function(str) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('<\\/?[^>]+?>', 'g'); } return str.replace(arguments.callee.regExp, ''); }, stripBBCodeTags: function(str) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('\\[\\/?[^\\]]+?\\]', 'g'); } return str.replace(arguments.callee.regExp, ''); }, escapeRegExp: function(text) { if (!arguments.callee.regExp) { var specials = new Array( '^', '$', '*', '+', '?', '.', '|', '/', '(', ')', '[', ']', '{', '}', '\\' ); arguments.callee.regExp = new RegExp( '(\\' + specials.join('|\\') + ')', 'g' ); } 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, '\\\''); }, removeSlashes: function(text) { // Removing slashes added by calling addSlashes(text) previously: return text.replace(/\\\\/g, '\\').replace(/\\\'/g, '\''); }, 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)) .replace(/%d/g, this.addLeadingZero(date.getDate())) .replace(/%H/g, this.addLeadingZero(date.getHours())) .replace(/%i/g, this.addLeadingZero(date.getMinutes())) .replace(/%s/g, this.addLeadingZero(date.getSeconds())); }, addLeadingZero: function(number) { number = number.toString(); if(number.length < 2) { number = '0'+number; } return number; }, getUserIDFromUserName: function(userName) { var index = this.arraySearch(userName, this.userNamesList); if(index !== false) { return this.usersList[index]; } return null; }, getUserNameFromUserID: function(userID) { var index = this.arraySearch(userID, this.usersList); if(index !== false) { return this.userNamesList[index]; } return null; }, getRoleClass: function(roleID) { switch(parseInt(roleID)) { case 0: return 'guest'; case 1: return 'user'; case 2: return 'moderator'; case 3: return 'admin'; case 4: return 'purple'; case 5: return 'chatBot'; case 6: return 'cmod'; case 7: return 'bots'; case 8: return 'dokuro'; case 9: return 'donator'; default: return 'default'; } }, handleInputFieldKeyPress: function(event) { if(event.keyCode == 13 && !event.shiftKey) { this.sendMessage(); try { event.preventDefault(); } catch(e) { event.returnValue = false; // IE } return false; } return true; }, handleInputFieldKeyUp: function(event) { this.updateMessageLengthCounter(); }, updateMessageLengthCounter: function() { if(this.dom['messageLengthCounter']) { this.updateDOM( 'messageLengthCounter', this.dom['inputField'].value.length + '/' + this.messageTextMaxLength, false, true ) } }, sendMessage: function(text) { text = text ? text : this.dom['inputField'].value; if(!text) { return; } text = this.parseInputMessage(text); if(text) { clearTimeout(this.timer); var message = 'lastID=' + this.lastID + '&text=' + this.encodeText(text); this.makeRequest(this.ajaxURL,'POST',message); } this.dom['inputField'].value = ''; this.dom['inputField'].focus(); this.updateMessageLengthCounter(); }, parseInputMessage: function(text) { if(text.charAt(0) == '/') { var textParts = text.split(' '); switch(textParts[0]) { case '/ignore': text = this.parseIgnoreInputCommand(text, textParts); break; default: text = this.parseCustomInputCommand(text, textParts); } if(text && this.settings['persistFontColor'] && this.settings['fontColor']) { text = this.assignFontColorToCommandMessage(text, textParts); } } else { text = this.parseCustomInputMessage(text); if(text && this.settings['persistFontColor'] && this.settings['fontColor']) { text = this.assignFontColorToMessage(text); } } return text; }, assignFontColorToMessage: function(text) { return '[color='+this.settings['fontColor']+']'+text+'[/color]'; }, assignFontColorToCommandMessage: function(text, textParts) { switch(textParts[0]) { case '/msg': case '/describe': if(textParts.length > 2) { return textParts[0]+' '+textParts[1]+' ' + '[color='+this.settings['fontColor']+']' + textParts.slice(2).join(' ') + '[/color]'; } break; case '/me': case '/action': if(textParts.length > 1) { return textParts[0]+' ' + '[color='+this.settings['fontColor']+']' + textParts.slice(1).join(' ') + '[/color]'; } break; } return text; }, parseIgnoreInputCommand: function(text, textParts) { var ignoredUserNames = this.getIgnoredUserNames(); if(textParts.length > 1) { var userName = this.encodeSpecialChars(textParts[1]); // Prevent adding the chatBot or current user to the list: if(userName == this.userName || userName == this.getEncodedChatBotName()) { // Display the list of ignored users instead: return this.parseIgnoreInputCommand(null, new Array('/ignore')); } if(ignoredUserNames.length > 0) { var i = ignoredUserNames.length; while(i--) { if(ignoredUserNames[i] === userName) { ignoredUserNames.splice(i,1); this.addChatBotMessageToChatList('/ignoreRemoved '+userName); this.setIgnoredUserNames(ignoredUserNames); this.updateChatlistView(); return null; } } } ignoredUserNames.push(userName); this.addChatBotMessageToChatList('/ignoreAdded '+userName); this.setIgnoredUserNames(ignoredUserNames); } else { if(ignoredUserNames.length == 0) { this.addChatBotMessageToChatList('/ignoreListEmpty -'); } else { this.addChatBotMessageToChatList('/ignoreList '+ignoredUserNames.join(' ')); } } this.updateChatlistView(); return null; }, parseSilentIgnoreInputCommand: function(text, textParts) { var ignoredUserNames = this.getIgnoredUserNames(); if(textParts.length > 1) { var userName = this.encodeSpecialChars(textParts[1]); // Prevent adding the chatBot or current user to the list: if(userName == this.userName || userName == this.getEncodedChatBotName()) { // Display the list of ignored users instead: return this.parseIgnoreInputCommand(null, new Array('/ignore')); } if(ignoredUserNames.length > 0) { var i = ignoredUserNames.length; while(i--) { if(ignoredUserNames[i] === userName) { this.updateChatlistView(); return null; } } } ignoredUserNames.push(userName); this.setIgnoredUserNames(ignoredUserNames); } this.updateChatlistView(); return null; }, getIgnoredUserNames: function() { if(!this.ignoredUserNames) { var ignoredUserNamesString = this.getSetting('ignoredUserNames'); if(ignoredUserNamesString) { this.ignoredUserNames = ignoredUserNamesString.split(' '); } else { this.ignoredUserNames = new Array(); } } return this.ignoredUserNames; }, setIgnoredUserNames: function(ignoredUserNames) { this.ignoredUserNames = ignoredUserNames; this.setSetting('ignoredUserNames', ignoredUserNames.join(' ')); }, ignoreMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { if(userID == this.chatBotID && messageText.charAt(0) == '/') { var textParts = messageText.split(' '); if(textParts.length > 1) { switch(textParts[0]) { case '/invite': case '/uninvite': case '/roll': userName = textParts[1]; break; } } } if(this.inArray(this.getIgnoredUserNames(), userName)) { return true; } return false; }, deleteMessage: function(messageID) { var messageNode = this.getMessageNode(messageID); if(messageNode) { var originalClass = this.getClass(messageNode); this.setClass(messageNode, originalClass+' deleteSelected'); if(confirm(this.lang['deleteMessageConfirm'])) { var nextSibling = messageNode.nextSibling; try { this.dom['chatList'].removeChild(messageNode); if(nextSibling) { this.updateChatListRowClasses(nextSibling); } this.updateChat('&delete='+messageID); } catch(e) { this.setClass(messageNode, originalClass); } } else { this.setClass(messageNode, originalClass); } } }, updateChatListRowClasses: function(node) { if(!node) { node = this.dom['chatList'].firstChild; } if(node) { var previousNode = node.previousSibling; var rowEven = (previousNode && this.getClass(previousNode) == 'rowOdd') ? true : false; while(node) { this.setClass(node, (rowEven ? 'rowEven' : 'rowOdd')) node = node.nextSibling; rowEven = !rowEven; } } }, getClass: function(node) { if(typeof node.className != 'undefined') { return node.className; // IE } else { return node.getAttribute('class'); } }, setClass: function(node, className) { if(typeof node.className != 'undefined') { node.className = className; // IE } else { node.setAttribute('class', className); } }, scriptLinkEncode: function(text) { return this.encodeText(this.addSlashes(this.decodeSpecialChars(text))); }, scriptLinkDecode: function(text) { return this.encodeSpecialChars(this.removeSlashes(this.decodeText(text))); }, getScriptLinkValue: function(value) { // This method returns plainText encoded values from javascript links // The value has to be utf8Decoded for MSIE and Opera: if(typeof arguments.callee.utf8Decode == 'undefined') { switch(navigator.appName) { case 'Microsoft Internet Explorer': case 'Opera': arguments.callee.utf8Decode = true; return this.utf8Decode(value); default: arguments.callee.utf8Decode = false; return value; } } else if(arguments.callee.utf8Decode) { return this.utf8Decode(value); } else { return value; } }, sendMessageWrapper: function(text) { this.sendMessage(this.getScriptLinkValue(text)); }, insertMessageWrapper: function(text) { this.insertText(this.getScriptLinkValue(text), true); }, switchChannel: function(channel) { if(!this.chatStarted) { this.clearChatList(); this.channelSwitch = true; this.loginChannelID = null; this.loginChannelName = channel; this.requestTeaserContent(); return; } clearTimeout(this.timer); var message = 'lastID=' + this.lastID + '&channelName=' + this.encodeText(channel); this.makeRequest(this.ajaxURL,'POST',message); if(this.dom['inputField'] && this.settings['autoFocus']) { this.dom['inputField'].focus(); } }, logout: function() { clearTimeout(this.timer); var message = 'logout=true'; this.makeRequest(this.ajaxURL,'POST',message); }, handleLogout: function(url) { window.location.href = url; }, toggleSetting: function(setting, buttonID) { this.setSetting(setting, !this.getSetting(setting)); if(buttonID) { this.updateButton(setting, buttonID); } }, updateButton: function(setting, buttonID) { var node = document.getElementById(buttonID); if(node) { this.setClass(node, (this.getSetting(setting) ? 'button' : 'button off')) } }, showHide: function(id, styleDisplay, displayInline) { var node = document.getElementById(id); if(node) { if(styleDisplay) { node.style.display = styleDisplay; } else { if(node.style.display == 'none') { node.style.display = (displayInline ? 'inline' : 'block'); } else { node.style.display = 'none'; } } } }, setPersistFontColor: function(bool) { this.settings['persistFontColor'] = bool; if(!this.settings['persistFontColor']) { this.settings['fontColor'] = null; if(this.dom['inputField']) { this.dom['inputField'].className = ''; } } }, setFontColor: function(color) { if(this.settings['persistFontColor']) { this.settings['fontColor'] = color; if(this.dom['inputField']) { this.dom['inputField'].className = color; } if(this.dom['colorCodesContainer']) { this.dom['colorCodesContainer'].style.display = 'none'; if(this.dom['inputField']) { this.dom['inputField'].focus(); } } } else { this.insert('[color=' + color + ']', '[/color]'); } }, insertText: function(text, clearInputField) { if(clearInputField) { this.dom['inputField'].value = ''; } this.insert(text, ''); }, insertBBCode: function(bbCode) { switch(bbCode) { case 'url': var url = prompt(this.lang['urlDialog'], 'http://'); if(url) this.insert('[url=' + url + ']', '[/url]'); else this.dom['inputField'].focus(); break; default: this.insert('[' + bbCode + ']', '[/' + bbCode + ']'); } }, insert: function(startTag, endTag) { this.dom['inputField'].focus(); // Internet Explorer: if(typeof document.selection != 'undefined') { // Insert the tags: var range = document.selection.createRange(); var insText = range.text; range.text = startTag + insText + endTag; // Adjust the cursor position: range = document.selection.createRange(); if (insText.length == 0) { range.move('character', -endTag.length); } else { range.moveStart('character', startTag.length + insText.length + endTag.length); } range.select(); } // Firefox, etc. (Gecko based browsers): else if(typeof this.dom['inputField'].selectionStart != 'undefined') { // Insert the tags: var start = this.dom['inputField'].selectionStart; var end = this.dom['inputField'].selectionEnd; var insText = this.dom['inputField'].value.substring(start, end); this.dom['inputField'].value = this.dom['inputField'].value.substr(0, start) + startTag + insText + endTag + this.dom['inputField'].value.substr(end); // Adjust the cursor position: var pos; if (insText.length == 0) { pos = start + startTag.length; } else { pos = start + startTag.length + insText.length + endTag.length; } this.dom['inputField'].selectionStart = pos; this.dom['inputField'].selectionEnd = pos; } // Other browsers: else { var pos = this.dom['inputField'].value.length; this.dom['inputField'].value = this.dom['inputField'].value.substr(0, pos) + startTag + endTag + this.dom['inputField'].value.substr(pos); } }, replaceText: function(text) { try{ text = this.replaceLineBreaks(text); if(text.charAt(0) == '/') { text = this.replaceCommands(text); } else { text = this.replaceBBCode(text); text = this.replaceHyperLinks(text); text = this.replaceEmoticons(text); } text = this.breakLongWords(text); text = this.replaceCustomText(text); } catch(e){ //alert(e); } return text; }, replaceCommands: function(text) { try { if(text.charAt(0) != '/') { return text; } var textParts = text.split(' '); switch(textParts[0]) { case '/login': return this.replaceCommandLogin(textParts); case '/logout': return this.replaceCommandLogout(textParts); case '/channelEnter': return this.replaceCommandChannelEnter(textParts); case '/channelLeave': return this.replaceCommandChannelLeave(textParts); case '/privmsg': return this.replaceCommandPrivMsg(textParts); case '/privmsgto': return this.replaceCommandPrivMsgTo(textParts); case '/privaction': return this.replaceCommandPrivAction(textParts); case '/privactionto': return this.replaceCommandPrivActionTo(textParts); case '/me': case '/action': return this.replaceCommandAction(textParts); case '/invite': return this.replaceCommandInvite(textParts); case '/inviteto': return this.replaceCommandInviteTo(textParts); case '/uninvite': return this.replaceCommandUninvite(textParts); case '/uninviteto': return this.replaceCommandUninviteTo(textParts); case '/queryOpen': return this.replaceCommandQueryOpen(textParts); case '/queryClose': return this.replaceCommandQueryClose(textParts); case '/ignoreAdded': return this.replaceCommandIgnoreAdded(textParts); case '/ignoreRemoved': return this.replaceCommandIgnoreRemoved(textParts); case '/ignoreList': return this.replaceCommandIgnoreList(textParts); case '/ignoreListEmpty': return this.replaceCommandIgnoreListEmpty(textParts); case '/kick': return this.replaceCommandKick(textParts); case '/who': return this.replaceCommandWho(textParts); case '/whoChannel': return this.replaceCommandWhoChannel(textParts); case '/whoEmpty': return this.replaceCommandWhoEmpty(textParts); case '/list': return this.replaceCommandList(textParts); case '/bans': return this.replaceCommandBans(textParts); case '/bansEmpty': return this.replaceCommandBansEmpty(textParts); case '/unban': return this.replaceCommandUnban(textParts); case '/whois': return this.replaceCommandWhois(textParts); case '/whereis': return this.replaceCommandWhereis(textParts); case '/roll': return this.replaceCommandRoll(textParts); case '/nick': return this.replaceCommandNick(textParts); case '/error': return this.replaceCommandError(textParts); default: return this.replaceCustomCommands(text, textParts); } } catch(e) { //alert(e); } return text; }, replaceCommandLogin: function(textParts) { return '' + this.lang['login'].replace(/%s/, textParts[1]) + ''; }, replaceCommandLogout: function(textParts) { var type = ''; if(textParts.length == 3) 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); privMsgText = this.replaceHyperLinks(privMsgText); privMsgText = this.replaceEmoticons(privMsgText); return '' + this.lang['privmsg'] + ' ' + privMsgText; }, replaceCommandPrivMsgTo: function(textParts) { var privMsgText = textParts.slice(2).join(' '); privMsgText = this.replaceBBCode(privMsgText); privMsgText = this.replaceHyperLinks(privMsgText); privMsgText = this.replaceEmoticons(privMsgText); return '' + this.lang['privmsgto'].replace(/%s/, textParts[1]) + ' ' + privMsgText; }, replaceCommandPrivAction: function(textParts) { var privActionText = textParts.slice(1).join(' '); privActionText = this.replaceBBCode(privActionText); privActionText = this.replaceHyperLinks(privActionText); privActionText = this.replaceEmoticons(privActionText); return '' + privActionText + ' ' + this.lang['privmsg'] + ' '; }, replaceCommandPrivActionTo: function(textParts) { var privActionText = textParts.slice(2).join(' '); privActionText = this.replaceBBCode(privActionText); privActionText = this.replaceHyperLinks(privActionText); privActionText = this.replaceEmoticons(privActionText); return '' + privActionText + ' ' + this.lang['privmsgto'].replace(/%s/, textParts[1]) + ' '; }, replaceCommandAction: function(textParts) { var actionText = textParts.slice(1).join(' '); actionText = this.replaceBBCode(actionText); actionText = this.replaceHyperLinks(actionText); actionText = this.replaceEmoticons(actionText); return '' + actionText + ''; }, replaceCommandInvite: function(textParts) { var inviteText = this.lang['invite'] .replace(/%s/, textParts[1]) .replace( /%s/, '' + textParts[2] + '' ); 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 = new Array(); var channelName; for(var i=0; i'+channels[i]+'' : channels[i]; listChannels.push( '' + channelName + '' ); } return '' + this.lang['list'] + ' ' + listChannels.join(', ') + ''; }, replaceCommandBans: function(textParts) { var users = textParts.slice(1); var listUsers = new Array(); for(var i=0; i' + users[i] + '' ); } 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) { return '' + this.lang['whereis'].replace(/%s/, textParts[1]).replace( /%s/, '' + 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) { errorMessage = 'Error: Unknown.'; } else if(textParts.length > 2) { errorMessage = errorMessage.replace(/%s/, textParts.slice(2).join(' ')); } return '' + errorMessage + ''; }, getInlineUserMenu: function(users) { var menu = ''; for(var i=0; i0) { menu += ', '; } menu += '' + ((users[i] == this.userName) ? ''+users[i]+'' : users[i]) + '' + ''; } this.userMenuCounter++; return menu; }, containsUnclosedTags: function(str) { if (!arguments.callee.regExpOpenTags || !arguments.callee.regExpCloseTags) { arguments.callee.regExpOpenTags = new RegExp('<[^>\\/]+?>', 'gm'); arguments.callee.regExpCloseTags = new RegExp('<\\/[^>]+?>', 'gm'); } var openTags = str.match(arguments.callee.regExpOpenTags); var closeTags = str.match(arguments.callee.regExpCloseTags); // Return true if the number of tags doesn't match: if((!openTags && closeTags) || (openTags && !closeTags) || (openTags && closeTags && (openTags.length != closeTags.length))) { return true; } return false; }, breakLongWords: function(text) { if(!this.settings['wordWrap']) return text; var newText = ''; var charCounter = 0; var currentChar, withinTag, withinEntity; for(var 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) == ';') { withinEntity = false; // 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') { charCounter = 0; } else { // We are not within a tag or entity, increase the charCounter: charCounter++; } if(charCounter > this.settings['maxWordLength']) { // maxWordLength has been reached, break here and reset the charCounter: newText += this.getBreakString(); charCounter = 0; } } // Add the current char to the text: newText += currentChar; } return newText; }, getBreakString: function() { // Returns the character sequence used to wrap long words if(typeof arguments.callee.breakString == 'undefined') { arguments.callee.breakString = '​'; } return arguments.callee.breakString; }, replaceBBCode: function(text) { if(!this.settings['bbCode']) { // If BBCode is disabled, just strip the text from BBCode tags: if (!arguments.callee.regExpStripBBCode) { arguments.callee.regExpStripBBCode = new RegExp( '\\[(?:\\/)?(\\w+)(?:=([^<>]*?))?\\]', 'gm' ); } return text.replace( arguments.callee.regExpStripBBCode, '' ); } // Remove the BBCode tags: if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp( '\\[(\\w+)(?:=([^<>]*?))?\\](.+?)\\[\\/\\1\\]', 'gm' ); } return text.replace( arguments.callee.regExp, this.replaceBBCodeCallback ); }, replaceBBCodeCallback: function(str, p1, p2, p3) { // Only replace predefined BBCode tags: if(!ajaxChat.inArray(ajaxChat.bbCodeTags, p1)) { return str; } // Avoid invalid XHTML (unclosed tags): if(ajaxChat.containsUnclosedTags(p3)) { return str; } switch(p1) { case 'color': return ajaxChat.replaceBBCodeColor(p3, p2); case 'url': return ajaxChat.replaceBBCodeUrl(p3, p2); case 'img': return ajaxChat.replaceBBCodeImage(p3); case 'quote': return ajaxChat.replaceBBCodeQuote(p3, p2); case 'code': return ajaxChat.replaceBBCodeCode(p3); case 'u': return ajaxChat.replaceBBCodeUnderline(p3); default: return ajaxChat.replaceCustomBBCode(p1, p2, p3); } }, replaceBBCodeColor: function(content, attribute) { if(this.settings['bbCodeColors']) { // Only allow predefined color codes: if(!attribute || !this.inArray(ajaxChat.colorCodes, attribute)) return content; return '' + this.replaceBBCode(content) + ''; } return content; }, replaceBBCodeUrl: function(content, attribute) { var url; if(attribute) url = attribute.replace(/\s/gm, this.encodeText(' ')); else url = this.stripBBCodeTags(content.replace(/\s/gm, this.encodeText(' '))); if (!arguments.callee.regExpUrl) { arguments.callee.regExpUrl = new RegExp( '^(?:(?:http)|(?:https)|(?:ftp)|(?:irc)):\\/\\/', '' ); } if(!url || !url.match(arguments.callee.regExpUrl)) return content; return '' + this.replaceBBCode(content) + ''; }, replaceBBCodeImage: function(url) { ++this.imageID; if(this.settings['bbCodeImages']) { if (!arguments.callee.regExpUrl) { arguments.callee.regExpUrl = new RegExp( this.regExpMediaUrl, '' ); } if(!url || !url.match(arguments.callee.regExpUrl)) return url; url = this.stripTags(url.replace(/\s/gm, this.encodeText(' '))); url = this.stripTags(url.replace(/\r/gm, this.encodeText(' '))); url = this.stripTags(url.replace(/\n/gm, this.encodeText(' '))); //return ''+''; return ''+url+' [Embed] '; } return url; }, parseEmbedImage: function(id,mode) { var image = document.getElementById('img'+id); var url = image.getAttribute('href'); var embed = document.getElementById('imge'+id); var maxWidth = this.dom['chatList'].offsetWidth-50; var maxHeight = this.dom['chatList'].offsetHeight-50; if(mode) { image.innerHTML = url; embed.innerHTML = 'Embed'; embed.setAttribute('onclick','ajaxChat.parseEmbedImage(\''+id+'\',0);'); } else { image.innerHTML = ''; embed.innerHTML = 'Remove'; embed.setAttribute('onclick','ajaxChat.parseEmbedImage(\''+id+'\',1);'); } }, replaceBBCodeQuote: function(content, attribute) { if(attribute) return '' + this.lang['cite'].replace(/%s/, attribute) + '' + this.replaceBBCode(content) + ''; return '' + this.replaceBBCode(content) + ''; }, replaceBBCodeCode: function(content) { // Replace vertical tabs and multiple spaces with two non-breaking space characters: return '' + this.replaceBBCode(content.replace(/\t|(?: )/gm, '  ')) + ''; }, replaceBBCodeUnderline: function(content) { return '' + this.replaceBBCode(content) + ''; }, replaceHyperLinks: function(text) { if(!this.settings['hyperLinks']) { return text; } if(!arguments.callee.regExp) { arguments.callee.regExp = new RegExp( '(^|\\s|>)((?:(?:http)|(?:https)|(?:ftp)|(?:irc)):\\/\\/[^\\s<>]+)(<\\/a>)?', 'gm' ); } return text.replace( arguments.callee.regExp, // Specifying an anonymous function as second parameter: function(str, p1, p2, p3) { // Do not replace URL's inside URL's: if(p3) { return str; } return p1 + '' + p2 + ''; } ); }, replaceLineBreaks: function(text) { if (!arguments.callee.regExp) { arguments.callee.regExp = new RegExp('\\n', 'g'); } if(!this.settings['lineBreaks']) { return text.replace(arguments.callee.regExp, ' '); } else { return text.replace(arguments.callee.regExp, '
    '); } }, replaceEmoticons: function(text) { if(!this.settings['emoticons']) { return text; } if(!arguments.callee.regExp) { var regExpStr = '^(.*)('; for(var i=0; i' + ajaxChat.replaceEmoticons(p3); } return str; }, getActiveStyle: function() { var cookie = this.readCookie(this.sessionName + '_style'); var style = cookie ? cookie : this.getPreferredStyleSheet(); return style; }, initStyle: function() { this.styleInitiated = true; this.setActiveStyleSheet(this.getActiveStyle()); }, persistStyle: function() { if(this.styleInitiated) { this.createCookie(this.sessionName + '_style', this.getActiveStyleSheet(), this.cookieExpiration); } }, setSelectedStyle: function() { if(this.dom['styleSelection']) { var style = this.getActiveStyle(); var styleOptions = this.dom['styleSelection'].getElementsByTagName('option'); for(var i=0; imenuItem ) // encodedUserName contains the userName ready to be used for javascript links // userID is only available for the online users menu - not for the inline user menu // use (encodedUserName == this.encodedUserName) to check for the current user getCustomUserMenuItems: function(encodedUserName, userID) { return ''; }, // Override to parse custom input messages: // Return replaced text // text contains the whole message parseCustomInputMessage: function(text) { return text; }, // Override to parse custom input commands: // Return parsed text // text contains the whole message, textParts the message split up as words array parseCustomInputCommand: function(text, textParts) { return text; }, // Override to replace custom text: // Return replaced text // text contains the whole message replaceCustomText: function(text) { return text; }, // Override to replace custom commands: // Return replaced text for custom commands // text contains the whole message, textParts the message split up as words array replaceCustomCommands: function(text, textParts) { return text; }, // Override to replace custom BBCodes: // Return replaced text and call replaceBBCode recursively for the content text // tag contains the BBCode tag, attribute the BBCode attribute and content the content text // This method is only called for BBCode tags which are in the bbCodeTags list replaceCustomBBCode: function(tag, attribute, content) { return '<' + tag + '>' + this.replaceBBCode(content) + ''; }, // Override to perform custom actions on new messages: // Return true if message is to be added to the chatList, else false customOnNewMessage: function(dateObject, userID, userName, userRole, messageID, messageText, channelID, ip) { return true; } }