git-svn-id: https://webim.svn.sourceforge.net/svnroot/webim/trunk@106 c66351dc-e62f-0410-b875-e3a5c0b9693f
This commit is contained in:
Evgeny Gryaznov 2008-09-29 16:10:06 +00:00
parent 91483bb642
commit c2206ec72b
4 changed files with 1234 additions and 0 deletions

30
src/messenger/js/brws.js Normal file
View File

@ -0,0 +1,30 @@
var myAgent = "";
var myVer = 0;
var myRealAgent = "";
function detectAgent() {
var AGENTS = ["opera","msie","safari","firefox","netscape","mozilla"];
var agent = navigator.userAgent.toLowerCase();
for (var i = 0; i < AGENTS.length; i++) {
var agentStr = AGENTS[i];
if (agent.indexOf(agentStr) != -1) {
myAgent = agentStr;
if (!window.RegExp)
break;
var versionExpr = new RegExp(agentStr + "[ \/]?([0-9]+(\.[0-9]+)?)");
if (versionExpr.exec(agent) != null) {
myVer = parseFloat(RegExp.$1);
}
break;
}
}
myRealAgent = myAgent;
if( navigator.product == "Gecko")
myAgent = "moz";
}
detectAgent();
function getEl(name) {
return document.getElementById(name);
}

368
src/messenger/js/chat.js Normal file
View File

