3003 lines
No EOL
86 KiB
JavaScript
3003 lines
No EOL
86 KiB
JavaScript
/*
|
|
* @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['sounds'] = '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<settingsArray.length; i++) {
|
|
setting = settingsArray[i].split('=');
|
|
if(setting.length == 2) {
|
|
key = setting[0];
|
|
value = this.decodeText(setting[1]);
|
|
switch(value) {
|
|
case 'true':
|
|
value = true;
|
|
break;
|
|
case 'false':
|
|
value = false;
|
|
break;
|
|
case 'null':
|
|
value = null;
|
|
break;
|
|
default:
|
|
number = parseFloat(value);
|
|
if(!isNaN(number)) {
|
|
if(parseInt(number) == number) {
|
|
value = parseInt(number);
|
|
} else {
|
|
value = number;
|
|
}
|
|
}
|
|
}
|
|
if(this.inArray(this.nonPersistentSettings, key)) {
|
|
// The setting is not used, store it for the persistSettings method:
|
|
this.unusedSettings[key] = value;
|
|
} else {
|
|
this.settings[key] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
persistSettings: function() {
|
|
if(this.settingsInitiated) {
|
|
var settingsArray = new Array();
|
|
for(var property in this.settings) {
|
|
if(this.inArray(this.nonPersistentSettings, property)) {
|
|
if(this.unusedSettings && this.unusedSettings[property]) {
|
|
// Store the unusedSetting previously stored:
|
|
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);
|
|
}
|
|
},
|
|
|
|
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) {
|
|
if(property == key) {
|
|
return this.settings[key];
|
|
}
|
|
}
|
|
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:
|
|
if(this.dom['inputField']) {
|
|
this.dom['inputField'].className = this.settings['fontColor'];
|
|
}
|
|
}
|
|
},
|
|
|
|
initialize: function() {
|
|
this.setUnloadHandler();
|
|
this.initializeDocumentNodes();
|
|
this.loadPageAttributes();
|
|
this.initEmoticons();
|
|
this.initColorCodes();
|
|
this.initializeSettings();
|
|
this.setSelectedStyle();
|
|
this.customInitialize();
|
|
//preload the Alert icon (it can't display if there's no connection unless it's cached!)
|
|
this.setStatus('Alert');
|
|
if(typeof this.initializeFunction == 'function') {
|
|
this.initializeFunction();
|
|
}
|
|
if(!this.isCookieEnabled()) {
|
|
this.addChatBotMessageToChatList('/error CookiesRequired');
|
|
} else {
|
|
if(this.startChatOnLoad) {
|
|
this.startChat();
|
|
} else {
|
|
this.setStartChatHandler();
|
|
this.requestTeaserContent();
|
|
}
|
|
}
|
|
},
|
|
|
|
requestTeaserContent: function() {
|
|
var params = '&view=teaser';
|
|
params += '&getInfos=' + this.encodeText('userID,userName,userRole');
|
|
if(!isNaN(parseInt(this.loginChannelID))) {
|
|
params += '&channelID='+this.loginChannelID;
|
|
} else if(this.loginChannelName !== null) {
|
|
params += '&channelName='+this.encodeText(this.loginChannelName);
|
|
}
|
|
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']) {
|
|
this.dom['inputField'].focus();
|
|
}
|
|
this.loadHTML5Sounds();
|
|
this.startChatUpdate();
|
|
},
|
|
|
|
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';
|
|
},
|
|
|
|
setLoadHandler: function() {
|
|
// Make sure initialize() is called on page load:
|
|
var onload = window.onload;
|
|
if(typeof onload != 'function') {
|
|
window.onload = function() {
|
|
ajaxChat.initialize();
|
|
}
|
|
} else {
|
|
window.onload = function() {
|
|
onload();
|
|
ajaxChat.initialize();
|
|
}
|
|
}
|
|
},
|
|
|
|
setUnloadHandler: function() {
|
|
// Make sure finalize() is called on page unload:
|
|
var onunload = window.onunload;
|
|
if(typeof onunload != 'function') {
|
|
window.onunload = function() {
|
|
ajaxChat.finalize();
|
|
}
|
|
} else {
|
|
window.onunload = function() {
|
|
ajaxChat.finalize();
|
|
onunload();
|
|
}
|
|
}
|
|
},
|
|
|
|
updateDOM: function(id, str, prepend, overwrite) {
|
|
var domNode = this.dom[id] ? this.dom[id] : document.getElementById(id);
|
|
if(!domNode) {
|
|
return;
|
|
}
|
|
try {
|
|
// Test for validity before adding the string to the DOM:
|
|
domNode.cloneNode(false).innerHTML = str;
|
|
if(overwrite) {
|
|
domNode.innerHTML = str;
|
|
} else if(prepend) {
|
|
domNode.innerHTML = str + domNode.innerHTML;
|
|
} else {
|
|
domNode.innerHTML += str;
|
|
}
|
|
} catch(e) {
|
|
this.addChatBotMessageToChatList('/error DOMSyntax '+id);
|
|
this.updateChatlistView();
|
|
}
|
|
},
|
|
|
|
initializeDocumentNodes: function() {
|
|
this.dom = new Object();
|
|
for(var key in this.domIDs) {
|
|
this.dom[key] = document.getElementById(this.domIDs[key]);
|
|
}
|
|
},
|
|
|
|
initEmoticons: function() {
|
|
this.DOMbuffer = "";
|
|
for(var i=0; i<this.emoticonCodes.length; i++) {
|
|
// Replace specials characters in emoticon codes:
|
|
this.emoticonCodes[i] = this.encodeSpecialChars(this.emoticonCodes[i]);
|
|
this.DOMbuffer = this.DOMbuffer
|
|
+ '<a href="javascript:ajaxChat.insertText(\''
|
|
+ this.scriptLinkEncode(this.emoticonCodes[i])
|
|
+ '\');"><img src="'
|
|
+ this.dirs['emoticons']
|
|
+ this.emoticonFiles[i]
|
|
+ '" alt="'
|
|
+ this.emoticonCodes[i]
|
|
+ '" title="'
|
|
+ this.emoticonCodes[i]
|
|
+ '"/></a>';
|
|
}
|
|
if(this.dom['emoticonsContainer']) {
|
|
this.updateDOM('emoticonsContainer', this.DOMbuffer);
|
|
}
|
|
this.DOMbuffer = "";
|
|
},
|
|
|
|
initColorCodes: function() {
|
|
if(this.dom['colorCodesContainer']) {
|
|
this.DOMbuffer = "";
|
|
for(var i=0; i<this.colorCodes.length; i++) {
|
|
this.DOMbuffer = this.DOMbuffer
|
|
+ '<a class="'
|
|
+ this.colorCodes[i]
|
|
+ '" '
|
|
+ 'href="javascript:ajaxChat.setFontColor(\''
|
|
+ this.colorCodes[i]
|
|
+ '\');" title="'
|
|
+ this.colorCodes[i]
|
|
+ '"></a>'
|
|
+ "\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',
|
|
'<object id="ajaxChatFlashInterface" style="position:absolute; left:-100px;" '
|
|
+'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
|
|
+'codebase="'
|
|
+ window.location.protocol
|
|
+'//download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,0,0" '
|
|
+'height="1" width="1">'
|
|
+'<param name="flashvars" value="bridgeName=ajaxChat"/>'
|
|
+'<param name="src" value="FABridge.swf"/>'
|
|
+'<embed name="ajaxChatFlashInterface" pluginspage="'
|
|
+ window.location.protocol
|
|
+'//www.macromedia.com/go/getflashplayer" '
|
|
+'src="FABridge.swf" height="1" width="1" flashvars="bridgeName=ajaxChat"/>'
|
|
+'</object>'
|
|
);
|
|
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(
|
|
'<register chatID="'
|
|
+this.socketServerChatID
|
|
+'" userID="'
|
|
+this.userID
|
|
+'" regID="'
|
|
+this.socketRegistrationID
|
|
+'"/>'
|
|
);
|
|
} 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<infoNodes.length; i++) {
|
|
infoType = infoNodes[i].getAttribute('type');
|
|
infoData = infoNodes[i].firstChild ? infoNodes[i].firstChild.nodeValue : '';
|
|
this.handleInfoMessage(infoType, infoData);
|
|
}
|
|
},
|
|
|
|
handleInfoMessage: function(infoType, infoData) {
|
|
switch(infoType) {
|
|
case 'channelSwitch':
|
|
this.clearChatList();
|
|
this.clearOnlineUsersList();
|
|
this.setSelectedChannel(infoData);
|
|
this.channelName = infoData;
|
|
this.channelSwitch = true;
|
|
break;
|
|
case 'channelName':
|
|
this.setSelectedChannel(infoData);
|
|
this.channelName = infoData;
|
|
break;
|
|
case 'channelID':
|
|
this.channelID = infoData;
|
|
break;
|
|
case 'userID':
|
|
this.userID = infoData;
|
|
break;
|
|
case 'userName':
|
|
this.userName = infoData;
|
|
this.encodedUserName = this.scriptLinkEncode(this.userName);
|
|
this.userNodeString = null;
|
|
break;
|
|
case 'userRole':
|
|
this.userRole = infoData;
|
|
break;
|
|
case 'logout':
|
|
this.handleLogout(infoData);
|
|
return;
|
|
case 'socketRegistrationID':
|
|
this.socketRegistrationID = infoData;
|
|
this.socketRegister();
|
|
default:
|
|
this.handleCustomInfoMessage(infoType, infoData);
|
|
}
|
|
},
|
|
|
|
handleOnlineUsers: function(userNodes) {
|
|
if(userNodes.length) {
|
|
var index,userID,userName,userRole;
|
|
var onlineUsers = new Array();
|
|
for(var i=0; i<userNodes.length; i++) {
|
|
userID = userNodes[i].getAttribute('userID');
|
|
userName = userNodes[i].firstChild ? userNodes[i].firstChild.nodeValue : '';
|
|
userRole = userNodes[i].getAttribute('userRole');
|
|
onlineUsers.push(userID);
|
|
index = this.arraySearch(userID, this.usersList);
|
|
if(index === false) {
|
|
this.addUserToOnlineList(
|
|
userID,
|
|
userName,
|
|
userRole
|
|
);
|
|
} else if(this.userNamesList[index] != userName) {
|
|
this.removeUserFromOnlineList(userID, index);
|
|
this.addUserToOnlineList(
|
|
userID,
|
|
userName,
|
|
userRole
|
|
);
|
|
}
|
|
}
|
|
// Clear the offline users from the online users list:
|
|
for(var i=0; i<this.usersList.length; i++) {
|
|
if(!this.inArray(onlineUsers, this.usersList[i])) {
|
|
this.removeUserFromOnlineList(this.usersList[i], i);
|
|
}
|
|
}
|
|
this.setOnlineListRowClasses();
|
|
}
|
|
},
|
|
|
|
handleChatMessages: function(messageNodes) {
|
|
if(messageNodes.length) {
|
|
var userNode,userName,textNode,messageText;
|
|
for(var i=0; i<messageNodes.length; i++) {
|
|
this.DOMbuffering = true;
|
|
userNode = messageNodes[i].getElementsByTagName('username')[0];
|
|
userName = userNode.firstChild ? userNode.firstChild.nodeValue : '';
|
|
textNode = messageNodes[i].getElementsByTagName('text')[0];
|
|
messageText = textNode.firstChild ? textNode.firstChild.nodeValue : '';
|
|
if (i == (messageNodes.length - 1)) {this.DOMbuffering = false;}
|
|
this.addMessageToChatList(
|
|
new Date(messageNodes[i].getAttribute('dateTime')),
|
|
messageNodes[i].getAttribute('userID'),
|
|
userName,
|
|
messageNodes[i].getAttribute('userRole'),
|
|
messageNodes[i].getAttribute('id'),
|
|
messageText,
|
|
messageNodes[i].getAttribute('channelID'),
|
|
messageNodes[i].getAttribute('ip')
|
|
);
|
|
}
|
|
this.DOMbuffering = false;
|
|
this.updateChatlistView();
|
|
this.lastID = messageNodes[messageNodes.length-1].getAttribute('id');
|
|
}
|
|
},
|
|
|
|
setSelectedChannel: function(channel) {
|
|
if(this.dom['channelSelection']) {
|
|
// Replace the entities in the channel name with their character equivalent:
|
|
channel = this.decodeSpecialChars(channel);
|
|
var channelSelected = false;
|
|
for(var i=0; i<this.dom['channelSelection'].options.length; i++) {
|
|
if(this.dom['channelSelection'].options[i].value == channel) {
|
|
this.dom['channelSelection'].options[i].selected = true;
|
|
channelSelected = true;
|
|
break;
|
|
}
|
|
}
|
|
// The given channel is not in the list, add it:
|
|
if(!channelSelected) {
|
|
var option = document.createElement('option');
|
|
var text = document.createTextNode(channel);
|
|
option.appendChild(text);
|
|
option.setAttribute('value', channel);
|
|
option.setAttribute('selected', 'selected');
|
|
this.dom['channelSelection'].appendChild(option);
|
|
}
|
|
}
|
|
},
|
|
|
|
removeUserFromOnlineList: function(userID, index) {
|
|
this.usersList.splice(index, 1);
|
|
this.userNamesList.splice(index, 1);
|
|
if(this.dom['onlineList']) {
|
|
this.dom['onlineList'].removeChild(this.getUserNode(userID));
|
|
}
|
|
},
|
|
|
|
addUserToOnlineList: function(userID, userName, userRole) {
|
|
this.usersList.push(userID);
|
|
this.userNamesList.push(userName);
|
|
if(this.dom['onlineList']) {
|
|
this.updateDOM(
|
|
'onlineList',
|
|
this.getUserNodeString(userID, userName, userRole),
|
|
(this.userID == userID)
|
|
);
|
|
}
|
|
},
|
|
|
|
getUserNodeString: function(userID, userName, userRole) {
|
|
if(this.userNodeString && userID == this.userID) {
|
|
return this.userNodeString;
|
|
} else {
|
|
var encodedUserName = this.scriptLinkEncode(userName);
|
|
var str = '<div id="'
|
|
+ this.getUserDocumentID(userID)
|
|
+ '"><a href="javascript:ajaxChat.toggleUserMenu(\''
|
|
+ this.getUserMenuDocumentID(userID)
|
|
+ '\', \''
|
|
+ encodedUserName
|
|
+ '\', '
|
|
+ userID
|
|
+ ');" class="'
|
|
+ this.getRoleClass(userRole)
|
|
+ '" title="'
|
|
+ this.lang['toggleUserMenu'].replace(/%s/, userName)
|
|
+ '">'
|
|
+ userName
|
|
+ '</a>'
|
|
+ '<ul class="userMenu" id="'
|
|
+ this.getUserMenuDocumentID(userID)
|
|
+ '"'
|
|
+ ((userID == this.userID) ?
|
|
'>'+this.getUserNodeStringItems(encodedUserName, userID, false) :
|
|
' style="display:none;">')
|
|
+ '</ul>'
|
|
+'</div>';
|
|
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 = '<li><a href="https://flashii.net/profile.php?u='
|
|
+ userID
|
|
+ '" target="_blank">'
|
|
+ this.lang['userMenuViewProfile']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/msg '
|
|
+ encodedUserName
|
|
+ ' \');">'
|
|
+ this.lang['userMenuSendPrivateMessage']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/describe '
|
|
+ encodedUserName
|
|
+ ' \');">'
|
|
+ this.lang['userMenuDescribe']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/query '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuOpenPrivateChannel']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/query\');">'
|
|
+ this.lang['userMenuClosePrivateChannel']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/ignore '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuIgnore']
|
|
+ '</a></li>';
|
|
if (isInline) {
|
|
menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/invite '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuInvite']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/uninvite '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuUninvite']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/whereis '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuWhereis']
|
|
+ '</a></li>';
|
|
}
|
|
if(this.userRole == 2 || this.userRole == 3 || this.userRole == 6) {
|
|
menu += '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/kick '
|
|
+ encodedUserName
|
|
+ ' \');">'
|
|
+ this.lang['userMenuKick']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/whois '
|
|
+ encodedUserName
|
|
+ '\');">'
|
|
+ this.lang['userMenuWhois']
|
|
+ '</a></li>';
|
|
}
|
|
} else {
|
|
menu = '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/quit\');">'
|
|
+ this.lang['userMenuLogout']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/who\');">'
|
|
+ this.lang['userMenuWho']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/ignore\');">'
|
|
+ this.lang['userMenuIgnoreList']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/list\');">'
|
|
+ this.lang['userMenuList']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/action \');">'
|
|
+ this.lang['userMenuAction']
|
|
+ '</a></li>'
|
|
+ '<li><a href="javascript:ajaxChat.insertMessageWrapper(\'/nick \');">'
|
|
+ this.lang['userMenuNick']
|
|
+ '</a></li>';
|
|
if(this.userRole == 2 || this.userRole == 3 || this.userRole == 4 || this.userRole == 6 || this.userRole == 9) {
|
|
menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/join\');">'
|
|
+ this.lang['userMenuEnterPrivateRoom']
|
|
+ '</a></li>'
|
|
+ '<li><a href="?view=logs">'
|
|
+ this.lang['userMenuLogs']
|
|
+ '</a></li>';
|
|
if(this.userRole == 2 || this.userRole == 3 || this.userRole == 6) {
|
|
menu += '<li><a href="javascript:ajaxChat.sendMessageWrapper(\'/bans\');">'
|
|
+ this.lang['userMenuBans']
|
|
+ '</a></li>';
|
|
}
|
|
}
|
|
}
|
|
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'] ? '<span class="dateTime">'
|
|
+ this.formatDate(this.settings['dateFormat'], dateObject) + '</span> ' : '';
|
|
return '<div id="'
|
|
+ this.getMessageDocumentID(messageID)
|
|
+ '" class="'
|
|
+ rowClass
|
|
+ '">'
|
|
+ this.getDeletionLink(messageID, userID, userRole, channelID)
|
|
+ dateTime
|
|
+ '<span class="'
|
|
+ userClass
|
|
+ '"'
|
|
+ this.getChatListUserNameTitle(userID, userName, userRole, ip)
|
|
+ ' dir="'
|
|
+ this.baseDirection
|
|
+ '" onclick="ajaxChat.insertText(this.firstChild.nodeValue);">'
|
|
+ userName
|
|
+ '</span>'
|
|
+ colon
|
|
+ this.replaceText(messageText)
|
|
+ '</div>';
|
|
},
|
|
|
|
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 '<a class="delete" title="'
|
|
+ arguments.callee.deleteMessage
|
|
+ '" href="javascript:ajaxChat.deleteMessage('
|
|
+ messageID
|
|
+ ');"> </a>' // 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; i<plainText.length; i++) {
|
|
var c=plainText.charCodeAt(i);
|
|
if(c<128) {
|
|
utf8Text += String.fromCharCode(c);
|
|
} else if((c>127) && (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(i<utf8Text.length) {
|
|
c = utf8Text.charCodeAt(i);
|
|
if(c<128) {
|
|
plainText += String.fromCharCode(c);
|
|
i++;
|
|
} else if((c>191) && (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 '<span class="chatBotMessage">'
|
|
+ this.lang['login'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandLogout: function(textParts) {
|
|
var type = '';
|
|
if(textParts.length == 3)
|
|
type = textParts[2];
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['logout' + type].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandChannelEnter: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['channelEnter'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandChannelLeave: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['channelLeave'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandPrivMsg: function(textParts) {
|
|
var privMsgText = textParts.slice(1).join(' ');
|
|
privMsgText = this.replaceBBCode(privMsgText);
|
|
privMsgText = this.replaceHyperLinks(privMsgText);
|
|
privMsgText = this.replaceEmoticons(privMsgText);
|
|
return '<span class="privmsg">'
|
|
+ this.lang['privmsg']
|
|
+ '</span> '
|
|
+ privMsgText;
|
|
},
|
|
|
|
replaceCommandPrivMsgTo: function(textParts) {
|
|
var privMsgText = textParts.slice(2).join(' ');
|
|
privMsgText = this.replaceBBCode(privMsgText);
|
|
privMsgText = this.replaceHyperLinks(privMsgText);
|
|
privMsgText = this.replaceEmoticons(privMsgText);
|
|
return '<span class="privmsg">'
|
|
+ this.lang['privmsgto'].replace(/%s/, textParts[1])
|
|
+ '</span> '
|
|
+ privMsgText;
|
|
},
|
|
|
|
replaceCommandPrivAction: function(textParts) {
|
|
var privActionText = textParts.slice(1).join(' ');
|
|
privActionText = this.replaceBBCode(privActionText);
|
|
privActionText = this.replaceHyperLinks(privActionText);
|
|
privActionText = this.replaceEmoticons(privActionText);
|
|
return '<span class="action">'
|
|
+ privActionText
|
|
+ '</span> <span class="privmsg">'
|
|
+ this.lang['privmsg']
|
|
+ '</span> ';
|
|
},
|
|
|
|
replaceCommandPrivActionTo: function(textParts) {
|
|
var privActionText = textParts.slice(2).join(' ');
|
|
privActionText = this.replaceBBCode(privActionText);
|
|
privActionText = this.replaceHyperLinks(privActionText);
|
|
privActionText = this.replaceEmoticons(privActionText);
|
|
return '<span class="action">'
|
|
+ privActionText
|
|
+ '</span> <span class="privmsg">'
|
|
+ this.lang['privmsgto'].replace(/%s/, textParts[1])
|
|
+ '</span> ';
|
|
},
|
|
|
|
replaceCommandAction: function(textParts) {
|
|
var actionText = textParts.slice(1).join(' ');
|
|
actionText = this.replaceBBCode(actionText);
|
|
actionText = this.replaceHyperLinks(actionText);
|
|
actionText = this.replaceEmoticons(actionText);
|
|
return '<span class="action">'
|
|
+ actionText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandInvite: function(textParts) {
|
|
var inviteText = this.lang['invite']
|
|
.replace(/%s/, textParts[1])
|
|
.replace(
|
|
/%s/,
|
|
'<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
|
|
+ this.scriptLinkEncode(textParts[2])
|
|
+ '\');" title="'
|
|
+ this.lang['joinChannel'].replace(/%s/, textParts[2])
|
|
+ '">'
|
|
+ textParts[2]
|
|
+ '</a>'
|
|
);
|
|
return '<span class="chatBotMessage">'
|
|
+ inviteText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandInviteTo: function(textParts) {
|
|
var inviteText = this.lang['inviteto']
|
|
.replace(/%s/, textParts[1])
|
|
.replace(/%s/, textParts[2]);
|
|
return '<span class="chatBotMessage">'
|
|
+ inviteText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandUninvite: function(textParts) {
|
|
var uninviteText = this.lang['uninvite']
|
|
.replace(/%s/, textParts[1])
|
|
.replace(/%s/, textParts[2]);
|
|
return '<span class="chatBotMessage">'
|
|
+ uninviteText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandUninviteTo: function(textParts) {
|
|
var uninviteText = this.lang['uninviteto']
|
|
.replace(/%s/, textParts[1])
|
|
.replace(/%s/, textParts[2]);
|
|
return '<span class="chatBotMessage">'
|
|
+ uninviteText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandQueryOpen: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['queryOpen'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandQueryClose: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['queryClose'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandIgnoreAdded: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['ignoreAdded'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandIgnoreRemoved: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['ignoreRemoved'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandIgnoreList: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['ignoreList'] + ' '
|
|
+ this.getInlineUserMenu(textParts.slice(1))
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandIgnoreListEmpty: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['ignoreListEmpty']
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandKick: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['logoutKicked'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandWho: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['who'] + ' '
|
|
+ this.getInlineUserMenu(textParts.slice(1))
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandWhoChannel: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['whoChannel'].replace(/%s/, textParts[1]) + ' '
|
|
+ this.getInlineUserMenu(textParts.slice(2))
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandWhoEmpty: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['whoEmpty']
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandList: function(textParts) {
|
|
var channels = textParts.slice(1);
|
|
var listChannels = new Array();
|
|
var channelName;
|
|
for(var i=0; i<channels.length; i++) {
|
|
channelName = (channels[i] == this.channelName) ? '<b>'+channels[i]+'</b>' : channels[i];
|
|
listChannels.push(
|
|
'<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
|
|
+ this.scriptLinkEncode(channels[i])
|
|
+ '\');" title="'
|
|
+ this.lang['joinChannel'].replace(/%s/, channels[i])
|
|
+ '">'
|
|
+ channelName
|
|
+ '</a>'
|
|
);
|
|
}
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['list'] + ' '
|
|
+ listChannels.join(', ')
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandBans: function(textParts) {
|
|
var users = textParts.slice(1);
|
|
var listUsers = new Array();
|
|
for(var i=0; i<users.length; i++) {
|
|
listUsers.push(
|
|
'<a href="javascript:ajaxChat.sendMessageWrapper(\'/unban '
|
|
+ this.scriptLinkEncode(users[i])
|
|
+ '\');" title="'
|
|
+ this.lang['unbanUser'].replace(/%s/, users[i])
|
|
+ '">'
|
|
+ users[i]
|
|
+ '</a>'
|
|
);
|
|
}
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['bans'] + ' '
|
|
+ listUsers.join(', ')
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandBansEmpty: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['bansEmpty']
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandUnban: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['unban'].replace(/%s/, textParts[1])
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandWhois: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['whois'].replace(/%s/, textParts[1]) + ' <a target="_blank" href="https://flash.moe/whois/'
|
|
+ textParts[2]
|
|
+ '">'
|
|
+ textParts[2]
|
|
+ '</a></span>';
|
|
},
|
|
|
|
replaceCommandWhereis: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['whereis'].replace(/%s/, textParts[1]).replace(
|
|
/%s/,
|
|
'<a href="javascript:ajaxChat.sendMessageWrapper(\'/join '
|
|
+ this.scriptLinkEncode(textParts[2])
|
|
+ '\');" title="'
|
|
+ this.lang['joinChannel'].replace(/%s/, textParts[2])
|
|
+ '">'
|
|
+ textParts[2]
|
|
+ '</a>'
|
|
)
|
|
+ '</span>';
|
|
},
|
|
|
|
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 '<span class="chatBotMessage">'
|
|
+ rollText
|
|
+ '</span>';
|
|
},
|
|
|
|
replaceCommandNick: function(textParts) {
|
|
return '<span class="chatBotMessage">'
|
|
+ this.lang['nick'].replace(/%s/, textParts[1]).replace(/%s/, textParts[2])
|
|
+ '</span>';
|
|
},
|
|
|
|
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 '<span class="chatBotErrorMessage">'
|
|
+ errorMessage
|
|
+ '</span>';
|
|
},
|
|
|
|
getInlineUserMenu: function(users) {
|
|
var menu = '';
|
|
for(var i=0; i<users.length; i++) {
|
|
if(i>0) {
|
|
menu += ', ';
|
|
}
|
|
menu += '<a href="javascript:ajaxChat.toggleUserMenu(\''
|
|
+ this.getInlineUserMenuDocumentID(this.userMenuCounter, i)
|
|
+ '\', \''
|
|
+ this.scriptLinkEncode(users[i])
|
|
+ '\', null);" title="'
|
|
+ this.lang['toggleUserMenu'].replace(/%s/, users[i])
|
|
+ '" dir="'
|
|
+ this.baseDirection
|
|
+ '">'
|
|
+ ((users[i] == this.userName) ? '<b>'+users[i]+'</b>' : users[i])
|
|
+ '</a>'
|
|
+ '<ul class="inlineUserMenu" id="'
|
|
+ this.getInlineUserMenuDocumentID(this.userMenuCounter, i)
|
|
+ '" style="display:none;">'
|
|
+ '</ul>';
|
|
}
|
|
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<text.length; i++) {
|
|
currentChar = text.charAt(i);
|
|
|
|
// Check if we are within a tag or entity:
|
|
if(currentChar == '<') {
|
|
withinTag = true;
|
|
// Reset the charCounter after newline tags (<br/>):
|
|
if(i>5 && text.substr(i-5,4) == '<br/')
|
|
charCounter = 0;
|
|
} else if(withinTag && i>0 && text.charAt(i-1) == '>') {
|
|
withinTag = false;
|
|
// Reset the charCounter after newline tags (<br/>):
|
|
if(i>4 && text.substr(i-5,4) == '<br/')
|
|
charCounter = 0;
|
|
} else if(currentChar == '&') {
|
|
withinEntity = true;
|
|
} else if(withinEntity && i>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 '<span class="'
|
|
+ attribute + '">'
|
|
+ this.replaceBBCode(content)
|
|
+ '</span>';
|
|
}
|
|
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 '<a href="'
|
|
+ url
|
|
+ '" onclick="window.open(this.href); return false;">'
|
|
+ this.replaceBBCode(content)
|
|
+ '</a>';
|
|
},
|
|
|
|
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 '<a href="'+url+'" onclick="window.open(this.href); return false;">'+'<img class="bbCodeImage" style="max-width:'+maxWidth+'px; max-height:'+maxHeight+'px;" src="'+url+'" alt="" onload="ajaxChat.updateChatlistView();"/></a>';
|
|
return '<a href="'+url+'" onclick="window.open(this.href); return false;" id="img'+this.imageID+'">'+url+'</a> [<a href="javascript:;" id="imge'+this.imageID+'" onclick="ajaxChat.parseEmbedImage(\''+this.imageID+'\',0);">Embed</a>] ';
|
|
}
|
|
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 = '<img class="bbCodeImage" style="max-width:'+maxWidth+'px; max-height:'+maxHeight+'px;" src="'+url+'" alt="" onload="ajaxChat.updateChatlistView();"/>';
|
|
embed.innerHTML = 'Remove';
|
|
embed.setAttribute('onclick','ajaxChat.parseEmbedImage(\''+id+'\',1);');
|
|
}
|
|
},
|
|
|
|
replaceBBCodeQuote: function(content, attribute) {
|
|
if(attribute)
|
|
return '<span class="quote"><cite>'
|
|
+ this.lang['cite'].replace(/%s/, attribute)
|
|
+ '</cite><q>'
|
|
+ this.replaceBBCode(content)
|
|
+ '</q></span>';
|
|
return '<span class="quote"><q>'
|
|
+ this.replaceBBCode(content)
|
|
+ '</q></span>';
|
|
},
|
|
|
|
replaceBBCodeCode: function(content) {
|
|
// Replace vertical tabs and multiple spaces with two non-breaking space characters:
|
|
return '<code>'
|
|
+ this.replaceBBCode(content.replace(/\t|(?: )/gm, '  '))
|
|
+ '</code>';
|
|
},
|
|
|
|
replaceBBCodeUnderline: function(content) {
|
|
return '<span style="text-decoration:underline;">'
|
|
+ this.replaceBBCode(content)
|
|
+ '</span>';
|
|
},
|
|
|
|
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
|
|
+ '<a href="'
|
|
+ p2
|
|
+ '" onclick="window.open(this.href); return false;">'
|
|
+ p2
|
|
+ '</a>';
|
|
}
|
|
);
|
|
},
|
|
|
|
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, '<br/>');
|
|
}
|
|
},
|
|
|
|
replaceEmoticons: function(text) {
|
|
if(!this.settings['emoticons']) {
|
|
return text;
|
|
}
|
|
if(!arguments.callee.regExp) {
|
|
var regExpStr = '^(.*)(';
|
|
for(var i=0; i<this.emoticonCodes.length; i++) {
|
|
if(i!=0)
|
|
regExpStr += '|';
|
|
regExpStr += '(?:' + this.escapeRegExp(this.emoticonCodes[i]) + ')';
|
|
}
|
|
regExpStr += ')(.*)$';
|
|
arguments.callee.regExp = new RegExp(regExpStr, 'gm');
|
|
}
|
|
return text.replace(
|
|
arguments.callee.regExp,
|
|
this.replaceEmoticonsCallback
|
|
);
|
|
},
|
|
|
|
replaceEmoticonsCallback: function(str, p1, p2, p3) {
|
|
if (!arguments.callee.regExp) {
|
|
arguments.callee.regExp = new RegExp('(="[^"]*$)|(&[^;]*$)', '');
|
|
}
|
|
// 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);
|
|
return ajaxChat.replaceEmoticons(p1)
|
|
+ '<img src="'
|
|
+ ajaxChat.dirs['emoticons']
|
|
+ ajaxChat.emoticonFiles[index]
|
|
+ '" alt="'
|
|
+ p2
|
|
+ '" />'
|
|
+ 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; i<styleOptions.length; i++) {
|
|
if(styleOptions[i].value == style) {
|
|
styleOptions[i].selected = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
getSelectedStyle: function() {
|
|
var styleOptions = this.dom['styleSelection'].getElementsByTagName('option');
|
|
if(this.dom['styleSelection'].selectedIndex == -1) {
|
|
return styleOptions[0].value;
|
|
} else {
|
|
return styleOptions[this.dom['styleSelection'].selectedIndex].value;
|
|
}
|
|
},
|
|
|
|
setActiveStyleSheet: function(title) {
|
|
var i, a, main;
|
|
var titleFound = false;
|
|
for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
|
|
if(a.getAttribute('rel').indexOf('style') != -1 && a.getAttribute('title')) {
|
|
a.disabled = true;
|
|
if(a.getAttribute('title') == title) {
|
|
a.disabled = false;
|
|
titleFound = true;
|
|
}
|
|
}
|
|
}
|
|
if(!titleFound && title != null) {
|
|
this.setActiveStyleSheet(this.getPreferredStyleSheet());
|
|
}
|
|
},
|
|
|
|
getActiveStyleSheet: function() {
|
|
var i, a;
|
|
for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
|
|
if(a.getAttribute('rel').indexOf('style') != -1 && a.getAttribute('title') && !a.disabled) {
|
|
return a.getAttribute('title');
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
getPreferredStyleSheet: function() {
|
|
var i,a;
|
|
for(i=0; (a = document.getElementsByTagName('link')[i]); i++) {
|
|
if(a.getAttribute('rel').indexOf('style') != -1
|
|
&& a.getAttribute('rel').indexOf('alt') == -1
|
|
&& a.getAttribute('title')
|
|
) {
|
|
return a.getAttribute('title');
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
switchLanguage: function(langCode) {
|
|
window.location.search = '?lang='+langCode;
|
|
},
|
|
|
|
createCookie: function(name,value,days) {
|
|
var expires = '';
|
|
if(days) {
|
|
var date = new Date();
|
|
date.setTime(date.getTime()+(days*24*60*60*1000));
|
|
expires = '; expires='+date.toGMTString();
|
|
}
|
|
var path = '; path='+this.cookiePath;
|
|
var domain = this.cookieDomain ? '; domain='+this.cookieDomain : '';
|
|
var secure = this.cookieSecure ? '; secure' : '';
|
|
document.cookie = name+'='+encodeURIComponent(value)+expires+path+domain+secure;
|
|
},
|
|
|
|
readCookie: function(name) {
|
|
if(!document.cookie)
|
|
return null;
|
|
var nameEQ = name + '=';
|
|
var ca = document.cookie.split(';');
|
|
for(var i=0; i<ca.length; i++) {
|
|
var c = ca[i];
|
|
while(c.charAt(0) == ' ') {
|
|
c = c.substring(1, c.length);
|
|
}
|
|
if(c.indexOf(nameEQ) == 0) {
|
|
return decodeURIComponent(c.substring(nameEQ.length, c.length));
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
isCookieEnabled: function() {
|
|
this.createCookie(this.sessionName + '_cookie_test', true, 1);
|
|
var cookie = this.readCookie(this.sessionName + '_cookie_test');
|
|
if(cookie) {
|
|
// Unset the test cookie:
|
|
this.createCookie(this.sessionName + '_cookie_test', true, -1);
|
|
// Cookie test successfull, return true:
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
finalize: function() {
|
|
if(typeof this.finalizeFunction == 'function') {
|
|
this.finalizeFunction();
|
|
}
|
|
// Ensure the socket connection is closed on unload:
|
|
if(this.socket) {
|
|
try {
|
|
this.socket.close();
|
|
this.socket = null;
|
|
} catch(e) {
|
|
//alert(e);
|
|
}
|
|
}
|
|
this.persistSettings();
|
|
this.persistStyle();
|
|
this.customFinalize();
|
|
},
|
|
|
|
// Override to perform custom actions on flash initialization:
|
|
initializeCustomFlashInterface: function() {
|
|
},
|
|
|
|
// Override to handle custom info messages
|
|
handleCustomInfoMessage: function(infoType, infoData) {
|
|
},
|
|
|
|
// Override to add custom initialization code
|
|
// This method is called on page load
|
|
customInitialize: function() {
|
|
},
|
|
|
|
// Override to add custom finalization code
|
|
// This method is called on page unload
|
|
customFinalize: function() {
|
|
},
|
|
|
|
// Override to add custom user menu items:
|
|
// Return a string with list items ( <li>menuItem</li> )
|
|
// 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) + '</' + tag + '>';
|
|
},
|
|
|
|
// 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;
|
|
}
|
|
|
|
} |