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._options.onTimeout = this.handleTimeout.bind(this); this._options.timeout = 5000; this.frequency = (this._options.frequency || 2); this.updater = {}; this.update(); }, handleException: function(_request, ex) { if( this._options.handleError ) this._options.handleError("offline, reconnecting"); this.stopUpdate(); this.timer = setTimeout(this.update.bind(this), 1000); }, handleTimeout: function(_request) { if( this._options.handleError ) this._options.handleError("timeout, reconnecting"); this.stopUpdate(); this.timer = setTimeout(this.update.bind(this), 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) { try { var xmlRoot = Ajax.getXml(presponse); if( xmlRoot ) { (this._options.updateContent || Ajax.emptyFunction)( xmlRoot ); } else { if( this._options.handleError ) this._options.handleError("reconnecting"); } } catch(e) { } 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 = ''; }, 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 = ''; row = _table.insertRow(_index); cell = row.insertCell(-1); cell.colSpan = 13; cell.height = 2; }, popupLink: function(link, title, wndid, inner, width, height,linkclass) { return ''+ inner+''; }, generateOneRowTable: function(content) { return '' + content + '
'; }, viewOpenCell: function(username,servlet,id,canview,canopen,ban,message,cantakenow) { var cellsCount = 2; var link = servlet+"?thread="+id; var gen = ''; if(canopen || canview ) { gen += HtmlGenerationUtils.popupLink( (cantakenow||!canview) ? link : link+"&viewonly=true", localized[canopen ? 0 : 1], "ImCenter"+id, username, 640, 480, ban); } else { gen += '' + username + ''; } gen += ''; if( canopen ) { gen += ''; gen += HtmlGenerationUtils.popupLink( link, localized[0], "ImCenter"+id, ''+localized[0]+'', 640, 480, null); gen += ''; cellsCount++; } if( canview ) { gen += ''; gen += HtmlGenerationUtils.popupLink( link+"&viewonly=true", localized[1], "ImCenter"+id, ''+localized[1]+'', 640, 480, null); gen += ''; cellsCount++; } if( message != "" ) { gen += ''; gen += message.length > 30 ? message.substring(0,30) + '...' : message; gen += ''; } return HtmlGenerationUtils.generateOneRowTable(gen); }, banCell: function(id,banid){ return ''+ HtmlGenerationUtils.popupLink( webimRoot+'/operator/ban.php?'+(banid ? 'id='+banid : 'thread='+id), localized[2], "ban"+id, ''+localized[2]+'', 550, 440, null)+ ''; } }; 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, canban = false, ban = null, banid = 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; else if( attr.nodeName == "canview" ) canview = true; else if( attr.nodeName == "canban" ) canban = true; else if( attr.nodeName == "ban" ) ban = attr.nodeValue; else if( attr.nodeName == "banid" ) banid = attr.nodeValue; } 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 = ''+NodeUtils.getNodeValue(node,"useragent")+''; if(ban != null) { etc = ''+NodeUtils.getNodeValue(node,"reason")+''; } if(canban) { etc += HtmlGenerationUtils.banCell(id,banid); } etc = HtmlGenerationUtils.generateOneRowTable(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,stateid!='chat')); 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,stateid!='chat')); 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(root) { 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 ) { playSound(webimRoot+'/sounds/new_user.wav'); window.focus(); } } else if( root.tagName == 'error' ) { this.setStatus(NodeUtils.getNodeValue(root,"descr") ); } else { this.setStatus( "reconnecting" ); } } }); var webimRoot = ""; EventHelper.register(window, 'onload', function(){ webimRoot = updaterOptions.wroot; new Ajax.ThreadListUpdater(({table:$("threadlist"),status:$("connstatus")}).extend(updaterOptions || {})); });