@ -0,0 +1,368 @@
var FrameUtils = {
getDocument: function(frm) {
if (frm.contentDocument) {
return frm.contentDocument;
} else if (frm.contentWindow) {
return frm.contentWindow.document;
} else if (frm.document) {
return frm.document;
} else {
alert( myRealAgent + ": cannot find document in frame " + frm);
//for( var a in frm )
// alert( a );
return null;
}
},
initFrame: function(frm) {
var doc = this.getDocument(frm);
doc.open();
doc.write("<html><head>");
doc.write("<link rel=\"stylesheet\" type=\"text/css\" media=\"all\" href=\""+Chat.webimRoot+"/chat.css\" />");
doc.write("</head><body bgcolor='#FFFFFF' text='#000000' link='#C28400' vlink='#C28400' alink='#C28400' marginwidth='0' marginheight='0' leftmargin='0' rightmargin='0' topmargin='0' bottommargin='0'>");
doc.write("<table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td valign='top' class='message' id='content'></td></tr></table><a id='bottom'/>");
doc.write("</body></html>");
doc.close();
frm.onload = function() {
if( frm./**/myHtml ) {
FrameUtils.getDocument(frm).getElementById('content').innerHTML += frm.myHtml;
FrameUtils.scrollDown(frm);
}
};
},
insertIntoFrame: function(frm, htmlcontent) {
var vcontent = this.getDocument(frm).getElementById('content');
if( vcontent == null ) {
if( !frm.myHtml ) frm.myHtml = "";
frm.myHtml += htmlcontent;
} else {
vcontent.innerHTML += htmlcontent;
}
},
scrollDown: function(frm) {
var vbottom = this.getDocument(frm).getElementById('bottom');
if( myAgent == 'opera' ) {
frm.contentWindow.scrollTo(0,this.getDocument(frm).getElementById('content').clientHeight);
} else if( vbottom )
vbottom.scrollIntoView(false);
}
};
Ajax.ChatThreadUpdater = Class.create();
Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.onComplete = this.requestComplete.bind(this);
this._options.onException = this.handleException.bind(this);
this.updater = {};
this.frequency = (this._options.frequency || 2);
this.cansend = true;
FrameUtils.initFrame(this._options.container);
if( this._options.message ) {
this._options.message.onkeydown = this.handleKeyDown.bind(this);
this._options.message.onfocus = (function() { this.focused = true; }).bind(this);
this._options.message.onblur = (function() { this.focused = false; }).bind(this)
}
this.update();
},
handleException: function(_request, ex) {
this.setStatus(ex.name + " occured: " + ex.message);
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
updateOptions: function(act) {
this._options.parameters = 'act='+act+'&thread=' + (this._options.threadid || -1) +
'&token=' + (this._options.token || 0)+
'&lastid=' + (this._options.lastid || 0);
if( this._options.user )
this._options.parameters += "&user=true";
if( act == 'refresh' && this._options.message && this._options.message.value != '' )
this._options.parameters += "&typed=1";
},
enableInput: function(val) {
if( this._options.message )
this._options.message.disabled = !val;
},
stopUpdate: function() {
this.enableInput(true);
if( this.updater._options )
this.updater._options.onComplete = undefined;
clearTimeout(this.timer);
},
update: function() {
this.updateOptions("refresh");
this.updater = new Ajax.Request(this._options.servl, this._options);
},
requestComplete: function(_response) {
this.enableInput(true);
this.cansend = true;
var xmlRoot = Ajax.getXml(_response);
if( xmlRoot && xmlRoot.tagName == 'thread' ) {
this.updateContent( xmlRoot );
} else {
this.handleError(_response, xmlRoot, 'refresh messages failed');
}
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
postMessage: function(msg) {
if( msg == "" || !this.cansend) {
return;
}
this.cansend = false;
this.stopUpdate();
this.updateOptions("post");
var postOptions = {}.extend(this._options);
postOptions.parameters += "&message=" + encodeURIComponent(msg);
postOptions.onComplete = (function(presponse) {
this.requestComplete( presponse );
if( this._options.message ) {
this._options.message.value = '';
this._options.message.focus();
}
}).bind(this);
if( myRealAgent != 'opera' )
this.enableInput(false);
this.updater = new Ajax.Request(this._options.servl, postOptions);
},
changeName: function(newname) {
new Ajax.Request(this._options.servl, {parameters:'act=rename&thread=' + (this._options.threadid || -1) +
'&token=' + (this._options.token || 0) + '&name=' + encodeURIComponent(newname)});
},
onThreadClosed: function(_response) {
var xmlRoot = Ajax.getXml(_response);
if( xmlRoot && xmlRoot.tagName == 'closed' ) {
setTimeout('window.close()', 2000);
} else {
this.handleError(_response, xmlRoot, 'cannot close');
}
},
closeThread: function() {
var _params = 'act=close&thread=' + (this._options.threadid || -1) + '&token=' + (this._options.token || 0);
if( this._options.user )
_params += "&user=true";
new Ajax.Request(this._options.servl, {parameters:_params, onComplete: this.onThreadClosed.bind(this)});
},
processMessage: function(_target, message) {
var destHtml = NodeUtils.getNodeText(message);
FrameUtils.insertIntoFrame(_target, destHtml );
},
showTyping: function(istyping) {
if( $("typingdiv") ) {
$("typingdiv").style.display=istyping ? 'inline' : 'none';
}
},
setupAvatar: function(avatar) {
var imageLink = NodeUtils.getNodeText(avatar);
if( this._options.avatar && this._options.user ) {
this._options.avatar.innerHTML = imageLink != ""
? "<img src=\""+Chat.webimRoot+"/images/free.gif\" width=\"7\" height=\"1\" border=\"0\" alt=\"\" /><img src=\""
+imageLink+ "\" border=\"0\" alt=\"\"/>"
: "";
}
},
updateContent: function(xmlRoot) {
var haveMessage = false;
var result_div = this._options.container;
var _lastid = NodeUtils.getAttrValue(xmlRoot, "lastid");
if( _lastid ) {
this._options.lastid = _lastid;
}
var typing = NodeUtils.getAttrValue(xmlRoot, "typing");
if( typing ) {
this.showTyping(typing == '1');
}
for( var i = 0; i < xmlRoot.childNodes.length; i++ ) {
var node = xmlRoot.childNodes[i];
if( node.tagName == 'message' ) {
haveMessage = true;
this.processMessage(result_div, node);
} else if( node.tagName == 'avatar' ) {
this.setupAvatar(node);
}
// TODO thread events
}
if( haveMessage ) {
FrameUtils.scrollDown(this._options.container);
if( !this.focused )
window.focus();
}
},
handleKeyDown: function(k) {
if( k ){ ctrl=k.ctrlKey;k=k.which; } else { k=event.keyCode;ctrl=event.ctrlKey; }
if( this._options.message && ((k==13 && (ctrl || myRealAgent == 'opera')) || (k==10)) ) {
var mmsg = this._options.message.value;
if( myRealAgent == 'opera' ) {
mmsg = mmsg.replace(/[\r\n]+$/,'');
}
this.postMessage( mmsg );
return false;
}
return true;
},
handleError: function(_response, xmlRoot, _action) {
if( xmlRoot && xmlRoot.tagName == 'error' ) {
this.setStatus(NodeUtils.getNodeValue(xmlRoot,"descr"));
} else {
this.setStatus(_action+', ' + Ajax.getError(_response));
}
},
setStatus: function(k) {
if( this.statusTimeout )
clearTimeout(this.statusTimeout);
window.status = k;
this.statusTimeout = setTimeout(this.clearStatus.bind(this), 4000);
},
clearStatus: function() {
window.status = "";
}
});
HSplitter = Class.create();
HSplitter.prototype = {
initialize: function(_options) {
this._options = _options;
this.captured = 0;
if( this._options.first && this._options.second && this._options.control ) {
this._options.control.onmousedown = this.onmousedownEvent.bind(this);
this._options.control.onmouseup = this.onmouseupEvent.bind(this);
this._options.control.onmousemove = this.onmouseMoveEvent.bind(this);
}
},
onmousedownEvent: function(e) {
var ev = e || event;
if( this._options.control.setCapture )
this._options.control.setCapture();
this.start_height = this._options.first.style.pixelHeight || this._options.first.clientHeight;
this.start_offset = ev.screenY;
this._options.maxfirst = this._options.first.style.pixelHeight + this._options.second.clientHeight - this._options.minsec;
this.captured = 1;
},
onmouseupEvent: function() {
if( this.captured ) {
if( this._options.control.releaseCapture )
this._options.control.releaseCapture();
this.captured = 0;
}
},
onmouseMoveEvent: function(e) {
var ev = e || event;
if( this.captured ) {
var new_height = this.start_height - (ev.screenY - this.start_offset);
if( new_height > this._options.maxfirst )
new_height = this._options.maxfirst;
else if( new_height < this._options.minfirst )
new_height = this._options.minfirst;
if( myAgent == 'moz' )
this._options.first.style.height=new_height+'px';
else
this._options.first.style.pixelHeight = new_height;
}
}
};
var Chat = {
threadUpdater : {},
hSplitter : {},
applyName: function() {
Chat.threadUpdater.changeName($('uname').value);
$('changename1').style.display='none';
$('changename2').style.display='inline';
},
showNameField: function() {
$('changename1').style.display='inline';
$('changename2').style.display='none';
}
};
Behaviour.register({
'#postmessage a' : function(el) {
el.onclick = function() {
var message = $('msgwnd');
if( message )
Chat.threadUpdater.postMessage(message.value);
};
},
'a#sndmessagelnk' : function(el) {
if( myRealAgent == 'opera' ) {
el.innerHTML = el.innerHTML.replace('Ctrl-','');
}
},
'select#predefined' : function(el) {
el.onchange = function() {
var message = $('msgwnd');
message.value = this.options[this.selectedIndex].innerText || this.options[this.selectedIndex].innerHTML;
this.selectedIndex = 0;
message.focus();
};
},
'div#changename2 a' : function(el) {
el.onclick = function() {
Chat.showNameField();
return false;
};
},
'div#changename1 a' : function(el) {
el.onclick = function() {
Chat.applyName();
return false;
};
},
'div#changename1 input#uname' : function(el) {
el.onkeydown = function(e) {
var ev = e || event;
if( ev.keyCode == 13 ) {
Chat.applyName();
}
};
},
'a#refresh' : function(el) {
el.onclick = function() {
Chat.threadUpdater.stopUpdate();
Chat.threadUpdater.update();
};
},
'a.closethread' : function(el) {
el.onclick = function() {
Chat.threadUpdater.closeThread();
};
}
});
EventHelper.register(window, 'onload', function(){
Chat.webimRoot = threadParams.wroot;
Chat.hSplitter = new HSplitter({control:$("spl1"), first:$("msgwndtd"), second:$("chatwndtd"), minfirst:30, minsec:30});
Chat.threadUpdater = new Ajax.ChatThreadUpdater(({container:myRealAgent=='safari'?self.frames[0]:$("chatwnd"),avatar:$("avatarwnd"),message:$("msgwnd")}).extend( threadParams || {} ));
});

