'+msg+'';
// finaly append this to the message list
container.appendChild(div);
this.gui.scrollDown(tabid, div);
*/
},
handleComingRequest: function( cmds )
{
var msg_html = $H();
var max_msgid = $H();
//alert(cmds.inspect());
for(var mid = 0; mid < cmds.length ; mid++)
{
var id = cmds[mid][0];
var date = cmds[mid][1];
var time = cmds[mid][2];
var sender = cmds[mid][3];
var recipientid = cmds[mid][4];
var cmd = cmds[mid][5];
var param = cmds[mid][6];
var fromtoday = cmds[mid][7];
var oldmsg = cmds[mid][8];
// format and post message
var line = '';
line += '';
line += ''+ date +' ';
line += ''+ time +' ';
if (cmd == 'send')
{
line += ' ';
line += '‹';
line += '';
line += sender.escapeHTML();
line += '';
line += '›';
line += ' ';
}
if (cmd == 'notice')
line += '* ' + this.parseMessage(param) +' ';
else if (cmd == 'me')
line += '* '+ sender.escapeHTML() + ' ' + this.parseMessage(param) +' ';
else
line += ''+ this.parseMessage(param) +' ';
line += '
';
if (oldmsg == 0)
if (cmd == 'send' || cmd == 'me')
{
// notify the hidden tab a message has been received
// don't notify anything if this is old messages
var tabid = recipientid;
if (this.gui.getTabId() != tabid)
this.gui.notifyTab(tabid);
// notify the window (change the title)
if (!this.detectactivity.isActive() && pfc_notify_window)
this.gui.notifyWindow();
}
if (msg_html.get(recipientid) == null)
msg_html.set(recipientid, line);
else
msg_html.set(recipientid, msg_html.get(recipientid) + line);
// remember the max message id in order to clean old lines
if (!max_msgid.get(recipientid)) max_msgid.set(recipientid, 0);
if (max_msgid.get(recipientid) < id) max_msgid.set(recipientid, id);
}
// loop on all recipients and post messages
var keys = msg_html.keys();
for( var i=0; i scrollDown(..) will be broken
m.innerHTML = msg_html.get(recipientid);
this.colorizeNicks(m);
this.refresh_clock(m);
// finaly append this to the message list
recipientdiv.appendChild(m);
this.gui.scrollDown(tabid, m);
// delete the old messages from the client (save some memory)
var limit_msgid = max_msgid.get(recipientid) - pfc_max_displayed_lines;
var elt = $('pfc_msg_'+recipientid+'_'+limit_msgid);
while (elt)
{
// delete this element to save browser memory
if(elt.parentNode)
elt.parentNode.removeChild(elt);
else if(elt.parentElement) // older IE browsers (<6.0) may not support parentNode
elt.parentElement.removeChild(elt);
else // if all else fails
elt.innerHTML = '';
limit_msgid--;
elt = $('pfc_msg_'+recipientid+'_'+limit_msgid);
}
}
},
calcDelay: function()
{
var lastact = new Date().getTime() - this.last_activity_time;
var dlist = this.refresh_delay_steps.slice();
var delay = dlist.shift();
if (this.refresh_delay > delay) delay = this.refresh_delay;
var limit;
while (typeof (limit = dlist.shift()) != "undefined")
{
var d = dlist.shift();
if (d < delay) continue;
if (lastact > limit) delay = d;
}
return delay;
},
/**
* Call the ajax request function
* Will query the server
*/
sendRequest: function(cmd, recipientid)
{
// do not send another ajax requests if the last one is not yet finished
if (cmd == '/update' && this.pfc_ajax_connected) return;
var delay = this.calcDelay();
if (cmd != "/update")
{
// setup a new timeout to update the chat in 5 seconds (in refresh_delay more exactly)
clearTimeout(this.timeout);
this.timeout = setTimeout('pfc.updateChat(true)', delay);
this.timeout_time = new Date().getTime() + delay;
if (pfc_debug)
trace('sendRequest: '+cmd);
}
// prepare the command string
var rx = new RegExp('(^\/[^ ]+) *(.*)','ig');
if (!recipientid) recipientid = this.gui.getTabId();
cmd = cmd.replace(rx, '$1 '+this.clientid+' '+(recipientid==''?'0':recipientid)+' $2');
// send the real ajax request
var url = pfc_server_script_url;
new Ajax.Request(url, {
method: 'post',
parameters: {'pfc_ajax':1, 'f':'handleRequest', 'cmd': cmd },
onCreate: function(transport) {
this.pfc_ajax_connected = true;
// request time counter used by ping indicator
this.last_request_time = new Date().getTime();
}.bind(this),
onSuccess: function(transport) {
if (!transport.status) return; // fix strange behavior on KHTML
// request time counter used by ping indicator
this.last_response_time = new Date().getTime();
// evaluate the javascript response
eval( transport.responseText );
}.bind(this),
onComplete: function(transport) {
this.pfc_ajax_connected = false;
// calculate the ping and display it
this.ping = Math.abs(this.last_response_time - this.last_request_time);
if ($('pfc_ping')) $('pfc_ping').innerHTML = this.ping+'ms'+' ['+parseInt(this.calcDelay() / 1000)+'s]';
}.bind(this)
});
},
/**
* update function to poll the server each 'refresh_delay' time
*/
updateChat: function(start)
{
clearTimeout(this.timeout);
if (start)
{
this.sendRequest('/update');
// setup the next update
var delay = this.calcDelay();
this.timeout = setTimeout('pfc.updateChat(true)', delay);
this.timeout_time = new Date().getTime() + delay;
}
},
/**
* Stores the caret/selection position for IE 6.x and 7.x
* Returns true if text range start and end values were updated.
* Code based on: http://www.bazon.net/mishoo/articles.epl?art_id=1292
*/
storeSelectionPos: function(obj)
{
// We don't need to store the start and end positions if the browser
// supports the Gecko selection model. However, these values may be
// useful for debugging. Also, Opera recognizes Gecko and IE range
// commands, so we need to ensure Opera only uses the Gecko model.
/* WARNING: Do not use this for textareas. They require a more
complex algorithm. */
if (obj.setSelectionRange)
{
obj.selStart = obj.selectionStart;
obj.selEnd = obj.selectionEnd;
return true;
}
// IE
else if (obj.createTextRange && document.selection)
{
// Determine current selection start position.
var range = document.selection.createRange();
var isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
if (!isCollapsed)
range.collapse(true);
var b = range.getBookmark();
obj.selStart = b.charCodeAt(2) - b.charCodeAt(0) - 1;
// Determine current selection end position.
range = document.selection.createRange();
isCollapsed = range.compareEndPoints("StartToEnd", range) == 0;
if (!isCollapsed)
range.collapse(false);
b = range.getBookmark();
obj.selEnd = b.charCodeAt(2) - b.charCodeAt(0) - 1;
return true;
}
// Browser does not support selection range processing.
else
return false;
},
/**
* Sets the selection/caret in the object based on the
* object's selStart and selEnd parameters.
* This should only be needed for IE only.
*/
setSelection: function(obj)
{
// This part of the function is included to prevent
// Opera from executing the IE portion.
/* WARNING: Do not attempt to use this function as
a wrapper for the Gekco based setSelectionRange.
It causes problems in Opera when executed from
the event trigger onFocus. */
if (obj.setSelectionRange)
{
return null;
}
// IE
else if (obj.createTextRange)
{
var range = obj.createTextRange();
range.collapse(true);
range.moveStart("character", obj.selStart);
range.moveEnd("character", obj.selEnd - obj.selStart);
range.select();
return range;
}
// Browser does not support selection range processing.
else
return null;
},
/**
* insert a smiley
*/
insertSmiley: function(smiley)
{
var w = this.el_words;
if (w.setSelectionRange)
{
// Gecko
var s = w.selectionStart;
var e = w.selectionEnd;
w.value = w.value.substring(0, s) + smiley + w.value.substr(e);
w.setSelectionRange(s + smiley.length, s + smiley.length);
w.focus();
}
else if (w.createTextRange)
{
// IE
w.focus();
// Get range based on stored values.
var range = this.setSelection(w);
range.text = smiley;
// Move caret position to end of smiley and collapse selection, if any.
// Check if internally kept values for selection are initialized.
w.selStart = (w.selStart) ? w.selStart + smiley.length : smiley.length;
w.selEnd = w.selStart;
}
else
{
// Unsupported browsers get smiley at end of string like old times.
w.value += smiley;
w.focus();
}
},
updateNickBox: function(nickid)
{
// @todo optimize this function because it is called lot of times so it could cause CPU consuming on client side
var chanids = this.chanmeta.keys();
for(var i = 0; chanids.length > i; i++)
{
this.updateNickListBox(chanids[i]);
}
},
/**
* fill the nickname list with connected nicknames
*/
updateNickListBox: function(chanid)
{
var className = (!is_ie7 && !is_ie6) ? 'class' : 'className';
var nickidlst = this.getChanMeta(chanid,'users').get('nickid');
var nickdiv = this.gui.getOnlineContentFromTabId(chanid);
var ul = document.createElement('ul');
ul.setAttribute(className, 'pfc_nicklist');
for (var i=0; i 1 &&
!navigator.appName.match("Explorer|Konqueror") &&
!navigator.appVersion.match("KHTML"))
{
msg = '';
for( var i = 0; i' + (delta>0 ? ttt[i].substring(7,range1)+ ' ... ' + ttt[i].substring(range2,ttt[i].length) : ttt[i]) + '';
}
else
{
msg = msg + ttt[i];
}
}
}
else
{
// fallback for IE6/Konqueror which do not support split with regexp
replace = '$1$2$3';
msg = msg.replace(rx_url, replace);
}
*/
// Remove auto-linked entries.
if ( false )
{
rx = new RegExp('.*?<\/a>','ig');
msg = msg.replace(rx, '$1');
rx = new RegExp('.*?<\/a>','ig');
msg = msg.replace(rx, '$1');
}
// Replace double spaces outside of tags by " " entity.
rx = new RegExp(' (?= )(?![^<]*>)','g');
msg = msg.replace(rx, ' ');
// try to parse bbcode
rx = new RegExp('\\[b\\](.+?)\\[\/b\\]','ig');
msg = msg.replace(rx, '$1');
rx = new RegExp('\\[i\\](.+?)\\[\/i\\]','ig');
msg = msg.replace(rx, '$1');
rx = new RegExp('\\[u\\](.+?)\\[\/u\\]','ig');
msg = msg.replace(rx, '$1');
rx = new RegExp('\\[s\\](.+?)\\[\/s\\]','ig');
msg = msg.replace(rx, '$1');
// rx = new RegExp('\\[pre\\](.+?)\\[\/pre\\]','ig');
// msg = msg.replace(rx, '$1
');
/*
rx = new RegExp('\\[email\\]([A-z0-9][\\w.-]*@[A-z0-9][\\w\\-\\.]+\\.[A-z0-9]{2,6})\\[\/email\\]','ig');
msg = msg.replace(rx, '$1');
rx = new RegExp('\\[email=([A-z0-9][\\w.-]*@[A-z0-9][\\w\\-\\.]+\\.[A-z0-9]{2,6})\\](.+?)\\[\/email\\]','ig');
msg = msg.replace(rx, '$2');
*/
rx = new RegExp('\\[color=([a-zA-Z]+|\\#?[0-9a-fA-F]{6}|\\#?[0-9a-fA-F]{3})\\](.+?)\\[\/color\\]','ig');
msg = msg.replace(rx, '$2');
// parse bbcode colors twice because the current_text_color is a bbcolor
// so it's possible to have a bbcode color imbrication
rx = new RegExp('\\[color=([a-zA-Z]+|\\#?[0-9a-fA-F]{6}|\\#?[0-9a-fA-F]{3})\\](.+?)\\[\/color\\]','ig');
msg = msg.replace(rx, '$2');
// try to parse smileys
var smileys = this.res.getSmileyHash();
var sl = this.res.getSmileyKeys(); // Keys should be sorted by length from pfc.gui.loadSmileyBox()
for(var i = 0; i < sl.length; i++)
{
// We don't want to replace smiley strings inside of tags.
// Use negative lookahead to search for end of tag.
rx = new RegExp(RegExp.escape(sl[i]) + '(?![^<]*>)','g');
msg = msg.replace(rx, '');
}
// try to parse nickname for highlighting
rx = new RegExp('(^|[ :,;])'+RegExp.escape(this.nickname)+'([ :,;]|$)','gi');
msg = msg.replace(rx, '$1'+ this.nickname +'$2');
// this piece of code is replaced by the word-wrap CSS3 rule.
/*
// don't allow to post words bigger than 65 caracteres
// doesn't work with crappy IE and Konqueror !
rx = new RegExp('([^ \\:\\<\\>\\/\\&\\;]{60})','ig');
var ttt = msg.split(rx);
if (ttt.length > 1 &&
!navigator.appName.match("Explorer|Konqueror") &&
!navigator.appVersion.match("KHTML"))
{
msg = '';
for( var i = 0; i i; i++)
nicktochange[i].style.color = color;
},
/**
* Returns a list of elements which have a clsName class
*/
getElementsByClassName: function( root, clsName, clsIgnore )
{
var i, matches = new Array();
var els = root.getElementsByTagName('*');
var rx1 = new RegExp('.*'+clsName+'.*');
var rx2 = new RegExp('.*'+clsIgnore+'.*');
for(i=0; i i; i++)
if (show)
elts[i].style.display = 'inline';
else
elts[i].style.display = 'none';
},
/**
* Nickname marker show/hide
*/
nickmarker_swap: function()
{
if (this.nickmarker) {
this.nickmarker = false;
} else {
this.nickmarker = true;
}
this.refresh_nickmarker()
setCookie('pfc_nickmarker', this.nickmarker);
},
refresh_nickmarker: function(root)
{
var nickmarker_icon = $('pfc_nickmarker');
if (!root) root = $('pfc_channels_content');
if (this.nickmarker)
{
nickmarker_icon.src = this.res.getFileUrl('images/color-on.gif');
nickmarker_icon.alt = this.res.getLabel("Hide nickname marker");
nickmarker_icon.title = nickmarker_icon.alt;
this.colorizeNicks(root);
}
else
{
nickmarker_icon.src = this.res.getFileUrl('images/color-off.gif');
nickmarker_icon.alt = this.res.getLabel("Show nickname marker");
nickmarker_icon.title = nickmarker_icon.alt;
var elts = this.getElementsByClassName(root, 'pfc_nickmarker', '');
for(var i = 0; elts.length > i; i++)
{
// this is not supported in konqueror =>>> elts[i].removeAttribute('style');
elts[i].style.color = '';
}
}
},
/**
* Date/Hour show/hide
*/
clock_swap: function()
{
if (this.clock) {
this.clock = false;
} else {
this.clock = true;
}
this.refresh_clock();
setCookie('pfc_clock', this.clock);
},
refresh_clock: function( root )
{
var clock_icon = $('pfc_clock');
if (!root) root = $('pfc_channels_content');
if (this.clock)
{
clock_icon.src = this.res.getFileUrl('images/clock-on.gif');
clock_icon.alt = this.res.getLabel('Hide dates and hours');
clock_icon.title = clock_icon.alt;
this.showClass(root, 'pfc_date', 'pfc_invisible', true);
this.showClass(root, 'pfc_heure', 'pfc_invisible', true);
}
else
{
clock_icon.src = this.res.getFileUrl('images/clock-off.gif');
clock_icon.alt = this.res.getLabel('Show dates and hours');
clock_icon.title = clock_icon.alt;
this.showClass(root, 'pfc_date', 'pfc_invisible', false);
this.showClass(root, 'pfc_heure', 'pfc_invisible', false);
}
// browser automaticaly scroll up misteriously when showing the dates
// $('pfc_chat').scrollTop += 30;
},
/**
* Sound button
*/
sound_swap: function()
{
if (this.issoundenable) {
this.issoundenable = false;
} else {
this.issoundenable = true;
}
this.refresh_sound();
setCookie('pfc_issoundenable', this.issoundenable);
},
refresh_sound: function( root )
{
var snd_icon = $('pfc_sound');
if (this.issoundenable)
{
snd_icon.src = this.res.getFileUrl('images/sound-on.gif');
snd_icon.alt = this.res.getLabel('Disable sound notifications');
snd_icon.title = snd_icon.alt;
}
else
{
snd_icon.src = this.res.getFileUrl('images/sound-off.gif');
snd_icon.alt = this.res.getLabel('Enable sound notifications');
snd_icon.title = snd_icon.alt;
}
},
/**
* Connect/disconnect button
*/
connect_disconnect: function()
{
if (this.isconnected)
this.sendRequest('/quit');
else
{
if (this.nickname == '')
this.askNick();
else
this.sendRequest('/connect "'+this.nickname+'"');
}
},
refresh_loginlogout: function()
{
var loginlogout_icon = $('pfc_loginlogout');
if (this.isconnected)
{
loginlogout_icon.src = this.res.getFileUrl('images/logout.gif');
loginlogout_icon.alt = this.res.getLabel('Disconnect');
loginlogout_icon.title = loginlogout_icon.alt;
}
else
{
this.clearMessages();
this.clearNickList();
loginlogout_icon.src = this.res.getFileUrl('images/login.gif');
loginlogout_icon.alt = this.res.getLabel('Connect');
loginlogout_icon.title = loginlogout_icon.alt;
}
},
/**
* Minimize/Maximized the chat zone
*/
swap_minimize_maximize: function()
{
if (this.minmax_status) {
this.minmax_status = false;
} else {
this.minmax_status = true;
}
setCookie('pfc_minmax_status', this.minmax_status);
this.refresh_minimize_maximize();
},
refresh_minimize_maximize: function()
{
var content = $('pfc_content_expandable');
var btn = $('pfc_minmax');
if (this.minmax_status)
{
btn.src = this.res.getFileUrl('images/maximize.gif');
btn.alt = this.res.getLabel('Magnify');
btn.title = btn.alt;
content.style.display = 'none';
}
else
{
btn.src = this.res.getFileUrl('images/minimize.gif');
btn.alt = this.res.getLabel('Cut down');
btn.title = btn.alt;
content.style.display = 'block';
}
},
/**
* BBcode ToolBar
*/
insert_text: function(open, close, promptifselempty)
{
var msgfield = $('pfc_words');
var pfcp = this.getPrompt();
pfcp.msgfield = msgfield;
pfcp.open = open;
pfcp.close = close;
pfcp.promptifselempty = promptifselempty;
pfcp.callback = this.insert_text_callback;
// Gecko
/* Always check for Gecko selection processing commands
first. This is needed for Opera. */
if (msgfield.selectionStart || msgfield.selectionStart == '0')
{
var startPos = msgfield.selectionStart;
var endPos = msgfield.selectionEnd;
var text = msgfield.value.substring(startPos, endPos);
if (startPos == endPos && promptifselempty)
{
pfcp.prompt(this.res.getLabel('Enter the text to format'), '');
pfcp.focus();
}
else
this.insert_text_callback(text, pfcp);
}
// IE
else if (document.selection && document.selection.createRange)
{
msgfield.focus();
// Get selection range.
pfcp.range = this.setSelection(msgfield);
var text = pfcp.range.text;
if (text == "" && promptifselempty)
{
pfcp.prompt(this.res.getLabel('Enter the text to format'), '');
pfcp.focus();
}
else
this.insert_text_callback(text, pfcp);
}
// Fallback support for other browsers
else
{
pfcp.prompt(this.res.getLabel('Enter the text to format'), '');
pfcp.focus();
}
return;
},
insert_text_callback: function(text, pfcp)
{
var open = pfcp.open;
var close = pfcp.close;
var promptifselempty = pfcp.promptifselempty;
var msgfield = pfcp.msgfield;
var range = pfcp.range;
// Gecko
/* Always check for Gecko selection processing commands
first. This is needed for Opera. */
if (msgfield.selectionStart || msgfield.selectionStart == '0')
{
var startPos = msgfield.selectionStart;
var endPos = msgfield.selectionEnd;
var extralength = 0;
if (startPos == endPos && promptifselempty)
{
if (text == null) text = "";
extralength = text.length;
}
if (text.length > 0 || !promptifselempty)
{
msgfield.value = msgfield.value.substring(0, startPos) + open + text + close + msgfield.value.substring(endPos, msgfield.value.length);
var caretPos = endPos + open.length + extralength + close.length;
msgfield.setSelectionRange(caretPos, caretPos);
msgfield.focus();
}
}
// IE
else if (document.selection && document.selection.createRange)
{
if (text == null) text = "";
if (text.length > 0 || !promptifselempty)
{
msgfield.focus();
range.text = open + text + close;
// Increment caret position.
// Check if internally kept values for selection are initialized.
msgfield.selStart = (msgfield.selStart) ? msgfield.selStart + open.length + text.length + close.length : open.length + text.length + close.length;
msgfield.selEnd = msgfield.selStart;
msgfield.focus();
}
}
// Fallback support for other browsers
else
{
if (text == null) text = "";
if (text.length > 0 || !promptifselempty)
{
msgfield.value += open + text + close;
msgfield.focus();
}
}
},
/**
* Minimize/Maximize none/inline
*/
minimize_maximize: function(idname, type)
{
var element = $(idname);
if(element.style)
{
if(element.style.display == type )
{
element.style.display = 'none';
}
else
{
element.style.display = type;
}
}
},
switch_text_color: function(color)
{
/* clear any existing borders on the color buttons */
var colorbtn = this.getElementsByClassName($('pfc_colorlist'), 'pfc_color', '');
for(var i = 0; colorbtn.length > i; i++)
{
colorbtn[i].style.border = 'none';
colorbtn[i].style.padding = '0';
}
/* assign the new border style to the selected button */
this.current_text_color = color;
setCookie('pfc_current_text_color', this.current_text_color);
var idname = 'pfc_color_' + color;
$(idname).style.border = '1px solid #555';
$(idname).style.padding = '1px';
// assigne the new color to the input text box
this.el_words.style.color = '#'+color;
this.el_words.focus();
},
/**
* Smiley show/hide
*/
showHideSmileys: function()
{
if (this.showsmileys)
{
this.showsmileys = false;
}
else
{
this.showsmileys = true;
}
setCookie('pfc_showsmileys', this.showsmileys);
this.refresh_Smileys();
},
refresh_Smileys: function()
{
// first of all : show/hide the smiley box
var content = $('pfc_smileys');
if (this.showsmileys)
content.style.display = 'block';
else
content.style.display = 'none';
// then switch the button icon
var btn = $('pfc_showHideSmileysbtn');
if (this.showsmileys)
{
if (btn)
{
btn.src = this.res.getFileUrl('images/smiley-on.gif');
btn.alt = this.res.getLabel('Hide smiley box');
btn.title = btn.alt;
}
}
else
{
if (btn)
{
btn.src = this.res.getFileUrl('images/smiley-off.gif');
btn.alt = this.res.getLabel('Show smiley box');
btn.title = btn.alt;
}
}
},
/**
* Show Hide who's online
*/
showHideWhosOnline: function()
{
if (this.showwhosonline)
{
this.showwhosonline = false;
}
else
{
this.showwhosonline = true;
}
setCookie('pfc_showwhosonline', this.showwhosonline);
this.refresh_WhosOnline();
},
refresh_WhosOnline: function()
{
// first of all : show/hide the nickname list box
var root = $('pfc_channels_content');
var contentlist = this.getElementsByClassName(root, 'pfc_online', '');
for(var i = 0; i < contentlist.length; i++)
{
var content = contentlist[i];
if (this.showwhosonline)
content.style.display = 'block';
else
content.style.display = 'none';
content.style.zIndex = '100'; // for IE6, force the nickname list borders to be shown
}
// then refresh the button icon
var btn = $('pfc_showHideWhosOnlineBtn');
if (!btn) return;
if (this.showwhosonline)
{
btn.src = this.res.getFileUrl('images/online-on.gif');
btn.alt = this.res.getLabel('Hide online users box');
btn.title = btn.alt;
}
else
{
btn.src = this.res.getFileUrl('images/online-off.gif');
btn.alt = this.res.getLabel('Show online users box');
btn.title = btn.alt;
}
this.refresh_Chat();
},
/**
* Resize chat
*/
refresh_Chat: function()
{
// resize all the tabs content
var root = $('pfc_channels_content');
var contentlist = this.getElementsByClassName(root, 'pfc_chat', '');
for(var i = 0; i < contentlist.length; i++)
{
var chatdiv = contentlist[i];
if (!this.showwhosonline)
{
chatdiv.style.width = '100%';
}
else
{
chatdiv.style.width = '';
}
}
},
getPrompt: function()
{
if (!this.pfc)
this.pfc = new pfcPrompt($('pfc_container'));
return this.pfc;
}
};