mirror of
https://github.com/Mibew/design.git
synced 2024-11-15 09:24:12 +03:00
Implement new chat system
This commit is contained in:
parent
f1224a98ee
commit
30cb668a73
@ -1,25 +1,30 @@
|
||||
/*
|
||||
This file is part of Mibew Messenger project.
|
||||
http://mibew.org
|
||||
|
||||
|
||||
Copyright (c) 2005-2011 Mibew Messenger Community
|
||||
License: http://mibew.org/license.php
|
||||
*/
|
||||
var FrameUtils={getDocument:function(a){return a.contentDocument?a.contentDocument:a.contentWindow?a.contentWindow.document:a.document?a.document:null},initFrame:function(a){var b=this.getDocument(a);b.open();b.write("<html><head>");b.write('<link rel="stylesheet" type="text/css" media="all" href="'+Chat.cssfile+'">');b.write("</head><body bgcolor='#FFFFFF' text='#000000' link='#C28400' vlink='#C28400' alink='#C28400'>");b.write("<table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td valign='top' class='message' id='content'></td></tr></table><a id='bottom' name='bottom'></a>");
|
||||
b.write("</body></html>");b.close();a.onload=function(){a.myHtml&&(FrameUtils.getDocument(a).getElementById("content").innerHTML+=a.myHtml,FrameUtils.scrollDown(a))}},insertIntoFrame:function(a,b){var c=this.getDocument(a).getElementById("content");if(null==c){if(!a.myHtml)a.myHtml="";a.myHtml+=b}else c.innerHTML+=b},scrollDown:function(a){var b=this.getDocument(a).getElementById("bottom");if("opera"==myAgent)try{a.contentWindow.scrollTo(0,this.getDocument(a).getElementById("content").clientHeight)}catch(c){}b&&
|
||||
b.scrollIntoView(!1)}};Ajax.ChatThreadUpdater=Class.create();
|
||||
Class.inherit(Ajax.ChatThreadUpdater,Ajax.Base,{initialize:function(a){this.setOptions(a);this._options.onComplete=this.requestComplete.bind(this);this._options.onException=this.handleException.bind(this);this._options.onTimeout=this.handleTimeout.bind(this);this._options.timeout=5E3;this.updater={};this.frequency=this._options.frequency||2;this.lastupdate=0;this.focused=this.skipNextsound=this.cansend=!0;this.ownThread=null!=this._options.message;FrameUtils.initFrame(this._options.container);if(this._options.message)this._options.message.onkeydown=
|
||||
this.handleKeyDown.bind(this),this._options.message.onfocus=function(){this.focused=!0}.bind(this),this._options.message.onblur=function(){this.focused=!1}.bind(this);this.update()},handleException:function(){this.setStatus("offline, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},handleTimeout:function(){this.setStatus("timeout, reconnecting");this.stopUpdate();this.timer=setTimeout(this.update.bind(this),1E3)},updateOptions:function(a){this._options.parameters=
|
||||
"act="+a+"&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0)+"&lastid="+(this._options.lastid||0);this._options.user&&(this._options.parameters+="&user=true");"refresh"==a&&this._options.message&&""!=this._options.message.value&&(this._options.parameters+="&typed=1")},enableInput:function(a){if(this._options.message)this._options.message.disabled=!a},stopUpdate:function(){this.enableInput(!0);if(this.updater._options)this.updater._options.onComplete=void 0;clearTimeout(this.timer)},
|
||||
update:function(){this.updateOptions("refresh");this.updater=new Ajax.Request(this._options.servl,this._options)},requestComplete:function(a){try{this.enableInput(!0);this.cansend=!0;var b=Ajax.getXml(a);b&&"thread"==b.tagName?this.updateContent(b):this.handleError(a,b,"refresh messages failed")}catch(c){}this.skipNextsound=!1;this.timer=setTimeout(this.update.bind(this),1E3*this.frequency)},postMessage:function(a){if(""!=a&&this.cansend){this.cansend=!1;this.stopUpdate();this.skipNextsound=!0;this.updateOptions("post");
|
||||
var b={}.extend(this._options);b.parameters+="&message="+encodeURIComponent(a);b.onComplete=function(a){this.requestComplete(a);if(this._options.message)this._options.message.value="",this._options.message.focus()}.bind(this);"opera"!=myRealAgent&&this.enableInput(!1);this.updater=new Ajax.Request(this._options.servl,b)}},changeName:function(a){this.skipNextsound=!0;new Ajax.Request(this._options.servl,{parameters:"act=rename&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0)+
|
||||
"&name="+encodeURIComponent(a)})},onThreadClosed:function(a){var b=Ajax.getXml(a);b&&"closed"==b.tagName?setTimeout("window.close()",2E3):this.handleError(a,b,"cannot close")},closeThread:function(){if("undefined"!=typeof Chat.localizedStrings.closeConfirmation&&Chat.localizedStrings.closeConfirmation&&!confirm(Chat.localizedStrings.closeConfirmation))return!1;var a="act=close&thread="+(this._options.threadid||0)+"&token="+(this._options.token||0);this._options.user&&(a+="&user=true");new Ajax.Request(this._options.servl,
|
||||
{parameters:a,onComplete:this.onThreadClosed.bind(this)})},processMessage:function(a,b){var c=NodeUtils.getNodeText(b);FrameUtils.insertIntoFrame(a,c)},showTyping:function(a){if($("typingdiv"))$("typingdiv").style.display=a?"inline":"none"},setupAvatar:function(a){a=NodeUtils.getNodeText(a);if(this._options.avatar&&this._options.user)this._options.avatar.innerHTML=""!=a?'<img src="'+Chat.webimRoot+'/images/free.gif" width="7" height="1" border="0" alt="" /><img src="'+a+'" border="0" alt=""/>':""},
|
||||
updateContent:function(a){var b=!1,c=this._options.container,d=NodeUtils.getAttrValue(a,"lastid");if(d)this._options.lastid=d;(d=NodeUtils.getAttrValue(a,"typing"))&&this.showTyping("1"==d);if((d=NodeUtils.getAttrValue(a,"canpost"))&&("1"==d&&!this.ownThread||this.ownThread&&"1"!=d))window.location.href=window.location.href;for(d=0;d<a.childNodes.length;d++){var e=a.childNodes[d];"message"==e.tagName?(b=!0,this.processMessage(c,e)):"avatar"==e.tagName&&this.setupAvatar(e)}0<=window.location.search.indexOf("trace=on")?
|
||||
(a="updated",0<this.lastupdate&&(c=((new Date).getTime()-this.lastupdate)/1E3,a=a+", "+c+" secs",10<c&&alert(a)),this.lastupdate=(new Date).getTime(),this.setStatus(a)):this.clearStatus();b&&(FrameUtils.scrollDown(this._options.container),this.skipNextsound||(b=$("soundimg"),(null==b||b.className.match(/\bisound\b/))&&playSound(Chat.webimRoot+"/sounds/new_message.wav")),this.focused||window.focus())},isSendkey:function(a,b){return 13==b&&(a||this._options.ignorectrl)||10==b},handleKeyDown:function(a){a?
|
||||
(ctrl=a.ctrlKey,a=a.which):(a=event.keyCode,ctrl=event.ctrlKey);return this._options.message&&this.isSendkey(ctrl,a)?(a=this._options.message.value,this._options.ignorectrl&&(a=a.replace(/[\r\n]+$/,"")),this.postMessage(a),!1):!0},handleError:function(a,b){b&&"error"==b.tagName?this.setStatus(NodeUtils.getNodeValue(b,"descr")):this.setStatus("reconnecting")},showStatusDiv:function(a){if($("engineinfo"))$("engineinfo").style.display="inline",$("engineinfo").innerHTML=a},setStatus:function(a){this.statusTimeout&&
|
||||
clearTimeout(this.statusTimeout);this.showStatusDiv(a);this.statusTimeout=setTimeout(this.clearStatus.bind(this),4E3)},clearStatus:function(){$("engineinfo").style.display="none"}});
|
||||
b.write("</body></html>");b.close();a.onload=function(){a.myHtml&&(FrameUtils.getDocument(a).getElementById("content").innerHTML+=a.myHtml,FrameUtils.scrollDown(a))}},insertIntoFrame:function(a,b){var c=this.getDocument(a).getElementById("content");null==c?(a.myHtml||(a.myHtml=""),a.myHtml+=b):c.innerHTML+=b},scrollDown:function(a){var b=this.getDocument(a).getElementById("bottom");if("opera"==myAgent)try{a.contentWindow.scrollTo(0,this.getDocument(a).getElementById("content").clientHeight)}catch(c){}b&&
|
||||
b.scrollIntoView(!1)}};ChatServer=Class.create();
|
||||
ChatServer.prototype={initialize:function(a){this.updateTimer=null;this.options={servl:"",requestsFrequency:2,onTimeout:function(){},onTransportError:function(){},onCallError:function(){},onUpdateError:function(){},onResponseError:function(){}}.extend(a);this.callbacks={};this.callPeriodically=[];this.ajaxOptions={_method:"post",asynchronous:!0,timeout:5E3,onComplete:this.receiveResponse.bind(this),onException:this.onTransportError.bind(this),onTimeout:this.onTimeout.bind(this)};this.ajaxRequest=
|
||||
null;this.buffer=[];this.functions={};this.mibewAPI=new MibewAPI(new MibewAPICoreInteraction)},callFunctions:function(a,b,c){try{if(!(a instanceof Array))throw Error("The first arguments must be an array");for(var d in a)a.hasOwnProperty(d)&&this.mibewAPI.checkFunction(a[d],!1);var e=this.generateToken();this.callbacks[e]=b;this.buffer.push({token:e,functions:a});c&&this.update()}catch(f){return this.options.onCallError(f),!1}return!0},callFunctionsPeriodically:function(a,b){this.callPeriodically.push({functionsListBuilder:a,
|
||||
callbackFunction:b})},generateToken:function(){var a;do a="wnd"+(new Date).getTime().toString()+Math.round(50*Math.random()).toString();while(a in this.callbacks);return a},processRequest:function(a){var b=new MibewAPIExecutionContext,c=this.mibewAPI.getResultFunction(a.functions,this.callbacks.hasOwnProperty(a.token));if(null===c)for(var d in a.functions)a.functions.hasOwnProperty(d)&&(this.processFunction(a.functions[d],b),this.buffer.push(this.mibewAPI.buildResult(b.getResults(),a.token)));else this.callbacks.hasOwnProperty(a.token)&&
|
||||
(this.callbacks[a.token](c.arguments),delete this.callbacks[a.token])},processFunction:function(a,b){if(this.functions.hasOwnProperty(a["function"])){var c=b.getArgumentsList(a),d={},e;for(e in this.functions[a["function"]])this.functions[a["function"]].hasOwnProperty(e)&&d.extend(this.functions[a["function"]][e](c));b.storeFunctionResults(a,d)}},sendRequests:function(a){this.ajaxRequest=new Ajax.Request(this.options.servl,this.ajaxOptions.extend({parameters:"data="+this.mibewAPI.encodePackage(a)}))},
|
||||
runUpdater:function(){null==this.updateTimer&&this.update();this.updateTimer=setTimeout(this.update.bind(this),1E3*this.options.requestsFrequency)},restartUpdater:function(){this.updateTimer&&clearTimeout(this.updateTimer);this.ajaxRequest._options&&(this.ajaxRequest._options.onComplete=void 0);this.update();this.updateTimer=setTimeout(this.update.bind(this),1E3)},update:function(){this.updateTimer&&clearTimeout(this.updateTimer);for(var a=0;a<this.callPeriodically.length;a++)this.callFunctions(this.callPeriodically[a].functionsListBuilder(),
|
||||
this.callPeriodically[a].callbackFunction);if(0==this.buffer.length)this.runUpdater();else try{this.sendRequests(this.buffer),this.buffer=[]}catch(b){this.options.onUpdateError(b)}},receiveResponse:function(a){""==a.response&&this.runUpdater();try{var b=this.mibewAPI.decodePackage(a.response),c;for(c in b.requests)this.processRequest(b.requests[c])}catch(d){this.options.onResponseError(d)}finally{this.runUpdater()}},registerFunction:function(a,b){a in this.functions||(this.functions[a]=[]);this.functions[a].push(b)},
|
||||
onTransportError:function(a,b){this.restartUpdater();this.options.onTransportError(b)},onTimeout:function(){this.restartUpdater();this.options.onTimeout()}};ChatThreadUpdater=Class.create();
|
||||
ChatThreadUpdater.prototype={initialize:function(a,b,c){this._options=c;this.thread={threadid:0,token:0,lastid:0,user:!1}.extend(b||{});this.chatServer=a;this.focused=this.skipNextsound=this.cansend=!0;this.ownThread=null!=this._options.message;FrameUtils.initFrame(this._options.container);this._options.message&&(this._options.message.onkeydown=this.handleKeyDown.bind(this),this._options.message.onfocus=function(){this.focused=!0}.bind(this),this._options.message.onblur=function(){this.focused=!1}.bind(this));
|
||||
this.chatServer.callFunctionsPeriodically(this.updateFunctionBuilder.bind(this),this.updateChatState.bind(this));this.chatServer.registerFunction("updateMessages",this.updateMessages.bind(this));this.chatServer.registerFunction("setupAvatar",this.setupAvatar.bind(this));this.chatServer.runUpdater()},handleException:function(){this.setStatus("offline, reconnecting");this.enableInput(!0)},handleTimeout:function(){this.setStatus("timeout, reconnecting");this.enableInput(!0)},enableInput:function(a){this._options.message&&
|
||||
(this._options.message.disabled=!a)},refresh:function(){this.chatServer.restartUpdater()},postMessage:function(a){""!=a&&this.cansend&&(this.cansend=!1,this.skipNextsound=!0,"opera"!=myRealAgent&&this.enableInput(!1),this.chatServer.callFunctions([{"function":"post",arguments:{references:{},"return":{},message:a,threadId:this.thread.threadid,token:this.thread.token,user:this.thread.user}}],function(){this.enableInput(!0);this.cansend=!0;this.skipNextsound=!1;this._options.message&&(this._options.message.value=
|
||||
"",this._options.message.focus())}.bind(this),!0))},changeName:function(a){this.skipNextsound=!0;this.chatServer.callFunctions([{"function":"rename",arguments:{references:{},"return":{},threadId:this.thread.threadid,token:this.thread.token,name:a}}],function(a){a.errorCode&&this.handleError(a,"cannot rename")}.bind(this),!0)},closeThread:function(){(!this._options.localizedStrings.closeConfirmation||confirm(this._options.localizedStrings.closeConfirmation))&&this.chatServer.callFunctions([{"function":"close",
|
||||
arguments:{references:{},"return":{closed:"closed"},threadId:this.thread.threadid,token:this.thread.token,lastId:this.thread.lastid,user:this.thread.user}}],this.onThreadClosed.bind(this),!0)},onThreadClosed:function(a){a.closed?window.close():this.handleError(a,"cannot close")},processMessage:function(a,b){FrameUtils.insertIntoFrame(a,b)},showTyping:function(a){$("typingdiv")&&($("typingdiv").style.display=a?"inline":"none")},setupAvatar:function(a){this._options.avatar&&this.thread.user&&(this._options.avatar.innerHTML=
|
||||
""!=a.imageLink?'<img src="'+this._options.webimRoot+'/images/free.gif" width="7" height="1" border="0" alt="" /><img src="'+a.imageLink+'" border="0" alt=""/>':"")},updateMessages:function(a){a.lastId&&(this.thread.lastid=a.lastId);for(var b=0;b<a.messages.length;b++)this.processMessage(this._options.container,a.messages[b]);this.clearStatus();0<a.messages.length&&(FrameUtils.scrollDown(this._options.container),this.skipNextsound||(a=$("soundimg"),(null==a||a.className.match(/\bisound\b/))&&playSound(this._options.webimRoot+
|
||||
"/sounds/new_message.wav")),this.focused||window.focus());this.skipNextsound=!1},updateFunctionBuilder:function(){return[{"function":"update",arguments:{"return":{typing:"typing",canPost:"canPost"},references:{},threadId:this.thread.threadid,token:this.thread.token,lastId:this.thread.lastid,typed:this._options.message&&""!=this._options.message.value,user:this.thread.user}}]},updateChatState:function(a){if(a.errorCode)this.handleError(a,"refresh failed");else if("undefined"!=typeof a.typing&&this.showTyping(a.typing),
|
||||
"undefined"!=typeof a.canPost&&(a.canPost&&!this.ownThread||this.ownThread&&!a.canPost))window.location.href=window.location.href},isSendkey:function(a,b){return 13==b&&(a||this._options.ignorectrl)||10==b},handleKeyDown:function(a){a?(ctrl=a.ctrlKey,a=a.which):(a=event.keyCode,ctrl=event.ctrlKey);return this._options.message&&this.isSendkey(ctrl,a)?(a=this._options.message.value,this._options.ignorectrl&&(a=a.replace(/[\r\n]+$/,"")),this.postMessage(a),!1):!0},handleError:function(a){a.errorCode?
|
||||
this.setStatus(a.errorMessage):this.setStatus("reconnecting")},showStatusDiv:function(a){$("engineinfo")&&($("engineinfo").style.display="inline",$("engineinfo").innerHTML=a)},setStatus:function(a){this.statusTimeout&&clearTimeout(this.statusTimeout);this.showStatusDiv(a);this.statusTimeout=setTimeout(this.clearStatus.bind(this),4E3)},clearStatus:function(){$("engineinfo").style.display="none"}};
|
||||
var Chat={threadUpdater:{},applyName:function(){Chat.threadUpdater.changeName($("uname").value);$("changename1").style.display="none";$("changename2").style.display="inline";$("unamelink").innerHTML=htmlescape($("uname").value)},showNameField:function(){$("changename1").style.display="inline";$("changename2").style.display="none"}};
|
||||
Behaviour.register({"#postmessage a":function(a){a.onclick=function(){var a=$("msgwnd");a&&Chat.threadUpdater.postMessage(a.value)}},"select#predefined":function(a){a.onchange=function(){var a=$("msgwnd");if(0!=this.selectedIndex)a.value=Chat.predefinedAnswers[this.selectedIndex-1];this.selectedIndex=0;a.focus()}},"div#changename2 a":function(a){a.onclick=function(){Chat.showNameField();return!1}},"div#changename1 a":function(a){a.onclick=function(){Chat.applyName();return!1}},"div#changename1 input#uname":function(a){a.onkeydown=
|
||||
function(a){13==(a||event).keyCode&&Chat.applyName()}},"a#refresh":function(a){a.onclick=function(){Chat.threadUpdater.stopUpdate();Chat.threadUpdater.update()}},"a#togglesound":function(a){a.onclick=function(){var a=$("soundimg");if(a)a.className=a.className.match(/\bisound\b/)?"tplimage inosound":"tplimage isound",(a=$("msgwnd"))&&a.focus()}},"a.closethread":function(a){a.onclick=function(){Chat.threadUpdater.closeThread()}}});
|
||||
EventHelper.register(window,"onload",function(){Chat.webimRoot=threadParams.wroot;Chat.cssfile=threadParams.cssfile;Chat.predefinedAnswers="undefined"!=typeof predefinedAnswers?predefinedAnswers:[];Chat.localizedStrings=localizedStrings;Chat.threadUpdater=new Ajax.ChatThreadUpdater({ignorectrl:-1,container:"safari"==myRealAgent?self.frames[0]:$("chatwnd"),avatar:$("avatarwnd"),message:$("msgwnd")}.extend(threadParams||{}))});
|
||||
Behaviour.register({"#postmessage a":function(a){a.onclick=function(){var a=$("msgwnd");a&&Chat.threadUpdater.postMessage(a.value)}},"select#predefined":function(a){a.onchange=function(){var a=$("msgwnd");0!=this.selectedIndex&&(a.value=Chat.predefinedAnswers[this.selectedIndex-1]);this.selectedIndex=0;a.focus()}},"div#changename2 a":function(a){a.onclick=function(){Chat.showNameField();return!1}},"div#changename1 a":function(a){a.onclick=function(){Chat.applyName();return!1}},"div#changename1 input#uname":function(a){a.onkeydown=
|
||||
function(a){13==(a||event).keyCode&&Chat.applyName()}},"a#refresh":function(a){a.onclick=function(){Chat.threadUpdater.refresh()}},"a#togglesound":function(a){a.onclick=function(){var a=$("soundimg");a&&(a.className=a.className.match(/\bisound\b/)?"tplimage inosound":"tplimage isound",(a=$("msgwnd"))&&a.focus())}},"a.closethread":function(a){a.onclick=function(){Chat.threadUpdater.closeThread()}}});
|
||||
EventHelper.register(window,"onload",function(){Chat.cssfile=chatParams.cssfile;Chat.predefinedAnswers=chatParams.predefinedAnswers||[];Chat.localizedStrings=chatParams.localizedStrings;Chat.threadUpdater=new ChatThreadUpdater(new ChatServer(chatParams.serverParams),chatParams.threadParams,{ignorectrl:-1,container:"safari"==myRealAgent?self.frames[0]:$("chatwnd"),avatar:$("avatarwnd"),message:$("msgwnd")}.extend(chatParams.threadUpdaterParams||{}))});
|
||||
|
@ -59,220 +59,734 @@ var FrameUtils = {
|
||||
}
|
||||
};
|
||||
|
||||
Ajax.ChatThreadUpdater = Class.create();
|
||||
Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
|
||||
ChatServer = Class.create();
|
||||
/**
|
||||
* @todo Think about error handling
|
||||
*/
|
||||
ChatServer.prototype = {
|
||||
/**
|
||||
* @constructor
|
||||
*/
|
||||
initialize: function(options) {
|
||||
var chatServer = this;
|
||||
|
||||
initialize: function(_options) {
|
||||
this.setOptions(_options);
|
||||
this._options.onComplete = this.requestComplete.bind(this);
|
||||
this._options.onException = this.handleException.bind(this);
|
||||
this._options.onTimeout = this.handleTimeout.bind(this);
|
||||
this._options.timeout = 5000;
|
||||
this.updater = {};
|
||||
this.frequency = (this._options.frequency || 2);
|
||||
this.lastupdate = 0;
|
||||
this.cansend = true;
|
||||
this.skipNextsound = true;
|
||||
this.focused = true;
|
||||
this.ownThread = this._options.message != null;
|
||||
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();
|
||||
/**
|
||||
* Update timer
|
||||
*/
|
||||
this.updateTimer = null;
|
||||
|
||||
/**
|
||||
* Options for the ChatServer object
|
||||
* @private
|
||||
* @todo Check onResponseError handler
|
||||
*/
|
||||
this.options = {
|
||||
// Server gateway URL
|
||||
servl: "",
|
||||
// Frequency for automatic updater
|
||||
requestsFrequency: 2,
|
||||
// Call on request timeout
|
||||
onTimeout: function() {},
|
||||
// Call when transport error was caught
|
||||
onTransportError: function(e) {},
|
||||
// Call when callFunctions related error was caught
|
||||
onCallError: function(e) {},
|
||||
// Call when update related error was caught
|
||||
onUpdateError: function(e) {},
|
||||
// Call when response related error was caught
|
||||
onResponseError: function(e) {}
|
||||
}.extend(options);
|
||||
|
||||
/**
|
||||
* Binds request's token and callback function
|
||||
* @type Object
|
||||
* @private
|
||||
*/
|
||||
this.callbacks = {};
|
||||
|
||||
/**
|
||||
* Array of periodically called functions
|
||||
* @type Array
|
||||
* @private
|
||||
*/
|
||||
this.callPeriodically = [];
|
||||
|
||||
/**
|
||||
* Options for an Ajax.Request object
|
||||
* @type Array
|
||||
* @private
|
||||
*/
|
||||
this.ajaxOptions = {
|
||||
_method: 'post',
|
||||
asynchronous: true,
|
||||
timeout: 5000,
|
||||
onComplete: chatServer.receiveResponse.bind(chatServer),
|
||||
onException: chatServer.onTransportError.bind(chatServer),
|
||||
onTimeout: chatServer.onTimeout.bind(chatServer)
|
||||
}
|
||||
|
||||
/**
|
||||
* An object of the Ajax.Request class
|
||||
* @type Ajax.Request
|
||||
* @private
|
||||
*/
|
||||
this.ajaxRequest = null;
|
||||
|
||||
/**
|
||||
* This buffer store requests and responses between sending packages
|
||||
* @private
|
||||
*/
|
||||
this.buffer = [];
|
||||
|
||||
/**
|
||||
* Contains object of registered functions handlers
|
||||
* @private
|
||||
*/
|
||||
this.functions = {}
|
||||
|
||||
/**
|
||||
* An instance of the MibewAPI class
|
||||
* @type MibewAPI
|
||||
* @private
|
||||
*/
|
||||
this.mibewAPI = new MibewAPI(new MibewAPICoreInteraction());
|
||||
},
|
||||
|
||||
handleException: function(_request, ex) {
|
||||
this.setStatus("offline, reconnecting");
|
||||
this.stopUpdate();
|
||||
this.timer = setTimeout(this.update.bind(this), 1000);
|
||||
/**
|
||||
* Make call to the chat server
|
||||
*
|
||||
* @param {Oblect[]} functionsList List of the function objects. See Mibew API
|
||||
* for details.
|
||||
* @param {Function} callbackFunction
|
||||
* @param {Boolean} forceSend Force requests buffer send right after call
|
||||
* @returns {Boolean} boolean true on success and false on failure
|
||||
*/
|
||||
callFunctions: function(functionsList, callbackFunction, forceSend) {
|
||||
try {
|
||||
// Check function objects
|
||||
if (!(functionsList instanceof Array)) {
|
||||
throw new Error("The first arguments must be an array");
|
||||
}
|
||||
for (var i in functionsList) {
|
||||
// Filter 'Prototype' properties
|
||||
if (! functionsList.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
this.mibewAPI.checkFunction(functionsList[i], false);
|
||||
}
|
||||
|
||||
// Generate request token
|
||||
var token = this.generateToken();
|
||||
// Store callback function
|
||||
this.callbacks[token] = callbackFunction;
|
||||
|
||||
// Add request to buffer
|
||||
this.buffer.push({
|
||||
'token': token,
|
||||
'functions': functionsList
|
||||
});
|
||||
if (forceSend) {
|
||||
// Force update
|
||||
this.update();
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle errors
|
||||
this.options.onCallError(e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
handleTimeout: function(_request) {
|
||||
this.setStatus("timeout, reconnecting");
|
||||
this.stopUpdate();
|
||||
this.timer = setTimeout(this.update.bind(this), 1000);
|
||||
/**
|
||||
* Call function at every request to build functions list
|
||||
*
|
||||
* @param {Function} functionsListBuilder Call before every request to build a
|
||||
* list of functions that must be called
|
||||
* @param {Function} callbackFunction Call after response received
|
||||
*/
|
||||
callFunctionsPeriodically: function(functionsListBuilder, callbackFunction) {
|
||||
this.callPeriodically.push({
|
||||
functionsListBuilder: functionsListBuilder,
|
||||
callbackFunction: callbackFunction
|
||||
});
|
||||
},
|
||||
|
||||
updateOptions: function(act) {
|
||||
this._options.parameters = 'act='+act+'&thread=' + (this._options.threadid || 0) +
|
||||
'&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";
|
||||
/**
|
||||
* Generates unique request token
|
||||
*
|
||||
* @private
|
||||
* @returns {String} Request token
|
||||
*/
|
||||
generateToken: function() {
|
||||
var token;
|
||||
do {
|
||||
// Create token
|
||||
token = "wnd" +
|
||||
(new Date()).getTime().toString() +
|
||||
(Math.round(Math.random() * 50)).toString();
|
||||
// Check token uniqueness
|
||||
} while(token in this.callbacks);
|
||||
return token;
|
||||
},
|
||||
|
||||
enableInput: function(val) {
|
||||
if( this._options.message )
|
||||
this._options.message.disabled = !val;
|
||||
/**
|
||||
* Process request
|
||||
*
|
||||
* @param {Object} requestObject Request object. See Mibew API for details.
|
||||
* @private
|
||||
*/
|
||||
processRequest: function(requestObject) {
|
||||
var context = new MibewAPIExecutionContext();
|
||||
|
||||
// Get result function
|
||||
var resultFunction = this.mibewAPI.getResultFunction(
|
||||
requestObject.functions,
|
||||
this.callbacks.hasOwnProperty(requestObject.token)
|
||||
);
|
||||
|
||||
if (resultFunction === null) {
|
||||
// Result function not found
|
||||
for (var i in requestObject.functions) {
|
||||
if (! requestObject.functions.hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
// Execute functions
|
||||
this.processFunction(requestObject.functions[i], context);
|
||||
// Build and store result
|
||||
this.buffer.push(this.mibewAPI.buildResult(
|
||||
context.getResults(),
|
||||
requestObject.token
|
||||
));
|
||||
}
|
||||
} else {
|
||||
// Result function found
|
||||
if (this.callbacks.hasOwnProperty(requestObject.token)) {
|
||||
// Invoke callback
|
||||
this.callbacks[requestObject.token](resultFunction.arguments);
|
||||
// Remove callback
|
||||
delete this.callbacks[requestObject.token];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
stopUpdate: function() {
|
||||
this.enableInput(true);
|
||||
if( this.updater._options )
|
||||
this.updater._options.onComplete = undefined;
|
||||
clearTimeout(this.timer);
|
||||
/**
|
||||
* Process function
|
||||
*
|
||||
* @param {Object} functionObject Function object. See Mibew API for details
|
||||
* @param {MibewAPIExecutionContext} context Execution context
|
||||
* @private
|
||||
*/
|
||||
processFunction: function(functionObject, context) {
|
||||
if (! this.functions.hasOwnProperty(functionObject["function"])) {
|
||||
return;
|
||||
}
|
||||
// Get function arguments with replaced refences
|
||||
var functionArguments = context.getArgumentsList(functionObject);
|
||||
|
||||
var results = {};
|
||||
for (var i in this.functions[functionObject["function"]]) {
|
||||
if (! this.functions[functionObject["function"]].hasOwnProperty(i)) {
|
||||
continue;
|
||||
}
|
||||
// Get results
|
||||
results.extend(this.functions[functionObject["function"]][i](
|
||||
functionArguments
|
||||
));
|
||||
}
|
||||
|
||||
// Add function results to the execution context
|
||||
context.storeFunctionResults(functionObject, results);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send the request to the chat server
|
||||
*
|
||||
* @param {Object[]} requestsList Array of requests that must be sent to the
|
||||
* chat server
|
||||
* @private
|
||||
*/
|
||||
sendRequests: function(requestsList) {
|
||||
// Create new AJAX request
|
||||
this.ajaxRequest = new Ajax.Request(
|
||||
this.options.servl,
|
||||
this.ajaxOptions.extend({
|
||||
parameters: 'data=' + this.mibewAPI.encodePackage(requestsList)
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets up next automatic updater iteration
|
||||
*/
|
||||
runUpdater: function() {
|
||||
if (this.updateTimer == null) {
|
||||
this.update();
|
||||
}
|
||||
this.updateTimer = setTimeout(
|
||||
this.update.bind(this),
|
||||
this.options.requestsFrequency * 1000
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Restarts the automatic updater
|
||||
*/
|
||||
restartUpdater: function() {
|
||||
// Clear timeout
|
||||
if (this.updateTimer) {
|
||||
clearTimeout(this.updateTimer);
|
||||
}
|
||||
// Clear request onComplete callback
|
||||
if (this.ajaxRequest._options) {
|
||||
this.ajaxRequest._options.onComplete = undefined;
|
||||
}
|
||||
// Update thread
|
||||
this.update();
|
||||
// Restart updater. Try to reconnect after a while
|
||||
this.updateTimer = setTimeout(
|
||||
this.update.bind(this),
|
||||
1000
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send request for update thread and client code's requests
|
||||
* @private
|
||||
*/
|
||||
update: function() {
|
||||
this.updateOptions("refresh");
|
||||
this.updater = new Ajax.Request(this._options.servl, this._options);
|
||||
if (this.updateTimer) {
|
||||
clearTimeout(this.updateTimer);
|
||||
}
|
||||
for (var i = 0; i < this.callPeriodically.length; i++) {
|
||||
this.callFunctions(
|
||||
this.callPeriodically[i].functionsListBuilder(),
|
||||
this.callPeriodically[i].callbackFunction
|
||||
);
|
||||
}
|
||||
// Check buffer length
|
||||
if (this.buffer.length == 0) {
|
||||
// Rerun updater later
|
||||
this.runUpdater();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Send requests
|
||||
this.sendRequests(this.buffer);
|
||||
// Clear requests buffer
|
||||
this.buffer = [];
|
||||
} catch (e) {
|
||||
// Handle errors
|
||||
this.options.onUpdateError(e);
|
||||
}
|
||||
},
|
||||
|
||||
requestComplete: function(_response) {
|
||||
try {
|
||||
/**
|
||||
* Process response from the Core
|
||||
*
|
||||
* @param {String} responseObject The response object provided by
|
||||
* Ajax.Request class
|
||||
* @private
|
||||
*/
|
||||
receiveResponse: function(responseObject) {
|
||||
// Do not parse empty responses
|
||||
if (responseObject.response == '') {
|
||||
this.runUpdater();
|
||||
}
|
||||
try {
|
||||
var packageObject = this.mibewAPI.decodePackage(responseObject.response);
|
||||
for (var i in packageObject.requests) {
|
||||
this.processRequest(packageObject.requests[i]);
|
||||
}
|
||||
} catch (e) {
|
||||
this.options.onResponseError(e);
|
||||
} finally {
|
||||
this.runUpdater();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add function that can be called by the Core
|
||||
*
|
||||
* @param {String} functionName Name of the function
|
||||
* @param {Function} handler Provided function
|
||||
*/
|
||||
registerFunction: function(functionName, handler) {
|
||||
if (!(functionName in this.functions)) {
|
||||
this.functions[functionName] = [];
|
||||
}
|
||||
this.functions[functionName].push(handler);
|
||||
},
|
||||
|
||||
/**
|
||||
* Call on all AJAX transport errors
|
||||
* @param {Ajax.Request} transport AJAX Transport object
|
||||
* @param {Error} e Error object
|
||||
*/
|
||||
onTransportError: function (transport, e) {
|
||||
this.restartUpdater();
|
||||
this.options.onTransportError(e);
|
||||
},
|
||||
|
||||
/**
|
||||
* Call on all timeouts
|
||||
*/
|
||||
onTimeout: function(transport) {
|
||||
this.restartUpdater();
|
||||
this.options.onTimeout()
|
||||
}
|
||||
}
|
||||
|
||||
ChatThreadUpdater = Class.create();
|
||||
ChatThreadUpdater.prototype = {
|
||||
/**
|
||||
* @constructor
|
||||
* @todo Add error handlers to chatServer
|
||||
* @todo Think about code format
|
||||
*/
|
||||
initialize: function(chatServer, thread, options) {
|
||||
/**
|
||||
* Array of options
|
||||
* @type Array
|
||||
* @private
|
||||
*/
|
||||
this._options = options;
|
||||
|
||||
/**
|
||||
* An instance of the Thread class
|
||||
* @type ChatThread
|
||||
*/
|
||||
this.thread = {
|
||||
threadid: 0,
|
||||
token: 0,
|
||||
lastid: 0,
|
||||
user: false
|
||||
}.extend(thread || {});
|
||||
|
||||
/**
|
||||
* An instance of the ChatServer class
|
||||
* @type ChatServer
|
||||
*/
|
||||
this.chatServer = chatServer;
|
||||
|
||||
/**
|
||||
* Indicates if user can post messages
|
||||
* @type Boolean
|
||||
*/
|
||||
this.cansend = true;
|
||||
|
||||
/**
|
||||
* Indicates if next message's sound must be skipped
|
||||
* @type Boolean
|
||||
*/
|
||||
this.skipNextsound = true;
|
||||
|
||||
/**
|
||||
* Indicates if message input area ihn focus
|
||||
* @type Boolean
|
||||
*/
|
||||
this.focused = true;
|
||||
|
||||
/**
|
||||
* Indicates the thread belong to this operator
|
||||
* @type Boolean
|
||||
*/
|
||||
this.ownThread = this._options.message != null;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// Add periodic functions
|
||||
this.chatServer.callFunctionsPeriodically(
|
||||
this.updateFunctionBuilder.bind(this),
|
||||
this.updateChatState.bind(this)
|
||||
);
|
||||
|
||||
// Register functions
|
||||
this.chatServer.registerFunction(
|
||||
'updateMessages',
|
||||
this.updateMessages.bind(this)
|
||||
);
|
||||
this.chatServer.registerFunction(
|
||||
'setupAvatar',
|
||||
this.setupAvatar.bind(this)
|
||||
);
|
||||
|
||||
this.chatServer.runUpdater();
|
||||
},
|
||||
|
||||
/**
|
||||
* Exception handler. Updates status message
|
||||
*/
|
||||
handleException: function(e) {
|
||||
this.setStatus("offline, reconnecting");
|
||||
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');
|
||||
}
|
||||
} catch (e) {
|
||||
}
|
||||
this.skipNextsound = false;
|
||||
this.timer = setTimeout(this.update.bind(this), this.frequency * 1000);
|
||||
},
|
||||
|
||||
/**
|
||||
* Timeout handler. Updates status message
|
||||
*/
|
||||
handleTimeout: function() {
|
||||
this.setStatus("timeout, reconnecting");
|
||||
this.enableInput(true);
|
||||
},
|
||||
|
||||
/**
|
||||
* Enables or disables input field
|
||||
* @param {Boolean} val Use boolean true for enable input and false otherwise
|
||||
*/
|
||||
enableInput: function(val) {
|
||||
if( this._options.message ) {
|
||||
this._options.message.disabled = !val;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Load new messages by restarting thread updater.
|
||||
*/
|
||||
refresh: function() {
|
||||
this.chatServer.restartUpdater();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sends message to the chat server
|
||||
* @param {String} msg Message for send
|
||||
*/
|
||||
postMessage: function(msg) {
|
||||
if( msg == "" || !this.cansend) {
|
||||
return;
|
||||
}
|
||||
this.cansend = false;
|
||||
this.stopUpdate();
|
||||
this.skipNextsound = true;
|
||||
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);
|
||||
// Check if message can be sent
|
||||
if(msg == "" || !this.cansend) {
|
||||
return;
|
||||
}
|
||||
// Disable message sending
|
||||
this.cansend = false;
|
||||
// Disable next sound
|
||||
this.skipNextsound = true;
|
||||
// Disable input
|
||||
if(myRealAgent != 'opera') {
|
||||
this.enableInput(false);
|
||||
}
|
||||
// Post message
|
||||
this.chatServer.callFunctions(
|
||||
[{
|
||||
"function": "post",
|
||||
"arguments": {
|
||||
"references": {},
|
||||
"return": {},
|
||||
"message": msg,
|
||||
"threadId": this.thread.threadid,
|
||||
"token": this.thread.token,
|
||||
"user": this.thread.user
|
||||
}
|
||||
}],
|
||||
(function(){
|
||||
this.enableInput(true);
|
||||
this.cansend = true;
|
||||
this.skipNextsound = false;
|
||||
if(this._options.message) {
|
||||
this._options.message.value = '';
|
||||
this._options.message.focus();
|
||||
}
|
||||
}).bind(this),
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Change user name
|
||||
* @param {String} newname A new user name
|
||||
*/
|
||||
changeName: function(newname) {
|
||||
this.skipNextsound = true;
|
||||
new Ajax.Request(this._options.servl, {parameters:'act=rename&thread=' + (this._options.threadid || 0) +
|
||||
'&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');
|
||||
}
|
||||
this.skipNextsound = true;
|
||||
this.chatServer.callFunctions(
|
||||
[{
|
||||
"function": "rename",
|
||||
"arguments": {
|
||||
"references": {},
|
||||
"return": {},
|
||||
"threadId": this.thread.threadid,
|
||||
"token": this.thread.token,
|
||||
"name": newname
|
||||
}
|
||||
}],
|
||||
(function(args){
|
||||
if (args.errorCode) {
|
||||
this.handleError(args, 'cannot rename');
|
||||
}
|
||||
}).bind(this),
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send request for close chat to the core
|
||||
*/
|
||||
closeThread: function() {
|
||||
if(typeof Chat.localizedStrings.closeConfirmation != 'undefined' && Chat.localizedStrings.closeConfirmation){
|
||||
if(! confirm(Chat.localizedStrings.closeConfirmation)){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var _params = 'act=close&thread=' + (this._options.threadid || 0) + '&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)});
|
||||
// Show confirmation message if can
|
||||
if(this._options.localizedStrings.closeConfirmation){
|
||||
if(! confirm(this._options.localizedStrings.closeConfirmation)){
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Send request
|
||||
this.chatServer.callFunctions(
|
||||
[{
|
||||
"function": "close",
|
||||
"arguments": {
|
||||
"references": {},
|
||||
"return": {"closed": "closed"},
|
||||
"threadId": this.thread.threadid,
|
||||
"token": this.thread.token,
|
||||
"lastId": this.thread.lastid,
|
||||
"user": this.thread.user
|
||||
}
|
||||
}],
|
||||
this.onThreadClosed.bind(this),
|
||||
true
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback function for close chat request.
|
||||
*
|
||||
* Close chat window if closing success or warn on fail
|
||||
*/
|
||||
onThreadClosed: function(args) {
|
||||
if (args.closed) {
|
||||
window.close();
|
||||
} else {
|
||||
this.handleError(args, 'cannot close');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Add message to the message window
|
||||
* @param {Object} _target Target DOM element
|
||||
* @param {String} message HTML message to insert
|
||||
*/
|
||||
processMessage: function(_target, message) {
|
||||
var destHtml = NodeUtils.getNodeText(message);
|
||||
FrameUtils.insertIntoFrame(_target, destHtml );
|
||||
FrameUtils.insertIntoFrame(_target, message);
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays typing status
|
||||
* @param {Boolean} istyping Indicates the other side of conversation is
|
||||
* typing a message or not
|
||||
*/
|
||||
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=\"\"/>"
|
||||
: "";
|
||||
/**
|
||||
* Update operator's avatar
|
||||
* @param {Array} args Array of arguments passed from the core
|
||||
*/
|
||||
setupAvatar: function(args) {
|
||||
if (this._options.avatar && this.thread.user) {
|
||||
this._options.avatar.innerHTML = args.imageLink != ""
|
||||
? "<img src=\""+this._options.webimRoot+"/images/free.gif\" width=\"7\" height=\"1\" border=\"0\" alt=\"\" /><img src=\""
|
||||
+args.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');
|
||||
}
|
||||
|
||||
var canpost = NodeUtils.getAttrValue(xmlRoot, "canpost");
|
||||
if( canpost ) {
|
||||
if( canpost == '1' && !this.ownThread || this.ownThread && canpost != '1' ) {
|
||||
window.location.href = window.location.href;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
if(window.location.search.indexOf('trace=on')>=0) {
|
||||
var val = "updated";
|
||||
if(this.lastupdate > 0) {
|
||||
var seconds = ((new Date()).getTime() - this.lastupdate)/1000;
|
||||
val = val + ", " + seconds + " secs";
|
||||
if(seconds > 10) {
|
||||
alert(val);
|
||||
}
|
||||
}
|
||||
this.lastupdate = (new Date()).getTime();
|
||||
this.setStatus(val);
|
||||
} else {
|
||||
this.clearStatus();
|
||||
}
|
||||
if( haveMessage ) {
|
||||
FrameUtils.scrollDown(this._options.container);
|
||||
if(!this.skipNextsound) {
|
||||
var tsound = $('soundimg');
|
||||
if(tsound == null || tsound.className.match(new RegExp("\\bisound\\b")) ) {
|
||||
playSound(Chat.webimRoot+'/sounds/new_message.wav');
|
||||
}
|
||||
}
|
||||
if( !this.focused ) {
|
||||
window.focus();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add new messages to chat window
|
||||
* @param {Object} args object of function arguments passed from the server
|
||||
* @todo Fix skipNextSound
|
||||
*/
|
||||
updateMessages: function(args){
|
||||
// Update last message id
|
||||
if (args.lastId) {
|
||||
this.thread.lastid = args.lastId;
|
||||
}
|
||||
// Add messages
|
||||
for (var i = 0; i < args.messages.length; i++) {
|
||||
// TODO: Add template engine
|
||||
this.processMessage(this._options.container, args.messages[i]);
|
||||
}
|
||||
// Clear status string
|
||||
this.clearStatus();
|
||||
// There are some new messages
|
||||
if (args.messages.length > 0) {
|
||||
FrameUtils.scrollDown(this._options.container);
|
||||
if (!this.skipNextsound) {
|
||||
var tsound = $('soundimg');
|
||||
if (tsound == null || tsound.className.match(new RegExp("\\bisound\\b"))) {
|
||||
playSound(this._options.webimRoot+'/sounds/new_message.wav');
|
||||
}
|
||||
}
|
||||
if (!this.focused) {
|
||||
window.focus();
|
||||
}
|
||||
}
|
||||
this.skipNextsound = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Build update function to call at the core
|
||||
*/
|
||||
updateFunctionBuilder: function() {
|
||||
return [
|
||||
{
|
||||
"function": "update",
|
||||
"arguments": {
|
||||
"return": {'typing': 'typing', 'canPost': 'canPost'},
|
||||
"references": {},
|
||||
"threadId": this.thread.threadid,
|
||||
"token": this.thread.token,
|
||||
"lastId": this.thread.lastid,
|
||||
"typed": (this._options.message && this._options.message.value != ''),
|
||||
"user": this.thread.user
|
||||
}
|
||||
}
|
||||
];
|
||||
},
|
||||
|
||||
/**
|
||||
* Set current chat state message
|
||||
* @param {Array} args Array of arguments passed from the core
|
||||
*/
|
||||
updateChatState: function(args) {
|
||||
if (args.errorCode) {
|
||||
// Something went wrong
|
||||
this.handleError(args, 'refresh failed');
|
||||
return;
|
||||
}
|
||||
// Update typing indicator
|
||||
if (typeof args.typing != 'undefined') {
|
||||
this.showTyping(args.typing);
|
||||
}
|
||||
|
||||
// Check if user can post messages
|
||||
if (typeof args.canPost != 'undefined') {
|
||||
if ((args.canPost && !this.ownThread) || (this.ownThread && ! args.canPost)) {
|
||||
// Refresh the page
|
||||
window.location.href = window.location.href;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check if send key (Enter or Ctrl+Enter) pressed
|
||||
* @param {Boolean} ctrlpressed Indicates ctrl key is pressed or not
|
||||
* @param {Number} key Key code
|
||||
*/
|
||||
isSendkey: function(ctrlpressed, key) {
|
||||
return ((key==13 && (ctrlpressed || this._options.ignorectrl)) || (key==10));
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Key down handler
|
||||
*
|
||||
* @param {Object} k Event object
|
||||
*/
|
||||
handleKeyDown: function(k) {
|
||||
if( k ){ ctrl=k.ctrlKey;k=k.which; } else { k=event.keyCode;ctrl=event.ctrlKey; }
|
||||
if( k ){ctrl=k.ctrlKey;k=k.which;} else {k=event.keyCode;ctrl=event.ctrlKey;}
|
||||
if( this._options.message && this.isSendkey(ctrl, k) ) {
|
||||
var mmsg = this._options.message.value;
|
||||
if( this._options.ignorectrl ) {
|
||||
@ -284,14 +798,26 @@ Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
|
||||
return true;
|
||||
},
|
||||
|
||||
handleError: function(_response, xmlRoot, _action) {
|
||||
if( xmlRoot && xmlRoot.tagName == 'error' ) {
|
||||
this.setStatus(NodeUtils.getNodeValue(xmlRoot,"descr"));
|
||||
} else {
|
||||
this.setStatus("reconnecting");
|
||||
}
|
||||
/**
|
||||
* Update status message
|
||||
*
|
||||
* @param {Array} args Array of arguments. Must contain 'errorCode' and
|
||||
* 'errorMessage' keys
|
||||
* @param {String} descr Error description
|
||||
*/
|
||||
handleError: function(args, descr) {
|
||||
if (args.errorCode) {
|
||||
this.setStatus(args.errorMessage);
|
||||
} else {
|
||||
this.setStatus('reconnecting');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Displays status div and sets the status string into it
|
||||
*
|
||||
* @param {String} k Status string
|
||||
*/
|
||||
showStatusDiv: function(k) {
|
||||
if( $("engineinfo") ) {
|
||||
$("engineinfo").style.display='inline';
|
||||
@ -299,6 +825,11 @@ Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the status
|
||||
*
|
||||
* @param {String} k Status string
|
||||
*/
|
||||
setStatus: function(k) {
|
||||
if( this.statusTimeout )
|
||||
clearTimeout(this.statusTimeout);
|
||||
@ -306,11 +837,13 @@ Class.inherit( Ajax.ChatThreadUpdater, Ajax.Base, {
|
||||
this.statusTimeout = setTimeout(this.clearStatus.bind(this), 4000);
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the status string
|
||||
*/
|
||||
clearStatus: function() {
|
||||
$("engineinfo").style.display='none';
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var Chat = {
|
||||
threadUpdater : {},
|
||||
@ -368,8 +901,7 @@ Behaviour.register({
|
||||
},
|
||||
'a#refresh' : function(el) {
|
||||
el.onclick = function() {
|
||||
Chat.threadUpdater.stopUpdate();
|
||||
Chat.threadUpdater.update();
|
||||
Chat.threadUpdater.refresh();
|
||||
};
|
||||
},
|
||||
'a#togglesound' : function(el) {
|
||||
@ -396,9 +928,17 @@ Behaviour.register({
|
||||
});
|
||||
|
||||
EventHelper.register(window, 'onload', function(){
|
||||
Chat.webimRoot = threadParams.wroot;
|
||||
Chat.cssfile = threadParams.cssfile;
|
||||
Chat.predefinedAnswers = (typeof predefinedAnswers != 'undefined')?predefinedAnswers:Array();
|
||||
Chat.localizedStrings = localizedStrings;
|
||||
Chat.threadUpdater = new Ajax.ChatThreadUpdater(({ignorectrl:-1,container:myRealAgent=='safari'?self.frames[0]:$("chatwnd"),avatar:$("avatarwnd"),message:$("msgwnd")}).extend( threadParams || {} ));
|
||||
Chat.cssfile = chatParams.cssfile;
|
||||
Chat.predefinedAnswers = chatParams.predefinedAnswers || [];
|
||||
Chat.localizedStrings = chatParams.localizedStrings;
|
||||
Chat.threadUpdater = new ChatThreadUpdater(
|
||||
new ChatServer(chatParams.serverParams),
|
||||
chatParams.threadParams,
|
||||
{
|
||||
ignorectrl: -1,
|
||||
container: myRealAgent=='safari'?self.frames[0]:$("chatwnd"),
|
||||
avatar: $("avatarwnd"),
|
||||
message: $("msgwnd")
|
||||
}.extend(chatParams.threadUpdaterParams || {})
|
||||
);
|
||||
});
|
@ -26,33 +26,6 @@ function get_user_id()
|
||||
return (time() + microtime()) . rand(0, 99999999);
|
||||
}
|
||||
|
||||
function prepare_html_message($text, $allow_formating)
|
||||
{
|
||||
$escaped_text = htmlspecialchars($text);
|
||||
$text_w_links = preg_replace('/(https?|ftp):\/\/\S*/', '<a href="$0" target="_blank">$0</a>', $escaped_text);
|
||||
$multiline = str_replace("\n", "<br/>", $text_w_links);
|
||||
if (! $allow_formating) {
|
||||
return $multiline;
|
||||
}
|
||||
$formated = preg_replace('/<(span|strong)>(.*)<\/\1>/U', '<$1>$2</$1>', $multiline);
|
||||
$formated = preg_replace('/<span class="(.*)">(.*)<\/span>/U', '<span class="$1">$2</span>', $formated);
|
||||
return $formated;
|
||||
}
|
||||
|
||||
function message_to_html($msg)
|
||||
{
|
||||
if ($msg['ikind'] == Thread::KIND_AVATAR) {
|
||||
return "";
|
||||
}
|
||||
$message = "<span>" . date("H:i:s", $msg['created']) . "</span> ";
|
||||
$kind = Thread::kindToString($msg['ikind']);
|
||||
if ($msg['tname'])
|
||||
$message .= "<span class='n$kind'>" . htmlspecialchars($msg['tname']) . "</span>: ";
|
||||
$allow_formating = ($msg['ikind'] != Thread::KIND_USER && $msg['ikind'] != Thread::KIND_AGENT);
|
||||
$message .= "<span class='m$kind'>" . prepare_html_message($msg['tmessage'], $allow_formating) . "</span><br/>";
|
||||
return $message;
|
||||
}
|
||||
|
||||
function message_to_text($msg)
|
||||
{
|
||||
if ($msg['ikind'] == Thread::KIND_AVATAR) {
|
||||
@ -71,93 +44,6 @@ function message_to_text($msg)
|
||||
}
|
||||
}
|
||||
|
||||
function get_messages($threadid, $meth, $isuser, &$lastid)
|
||||
{
|
||||
global $webim_encoding;
|
||||
$db = Database::getInstance();
|
||||
|
||||
$msgs = $db->query(
|
||||
"select messageid,ikind,dtmcreated as created,tname,tmessage from {chatmessage} " .
|
||||
"where threadid = :threadid and messageid > :lastid " .
|
||||
($isuser ? "and ikind <> ". Thread::KIND_FOR_AGENT : "") .
|
||||
" order by messageid",
|
||||
array(
|
||||
':threadid' => $threadid,
|
||||
':lastid' => $lastid,
|
||||
),
|
||||
array('return_rows' => Database::RETURN_ALL_ROWS)
|
||||
|
||||
);
|
||||
|
||||
$messages = array();
|
||||
foreach ($msgs as $msg) {
|
||||
$message = "";
|
||||
if ($meth == 'xml') {
|
||||
switch ($msg['ikind']) {
|
||||
case Thread::KIND_AVATAR:
|
||||
$message = "<avatar>" . myiconv($webim_encoding, "utf-8", escape_with_cdata($msg['tmessage'])) . "</avatar>";
|
||||
break;
|
||||
default:
|
||||
$message = "<message>" . myiconv($webim_encoding, "utf-8", escape_with_cdata(message_to_html($msg))) . "</message>\n";
|
||||
}
|
||||
} else {
|
||||
if ($msg['ikind'] != Thread::KIND_AVATAR) {
|
||||
$message = (($meth == 'text') ? message_to_text($msg) : topage(message_to_html($msg)));
|
||||
}
|
||||
}
|
||||
|
||||
$messages[] = $message;
|
||||
if ($msg['messageid'] > $lastid) {
|
||||
$lastid = $msg['messageid'];
|
||||
}
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
|
||||
function print_thread_messages($thread, $token, $lastid, $isuser, $format, $agentid = null)
|
||||
{
|
||||
global $webim_encoding, $webimroot;
|
||||
$threadid = $thread->id;
|
||||
$istyping = abs(time() - $isuser ? $thread->lastPingAgent : $thread->lastPingUser) < Thread::CONNECTION_TIMEOUT
|
||||
&& (($isuser ? $thread->agentTyping : $thread->userTyping) == "1") ? "1" : "0";
|
||||
|
||||
if ($format == "xml") {
|
||||
$output = get_messages($threadid, "xml", $isuser, $lastid);
|
||||
|
||||
start_xml_output();
|
||||
print("<thread lastid=\"$lastid\" typing=\"" . $istyping . "\" canpost=\"" . (($isuser || $agentid != null && $agentid == $thread->agentId) ? 1 : 0) . "\">");
|
||||
foreach ($output as $msg) {
|
||||
print $msg;
|
||||
}
|
||||
print("</thread>");
|
||||
} else if ($format == "html") {
|
||||
$output = get_messages($threadid, "html", $isuser, $lastid);
|
||||
|
||||
start_html_output();
|
||||
$url = "$webimroot/thread.php?act=refresh&thread=$threadid&token=$token&html=on&user=" . ($isuser ? "true" : "false");
|
||||
|
||||
print(
|
||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" .
|
||||
"<html>\n<head>\n" .
|
||||
"<link href=\"$webimroot/styles/default/chat.css\" rel=\"stylesheet\" type=\"text/css\">\n" .
|
||||
"<meta http-equiv=\"Refresh\" content=\"" . Settings::get('updatefrequency_oldchat') . "; URL=$url&sn=11\">\n" .
|
||||
"<meta http-equiv=\"Pragma\" content=\"no-cache\">\n" .
|
||||
"<title>chat</title>\n" .
|
||||
"</head>\n" .
|
||||
"<body bgcolor='#FFFFFF' text='#000000' link='#C28400' vlink='#C28400' alink='#C28400' onload=\"if( location.hash != '#aend' ){location.hash='#aend';}\">" .
|
||||
"<table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td valign='top' class='message'>");
|
||||
|
||||
foreach ($output as $msg) {
|
||||
print $msg;
|
||||
}
|
||||
|
||||
print(
|
||||
"</td></tr></table><a name='aend'></a>" .
|
||||
"</body></html>");
|
||||
}
|
||||
}
|
||||
|
||||
function get_user_name($username, $addr, $id)
|
||||
{
|
||||
return str_replace(
|
||||
|
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
/*
|
||||
* Copyright 2005-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
function demo_print_message($msg, $format)
|
||||
{
|
||||
global $webim_encoding;
|
||||
if ($format == "xml") {
|
||||
print "<message>" . myiconv($webim_encoding, "utf-8", escape_with_cdata(message_to_html($msg))) . "</message>\n";
|
||||
} else {
|
||||
print topage(message_to_html($msg));
|
||||
}
|
||||
}
|
||||
|
||||
function demo_process_thread($act, $outformat, $lastid, $isuser, $canpost, $istyping, $postmessage)
|
||||
{
|
||||
global $webimroot;
|
||||
if ($act == "refresh" || $act == "post") {
|
||||
$lastid++;
|
||||
if ($outformat == "xml") {
|
||||
start_xml_output();
|
||||
print("<thread lastid=\"$lastid\" typing=\"" . ($istyping ? 1 : 0) . "\" canpost=\"" . ($canpost ? 1 : 0) . "\">");
|
||||
} else {
|
||||
start_html_output();
|
||||
$url = "$webimroot/thread.php?act=refresh&thread=0&token=123&html=on&user=" . ($isuser ? "true" : "false");
|
||||
|
||||
print(
|
||||
"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">" .
|
||||
"<html>\n<head>\n" .
|
||||
"<link href=\"$webimroot/styles/default/chat.css\" rel=\"stylesheet\" type=\"text/css\">\n" .
|
||||
"<meta http-equiv=\"Refresh\" content=\"" . Settings::get('updatefrequency_oldchat') . "; URL=$url&sn=11\">\n" .
|
||||
"<meta http-equiv=\"Pragma\" content=\"no-cache\">\n" .
|
||||
"<title>chat</title>\n" .
|
||||
"</head>\n" .
|
||||
"<body bgcolor='#FFFFFF' text='#000000' link='#C28400' vlink='#C28400' alink='#C28400'>" .
|
||||
"<table width='100%' cellspacing='0' cellpadding='0' border='0'><tr><td valign='top' class='message'>");
|
||||
|
||||
}
|
||||
if ($lastid == 1) {
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_FOR_AGENT, 'created' => time() - 15, 'tname' => '',
|
||||
'tmessage' => getstring2('chat.came.from', array("http://google.com"))), $outformat);
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_INFO, 'created' => time() - 15, 'tname' => '',
|
||||
'tmessage' => getstring('chat.wait')), $outformat);
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_EVENTS, 'created' => time() - 10, 'tname' => '',
|
||||
'tmessage' => getstring2("chat.status.operator.joined", array("Administrator"))), $outformat);
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_AGENT, 'created' => time() - 9, 'tname' => 'Administrator',
|
||||
'tmessage' => getstring("demo.chat.welcome")), $outformat);
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_USER, 'created' => time() - 5, 'tname' => getstring("chat.default.username"),
|
||||
'tmessage' => getstring("demo.chat.question")), $outformat);
|
||||
if ($canpost && $outformat == 'xml') {
|
||||
demo_print_message(
|
||||
array('ikind' => Thread::KIND_INFO, 'created' => time() - 5, 'tname' => '',
|
||||
'tmessage' => 'Hint: type something in message field to see typing notification'), $outformat);
|
||||
}
|
||||
}
|
||||
if ($act == 'post') {
|
||||
demo_print_message(
|
||||
array('ikind' => $isuser ? Thread::KIND_USER : Thread::KIND_AGENT, 'created' => time(), 'tmessage' => $postmessage,
|
||||
'tname' => $isuser ? getstring("chat.default.username") : "Administrator"), $outformat);
|
||||
}
|
||||
if ($outformat == "xml") {
|
||||
print("</thread>");
|
||||
} else {
|
||||
print(
|
||||
"</td></tr></table><a name='aend'></a>" .
|
||||
"</body></html>");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
@ -53,10 +53,10 @@ if( count($errors) > 0 ) {
|
||||
}
|
||||
|
||||
$history = "";
|
||||
$lastid = -1;
|
||||
$output = get_messages( $threadid,"text",true,$lastid );
|
||||
foreach( $output as $msg ) {
|
||||
$history .= $msg;
|
||||
$last_id = -1;
|
||||
$messages = $thread->getMessages(true, $last_id);
|
||||
foreach ($messages as $msg) {
|
||||
$history .= message_to_text($msg);
|
||||
}
|
||||
|
||||
$subject = getstring("mail.user.history.subject");
|
||||
|
@ -45,10 +45,20 @@ function thread_info($id)
|
||||
|
||||
|
||||
if (isset($_GET['threadid'])) {
|
||||
// Load thread info
|
||||
$threadid = verifyparam("threadid", "/^(\d{1,9})?$/", "");
|
||||
$thread_info = thread_info($threadid);
|
||||
$page['thread_info'] = $thread_info;
|
||||
|
||||
// Build messages list
|
||||
$lastid = -1;
|
||||
$page['threadMessages'] = get_messages($threadid, "html", false, $lastid);
|
||||
$page['thread_info'] = thread_info($threadid);
|
||||
$messages = $thread_info['thread']->getMessages(false, $lastid);
|
||||
foreach ($messages as $msg) {
|
||||
if ($msg['ikind'] == Thread::KIND_AVATAR) {
|
||||
continue;
|
||||
}
|
||||
$page['threadMessages'][] = Thread::themeMessage($msg);
|
||||
}
|
||||
}
|
||||
|
||||
prepare_menu($operator, false);
|
||||
|
@ -5,13 +5,30 @@
|
||||
<link rel="shortcut icon" href="${webimroot}/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" type="text/css" href="${tplroot}/chat.css">
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/common.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/mibewapi.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/json2.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/brws.js"></script>
|
||||
<script type="text/javascript" language="javascript"><!--
|
||||
var localizedStrings = {closeConfirmation:"${page:chat.close.confirmation}"};
|
||||
${if:agent}${if:canpost}
|
||||
var predefinedAnswers = ${page:fullPredefinedAnswers};
|
||||
${endif:canpost}${endif:agent}
|
||||
var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",frequency:${page:frequency},${if:user}user:"true",${endif:user}threadid:${page:ct.chatThreadId},token:${page:ct.token},cssfile:"${tplroot}/chat.css",ignorectrl:${page:ignorectrl} };
|
||||
var chatParams = {
|
||||
cssfile: "${tplroot}/chat.css",
|
||||
${if:agent}${if:canpost}
|
||||
predefinedAnswers: ${page:fullPredefinedAnswers},
|
||||
${endif:canpost}${endif:agent}
|
||||
threadParams: {
|
||||
user:${if:user}true${else:user}false${endif:user},
|
||||
threadid:${page:ct.chatThreadId},
|
||||
token:${page:ct.token}
|
||||
},
|
||||
serverParams: {
|
||||
servl: "${webimroot}/thread.php",
|
||||
requestsFrequency: ${page:frequency}
|
||||
},
|
||||
threadUpdaterParams: {
|
||||
webimRoot: "${webimroot}",
|
||||
ignorectrl:${page:ignorectrl},
|
||||
localizedStrings: {closeConfirmation:"${page:chat.close.confirmation}"}
|
||||
}
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/chat.js"></script>
|
||||
|
@ -5,13 +5,30 @@
|
||||
<link rel="shortcut icon" href="${webimroot}/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" type="text/css" href="${tplroot}/chat.css">
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/common.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/mibewapi.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/json2.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/brws.js"></script>
|
||||
<script type="text/javascript" language="javascript"><!--
|
||||
var localizedStrings = {closeConfirmation:"${page:chat.close.confirmation}"};
|
||||
${if:agent}${if:canpost}
|
||||
var predefinedAnswers = ${page:fullPredefinedAnswers};
|
||||
${endif:canpost}${endif:agent}
|
||||
var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",frequency:${page:frequency},${if:user}user:"true",${endif:user}threadid:${page:ct.chatThreadId},token:${page:ct.token},cssfile:"${tplroot}/chat.css",ignorectrl:${page:ignorectrl} };
|
||||
var chatParams = {
|
||||
cssfile: "${tplroot}/chat.css",
|
||||
${if:agent}${if:canpost}
|
||||
predefinedAnswers: ${page:fullPredefinedAnswers},
|
||||
${endif:canpost}${endif:agent}
|
||||
threadParams: {
|
||||
user:${if:user}true${else:user}false${endif:user},
|
||||
threadid:${page:ct.chatThreadId},
|
||||
token:${page:ct.token}
|
||||
},
|
||||
serverParams: {
|
||||
servl: "${webimroot}/thread.php",
|
||||
requestsFrequency: ${page:frequency}
|
||||
},
|
||||
threadUpdaterParams: {
|
||||
webimRoot: "${webimroot}",
|
||||
ignorectrl:${page:ignorectrl},
|
||||
localizedStrings: {closeConfirmation:"${page:chat.close.confirmation}"}
|
||||
}
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/chat.js"></script>
|
||||
|
@ -6,16 +6,31 @@
|
||||
<link rel="shortcut icon" href="${webimroot}/images/favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" type="text/css" href="${tplroot}/chat.css" media="all" />
|
||||
<script type="text/javascript" src="${webimroot}/js/${jsver}/common.js"></script>
|
||||
<script type="text/javascript" src="${webimroot}/js/${jsver}/mibewapi.js"></script>
|
||||
<script type="text/javascript" src="${webimroot}/js/${jsver}/json2.js"></script>
|
||||
<script type="text/javascript" src="${webimroot}/js/${jsver}/brws.js"></script>
|
||||
<script type="text/javascript">
|
||||
<!--
|
||||
var localizedStrings = {closeConfirmation:"${page:chat.close.confirmation}"};
|
||||
${if:agent}${if:canpost}
|
||||
var predefinedAnswers = ${page:fullPredefinedAnswers};
|
||||
${endif:canpost}${endif:agent}
|
||||
var threadParams = {
|
||||
servl:"${webimroot}/thread.php",wroot:"${webimroot}",frequency:${page:frequency},${if:user}user:"true",${endif:user}threadid:${page:ct.chatThreadId},token:${page:ct.token},cssfile:"${tplroot}/chat.css",ignorectrl:${page:ignorectrl}
|
||||
};
|
||||
var chatParams = {
|
||||
cssfile: "${tplroot}/chat.css",
|
||||
${if:agent}${if:canpost}
|
||||
predefinedAnswers: ${page:fullPredefinedAnswers},
|
||||
${endif:canpost}${endif:agent}
|
||||
threadParams: {
|
||||
user:${if:user}true${else:user}false${endif:user},
|
||||
threadid:${page:ct.chatThreadId},
|
||||
token:${page:ct.token}
|
||||
},
|
||||
serverParams: {
|
||||
servl: "${webimroot}/thread.php",
|
||||
requestsFrequency: ${page:frequency}
|
||||
},
|
||||
threadUpdaterParams: {
|
||||
webimRoot: "${webimroot}",
|
||||
ignorectrl:${page:ignorectrl},
|
||||
localizedStrings: {closeConfirmation:"${page:chat.close.confirmation}"}
|
||||
}
|
||||
}
|
||||
var stxt = 10;
|
||||
function getClientHeight() {
|
||||
return document.compatMode=='CSS1Compat' || !window.opera?document.documentElement.clientHeight:document.body.clientHeight;
|
||||
|
@ -5,13 +5,30 @@
|
||||
<link rel="shortcut icon" href="${webimroot}/images/favicon.ico" type="image/x-icon">
|
||||
<link rel="stylesheet" type="text/css" href="${tplroot}/chat.css">
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/common.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/mibewapi.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/json2.js"></script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/brws.js"></script>
|
||||
<script type="text/javascript" language="javascript"><!--
|
||||
var localizedStrings = {closeConfirmation:"${page:chat.close.confirmation}"};
|
||||
${if:agent}${if:canpost}
|
||||
var predefinedAnswers = ${page:fullPredefinedAnswers};
|
||||
${endif:canpost}${endif:agent}
|
||||
var threadParams = { servl:"${webimroot}/thread.php",wroot:"${webimroot}",frequency:${page:frequency},${if:user}user:"true",${endif:user}threadid:${page:ct.chatThreadId},token:${page:ct.token},cssfile:"${tplroot}/chat.css",ignorectrl:${page:ignorectrl} };
|
||||
var chatParams = {
|
||||
cssfile: "${tplroot}/chat.css",
|
||||
${if:agent}${if:canpost}
|
||||
predefinedAnswers: ${page:fullPredefinedAnswers},
|
||||
${endif:canpost}${endif:agent}
|
||||
threadParams: {
|
||||
user:${if:user}true${else:user}false${endif:user},
|
||||
threadid:${page:ct.chatThreadId},
|
||||
token:${page:ct.token}
|
||||
},
|
||||
serverParams: {
|
||||
servl: "${webimroot}/thread.php",
|
||||
requestsFrequency: ${page:frequency}
|
||||
},
|
||||
threadUpdaterParams: {
|
||||
webimRoot: "${webimroot}",
|
||||
ignorectrl:${page:ignorectrl},
|
||||
localizedStrings: {closeConfirmation:"${page:chat.close.confirmation}"}
|
||||
}
|
||||
}
|
||||
//-->
|
||||
</script>
|
||||
<script type="text/javascript" language="javascript" src="${webimroot}/js/${jsver}/chat.js"></script>
|
||||
|
@ -19,97 +19,13 @@ require_once('libs/init.php');
|
||||
require_once('libs/chat.php');
|
||||
require_once('libs/operator.php');
|
||||
require_once('libs/classes/thread.php');
|
||||
require_once('libs/classes/mibew_api.php');
|
||||
require_once('libs/classes/mibew_api_interaction.php');
|
||||
require_once('libs/classes/mibew_api_window_interaction.php');
|
||||
require_once('libs/classes/mibew_api_execution_context.php');
|
||||
require_once('libs/classes/thread_processor.php');
|
||||
|
||||
$act = verifyparam( "act", "/^(refresh|post|rename|close|ping)$/");
|
||||
$token = verifyparam( "token", "/^\d{1,9}$/");
|
||||
$threadid = verifyparam( "thread", "/^\d{1,9}$/");
|
||||
$isuser = verifyparam( "user", "/^true$/", "false") == 'true';
|
||||
$outformat = ((verifyparam( "html", "/^on$/", "off") == 'on') ? "html" : "xml");
|
||||
$istyping = verifyparam( "typed", "/^1$/", "") == '1';
|
||||
|
||||
if($threadid == 0 && ($token == 123 || $token == 124)) {
|
||||
require_once('libs/demothread.php');
|
||||
$lastid = verifyparam( "lastid", "/^\d{1,9}$/", 0);
|
||||
demo_process_thread($act,$outformat,$lastid,$isuser,$token == 123,$istyping,$act=="post"?getrawparam('message') : "");
|
||||
exit;
|
||||
}
|
||||
|
||||
$thread = Thread::load($threadid, $token);
|
||||
if (! $thread) {
|
||||
die("wrong thread");
|
||||
}
|
||||
|
||||
function show_ok_result($resid) {
|
||||
start_xml_output();
|
||||
echo "<$resid></$resid>";
|
||||
exit;
|
||||
}
|
||||
|
||||
function show_error($message) {
|
||||
start_xml_output();
|
||||
echo "<error><descr>$message</descr></error>";
|
||||
exit;
|
||||
}
|
||||
|
||||
$thread->ping($isuser, $istyping);
|
||||
|
||||
if( !$isuser && $act != "rename" ) {
|
||||
$operator = check_login();
|
||||
$thread->checkForReassign($operator);
|
||||
}
|
||||
|
||||
if( $act == "refresh" ) {
|
||||
$lastid = verifyparam( "lastid", "/^\d{1,9}$/", -1);
|
||||
print_thread_messages($thread, $token, $lastid, $isuser,$outformat, $isuser ? null : $operator['operatorid']);
|
||||
exit;
|
||||
|
||||
} else if( $act == "post" ) {
|
||||
$lastid = verifyparam( "lastid", "/^\d{1,9}$/", -1);
|
||||
$message = getrawparam('message');
|
||||
|
||||
$kind = $isuser ? Thread::KIND_USER : Thread::KIND_AGENT;
|
||||
$from = $isuser ? $thread->userName : $thread->agentName;
|
||||
|
||||
if(!$isuser && $operator['operatorid'] != $thread->agentId) {
|
||||
show_error("cannot send");
|
||||
}
|
||||
|
||||
$postedid = $thread->postMessage(
|
||||
$kind,
|
||||
$message,
|
||||
$from,
|
||||
$isuser ? null : $operator['operatorid']
|
||||
);
|
||||
if($isuser && $thread->shownMessageId == 0) {
|
||||
$thread->shownMessageId = $postedid;
|
||||
$thread->save();
|
||||
}
|
||||
print_thread_messages($thread, $token, $lastid, $isuser, $outformat, $isuser ? null : $operator['operatorid']);
|
||||
exit;
|
||||
|
||||
} else if( $act == "rename" ) {
|
||||
|
||||
if( Settings::get('usercanchangename') != "1" ) {
|
||||
show_error("server: forbidden to change name");
|
||||
}
|
||||
|
||||
$newname = getrawparam('name');
|
||||
|
||||
$thread->renameUser($newname);
|
||||
$data = strtr(base64_encode(myiconv($webim_encoding,"utf-8",$newname)), '+/=', '-_,');
|
||||
setcookie($namecookie, $data, time()+60*60*24*365);
|
||||
show_ok_result("rename");
|
||||
|
||||
} else if( $act == "ping" ) {
|
||||
show_ok_result("ping");
|
||||
|
||||
} else if( $act == "close" ) {
|
||||
|
||||
if( $isuser || $thread->agentId == $operator['operatorid']) {
|
||||
$thread->close($isuser);
|
||||
}
|
||||
show_ok_result("closed");
|
||||
|
||||
}
|
||||
$processor = ThreadProcessor::getInstance();
|
||||
$processor->receiveRequest($_POST['data']);
|
||||
|
||||
?>
|
Loading…
Reference in New Issue
Block a user