]"
if (obj) {
var str = object.prototype.tostring.call(obj);
var regexpmatch = str.match(/\[object\s+(\w+)/);
if (regexpmatch && regexpmatch.length==2) {
return regexpmatch[1];
}
}
// supplied argument was probably not an object, but what is better?
return "object";
}
};
/**
* functions to handle the various remoting transport
*/
dwr.engine.transport = {
/**
* actually send the block of data in the batch object.
* @private
* @param {object} batch
*/
send:function(batch) {
dwr.engine.batch.preparetosend(batch);
if (batch.fileupload) {
batch.transport = dwr.engine.transport.iframe;
}
else if (dwr.engine.iscrossdomain) {
batch.transport = dwr.engine.transport.scripttag;
}
// else if (batch.ispoll && dwr.engine.isie) {
// batch.transport = dwr.engine.transport.htmlfile;
// }
else {
batch.transport = dwr.engine.transport.xhr;
}
batch.transport.send(batch);
},
/**
* a generic function to remove all remoting artifacts
* @param {object} batch the batch that has completed
*/
remove:function(batch) {
dwr.engine.transport.iframe.remove(batch);
dwr.engine.transport.xhr.remove(batch);
},
/**
* called as a result of a request timeout
* @private
* @param {object} batch the batch that is aborting
*/
abort:function(batch) {
if (batch && !batch.completed) {
clearinterval(batch.interval);
dwr.engine.batch.remove(batch);
if (batch.req) {
batch.req.abort();
}
dwr.engine.transport.remove(batch);
dwr.engine._handleerror(batch, { name:"dwr.engine.timeout", message:"timeout" });
}
},
/**
* remoting through xhr
*/
xhr:{
/**
* the default http method to use
*/
httpmethod:"post",
/**
* the activex objects to use when we want to do an xmlhttprequest call.
* todo: we arrived at this by trial and error. other toolkits use
* different strings, maybe there is an officially correct version?
*/
xmlhttp:["msxml2.xmlhttp.6.0", "msxml2.xmlhttp.5.0", "msxml2.xmlhttp.4.0", "msxml2.xmlhttp.3.0", "msxml2.xmlhttp", "microsoft.xmlhttp"],
/**
* setup a batch for transfer through xhr
* @param {object} batch the batch to alter for xhr transmit
*/
send:function(batch) {
if (batch.ispoll) {
batch.map.partialresponse = dwr.engine._partialresponseyes;
}
// do proxies or ie force us to use early closing mode?
if (batch.ispoll && dwr.engine._pollwithxhr == "true") {
batch.map.partialresponse = dwr.engine._partialresponseno;
}
if (batch.ispoll && dwr.engine.isie) {
batch.map.partialresponse = dwr.engine._partialresponseno;
}
if (window.xmlhttprequest) {
batch.req = new xmlhttprequest();
}
else if (window.activexobject) {
batch.req = dwr.engine.util.newactivexobject(dwr.engine.transport.xhr.xmlhttp);
}
// proceed using xmlhttprequest
if (batch.async) {
batch.req.onreadystatechange = function() {
if (typeof dwr != 'undefined') dwr.engine.transport.xhr.statechange(batch);
};
}
// if we're polling, record this for monitoring
if (batch.ispoll) {
dwr.engine._pollreq = batch.req;
// in ie xhr is an activex control so you can't augment it like this
if (!document.all) batch.req.batch = batch;
}
httpmethod = dwr.engine.transport.xhr.httpmethod;
// workaround for safari 1.x post bug
var indexsafari = navigator.useragent.indexof("safari/");
if (indexsafari >= 0) {
var version = navigator.useragent.substring(indexsafari + 7);
if (parseint(version, 10) < 400) {
if (dwr.engine._allowgetforsafaributmakeforgeryeasier == "true") {
httpmethod = "get";
}
else {
dwr.engine._handlewarning(batch, {
name: "dwr.engine.oldsafari",
message: "safari get support disabled. see getahead.org/dwr/server/servlet and allowgetforsafaributmakeforgeryeasier."
});
}
}
}
batch.mode = batch.ispoll ? dwr.engine._modeplainpoll : dwr.engine._modeplaincall;
var request = dwr.engine.batch.constructrequest(batch, httpmethod);
try {
batch.req.open(httpmethod, request.url, batch.async);
try {
for (var prop in batch.headers) {
var value = batch.headers[prop];
if (typeof value == "string") batch.req.setrequestheader(prop, value);
}
if (!batch.headers["content-type"]) batch.req.setrequestheader("content-type", "text/plain");
}
catch (ex) {
dwr.engine._handlewarning(batch, ex);
}
batch.req.send(request.body);
if (!batch.async) dwr.engine.transport.xhr.statechange(batch);
}
catch (ex) {
dwr.engine._handleerror(batch, ex);
}
if (batch.ispoll && batch.map.partialresponse == dwr.engine._partialresponseyes) {
dwr.engine.transport.xhr.checkcometpoll();
}
},
/**
* called by xmlhttprequest to indicate that something has happened
* @private
* @param {object} batch the current remote operation
*/
statechange:function(batch) {
var toeval;
if (batch.completed) {
dwr.engine._debug("error: _statechange() with batch.completed");
return;
}
var req = batch.req;
try {
if (req.readystate != 4) return;
}
catch (ex) {
dwr.engine._handlewarning(batch, ex);
// it's broken - clear up and forget this call
dwr.engine.batch.remove(batch);
return;
}
try {
var reply = req.responsetext;
reply = dwr.engine._replyrewritehandler(reply);
var status = req.status; // causes mozilla to except on page moves
if (reply == null || reply == "") {
dwr.engine._handlewarning(batch, { name:"dwr.engine.missingdata", message:"no data received from server" });
}
else if (status != 200) {
dwr.engine._handleerror(batch, { name:"dwr.engine.http." + status, message:req.statustext });
}
else {
var contenttype = req.getresponseheader("content-type");
if (!contenttype.match(/^text\/plain/) && !contenttype.match(/^text\/javascript/)) {
if (contenttype.match(/^text\/html/) && typeof batch.texthtmlhandler == "function") {
batch.texthtmlhandler({ status:status, responsetext:reply, contenttype:contenttype });
}
else {
dwr.engine._handlewarning(batch, { name:"dwr.engine.invalidmimetype", message:"invalid content type: '" + contenttype + "'" });
}
}
else {
// comet replies might have already partially executed
if (batch.ispoll && batch.map.partialresponse == dwr.engine._partialresponseyes) {
dwr.engine.transport.xhr.processcometresponse(reply, batch);
}
else {
if (reply.search("//#dwr") == -1) {
dwr.engine._handlewarning(batch, { name:"dwr.engine.invalidreply", message:"invalid reply from server" });
}
else {
toeval = reply;
}
}
}
}
}
catch (ex) {
dwr.engine._handlewarning(batch, ex);
}
dwr.engine._callposthooks(batch);
// outside of the try/catch so errors propagate normally:
dwr.engine._receivedbatch = batch;
if (toeval != null) toeval = toeval.replace(dwr.engine._scripttagprotection, "");
dwr.engine._eval(toeval);
dwr.engine._receivedbatch = null;
dwr.engine.batch.validate(batch);
dwr.engine.batch.remove(batch);
},
/**
* check for reverse ajax activity
* @private
*/
checkcometpoll:function() {
if (dwr.engine._pollreq) {
var req = dwr.engine._pollreq;
var text = req.responsetext;
if (text != null) {
dwr.engine.transport.xhr.processcometresponse(text, req.batch);
}
}
// if the poll resources are still there, come back again
if (dwr.engine._pollreq) {
settimeout("dwr.engine.transport.xhr.checkcometpoll()", dwr.engine._pollcometinterval);
}
},
/**
* some more text might have come in, test and execute the new stuff.
* this method could also be called by the iframe transport
* @private
* @param {object} response from xhr.responsetext
* @param {object} batch the batch that the xhr object pertains to
*/
processcometresponse:function(response, batch) {
if (batch.charsprocessed == response.length) return;
if (response.length == 0) {
batch.charsprocessed = 0;
return;
}
var firststarttag = response.indexof("//#dwr-start#", batch.charsprocessed);
if (firststarttag == -1) {
// dwr.engine._debug("no start tag (search from " + batch.charsprocessed + "). skipping '" + response.substring(batch.charsprocessed) + "'");
batch.charsprocessed = response.length;
return;
}
// if (firststarttag > 0) {
// dwr.engine._debug("start tag not at start (search from " + batch.charsprocessed + "). skipping '" + response.substring(batch.charsprocessed, firststarttag) + "'");
// }
var lastendtag = response.lastindexof("//#dwr-end#");
if (lastendtag == -1) {
// dwr.engine._debug("no end tag. unchanged charsprocessed=" + batch.charsprocessed);
return;
}
// skip the end tag too for next time, remembering cr and lf
if (response.charcodeat(lastendtag + 11) == 13 && response.charcodeat(lastendtag + 12) == 10) {
batch.charsprocessed = lastendtag + 13;
}
else {
batch.charsprocessed = lastendtag + 11;
}
var exec = response.substring(firststarttag + 13, lastendtag);
try {
dwr.engine._receivedbatch = batch;
dwr.engine._eval(exec);
dwr.engine._receivedbatch = null;
}
catch (ex) {
dwr.engine._handleerror(batch, ex);
}
},
/**
* tidy-up when an xhr call is done
* @param {object} batch
*/
remove:function(batch) {
// xhr tidyup: avoid ie handles increase
if (batch.req) {
// if this is a poll frame then stop comet polling
if (batch.req == dwr.engine._pollreq) dwr.engine._pollreq = null;
delete batch.req;
}
}
},
/**
* functions for remoting through iframe
*/
iframe:{
/**
* setup a batch for transfer through iframe
* @param {object} batch the batch to alter for iframe transmit
*/
send:function(batch) {
if (batch.fileupload) {
batch.httpmethod = "post";
batch.enctype = "multipart/form-data";
}
var idname = dwr.engine.transport.iframe.getid(batch);
batch.div = document.createelement("div");
// add the div to the document first, otherwise ie 6 will ignore onload handler.
document.body.appendchild(batch.div);
batch.div.innerhtml = "";
batch.document = document;
dwr.engine.transport.iframe.beginloader(batch, idname);
},
/**
* create a unique id so multiple iframes can fire at the same time
* @param {object} batch a source of a unique number for the batch
* @return {string} a name prefix for created elements
*/
getid:function(batch) {
return batch.ispoll ? "dwr-if-poll-" + batch.map.batchid : "dwr-if-" + batch.map["c0-id"];
},
/**
* setup a form or construct a src attribute to use the iframe.
* this is abstracted from send() because the same logic will do for htmlfile
* @param {object} batch
*/
beginloader:function(batch, idname) {
batch.iframe = batch.document.getelementbyid(idname);
batch.iframe.batch = batch;
batch.mode = batch.ispoll ? dwr.engine._modehtmlpoll : dwr.engine._modehtmlcall;
if (batch.ispoll) dwr.engine._outstandingiframes.push(batch.iframe);
var request = dwr.engine.batch.constructrequest(batch, batch.httpmethod);
if (batch.httpmethod == "get") {
batch.iframe.setattribute("src", request.url);
}
else {
// setting enctype via the dom does not work in ie, create the form using innerhtml instead
var formhtml = "";
var div = batch.document.createelement("div");
div.innerhtml = formhtml;
batch.form = div.firstchild;
for (var prop in batch.map) {
var value = batch.map[prop];
if (typeof value != "function") {
if (value.tagname && value.tagname.tolowercase() == "input" && value.type && value.type.tolowercase() == "file") {
// since we can not set the value of a file object, we must post the actual file object
// that the user clicked browse on. we will put a clone in it's place.
var clone = value.clonenode(true);
value.removeattribute("id", prop);
value.setattribute("name", prop);
value.parentnode.insertbefore(clone, value);
value.parentnode.removechild(value);
batch.form.appendchild(value);
} else {
var forminput = batch.document.createelement("input");
forminput.setattribute("type", "hidden");
forminput.setattribute("name", prop);
forminput.setattribute("value", value);
batch.form.appendchild(forminput);
}
}
}
batch.document.body.appendchild(batch.form);
batch.form.submit();
}
},
/**
* called from iframe onload, check batch using batch-id
* @private
* @param {int} batchid the id of the batch that has loaded
*/
loadingcomplete:function(batchid) {
var batch = dwr.engine._batches[batchid];
if (batch) dwr.engine.batch.validate(batch);
},
/**
* functions designed to be called by the server
*/
remote:{
/**
* called by the server: an iframe reply is about to start
* @private
* @param {object} iframe
* @param {int} batchid
*/
beginiframeresponse:function(iframe, batchid) {
if (iframe != null) dwr.engine._receivedbatch = iframe.batch;
dwr.engine._callposthooks(dwr.engine._receivedbatch);
},
/**
* called by the server: an iframe reply is just completing
* @private
* @param {int} batchid
*/
endiframeresponse:function(batchid) {
dwr.engine.batch.remove(dwr.engine._receivedbatch);
dwr.engine._receivedbatch = null;
}
},
remove:function(batch) {
// todo: make it so that we don't need these if statements
if (batch.div) {
batch.div.parentnode.removechild(batch.div);
}
if (batch.iframe) {
batch.iframe.parentnode.removechild(batch.iframe);
}
if (batch.form) {
batch.form.parentnode.removechild(batch.form);
}
}
/*
// if we have an iframe comet solution where we need to read data streamed
// into an iframe then we need code like this to slurp the data out.
// compare this with xhr.checkcometpoll()
outstandingiframes:[],
checkcometpoll:function() {
for (var i = 0; i < dwr.engine.transport.iframe.outstandingiframes.length; i++) {
var text = "";
var iframe = dwr.engine.transport.iframe.outstandingiframes[i];
try {
text = dwr.engine.transport.iframe.gettextfromcometiframe(iframe);
}
catch (ex) {
dwr.engine._handlewarning(iframe.batch, ex);
}
if (text != "") dwr.engine.transport.xhr.processcometresponse(text, iframe.batch);
}
if (dwr.engine.transport.iframe.outstandingiframes.length > 0) {
settimeout("dwr.engine.transport.iframe.checkcometpoll()", dwr.engine._pollcometinterval);
}
}
// we probably also need to update dwr.engine.remote.beginiframeresponse()
// to call checkcometpoll.
// extract the whole (executed and all) text from the current iframe
gettextfromcometiframe:function(frameele) {
var body = frameele.contentwindow.document.body;
if (body == null) return "";
var text = body.innerhtml;
// we need to prevent ie from stripping line feeds
if (text.indexof("") == 0 || text.indexof("") == 0) {
text = text.substring(5, text.length - 7);
}
return text;
};
// and an addition to iframe.remove():
{
if (batch.iframe) {
// if this is a poll frame then stop comet polling
for (var i = 0; i < dwr.engine.transport.iframe.outstandingiframes.length; i++) {
if (dwr.engine.transport.iframe.outstandingiframes[i] == batch.iframe) {
dwr.engine.transport.iframe.outstandingiframes.splice(i, 1);
}
}
}
}
*/
},
/**
* functions for remoting through script tags
*/
scripttag:{
/**
* setup a batch for transfer through a script tag
* @param {object} batch the batch to alter for script tag transmit
*/
send:function(batch) {
batch.mode = batch.ispoll ? dwr.engine._modeplainpoll : dwr.engine._modeplaincall;
var request = dwr.engine.batch.constructrequest(batch, "get");
batch.script = document.createelement("script");
batch.script.id = "dwr-st-" + batch.map["c0-id"];
batch.script.src = request.url;
document.body.appendchild(batch.script);
}
},
/**
* remoting through ie's htmlfile activex control
*/
htmlfile:{
/**
* setup a batch for transfer through htmlfile
* @param {object} batch the batch to alter for htmlfile transmit
*/
send:function(batch) {
var idname = dwr.engine.transport.iframe.getid(batch);
batch.htmlfile = new window.activexobject("htmlfile");
batch.htmlfile.open();
batch.htmlfile.write("<" + "html>");
//batch.htmlfile.write("document.domain='" + document.domain + "';");
batch.htmlfile.write("");
batch.htmlfile.write("" + "html>");
batch.htmlfile.close();
batch.htmlfile.parentwindow.dwr = dwr;
batch.document = batch.htmlfile;
dwr.engine.transport.iframe.beginloader(batch, idname);
}
}
};
/**
* functions to manipulate batches
* @private
*/
dwr.engine.batch = {
/**
* generate a new standard batch
* @private
*/
create:function() {
var batch = {
async:dwr.engine._async,
charsprocessed:0,
handlers:{},
ispoll:false,
map:{ callcount:0, windowname:window.name },
paramcount:0,
prehooks:[],
posthooks:[],
timeout:dwr.engine._timeout,
errorhandler:dwr.engine._errorhandler,
warninghandler:dwr.engine._warninghandler,
texthtmlhandler:dwr.engine._texthtmlhandler
};
if (dwr.engine._prehook) {
batch.prehooks.push(dwr.engine._prehook);
}
if (dwr.engine._posthook) {
batch.posthooks.push(dwr.engine._posthook);
}
dwr.engine.batch.populateheadersandparameters(batch);
return batch;
},
/**
* generate a new batch for polling
* @private
* @see dwr.engine.batch.create()
*/
createpoll:function() {
var batch = {
async:true,
charsprocessed:0,
handlers:[{
callback:function(pause) {
dwr.engine._pollretries = 0;
settimeout("dwr.engine._poll()", pause);
}
}],
ispoll:true,
map:{ windowname:window.name },
paramcount:0,
path:dwr.engine._defaultpath,
prehooks:[],
posthooks:[],
timeout:0,
windowname:window.name,
errorhandler:dwr.engine._pollerrorhandler,
warninghandler:dwr.engine._pollerrorhandler,
texthtmlhandler:dwr.engine._texthtmlhandler
};
dwr.engine.batch.populateheadersandparameters(batch);
return batch;
},
/**
* copy the global headers and parameters into this batch object
* @private
* @param {object} batch the destination
*/
populateheadersandparameters:function(batch) {
var propname, data;
batch.headers = {};
if (dwr.engine._headers) {
for (propname in dwr.engine._headers) {
data = dwr.engine._headers[propname];
if (typeof data != "function") batch.headers[propname] = data;
}
}
batch.parameters = {};
if (dwr.engine._parameters) {
for (propname in dwr.engine._parameters) {
data = dwr.engine._parameters[propname];
if (typeof data != "function") batch.parameters[propname] = data;
}
}
},
/**
* augment this batch with a new call
* @private
* @param {object} batch
* @param {string} scriptname
* @param {string} methodname
* @param {object} args
*/
addcall:function(batch, scriptname, methodname, args) {
// from the other params, work out which is the function (or object with
// call meta-data) and which is the call parameters
var calldata;
var lastarg = args[args.length - 1];
if (typeof lastarg == "function" || lastarg == null) calldata = { callback:args.pop() };
else calldata = args.pop();
// merge from the calldata into the batch
dwr.engine.batch.merge(batch, calldata);
batch.handlers[batch.map.callcount] = {
exceptionhandler:calldata.exceptionhandler,
exceptionargs:calldata.exceptionargs || calldata.args || null,
exceptionscope:calldata.exceptionscope || calldata.scope || window,
callback:calldata.callbackhandler || calldata.callback,
callbackargs:calldata.callbackargs || calldata.args || null,
callbackscope:calldata.callbackscope || calldata.scope || window
};
// copy to the map the things that need serializing
var prefix = "c" + batch.map.callcount + "-";
batch.map[prefix + "scriptname"] = scriptname;
batch.map[prefix + "methodname"] = methodname;
batch.map[prefix + "id"] = batch.map.callcount;
var converted = [];
for (i = 0; i < args.length; i++) {
dwr.engine.serialize.convert(batch, converted, args[i], prefix + "param" + i);
}
},
/**
* take further options and merge them into a batch
* @private
* @param {object} batch the batch that we are altering
* @param {object} overrides the object containing properties to copy into batch
*/
merge:function(batch, overrides) {
var propname, data;
for (var i = 0; i < dwr.engine._propnames.length; i++) {
propname = dwr.engine._propnames[i];
if (overrides[propname] != null) batch[propname] = overrides[propname];
}
if (overrides.prehook != null) batch.prehooks.unshift(overrides.prehook);
if (overrides.posthook != null) batch.posthooks.push(overrides.posthook);
if (overrides.headers) {
for (propname in overrides.headers) {
data = overrides.headers[propname];
if (typeof data != "function") batch.headers[propname] = data;
}
}
if (overrides.parameters) {
for (propname in overrides.parameters) {
data = overrides.parameters[propname];
if (typeof data != "function") batch.map["p-" + propname] = "" + data;
}
}
},
/**
* executed just before a transport sends the batch
* @private
* @param {object} batch the batch to prepare for sending
*/
preparetosend:function(batch) {
batch.map.batchid = dwr.engine._nextbatchid;
dwr.engine._nextbatchid++;
dwr.engine._batches[batch.map.batchid] = batch;
dwr.engine._batcheslength++;
batch.completed = false;
// security details are filled in late so previous batches have completed
batch.map.page = window.location.pathname + window.location.search;
batch.map.httpsessionid = dwr.engine._gethttpsessionid();
batch.map.scriptsessionid = dwr.engine._scriptsessionid;
for (var i = 0; i < batch.prehooks.length; i++) {
batch.prehooks[i]();
}
batch.prehooks = null;
// set a timeout
if (batch.timeout && batch.timeout != 0) {
batch.interval = setinterval(function() { dwr.engine.transport.abort(batch); }, batch.timeout);
}
},
/**
* work out what the url should look like
* @private
* @param {object} batch the data that we are sending
* @param {object} httpmethod are we using get/post etc?
*/
constructrequest:function(batch, httpmethod) {
// a quick string to help people that use web log analysers
var urlbuffer = [];
urlbuffer.push(batch.path);
urlbuffer.push(batch.mode);
if (batch.ispoll == true) {
urlbuffer.push("reverseajax.dwr");
}
else if (batch.map.callcount == 1) {
urlbuffer.push(batch.map["c0-scriptname"]);
urlbuffer.push(".");
urlbuffer.push(batch.map["c0-methodname"]);
urlbuffer.push(".dwr");
}
else {
urlbuffer.push("multiple.");
urlbuffer.push(batch.map.callcount);
urlbuffer.push(".dwr");
}
// play nice with url re-writing
var sessionmatch = location.href.match(/jsessionid=([^?]+)/);
if (sessionmatch != null) {
urlbuffer.push(";jsessionid=");
urlbuffer.push(sessionmatch[1]);
}
var request = {};
var prop;
if (httpmethod == "get") {
// some browsers (opera/safari2) seem to fail to convert the callcount value
// to a string in the loop below so we do it manually here.
batch.map.callcount = "" + batch.map.callcount;
urlbuffer.push("?");
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
urlbuffer.push(encodeuricomponent(prop));
urlbuffer.push("=");
urlbuffer.push(encodeuricomponent(batch.map[prop]));
urlbuffer.push("&");
}
}
urlbuffer.pop(); // remove the trailing &
request.body = null;
}
else {
// performance: for iframe mode this is thrown away.
var bodybuffer = [];
for (prop in batch.map) {
if (typeof batch.map[prop] != "function") {
bodybuffer.push(prop);
bodybuffer.push("=");
bodybuffer.push(batch.map[prop]);
bodybuffer.push(dwr.engine._postseperator);
}
}
request.body = dwr.engine._contentrewritehandler(bodybuffer.join(""));
}
request.url = dwr.engine._urlrewritehandler(urlbuffer.join(""));
return request;
},
/**
* @private this function is invoked when a batch reply is received.
* it checks that there is a response for every call in the batch. otherwise,
* an error will be signaled (a call without a response indicates that the
* server failed to send complete batch response).
*/
validate:function(batch) {
// if some call left unreplied, report an error.
if (!batch.completed) {
for (var i = 0; i < batch.map.callcount; i++) {
if (batch.handlers[i] != null) {
dwr.engine._handlewarning(batch, { name:"dwr.engine.incompletereply", message:"incomplete reply from server" });
break;
}
}
}
},
/**
* a call has finished by whatever means and we need to shut it all down.
* @private
* @param {object} batch the batch that we are altering
*/
remove:function(batch) {
if (!batch) {
dwr.engine._debug("warning: null batch in dwr.engine.batch.remove()", true);
return;
}
if (batch.completed == "true") {
dwr.engine._debug("warning: double complete", true);
return;
}
batch.completed = true;
// transport tidyup
dwr.engine.transport.remove(batch);
// todo: co-locate all the functions that work on a set of batches
if (batch.map && (batch.map.batchid || batch.map.batchid == 0)) {
delete dwr.engine._batches[batch.map.batchid];
dwr.engine._batcheslength--;
}
// if there is anything on the queue waiting to go out, then send it.
// we don't need to check for ordered mode, here because when ordered mode
// gets turned off, we still process *waiting* batches in an ordered way.
if (dwr.engine._batchqueue.length != 0) {
var sendbatch = dwr.engine._batchqueue.shift();
dwr.engine.transport.send(sendbatch);
}
}
};
/**
* various utility functions
* @private
*/
dwr.engine.util = {
/**
* create one of a number of activex strings
* @param {object} axarray an array of strings to attempt to create activex objects from
*/
newactivexobject:function(axarray) {
var returnvalue;
for (var i = 0; i < axarray.length; i++) {
try {
returnvalue = new activexobject(axarray[i]);
break;
}
catch (ex) { /* ignore */ }
}
return returnvalue;
}
};
/**
* work out what type of browser we are working on
*/
var useragent = navigator.useragent;
var versionstring = navigator.appversion;
var version = parsefloat(versionstring);
dwr.engine.isopera = (useragent.indexof("opera") >= 0) ? version : 0;
dwr.engine.iskhtml = (versionstring.indexof("konqueror") >= 0) || (versionstring.indexof("safari") >= 0) ? version : 0;
dwr.engine.issafari = (versionstring.indexof("safari") >= 0) ? version : 0;
var geckopos = useragent.indexof("gecko");
dwr.engine.ismozilla = ((geckopos >= 0) && (!dwr.engine.iskhtml)) ? version : 0;
dwr.engine.isff = 0;
dwr.engine.isie = 0;
try {
if (dwr.engine.ismozilla) {
dwr.engine.isff = parsefloat(useragent.split("firefox/")[1].split(" ")[0]);
}
if ((document.all) && (!dwr.engine.isopera)) {
dwr.engine.isie = parsefloat(versionstring.split("msie ")[1].split(";")[0]);
}
}
catch(ex) { }
// fetch the scriptsessionid from the server
dwr.engine._execute(dwr.engine._defaultpath, '__system', 'pageloaded', function() {
dwr.engine._ordered = false;
});
/**
* routines for the dwr pubsub hub
*/
dwr.hub = {
/**
* publish some data to a given topic
* @param {object} topicname the topic to publish to
* @param {object} data the data to publish
*/
publish:function(topicname, data) {
dwr.engine._execute(dwr.engine._defaultpath, '__system', 'publish', topicname, data, {});
},
/**
* subscribe to get notifications of publish events to a given topic
* @param {string} topicname the topic to subscribe to
* @param {function} callback the function to call when a publish happens
* @param {object} scope the 'this' object on which the callback executes (optional)
* @param {object} subscriberdata data that the subscriber wishes to remember (optional)
* @return an opaque type for use with unsubscribe
*/
subscribe:function(topicname, callback, scope, subscriberdata) {
var subscription = "" + dwr.hub._subscriptionid++;
dwr.hub._subscriptions[subscription] = {
callback:callback,
scope:scope,
subscriberdata:subscriberdata
};
dwr.engine._execute(dwr.engine._defaultpath, '__system', 'subscribe', topicname, subscription, {});
return subscription;
},
/**
* called by the server: a publish event has happened that we care about
* @private
* @param {object} subscriptionid
* @param {object} publishdata
*/
_remotepublish:function(subscriptionid, publishdata) {
var subscriptiondata = dwr.hub._subscriptions[subscriptionid];
if (!subscriptiondata) return;
subscriptiondata.callback.call(subscriptiondata.scope, publishdata, subscriptiondata.subscriberdata);
},
/**
* subscribe to get notifications of publish events to a given topic
* @param {string} topicname the topic to subscribe to
* @param {function} callback the function to call when a publish happens
* @param {object} scope the 'this' object on which the callback executes (optional)
* @param {object} subscriberdata data that the subscriber wishes to remember (optional)
* @return an opaque type for use with unsubscribe
*/
subscribe:function(topicname, callback, scope, subscriberdata) {
var subscription = "" + dwr.hub._subscriptionid++;
dwr.hub._subscriptions[subscription] = {
callback:callback,
scope:scope,
subscriberdata:subscriberdata
};
dwr.engine._execute(dwr.engine._defaultpath, '__system', 'subscribe', topicname, subscription, {});
return subscription;
},
/**
* each time we subscribe to something, we use a unique number
*/
_subscriptionid:0,
/**
* we need to remember what we are subscribed to so we can recall the callback
*/
_subscriptions:{}
};
})();