234 lines
8.3 KiB
JavaScript
234 lines
8.3 KiB
JavaScript
|
|
/*********************************************************************
|
||
|
|
autolock.js
|
||
|
|
|
||
|
|
Ticket locking utility...loaded only when ticket locking is enabled!!
|
||
|
|
Mainly useful for renewing locks based on form activity since we do initial lock onview at PHP end.
|
||
|
|
|
||
|
|
It is work in process...feedback is welcomed!
|
||
|
|
|
||
|
|
Peter Rotich <peter@osticket.com>
|
||
|
|
Copyright (c) 2006-2010 osTicket
|
||
|
|
http://www.osticket.com
|
||
|
|
|
||
|
|
Released under the GNU General Public License WITHOUT ANY WARRANTY.
|
||
|
|
See LICENSE.TXT for details.
|
||
|
|
|
||
|
|
vim: expandtab sw=4 ts=4 sts=4:
|
||
|
|
$Id: $
|
||
|
|
**********************************************************************/
|
||
|
|
var autoLock = {
|
||
|
|
|
||
|
|
addEvent: function(elm, evType, fn, useCapture) {
|
||
|
|
if(elm.addEventListener) {
|
||
|
|
elm.addEventListener(evType, fn, useCapture);
|
||
|
|
return true;
|
||
|
|
}else if(elm.attachEvent) {
|
||
|
|
return elm.attachEvent('on' + evType, fn);
|
||
|
|
}else{
|
||
|
|
elm['on' + evType] = fn;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
removeEvent: function(elm, evType, fn, useCapture) {
|
||
|
|
if(elm.removeEventListener) {
|
||
|
|
elm.removeEventListener(evType, fn, useCapture);
|
||
|
|
return true;
|
||
|
|
}else if(elm.detachEvent) {
|
||
|
|
return elm.detachEvent('on' + evType, fn);
|
||
|
|
}else {
|
||
|
|
elm['on' + evType] = null;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
//Incoming event...
|
||
|
|
handleEvent: function(e) {
|
||
|
|
if(!autoLock.lockId) {
|
||
|
|
var now = new Date().getTime();
|
||
|
|
//Retry every 5 seconds??
|
||
|
|
if(autoLock.retry && (!autoLock.lastattemptTime || (now-autoLock.lastattemptTime)>5000)) {
|
||
|
|
autoLock.acquireLock(e,autoLock.warn);
|
||
|
|
autoLock.lastattemptTime=new Date().getTime();
|
||
|
|
}
|
||
|
|
}else{
|
||
|
|
autoLock.renewLock(e);
|
||
|
|
}
|
||
|
|
if(!autoLock.lasteventTime) //I hate nav away warnings..but
|
||
|
|
autoLock.addEvent(window,'beforeunload',autoLock.discardWarning,true);
|
||
|
|
autoLock.lasteventTime=new Date().getTime();
|
||
|
|
},
|
||
|
|
|
||
|
|
//Watch activity on individual form.
|
||
|
|
watchForm: function(fObj,fn) {
|
||
|
|
if(!fObj || !fObj.length)
|
||
|
|
return;
|
||
|
|
|
||
|
|
//Watch onSubmit event on the form.
|
||
|
|
autoLock.addEvent(fObj,'submit',autoLock.onSubmit,true);
|
||
|
|
//Watch activity on text + textareas + select fields.
|
||
|
|
for (var i=0; i<fObj.length; i++) {
|
||
|
|
switch(fObj[i].type) {
|
||
|
|
case 'textarea':
|
||
|
|
case 'text':
|
||
|
|
autoLock.addEvent(fObj[i],'keyup',autoLock.handleEvent,true);
|
||
|
|
break;
|
||
|
|
case 'select-one':
|
||
|
|
case 'select-multiple':
|
||
|
|
if(fObj.name!='reply') //Bug on double ajax call since select make it's own ajax call. TODO: fix it
|
||
|
|
autoLock.addEvent(fObj[i],'change',autoLock.handleEvent,true);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
//Watch all the forms on the document.
|
||
|
|
watchDocument: function() {
|
||
|
|
|
||
|
|
//Watch forms of interest only.
|
||
|
|
for (var i=0; i<document.forms.length; i++) {
|
||
|
|
if(!document.forms[i].ticket_id.value || parseInt(document.forms[i].ticket_id.value)!=autoLock.tid)
|
||
|
|
continue;
|
||
|
|
autoLock.watchForm(document.forms[i],autoLock.checkLock);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
Init: function(tid) {
|
||
|
|
|
||
|
|
//Check Ajax availability.
|
||
|
|
if(!Http || !Http.get) { return; }
|
||
|
|
|
||
|
|
//make sure we are on ticket view page!
|
||
|
|
void(autoLock.form=document.forms['replyform']);
|
||
|
|
if(!autoLock.form || !autoLock.form.ticket_id.value) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
void(autoLock.tid=parseInt(autoLock.form.ticket_id.value));
|
||
|
|
autoLock.lockId=0;
|
||
|
|
autoLock.timerId=0;
|
||
|
|
autoLock.lasteventTime=0;
|
||
|
|
autoLock.lastattemptTime=0;
|
||
|
|
autoLock.acquireTime=0;
|
||
|
|
autoLock.renewTime=0;
|
||
|
|
autoLock.renewFreq=0; //renewal frequency...based on returned lock time.
|
||
|
|
autoLock.time=0;
|
||
|
|
autoLock.lockAttempts=0; //Consecutive lock attempt errors
|
||
|
|
autoLock.maxattempts=2; //Maximum failed lock attempts before giving up.
|
||
|
|
autoLock.warn=true;
|
||
|
|
autoLock.retry=true;
|
||
|
|
autoLock.watchDocument();
|
||
|
|
autoLock.resetTimer();
|
||
|
|
autoLock.addEvent(window,'unload',autoLock.releaseLock,true); //Release lock regardless of any activity.
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
onSubmit: function(e) {
|
||
|
|
if(e.type=='submit') { //Submit. double check!
|
||
|
|
//remove nav away warning if any.
|
||
|
|
autoLock.removeEvent(window,'beforeunload',autoLock.discardWarning,true);
|
||
|
|
//Only warn if we had a failed lock attempt.
|
||
|
|
if(autoLock.warn && !autoLock.lockId && autoLock.lasteventTime) {
|
||
|
|
var answer=confirm('Unable to acquire a lock on the ticket. Someone else could be working on the same ticket. \
|
||
|
|
Please confirm if you wish to continue anyways.');
|
||
|
|
if(!answer) {
|
||
|
|
e.returnValue=false;
|
||
|
|
e.cancelBubble=true;
|
||
|
|
if(e.preventDefault) {
|
||
|
|
e.preventDefault();
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
},
|
||
|
|
|
||
|
|
acquireLock: function(e,warn) {
|
||
|
|
|
||
|
|
if(!autoLock.tid || autoLock.lockId) { return false; }
|
||
|
|
var warn = warn || false;
|
||
|
|
if(!autoLock.lockId) {
|
||
|
|
Http.get({
|
||
|
|
url: "ajax.php?api=tickets&f=acquireLock&tid="+autoLock.tid,
|
||
|
|
callback: autoLock.setLock
|
||
|
|
},['acquire',warn]);
|
||
|
|
}else{
|
||
|
|
autoLock.renewLock(e);
|
||
|
|
}
|
||
|
|
return autoLock.lockId;
|
||
|
|
},
|
||
|
|
|
||
|
|
//Renewal only happens on form activity..
|
||
|
|
renewLock: function(e) {
|
||
|
|
|
||
|
|
if(!autoLock.lockId) { return false; }
|
||
|
|
|
||
|
|
var now= new Date().getTime();
|
||
|
|
if(!autoLock.lastcheckTime || (now-autoLock.lastcheckTime)>=(autoLock.renewFreq*1000)){
|
||
|
|
Http.get({
|
||
|
|
url: "ajax.php?api=tickets&f=renewLock&id="+autoLock.lockId+'&tid='+autoLock.tid,
|
||
|
|
callback: autoLock.setLock
|
||
|
|
},['renew',autoLock.warn]);
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
releaseLock: function(e) {
|
||
|
|
|
||
|
|
if(!autoLock.tid) { return false; }
|
||
|
|
Http.get({
|
||
|
|
url: "ajax.php?api=tickets&f=releaseLock&id="+autoLock.lockId+'&tid='+autoLock.tid,
|
||
|
|
callback: function (resp){ alert(resp);}
|
||
|
|
});
|
||
|
|
},
|
||
|
|
|
||
|
|
setLock: function(reply,action,warn) {
|
||
|
|
var warn = warn || false;
|
||
|
|
if(reply.status == Http.Status.OK && reply.responseText) {
|
||
|
|
var lock = eval('('+reply.responseText+')');
|
||
|
|
if(lock.id) {
|
||
|
|
autoLock.renewFreq=lock.time?(lock.time/2):30;
|
||
|
|
autoLock.lastcheckTime=new Date().getTime();
|
||
|
|
}
|
||
|
|
autoLock.lockId=lock.id; //overwrite the lockid.
|
||
|
|
switch(action){
|
||
|
|
case 'renew':
|
||
|
|
if(!lock.id && lock.retry) {
|
||
|
|
autoLock.lockAttempts=1; //reset retries.
|
||
|
|
autoLock.acquireLock(e,false); //We lost the lock?? ..try to re acquire now.
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case 'acquire':
|
||
|
|
if(!lock.id) {
|
||
|
|
autoLock.lockAttempts++;
|
||
|
|
if(warn && (!lock.retry || autoLock.lockAttempts>=autoLock.maxattempts)) {
|
||
|
|
autoLock.retry=false;
|
||
|
|
alert('Unable to lock the ticket. Someone else could be working on the same ticket.');
|
||
|
|
}
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
},
|
||
|
|
|
||
|
|
|
||
|
|
discardWarning: function(e) {
|
||
|
|
e.returnValue="Any changes or info you've entered will be discarded!";
|
||
|
|
},
|
||
|
|
|
||
|
|
//TODO: Monitor events and elapsed time and warn user when the lock is about to expire.
|
||
|
|
monitorEvents: function() {
|
||
|
|
// warn user when lock is about to expire??;
|
||
|
|
//autoLock.resetTimer();
|
||
|
|
},
|
||
|
|
|
||
|
|
clearTimer: function() {
|
||
|
|
clearTimeout(autoLock.timerId);
|
||
|
|
},
|
||
|
|
|
||
|
|
resetTimer: function() {
|
||
|
|
clearTimeout(autoLock.timerId);
|
||
|
|
autoLock.timerId=setTimeout(function () { autoLock.monitorEvents() },30000);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
//Register ticket locking init on load!
|
||
|
|
autoLock.addEvent(window, 'load', autoLock.Init, false);
|