526
src/messenger/js/common.js Normal file
View File

@ -0,0 +1,526 @@
/*
* Web Messenger common script
* http://sourceforge.net/projects/webim
*
* Based on Prototype JavaScript framework, version 1.3.1
* http://prototype.conio.net/ (c) 2005 Sam Stephenson <sam@conio.net>
*/
//- getEl, myAgent, myRealAgent
//- localized
//- onComplete, obj, params, $apply$
//- threadParams, servl, frequency, user, threadid, token
//- updaterOptions, url, company, agentservl, noclients, wroot
var Class = {
create: function() {
return function() {
this./**/initialize./**/apply(this, arguments);
};
},
inherit: function(child,parent,body) {
Object./**/extend(Object.extend(child.prototype, parent.prototype), body );
}
};
Object.extend = function(destination, source) {
for (property in source) {
destination[property] = source[property];
}
return destination;
};
Object.prototype.extend = function(_object) {
return Object.extend.apply(this, [this, _object]);
};
Function.prototype./**/bind = function(_object) {
var __method = this;
return function() {
return __method.apply(_object, arguments);
}
};
Function.prototype./**/bindAsEventListener = function(_object) {
var __method = this;
return function(event) {
__method.call(_object, event || window.event);
}
};
Number.prototype./**/toColorPart = function() {
var digits = this.toString(16);
if (this < 16) return '0' + digits;
return digits;
};
var Try = {
these: function() {
var returnValue;
for (var i = 0; i < arguments.length; i++) {
var lambda = arguments[i];
try {
returnValue = lambda();
break;
} catch (e) {}
}
return returnValue;
}
};
/*--------------------------------------------------------------------------*/
var PeriodicalExecuter = Class.create();
PeriodicalExecuter.prototype = {
initialize: function(callback, frequency) {
this.callback = callback;
this.frequency = frequency;
this./**/currentlyExecuting = false;
this./**/registerCallback();
},
registerCallback: function() {
setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
},
onTimerEvent: function() {
if (!this.currentlyExecuting) {
try {
this.currentlyExecuting = true;
this.callback();
} finally {
this.currentlyExecuting = false;
}
}
}
};
/*--------------------------------------------------------------------------*/
function findObj( id )
{
var x;
if( !( x = document[ id ] ) && document.all ) x = document.all[ id ];
if( !x && document.getElementById ) x = document.getElementById( id );
if( !x && !document.all && document.getElementsByName )
{
x = document.getElementsByName( id );
if( x.length == 0 ) return null;
if( x.length == 1 ) return x[ 0 ];
}
return x;
}
if (!Array.prototype./**/push) {
Array.prototype.push = function() {
var startLength = this.length;
for (var i = 0; i < arguments.length; i++)
this[startLength + i] = arguments[i];
return this.length;
};
}
function $() {
var elems = new Array();
for (var i = 0; i < arguments.length; i++) {
var elem = arguments[i];
if (typeof elem == 'string')
elem = findObj(elem);
if (arguments.length == 1)
return elem;
elems.push(elem);
}
return elems;
}
if (!Function.prototype.apply) {
Function.prototype.apply = function(obj, params) {
var parameterStrings = new Array();
if (!obj) obj = window;
if (!params) params = new Array();
for (var i = 0; i < params.length; i++)
parameterStrings[i] = 'params[' + i + ']';
obj.$apply$ = this;
var result = eval('obj.$apply$(' +
parameterStrings.join(', ') + ')');
obj.$apply$ = null;
return result;
};
}
var Ajax = {
getTransport: function() {
return Try.these(
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
},
getXml: function(_response) {
if( _response &&
_response.status >= 200 &&
_response.status < 300 ) {
var xmlDoc = _response.responseXML;
if( xmlDoc && xmlDoc.documentElement )
return xmlDoc.documentElement;
}
return null;
},
getError: function(_response) {
return _response.statusText || "connection error N" + _response.status;
},
emptyFunction: function() {}
};
Ajax./**/Base = function() {};
Ajax.Base.prototype = {
setOptions: function(_options) {
this._options = {
_method: 'post',
asynchronous: true,
parameters: ''
}.extend(_options || {});
},
responseIsSuccess: function() {
return this./**/transport.status == undefined
|| this.transport.status == 0
|| (this.transport.status >= 200 && this.transport.status < 300);
},
responseIsFailure: function() {
return !this.responseIsSuccess();
}
};
Ajax./**/Request = Class.create();
Ajax.Request./**/Events =
['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
Class.inherit( Ajax.Request, Ajax.Base, {
initialize: function(url, _options) {
this.transport = Ajax.getTransport();
this.setOptions(_options);
this.request(url);
},
request: function(url) {
var parameters = this._options.parameters || '';
if (parameters.length > 0) parameters += '&_=';
try {
if (this._options._method == 'get' && parameters.length > 0)
url += '?' + parameters;
this.transport.open(this._options._method, url, this._options.asynchronous);
if (this._options.asynchronous) {
this.transport.onreadystatechange = this.onStateChange.bind(this);
setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10);
}
this.setRequestHeaders();
var pbody = this._options.postBody ? this._options.postBody : parameters;
this.transport.send(this._options._method == 'post' ? pbody : null);
} catch (e) {
this.dispatchException(e);
}
},
setRequestHeaders: function() {
var requestHeaders =
['X-Requested-With', 'XMLHttpRequest'];
if (this._options._method == 'post') {
requestHeaders.push('Content-type',
'application/x-www-form-urlencoded');
/* Force "Connection: close" for Mozilla browsers to work around
* a bug where XMLHttpReqeuest sends an incorrect Content-length
* header. See Mozilla Bugzilla #246651.
*/
if (this.transport.overrideMimeType)
requestHeaders.push('Connection', 'close');
}
if (this._options.requestHeaders)
requestHeaders.push.apply(requestHeaders, this._options.requestHeaders);
for (var i = 0; i < requestHeaders.length; i += 2)
this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
},
onStateChange: function() {
var readystate = this.transport.readyState;
if (readystate != 1)
this.respondToReadyState(this.transport.readyState);
},
header: function(name) {
try {
return this.transport.getResponseHeader(name);
} catch (e) {}
},
evalResponse: function() {
try {
return eval(this.transport.responseText);
} catch (e) {
this.dispatchException(e);
}
},
respondToReadyState: function(readystate) {
var event = Ajax.Request.Events[readystate];
if (event == 'Complete') {
try {
(this._options['on' + this.transport.status]
|| this._options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
|| Ajax.emptyFunction)(this.transport);
} catch (e) {
this.dispatchException(e);
}
if ((this.header('Content-type') || '').match("text\\/javascript"))
this.evalResponse();
}
try {
(this._options['on' + event] || Ajax.emptyFunction)(this.transport);
} catch (e) {
this.dispatchException(e);
}
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
this.transport.onreadystatechange = Ajax.emptyFunction;
},
dispatchException: function(exception) {
(this._options.onException || Ajax.emptyFunction)(this, exception);
}
});
var EventHelper = {
register : function(obj, ev,func){
var oldev = obj[ev];
if (typeof oldev != 'function') {
obj[ev] = func;
} else {
obj[ev] = function() {
oldev();
func();
}
}
}
};
/*
Behaviour v1.1 by Ben Nolan, June 2005. Based largely on the work
of Simon Willison (see comments by Simon below).
http://ripcord.co.nz/behaviour/
*/
var Behaviour = {
list : new Array,
register : function(sheet){
Behaviour.list.push(sheet);
},
init : function(){
EventHelper.register(window, 'onload', function(){
Behaviour.apply();
});
},
apply : function(){
for (h=0;sheet=Behaviour.list[h];h++){
for (selector in sheet) {
list = document.getElementsBySelector(selector);
if (!list)
continue;
for( i = 0; element = list[i]; i++ ) {
sheet[selector]( element );
}
}
}
}
};
Behaviour.init();
function getAllChildren(e) {
// Returns all children of element. Workaround required for IE5/Windows. Ugh.
return e.all ? e.all : e.getElementsByTagName('*');
}
document.getElementsBySelector = function(selector) {
// Attempt to fail gracefully in lesser browsers
if (!document.getElementsByTagName) {
return new Array();
}
// Split selector in to tokens
var tokens = selector.split(' ');
var currentContext = new Array(document);
for (var i = 0; i < tokens.length; i++) {
token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,'');;
if (token.indexOf('#') > -1) {
// Token is an ID selector
var bits = token.split('#');
var tag_name = bits[0];
var id = bits[1];
var element = document.getElementById(id);
if (element == null || tag_name && element.nodeName.toLowerCase() != tag_name ) {
// tag with that ID not found, return false
return new Array();
}
// Set currentContext to contain just this element
currentContext = new Array(element);
continue; // Skip to next token
}
if (token.indexOf('.') > -1) {
// Token contains a class selector
var bits = token.split('.');
var tag_name = bits[0];
var class_name = bits[1];
if (!tag_name) {
tag_name = '*';
}
// Get elements matching tag, filter them for class selector
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements;
if (tag_name == '*') {
elements = getAllChildren(currentContext[h]);
} else {
elements = currentContext[h].getElementsByTagName(tag_name);
}
if( elements == null )
continue;
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = new Array;
var currentContextIndex = 0;
for (var k = 0; k < found.length; k++) {
if (found[k].className && found[k].className.match(new RegExp("\\b"+class_name+"\\b"))) {
currentContext[currentContextIndex++] = found[k];
}
}
continue; // Skip to next token
}
// [evgeny] code for attribute selection is removed...
if (!currentContext[0]){
return;
}
// If we get here, token is JUST an element (not a class or ID selector)
tag_name = token;
var found = new Array;
var foundCount = 0;
for (var h = 0; h < currentContext.length; h++) {
var elements = currentContext[h].getElementsByTagName(tag_name);
for (var j = 0; j < elements.length; j++) {
found[foundCount++] = elements[j];
}
}
currentContext = found;
}
return currentContext;
};
var NodeUtils = {
getNodeValue: function(parent,name) {
var nodes = parent.getElementsByTagName( name );
if( nodes.length == 0 )
return "";
nodes = nodes[0].childNodes;
var reslt = "";
for( i = 0; i < nodes.length; i++ )
reslt += nodes[i].nodeValue;
return reslt;
},
getNodeText: function(_node) {
var _nodes = _node.childNodes;
var _text = "";
for( i = 0; i < _nodes.length; i++ )
_text += _nodes[i].nodeValue;
return _text;
},
getAttrValue: function(parent,name) {
for( k=0; k < parent.attributes.length; k++ )
if( parent.attributes[k].nodeName == name )
return parent.attributes[k].nodeValue;
return null;
}
};
var CommonUtils = {
getRow: function(_id,_table) {
var _row = _table.rows[_id];
if( _row != null )
return _row;
if( _table.rows['head'] != null )
return null;
for( k=0; k < _table.rows.length; k++ ) {
if( _table.rows[k].id == _id )
return _table.rows[k];
}
return null;
},
getCell: function(_id,_row,_table) {
var _cell = _row.cells[_id];
if( _cell != null )
return _cell;
if( _table.rows['head'] != null )
return null;
for( k=0; k < _row.cells.length; k++ ) {
if( _row.cells[k].id == _id )
return _row.cells[k];
}
return null;
},
insertCell: function(_row,_id,_className,_align,_height, _inner) {
var cell = _row.insertCell(-1);
cell.id = _id;
if(_align)
cell.align = _align;
cell.className = _className;
if(_height)
cell.height = _height;
cell.innerHTML = _inner;
}
};

310
src/messenger/js/users.js Normal file
View File

@ -0,0 +1,310 @@
Ajax.PeriodicalUpdater = Class.create();
Class.inherit( Ajax.PeriodicalUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.onComplete = this.requestComplete.bind(this);
this._options.onException = this.handleException.bind(this);
this.frequency = (this._options.frequency || 2);
this.updater = {};
this.update();
},
handleException: function(_request, ex) {
if( this._options.handleError )
this._options.handleError( ex.name + " occured: " + ex.message );
this.stopUpdate();
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
},
stopUpdate: function() {
if( this.updater._options )
this.updater._options.onComplete = undefined;
clearTimeout(this.timer);
},
update: function() {
if( this._options.updateParams )
this._options.parameters = (this._options.updateParams)();
this.updater = new Ajax.Request(this._options.url, this._options);
},
requestComplete: function(presponse) {
if (presponse != null && presponse.status == 200 ) {
var xmlDoc = presponse.responseXML;
(this._options.updateContent || Ajax.emptyFunction)( xmlDoc );
} else {
if( this._options.handleError )
this._options.handleError(Ajax.getError(_response));
}
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
}
});
var HtmlGenerationUtils = {
insertSplitter: function( _row ) {
var cell = _row.insertCell(-1);
cell.style.backgroundImage = 'url('+webimRoot+'/images/tablediv3.gif)';
cell.innerHTML = '<img src="'+webimRoot+'/images/free.gif" width="3" height="1" border="0" alt="">';
},
removeHr: function(_table, _index ) {
_table.deleteRow(_index+2);
_table.deleteRow(_index+1);
_table.deleteRow(_index);
},
insertHr: function(_table, _index) {
var row = _table.insertRow(_index);
var cell = row.insertCell(-1);
cell.colSpan = 13;
cell.height = 2;
row = _table.insertRow(_index);
cell = row.insertCell(-1);
cell.colSpan = 13;
cell.style.backgroundColor = '#E1E1E1';
cell.innerHTML = '<img src="'+webimRoot+'/images/free.gif" width="1" height="1" border="0" alt="">';
row = _table.insertRow(_index);
cell = row.insertCell(-1);
cell.colSpan = 13;
cell.height = 2;
},
popupLink: function(link, title, wndid, inner, width, height) {
return '<a href="'+link+'" target="_blank" title="'+title+'" onclick="this.newWindow = window.open(\''+link+'\', \''+
wndid+'\', \'toolbar=0,scrollbars=0,location=0,status=1,menubar=0,width='+width+',height='+height+',resizable=1\');this.newWindow.focus();this.newWindow.opener=window;return false;">'+
inner+'</a>';
},
generateOneRowTable: function(content) {
return '<table width="100%" cellspacing="0" cellpadding="0" border="0"><tr>' + content + '</tr></table>';
},
viewOpenCell: function(username,servlet,id,canview,canopen,ban,message) {
var cellsCount = 2;
var link = servlet+"?thread="+id;
var innerContent = ( ban == "full" ) ? "<i style='color:#aaaaaa;'>"+username+"</i>" : ( ( ban == "other" ) ? "<i>"+username+"</i>" : username );
var gen = '<td class="table" style="padding-left:0px; padding-right:0px;">';
gen += HtmlGenerationUtils.popupLink( canopen ? link : link+"&viewonly=true", localized[canopen ? 0 : 1], "ImCenter"+id, innerContent, 600, 420);
gen += '</td><td><img src="'+webimRoot+'/images/free.gif" width="5" height="1" border="0" alt=""></td>';
if( canopen ) {
gen += '<td width="30" align="center">';
gen += HtmlGenerationUtils.popupLink( link, localized[0], "ImCenter"+id, '<img src="'+webimRoot+'/images/tbliclspeak.gif" width="15" height="15" border="0" alt="'+localized[0]+'">', 600, 420);
gen += '</td>';
cellsCount++;
}
return HtmlGenerationUtils.generateOneRowTable(gen);
}
};
Ajax.ThreadListUpdater = Class.create();
Class.inherit( Ajax.ThreadListUpdater, Ajax.Base, {
initialize: function(_options) {
this.setOptions(_options);
this._options.updateParams = this.updateParams.bind(this);
this._options.handleError = this.handleError.bind(this);
this._options.updateContent = this.updateContent.bind(this);
this._options.lastrevision = 0;
this.threadTimers = new Object();
this.delta = 0;
this.t = this._options.table;
this.periodicalUpdater = new Ajax.PeriodicalUpdater(this._options);
},
updateParams: function() {
return "company=" + this._options.company + "&since=" + this._options.lastrevision;
},
setStatus: function(msg) {
this._options.status.innerHTML = msg;
},
handleError: function(s) {
this.setStatus( s );
},
updateThread: function(node) {
var id, stateid, vstate, canview = false, canopen = false, ban = null;
for( var i = 0; i < node.attributes.length; i++ ) {
var attr = node.attributes[i];
if( attr.nodeName == "id" )
id = attr.nodeValue;
else if( attr.nodeName == "stateid" )
stateid = attr.nodeValue;
else if( attr.nodeName == "state" )
vstate = attr.nodeValue;
else if( attr.nodeName == "canopen" )
canopen = true;
}
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
var row = CommonUtils.getRow("thr"+id, this.t);
if( stateid == "closed" ) {
if( row ) {
HtmlGenerationUtils.removeHr(this.t, row.rowIndex+1);
this.t.deleteRow(row.rowIndex);
}
this.threadTimers[id] = null;
return;
}
var vname = NodeUtils.getNodeValue(node,"name");
var vaddr = NodeUtils.getNodeValue(node,"addr");
var vtime = NodeUtils.getNodeValue(node,"time");
var agent = NodeUtils.getNodeValue(node,"agent");
var modified = NodeUtils.getNodeValue(node,"modified");
var message = NodeUtils.getNodeValue(node,"message");
var etc = "";
var startRow = CommonUtils.getRow(stateid, this.t);
var endRow = CommonUtils.getRow(stateid+"end", this.t);
if( row != null && (row.rowIndex <= startRow.rowIndex || row.rowIndex >= endRow.rowIndex ) ) {
HtmlGenerationUtils.removeHr(this.t, row.rowIndex+1);
this.t.deleteRow(row.rowIndex);
this.threadTimers[id] = null;
row = null;
}
if( row == null ) {
row = this.t.insertRow(startRow.rowIndex+1);
HtmlGenerationUtils.insertHr(this.t, startRow.rowIndex+2);
row.id = "thr"+id;
this.threadTimers[id] = new Array(vtime,modified,stateid);
CommonUtils.insertCell(row, "name", "table", null, 30, HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message) );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "contid", "table", "center", null, vaddr );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "state", "table", "center", null, vstate );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "op", "table", "center", null, agent );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "time", "table", "center", null, this.getTimeSince(vtime) );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "wait", "table", "center", null, (stateid!='chat' ? this.getTimeSince(modified) : '-') );
HtmlGenerationUtils.insertSplitter(row);
CommonUtils.insertCell(row, "etc", "table", "center", null, etc );
if( stateid == 'wait' || stateid == 'prio' )
return true;
} else {
this.threadTimers[id] = new Array(vtime,modified,stateid);
setcell(this.t, row,"name",HtmlGenerationUtils.viewOpenCell(vname,this._options.agentservl,id,canview,canopen,ban,message));
setcell(this.t, row,"contid",vaddr);
setcell(this.t, row,"state",vstate);
setcell(this.t, row,"op",agent);
setcell(this.t, row,"time",this.getTimeSince(vtime));
setcell(this.t, row,"wait",(stateid!='chat' ? this.getTimeSince(modified) : '-'));
setcell(this.t, row,"etc",etc);
}
return false;
},
updateQueueMessages: function() {
function updateQueue(t,id,nclients) {
var startRow = t.rows[id];
var endRow = t.rows[id+"end"];
if( startRow == null || endRow == null )
return;
var _status = endRow.cells["status"];
if( _status == null )
return;
_status.innerHTML = (startRow.rowIndex + 1 == endRow.rowIndex) ? nclients : "";
_status.height = (startRow.rowIndex + 1 == endRow.rowIndex) ? 30 : 10;
}
updateQueue(this.t, "wait", this._options.noclients);
updateQueue(this.t, "prio", this._options.noclients);
updateQueue(this.t, "chat", this._options.noclients);
},
getTimeSince: function(srvtime) {
var secs = Math.floor(((new Date()).getTime()-srvtime-this.delta)/1000);
var minutes = Math.floor(secs/60);
var prefix = "";
secs = secs % 60;
if( secs < 10 )
secs = "0" + secs;
if( minutes >= 60 ) {
var hours = Math.floor(minutes/60);
minutes = minutes % 60;
if( minutes < 10 )
minutes = "0" + minutes;
prefix = hours + ":";
}
return prefix + minutes+":"+secs;
},
updateTimers: function() {
for (var i in this.threadTimers) {
if (this.threadTimers[i] != null) {
var value = this.threadTimers[i];
var row = CommonUtils.getRow("thr"+i, this.t);
if( row != null ) {
function setcell(_table, row,id,pcontent) {
var cell = CommonUtils.getCell( id, row, _table );
if( cell )
cell.innerHTML = pcontent;
}
setcell(this.t, row,"time",this.getTimeSince(value[0]));
setcell(this.t, row,"wait",(value[2]!='chat' ? this.getTimeSince(value[1]) : '-'));
}
}
}
},
updateContent: function(xmldoc) {
var root = xmldoc.documentElement;
var newAdded = false;
if( root.tagName == 'threads' ) {
var _time = NodeUtils.getAttrValue(root, "time");
var _revision = NodeUtils.getAttrValue(root, "revision" );
if( _time )
this.delta = (new Date()).getTime() - _time;
if( _revision )
this._options.lastrevision = _revision;
for( var i = 0; i < root.childNodes.length; i++ ) {
var node = root.childNodes[i];
if( node.tagName == 'thread' )
if( this.updateThread(node) )
newAdded = true;
}
this.updateQueueMessages();
this.updateTimers();
this.setStatus( "Up to date" );
if( newAdded )
window.focus();
} else if( root.tagName == 'error' ) {
this.setStatus( "error: " + NodeUtils.getNodeValue(root,"descr") );
} else {
this.setStatus( "wrong response" );
}
}
});
var webimRoot = "";
EventHelper.register(window, 'onload', function(){
webimRoot = updaterOptions.wroot;
new Ajax.ThreadListUpdater(({table:$("threadlist"),status:$("connstatus")}).extend(updaterOptions || {}));
});