PageRenderTime 50ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 1ms

/jssdk1.0a/core/sdk/src/java/net/sangeeth/jssdk/resource/script/js/dwr/core.js

https://github.com/sangeeth/JsSDK
JavaScript | 1017 lines | 731 code | 92 blank | 194 comment | 262 complexity | bbc2cefb489010e23f45d98e432939da MD5 | raw file
  1. /*
  2. * Copyright 2005 Joe Walker
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /**
  17. * Declare a constructor function to which we can add real functions.
  18. */
  19. $export("js.dwr.core.DWREngine");
  20. $export("js.dwr.core.DWRUtil");
  21. function __DWREngine(){
  22. this.setErrorHandler = __DWREngine_setErrorHandler;
  23. this.setWarningHandler = __DWREngine_setWarningHandler;
  24. this.setTimeout = __DWREngine_setTimeout;
  25. this.setPreHook = __DWREngine_setPreHook;
  26. this.setPostHook = __DWREngine_setPostHook;
  27. this.setMethod = __DWREngine_setMethod;
  28. this.setVerb = __DWREngine_setVerb;
  29. this.setOrdered = __DWREngine_setOrdered;
  30. this.setAsync = __DWREngine_setAsync;
  31. this.setTextHtmlHandler = __DWREngine_setTextHtmlHandler;
  32. this.defaultMessageHandler = __DWREngine_defaultMessageHandler;
  33. this.beginBatch = __DWREngine_beginBatch;
  34. this.endBatch = __DWREngine_endBatch;
  35. this._execute = __DWREngine__execute;
  36. this._sendData = __DWREngine__sendData;
  37. this._stateChange = __DWREngine__stateChange;
  38. this._handleResponse = __DWREngine__handleResponse;
  39. this._handleServerError = __DWREngine__handleServerError;
  40. this._eval = __DWREngine__eval;
  41. this._abortRequest = __DWREngine__abortRequest;
  42. this._clearUp = __DWREngine__clearUp;
  43. this._handleError = __DWREngine__handleError;
  44. this._handleWarning = __DWREngine__handleWarning;
  45. this._handleMetaDataError = __DWREngine__handleMetaDataError;
  46. this._handleMetaDataWarning = __DWREngine__handleMetaDataWarning;
  47. this._serializeAll = __DWREngine__serializeAll;
  48. this._lookup = __DWREngine__lookup;
  49. this._serializeObject = __DWREngine__serializeObject;
  50. this._serializeXml = __DWREngine__serializeXml;
  51. this._serializeArray = __DWREngine__serializeArray;
  52. this._unserializeDocument = __DWREngine__unserializeDocument;
  53. this._newActiveXObject = __DWREngine__newActiveXObject;
  54. this._warningHandler = null;
  55. this._timeout = null;
  56. /** XHR remoting method constant. See function __DWREngine_setMethod() */
  57. this.XMLHttpRequest = 1;
  58. /** XHR remoting method constant. See function __DWREngine_setMethod() */
  59. this.IFrame = 2;
  60. // private:
  61. /** A function to call if something fails. */
  62. this._errorHandler = this.defaultMessageHandler;
  63. /** For debugging when something unexplained happens. */
  64. this._warningHandler = null;
  65. /** A function to be called before requests are marshalled. Can be null. */
  66. this._preHook = null;
  67. /** A function to be called after replies are received. Can be null. */
  68. this._postHook = null;
  69. /** An array of the batches that we have sent and are awaiting a reply on. */
  70. this._batches = [];
  71. /** In ordered mode, the array of batches waiting to be sent */
  72. this._batchQueue = [];
  73. /** A map of known ids to their handler objects */
  74. this._handlersMap = {};
  75. /** What is the default remoting method */
  76. this._method = this.XMLHttpRequest;
  77. /** What is the default remoting verb (ie GET or POST) */
  78. this._verb = "POST";
  79. /** Do we attempt to ensure that calls happen in the order in which they were sent? */
  80. this._ordered = false;
  81. /** Do we make the calls async? */
  82. this._async = true;
  83. /** The current batch (if we are in batch mode) */
  84. this._batch = null;
  85. /** The global timeout */
  86. this._timeout = 0;
  87. /** ActiveX objects to use when we want to convert an xml string into a DOM object. */
  88. this._DOMDocument = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"];
  89. /** The ActiveX objects to use when we want to do an XMLHttpRequest call. */
  90. this._XMLHTTP = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"];
  91. }
  92. js.dwr.core.DWREngine = new __DWREngine();
  93. /**
  94. * Set an alternative error handler from the default alert box.
  95. * @see http://getahead.ltd.uk/dwr/browser/engine/errors
  96. */
  97. function __DWREngine_setErrorHandler(handler) {
  98. this._errorHandler = handler;
  99. }
  100. /**
  101. * Set an alternative warning handler from the default alert box.
  102. * @see http://getahead.ltd.uk/dwr/browser/engine/errors
  103. */
  104. function __DWREngine_setWarningHandler(handler) {
  105. this._warningHandler = handler;
  106. }
  107. /**
  108. * Set a default timeout value for all calls. 0 (the default) turns timeouts off.
  109. * @see http://getahead.ltd.uk/dwr/browser/engine/errors
  110. */
  111. function __DWREngine_setTimeout(timeout) {
  112. this._timeout = timeout;
  113. }
  114. /**
  115. * The Pre-Hook is called before any DWR remoting is done.
  116. * @see http://getahead.ltd.uk/dwr/browser/engine/hooks
  117. */
  118. function __DWREngine_setPreHook(handler) {
  119. this._preHook = handler;
  120. }
  121. /**
  122. * The Post-Hook is called after any DWR remoting is done.
  123. * @see http://getahead.ltd.uk/dwr/browser/engine/hooks
  124. */
  125. function __DWREngine_setPostHook(handler) {
  126. this._postHook = handler;
  127. }
  128. /**
  129. * Set the preferred remoting method.
  130. * @param newMethod One of js.dwr.engine.DWREngine.XMLHttpRequest or js.dwr.engine.DWREngine.IFrame
  131. * @see http://getahead.ltd.uk/dwr/browser/engine/options
  132. */
  133. function __DWREngine_setMethod(newMethod) {
  134. if (newMethod != this.XMLHttpRequest && newMethod != this.IFrame) {
  135. this._handleError("Remoting method must be one of js.dwr.engine.DWREngine.XMLHttpRequest or js.dwr.engine.DWREngine.IFrame");
  136. return;
  137. }
  138. this._method = newMethod;
  139. };
  140. /**
  141. * Which HTTP verb do we use to send results? Must be one of "GET" or "POST".
  142. * @see http://getahead.ltd.uk/dwr/browser/engine/options
  143. */
  144. function __DWREngine_setVerb(verb) {
  145. if (verb != "GET" && verb != "POST") {
  146. this._handleError("Remoting verb must be one of GET or POST");
  147. return;
  148. }
  149. this._verb = verb;
  150. }
  151. /**
  152. * Ensure that remote calls happen in the order in which they were sent? (Default: false)
  153. * @see http://getahead.ltd.uk/dwr/browser/engine/ordering
  154. */
  155. function __DWREngine_setOrdered(ordered) {
  156. this._ordered = ordered;
  157. };
  158. /**
  159. * Do we ask the XHR object to be asynchronous? (Default: true)
  160. * @see http://getahead.ltd.uk/dwr/browser/engine/options
  161. */
  162. function __DWREngine_setAsync(async) {
  163. this._async = async;
  164. };
  165. /**
  166. * Setter for the text/html handler - what happens if a DWR request gets an HTML
  167. * reply rather than the expected Javascript. Often due to login timeout
  168. */
  169. function __DWREngine_setTextHtmlHandler(handler) {
  170. this._textHtmlHandler = handler;
  171. }
  172. /**
  173. * The default message handler.
  174. * @see http://getahead.ltd.uk/dwr/browser/engine/errors
  175. */
  176. function __DWREngine_defaultMessageHandler(message) {
  177. if (typeof message == "object" && message.name == "Error" && message.description) {
  178. alert("Error: " + message.description);
  179. }
  180. else {
  181. // Ignore NS_ERROR_NOT_AVAILABLE
  182. if (message.toString().indexOf("0x80040111") == -1) {
  183. alert(message);
  184. }
  185. }
  186. };
  187. /**
  188. * For reduced latency you can group several remote calls together using a batch.
  189. * @see http://getahead.ltd.uk/dwr/browser/engine/batch
  190. */
  191. function __DWREngine_beginBatch() {
  192. if (this._batch) {
  193. this._handleError("Batch already started.");
  194. return;
  195. }
  196. // Setup a batch
  197. this._batch = {
  198. map:{ callCount:0 },
  199. paramCount:0,
  200. ids:[],
  201. preHooks:[],
  202. postHooks:[]
  203. };
  204. };
  205. /**
  206. * Finished grouping a set of remote calls together. Go and execute them all.
  207. * @see http://getahead.ltd.uk/dwr/browser/engine/batch
  208. */
  209. function __DWREngine_endBatch(options) {
  210. var batch = this._batch;
  211. if (batch == null) {
  212. this._handleError("No batch in progress.");
  213. return;
  214. }
  215. // Merge the global batch level properties into the batch meta data
  216. if (options && options.preHook) batch.preHooks.unshift(options.preHook);
  217. if (options && options.postHook) batch.postHooks.push(options.postHook);
  218. if (this._preHook) batch.preHooks.unshift(this._preHook);
  219. if (this._postHook) batch.postHooks.push(this._postHook);
  220. if (batch.method == null) batch.method = this._method;
  221. if (batch.verb == null) batch.verb = this._verb;
  222. if (batch.async == null) batch.async = this._async;
  223. if (batch.timeout == null) batch.timeout = this._timeout;
  224. batch.completed = false;
  225. // We are about to send so this batch should not be globally visible
  226. this._batch = null;
  227. // If we are in ordered mode, then we don't send unless the list of sent
  228. // items is empty
  229. if (!this._ordered) {
  230. this._sendData(batch);
  231. this._batches[this._batches.length] = batch;
  232. }
  233. else {
  234. if (this._batches.length == 0) {
  235. // We aren't waiting for anything, go now.
  236. this._sendData(batch);
  237. this._batches[this._batches.length] = batch;
  238. }
  239. else {
  240. // Push the batch onto the waiting queue
  241. this._batchQueue[this._batchQueue.length] = batch;
  242. }
  243. }
  244. };
  245. /**
  246. * @private Send a request. Called by the Javascript interface stub
  247. * @param path part of URL after the host and before the exec bit without leading or trailing /s
  248. * @param scriptName The class to execute
  249. * @param methodName The method on said class to execute
  250. * @param func The callback function to which any returned data should be passed
  251. * if this is null, any returned data will be ignored
  252. * @param vararg_params The parameters to pass to the above class
  253. */
  254. function __DWREngine__execute(path, scriptName, methodName, vararg_params) {
  255. var singleShot = false;
  256. if (this._batch == null) {
  257. this.beginBatch();
  258. singleShot = true;
  259. }
  260. // To make them easy to manipulate we copy the arguments into an args array
  261. var args = [];
  262. for (var i = 0; i < arguments.length - 3; i++) {
  263. args[i] = arguments[i + 3];
  264. }
  265. // All the paths MUST be to the same servlet
  266. if (this._batch.path == null) {
  267. this._batch.path = path;
  268. }
  269. else {
  270. if (this._batch.path != path) {
  271. this._handleError("Can't batch requests to multiple DWR Servlets.");
  272. return;
  273. }
  274. }
  275. // From the other params, work out which is the function (or object with
  276. // call meta-data) and which is the call parameters
  277. var params;
  278. var callData;
  279. var firstArg = args[0];
  280. var lastArg = args[args.length - 1];
  281. if (typeof firstArg == "function") {
  282. callData = { callback:args.shift() };
  283. params = args;
  284. }
  285. else if (typeof lastArg == "function") {
  286. callData = { callback:args.pop() };
  287. params = args;
  288. }
  289. else if (lastArg != null && typeof lastArg == "object" && lastArg.callback != null && typeof lastArg.callback == "function") {
  290. callData = args.pop();
  291. params = args;
  292. }
  293. else if (firstArg == null) {
  294. // This could be a null callback function, but if the last arg is also
  295. // null then we can't tell which is the function unless there are only
  296. // 2 args, in which case we don't care!
  297. if (lastArg == null && args.length > 2) {
  298. this._handleError("Ambiguous nulls at start and end of parameter list. Which is the callback function?");
  299. }
  300. callData = { callback:args.shift() };
  301. params = args;
  302. }
  303. else if (lastArg == null) {
  304. callData = { callback:args.pop() };
  305. params = args;
  306. }
  307. else {
  308. this._handleError("Missing callback function or metadata object.");
  309. return;
  310. }
  311. // Get a unique ID for this call
  312. var random = Math.floor(Math.random() * 10001);
  313. var id = (random + "_" + new Date().getTime()).toString();
  314. var prefix = "c" + this._batch.map.callCount + "-";
  315. this._batch.ids.push(id);
  316. // batchMetaData stuff the we allow in callMetaData for convenience
  317. if (callData.method != null) {
  318. this._batch.method = callData.method;
  319. delete callData.method;
  320. }
  321. if (callData.verb != null) {
  322. this._batch.verb = callData.verb;
  323. delete callData.verb;
  324. }
  325. if (callData.async != null) {
  326. this._batch.async = callData.async;
  327. delete callData.async;
  328. }
  329. if (callData.timeout != null) {
  330. this._batch.timeout = callData.timeout;
  331. delete callData.timeout;
  332. }
  333. // callMetaData stuff that we handle with the rest of the batchMetaData
  334. if (callData.preHook != null) {
  335. this._batch.preHooks.unshift(callData.preHook);
  336. delete callData.preHook;
  337. }
  338. if (callData.postHook != null) {
  339. this._batch.postHooks.push(callData.postHook);
  340. delete callData.postHook;
  341. }
  342. // Default the error and warning handlers
  343. if (callData.errorHandler == null) callData.errorHandler = this._errorHandler;
  344. if (callData.warningHandler == null) callData.warningHandler = this._warningHandler;
  345. // Save the callMetaData
  346. this._handlersMap[id] = callData;
  347. this._batch.map[prefix + "scriptName"] = scriptName;
  348. this._batch.map[prefix + "methodName"] = methodName;
  349. this._batch.map[prefix + "id"] = id;
  350. // Serialize the parameters into batch.map
  351. for (i = 0; i < params.length; i++) {
  352. this._serializeAll(this._batch, [], params[i], prefix + "param" + i);
  353. }
  354. // Now we have finished remembering the call, we incr the call count
  355. this._batch.map.callCount++;
  356. if (singleShot) {
  357. this.endBatch();
  358. }
  359. };
  360. /** @private Actually send the block of data in the batch object. */
  361. function __DWREngine__sendData(batch) {
  362. // If the batch is empty, don't send anything
  363. if (batch.map.callCount == 0) return;
  364. // Call any pre-hooks
  365. for (var i = 0; i < batch.preHooks.length; i++) {
  366. batch.preHooks[i]();
  367. }
  368. batch.preHooks = null;
  369. // Set a timeout
  370. if (batch.timeout && batch.timeout != 0) {
  371. batch.interval = setInterval(function() { js.dwr.core.DWREngine._abortRequest(batch); }, batch.timeout);
  372. }
  373. // A quick string to help people that use web log analysers
  374. var urlPostfix;
  375. if (batch.map.callCount == 1) {
  376. urlPostfix = batch.map["c0-scriptName"] + "." + batch.map["c0-methodName"] + ".dwr";
  377. }
  378. else {
  379. urlPostfix = "Multiple." + batch.map.callCount + ".dwr";
  380. }
  381. // Get setup for XMLHttpRequest if possible
  382. if (batch.method == this.XMLHttpRequest) {
  383. if (window.XMLHttpRequest) {
  384. batch.req = new XMLHttpRequest();
  385. }
  386. // IE5 for the mac claims to support window.ActiveXObject, but throws an error when it's used
  387. else if (window.ActiveXObject && !(navigator.userAgent.indexOf("Mac") >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
  388. batch.req = this._newActiveXObject(this._XMLHTTP);
  389. }
  390. }
  391. var query = "";
  392. var prop;
  393. // This equates to (batch.method == XHR && browser supports XHR)
  394. if (batch.req) {
  395. batch.map.xml = "true";
  396. // Proceed using XMLHttpRequest
  397. if (batch.async) {
  398. batch.req.onreadystatechange = function() { js.dwr.core.DWREngine._stateChange(batch); };
  399. }
  400. // Workaround for Safari 1.x POST bug
  401. var indexSafari = navigator.userAgent.indexOf("Safari/");
  402. if (indexSafari >= 0) {
  403. var version = navigator.userAgent.substring(indexSafari + 7);
  404. if (parseInt(version, 10) < 400) batch.verb == "GET";
  405. }
  406. if (batch.verb == "GET") {
  407. // Some browsers (Opera/Safari2) seem to fail to convert the value
  408. // of batch.map.callCount to a string in the loop below so we do it
  409. // manually here.
  410. batch.map.callCount = "" + batch.map.callCount;
  411. for (prop in batch.map) {
  412. var qkey = encodeURIComponent(prop);
  413. var qval = encodeURIComponent(batch.map[prop]);
  414. if (qval == "") this._handleError("Found empty qval for qkey=" + qkey);
  415. query += qkey + "=" + qval + "&";
  416. }
  417. try {
  418. batch.req.open("GET", batch.path + "/exec/" + urlPostfix + "?" + query, batch.async);
  419. batch.req.send(null);
  420. if (!batch.async) this._stateChange(batch);
  421. }
  422. catch (ex) {
  423. this._handleMetaDataError(null, ex);
  424. }
  425. }
  426. else {
  427. for (prop in batch.map) {
  428. if (typeof batch.map[prop] != "function") {
  429. query += prop + "=" + batch.map[prop] + "\n";
  430. }
  431. }
  432. try {
  433. batch.req.open("POST", batch.path + "/exec/" + urlPostfix, batch.async);
  434. batch.req.setRequestHeader('Content-Type', 'text/plain');
  435. batch.req.send(query);
  436. if (!batch.async) this._stateChange(batch);
  437. }
  438. catch (ex) {
  439. this._handleMetaDataError(null, ex);
  440. }
  441. }
  442. }
  443. else {
  444. batch.map.xml = "false";
  445. var idname = "dwr-if-" + batch.map["c0-id"];
  446. // Proceed using iframe
  447. batch.div = document.createElement("div");
  448. batch.div.innerHTML = "<iframe src='javascript:void(0)' frameborder='0' width='0' height='0' id='" + idname + "' name='" + idname + "'></iframe>";
  449. document.body.appendChild(batch.div);
  450. batch.iframe = document.getElementById(idname);
  451. batch.iframe.setAttribute("style", "width:0px; height:0px; border:0px;");
  452. if (batch.verb == "GET") {
  453. for (prop in batch.map) {
  454. if (typeof batch.map[prop] != "function") {
  455. query += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";
  456. }
  457. }
  458. query = query.substring(0, query.length - 1);
  459. batch.iframe.setAttribute("src", batch.path + "/exec/" + urlPostfix + "?" + query);
  460. document.body.appendChild(batch.iframe);
  461. }
  462. else {
  463. batch.form = document.createElement("form");
  464. batch.form.setAttribute("id", "dwr-form");
  465. batch.form.setAttribute("action", batch.path + "/exec" + urlPostfix);
  466. batch.form.setAttribute("target", idname);
  467. batch.form.target = idname;
  468. batch.form.setAttribute("method", "POST");
  469. for (prop in batch.map) {
  470. var formInput = document.createElement("input");
  471. formInput.setAttribute("type", "hidden");
  472. formInput.setAttribute("name", prop);
  473. formInput.setAttribute("value", batch.map[prop]);
  474. batch.form.appendChild(formInput);
  475. }
  476. document.body.appendChild(batch.form);
  477. batch.form.submit();
  478. }
  479. }
  480. };
  481. /** @private Called by XMLHttpRequest to indicate that something has happened */
  482. function __DWREngine__stateChange(batch) {
  483. if (!batch.completed && batch.req.readyState == 4) {
  484. try {
  485. var reply = batch.req.responseText;
  486. if (reply == null || reply == "") {
  487. this._handleMetaDataWarning(null, "No data received from server");
  488. }
  489. else {
  490. var contentType = batch.req.getResponseHeader("Content-Type");
  491. if (!contentType.match(/^text\/plain/) && !contentType.match(/^text\/javascript/)) {
  492. if (this._textHtmlHandler && contentType.match(/^text\/html/)) {
  493. this._textHtmlHandler();
  494. }
  495. else {
  496. this._handleMetaDataWarning(null, "Invalid content type from server: '" + contentType + "'");
  497. }
  498. }
  499. else {
  500. // Skip checking the xhr.status because the above will do for most errors
  501. // and because it causes Mozilla to error
  502. if (reply.search("DWREngine._handle") == -1) {
  503. this._handleMetaDataWarning(null, "Invalid reply from server");
  504. }
  505. else {
  506. eval(reply);
  507. }
  508. }
  509. }
  510. // We're done. Clear up
  511. this._clearUp(batch);
  512. }
  513. catch (ex) {
  514. if (ex == null) ex = "Unknown error occured";
  515. this._handleMetaDataWarning(null, ex);
  516. }
  517. finally {
  518. // If there is anything on the queue waiting to go out, then send it.
  519. // We don't need to check for ordered mode, here because when ordered mode
  520. // gets turned off, we still process *waiting* batches in an ordered way.
  521. if (this._batchQueue.length != 0) {
  522. var sendbatch = this._batchQueue.shift();
  523. this._sendData(sendbatch);
  524. this._batches[this._batches.length] = sendbatch;
  525. }
  526. }
  527. }
  528. };
  529. /**
  530. * @private Called by reply scripts generated as a result of remote requests
  531. * @param id The identifier of the call that we are handling a response for
  532. * @param reply The data to pass to the callback function
  533. */
  534. function __DWREngine__handleResponse(id, reply) {
  535. // Clear this callback out of the list - we don't need it any more
  536. var handlers = this._handlersMap[id];
  537. this._handlersMap[id] = null;
  538. if (handlers) {
  539. // Error handlers inside here indicate an error that is nothing to do
  540. // with DWR so we handle them differently.
  541. try {
  542. if (handlers.callback) handlers.callback(reply);
  543. }
  544. catch (ex) {
  545. this._handleMetaDataError(handlers, ex);
  546. }
  547. }
  548. // Finalize the call for IFrame transport
  549. if (this._method == this.IFrame) {
  550. var responseBatch = this._batches[this._batches.length-1];
  551. // Only finalize after the last call has been handled
  552. if (responseBatch.map["c"+(responseBatch.map.callCount-1)+"-id"] == id) {
  553. this._clearUp(responseBatch);
  554. }
  555. }
  556. };
  557. /** @private This method is called by Javascript that is emitted by server */
  558. function __DWREngine__handleServerError(id, error) {
  559. // Clear this callback out of the list - we don't need it any more
  560. var handlers = this._handlersMap[id];
  561. this._handlersMap[id] = null;
  562. if (error.message) this._handleMetaDataError(handlers, error.message, error);
  563. else this._handleMetaDataError(handlers, error);
  564. };
  565. /** @private This is a hack to make the context be this window */
  566. function __DWREngine__eval(script) {
  567. return eval(script);
  568. }
  569. /** @private Called as a result of a request timeout */
  570. function __DWREngine__abortRequest(batch) {
  571. if (batch && !batch.completed) {
  572. clearInterval(batch.interval);
  573. this._clearUp(batch);
  574. if (batch.req) batch.req.abort();
  575. // Call all the timeout errorHandlers
  576. var handlers;
  577. for (var i = 0; i < batch.ids.length; i++) {
  578. handlers = this._handlersMap[batch.ids[i]];
  579. this._handleMetaDataError(handlers, "Timeout");
  580. }
  581. }
  582. };
  583. /** @private A call has finished by whatever means and we need to shut it all down. */
  584. function __DWREngine__clearUp(batch) {
  585. if (batch.completed) {
  586. this._handleError("Double complete");
  587. return;
  588. }
  589. // IFrame tidyup
  590. if (batch.div) batch.div.parentNode.removeChild(batch.div);
  591. if (batch.iframe) batch.iframe.parentNode.removeChild(batch.iframe);
  592. if (batch.form) batch.form.parentNode.removeChild(batch.form);
  593. // XHR tidyup: avoid IE handles increase
  594. if (batch.req) delete batch.req;
  595. for (var i = 0; i < batch.postHooks.length; i++) {
  596. batch.postHooks[i]();
  597. }
  598. batch.postHooks = null;
  599. // TODO: There must be a better way???
  600. for (var i = 0; i < this._batches.length; i++) {
  601. if (this._batches[i] == batch) {
  602. this._batches.splice(i, 1);
  603. break;
  604. }
  605. }
  606. batch.completed = true;
  607. };
  608. /** @private Generic error handling routing to save having null checks everywhere */
  609. function __DWREngine__handleError(reason, ex) {
  610. if (this._errorHandler) this._errorHandler(reason, ex);
  611. };
  612. /** @private Generic warning handling routing to save having null checks everywhere */
  613. function __DWREngine__handleWarning(reason, ex) {
  614. if (this._warningHandler) this._warningHandler(reason, ex);
  615. };
  616. /** @private Generic error handling routing to save having null checks everywhere */
  617. function __DWREngine__handleMetaDataError(handlers, reason, ex) {
  618. if (handlers && typeof handlers.errorHandler == "function") handlers.errorHandler(reason, ex);
  619. else this._handleError(reason, ex);
  620. };
  621. /** @private Generic error handling routing to save having null checks everywhere */
  622. function __DWREngine__handleMetaDataWarning(handlers, reason, ex) {
  623. if (handlers && typeof handlers.warningHandler == "function") handlers.warningHandler(reason, ex);
  624. else this._handleWarning(reason, ex);
  625. };
  626. /**
  627. * @private Marshall a data item
  628. * @param batch A map of variables to how they have been marshalled
  629. * @param referto An array of already marshalled variables to prevent recurrsion
  630. * @param data The data to be marshalled
  631. * @param name The name of the data being marshalled
  632. */
  633. function __DWREngine__serializeAll(batch, referto, data, name) {
  634. if (data == null) {
  635. batch.map[name] = "null:null";
  636. return;
  637. }
  638. switch (typeof data) {
  639. case "boolean":
  640. batch.map[name] = "boolean:" + data;
  641. break;
  642. case "number":
  643. batch.map[name] = "number:" + data;
  644. break;
  645. case "string":
  646. batch.map[name] = "string:" + encodeURIComponent(data);
  647. break;
  648. case "object":
  649. if (data instanceof String) batch.map[name] = "String:" + encodeURIComponent(data);
  650. else if (data instanceof Boolean) batch.map[name] = "Boolean:" + data;
  651. else if (data instanceof Number) batch.map[name] = "Number:" + data;
  652. else if (data instanceof Date) batch.map[name] = "Date:" + data.getTime();
  653. else if (data instanceof Array) batch.map[name] = this._serializeArray(batch, referto, data, name);
  654. else batch.map[name] = this._serializeObject(batch, referto, data, name);
  655. break;
  656. case "function":
  657. // We just ignore functions.
  658. break;
  659. default:
  660. this._handleWarning("Unexpected type: " + typeof data + ", attempting default converter.");
  661. batch.map[name] = "default:" + data;
  662. break;
  663. }
  664. };
  665. /** @private Have we already converted this object? */
  666. function __DWREngine__lookup(referto, data, name) {
  667. var lookup;
  668. // Can't use a map: http://getahead.ltd.uk/ajax/javascript-gotchas
  669. for (var i = 0; i < referto.length; i++) {
  670. if (referto[i].data == data) {
  671. lookup = referto[i];
  672. break;
  673. }
  674. }
  675. if (lookup) return "reference:" + lookup.name;
  676. referto.push({ data:data, name:name });
  677. return null;
  678. };
  679. /** @private Marshall an object */
  680. function __DWREngine__serializeObject(batch, referto, data, name) {
  681. var ref = this._lookup(referto, data, name);
  682. if (ref) return ref;
  683. // This check for an HTML is not complete, but is there a better way?
  684. // Maybe we should add: data.hasChildNodes typeof "function" == true
  685. if (data.nodeName && data.nodeType) {
  686. return this._serializeXml(batch, referto, data, name);
  687. }
  688. // treat objects as an associative arrays
  689. var reply = "Object:{";
  690. var element;
  691. for (element in data) {
  692. batch.paramCount++;
  693. var childName = "c" + this._batch.map.callCount + "-e" + batch.paramCount;
  694. this._serializeAll(batch, referto, data[element], childName);
  695. reply += encodeURIComponent(element) + ":reference:" + childName + ", ";
  696. }
  697. if (reply.substring(reply.length - 2) == ", ") {
  698. reply = reply.substring(0, reply.length - 2);
  699. }
  700. reply += "}";
  701. return reply;
  702. };
  703. /** @private Marshall an object */
  704. function __DWREngine__serializeXml(batch, referto, data, name) {
  705. var ref = this._lookup(referto, data, name);
  706. if (ref) return ref;
  707. var output;
  708. if (window.XMLSerializer) output = new XMLSerializer().serializeToString(data);
  709. else output = data.toXml;
  710. return "XML:" + encodeURIComponent(output);
  711. };
  712. /** @private Marshall an array */
  713. function __DWREngine__serializeArray(batch, referto, data, name) {
  714. var ref = this._lookup(referto, data, name);
  715. if (ref) return ref;
  716. var reply = "Array:[";
  717. for (var i = 0; i < data.length; i++) {
  718. if (i != 0) reply += ",";
  719. batch.paramCount++;
  720. var childName = "c" + this._batch.map.callCount + "-e" + batch.paramCount;
  721. this._serializeAll(batch, referto, data[i], childName);
  722. reply += "reference:";
  723. reply += childName;
  724. }
  725. reply += "]";
  726. return reply;
  727. };
  728. /** @private Convert an XML string into a DOM object. */
  729. function __DWREngine__unserializeDocument(xml) {
  730. var dom;
  731. if (window.DOMParser) {
  732. var parser = new DOMParser();
  733. dom = parser.parseFromString(xml, "text/xml");
  734. if (!dom.documentElement || dom.documentElement.tagName == "parsererror") {
  735. var message = dom.documentElement.firstChild.data;
  736. message += "\n" + dom.documentElement.firstChild.nextSibling.firstChild.data;
  737. throw message;
  738. }
  739. return dom;
  740. }
  741. else if (window.ActiveXObject) {
  742. dom = this._newActiveXObject(this._DOMDocument);
  743. dom.loadXML(xml); // What happens on parse fail with IE?
  744. return dom;
  745. }
  746. else {
  747. var div = document.createElement("div");
  748. div.innerHTML = xml;
  749. return div;
  750. }
  751. };
  752. /**
  753. * @private Helper to find an ActiveX object that works.
  754. * @param axarray An array of strings to attempt to create ActiveX objects from
  755. */
  756. function __DWREngine__newActiveXObject(axarray) {
  757. var returnValue;
  758. for (var i = 0; i < axarray.length; i++) {
  759. try {
  760. returnValue = new ActiveXObject(axarray[i]);
  761. break;
  762. }
  763. catch (ex) { /* ignore */ }
  764. }
  765. return returnValue;
  766. };
  767. /** @private To make up for the lack of encodeURIComponent() on IE5.0 */
  768. if (typeof window.encodeURIComponent === 'undefined') {
  769. js.dwr.core.DWREngine._okURIchars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_-";
  770. js.dwr.core.DWREngine._hexchars = "0123456789ABCDEF";
  771. js.dwr.core.DWREngine._utf8 = function(wide) {
  772. wide = "" + wide; // Make sure it is a string
  773. var c;
  774. var s;
  775. var enc = "";
  776. var i = 0;
  777. while (i < wide.length) {
  778. c = wide.charCodeAt(i++);
  779. // handle UTF-16 surrogates
  780. if (c >= 0xDC00 && c < 0xE000) continue;
  781. if (c >= 0xD800 && c < 0xDC00) {
  782. if (i >= wide.length) continue;
  783. s = wide.charCodeAt(i++);
  784. if (s < 0xDC00 || c >= 0xDE00) continue;
  785. c = ((c - 0xD800) << 10) + (s - 0xDC00) + 0x10000;
  786. }
  787. // output value
  788. if (c < 0x80) {
  789. enc += String.fromCharCode(c);
  790. }
  791. else if (c < 0x800) {
  792. enc += String.fromCharCode(0xC0 + (c >> 6), 0x80 + (c & 0x3F));
  793. }
  794. else if (c < 0x10000) {
  795. enc += String.fromCharCode(0xE0 + (c >> 12), 0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
  796. }
  797. else {
  798. enc += String.fromCharCode(0xF0 + (c >> 18), 0x80 + (c >> 12 & 0x3F), 0x80 + (c >> 6 & 0x3F), 0x80 + (c & 0x3F));
  799. }
  800. }
  801. return enc;
  802. }
  803. js.dwr.core.DWREngine._toHex = function(n) {
  804. return this._hexchars.charAt(n >> 4) + this._hexchars.charAt(n & 0xF);
  805. }
  806. window.encodeURIComponent = function(s) {
  807. s = this._utf8(s);
  808. var c;
  809. var enc = "";
  810. for (var i= 0; i<s.length; i++) {
  811. if (this._okURIchars.indexOf(s.charAt(i)) == -1) {
  812. enc += "%" + js.dwr.core.DWREngine._toHex(s.charCodeAt(i));
  813. }
  814. else {
  815. enc += s.charAt(i);
  816. }
  817. }
  818. return enc;
  819. }
  820. }
  821. /** @private To make up for the lack of Array.splice() on IE5.0 */
  822. if (typeof Array.prototype.splice === 'undefined') {
  823. Array.prototype.splice = function(ind, cnt)
  824. {
  825. if (arguments.length == 0) return ind;
  826. if (typeof ind != "number") ind = 0;
  827. if (ind < 0) ind = Math.max(0,this.length + ind);
  828. if (ind > this.length) {
  829. if (arguments.length > 2) ind = this.length;
  830. else return [];
  831. }
  832. if (arguments.length < 2) cnt = this.length-ind;
  833. cnt = (typeof cnt == "number") ? Math.max(0, cnt) : 0;
  834. removeArray = this.slice(ind, ind + cnt);
  835. endArray = this.slice(ind + cnt);
  836. this.length = ind;
  837. for (var i = 2; i < arguments.length; i++) this[this.length] = arguments[i];
  838. for (i = 0; i < endArray.length; i++) this[this.length] = endArray[i];
  839. return removeArray;
  840. }
  841. }
  842. /** @private To make up for the lack of Array.shift() on IE5.0 */
  843. if (typeof Array.prototype.shift === 'undefined') {
  844. Array.prototype.shift = function(str) {
  845. var val = this[0];
  846. for (var i = 1; i < this.length; ++i) this[i - 1] = this[i];
  847. this.length--;
  848. return val;
  849. }
  850. }
  851. /** @private To make up for the lack of Array.unshift() on IE5.0 */
  852. if (typeof Array.prototype.unshift === 'undefined') {
  853. Array.prototype.unshift = function() {
  854. var i = unshift.arguments.length;
  855. for (var j = this.length - 1; j >= 0; --j) this[j + i] = this[j];
  856. for (j = 0; j < i; ++j) this[j] = unshift.arguments[j];
  857. }
  858. }
  859. /** @private To make up for the lack of Array.push() on IE5.0 */
  860. if (typeof Array.prototype.push === 'undefined') {
  861. Array.prototype.push = function() {
  862. var sub = this.length;
  863. for (var i = 0; i < push.arguments.length; ++i) {
  864. this[sub] = push.arguments[i];
  865. sub++;
  866. }
  867. }
  868. }
  869. /** @private To make up for the lack of Array.pop() on IE5.0 */
  870. if (typeof Array.prototype.pop === 'undefined') {
  871. Array.prototype.pop = function() {
  872. var lastElement = this[this.length - 1];
  873. this.length--;
  874. return lastElement;
  875. }
  876. }
  877. function __DWRUtil() {
  878. this.intervalId = null;
  879. this.useLoadingMessage = __DWRUtil_useLoadingMessage;
  880. }
  881. js.dwr.core.DWRUtil = new __DWRUtil();
  882. function __DWRUtil_useLoadingMessage(message) {
  883. var instance = this;
  884. var loadingMessage;
  885. if (message) loadingMessage = message;
  886. else loadingMessage = "Loading";
  887. try {
  888. js.dwr.core.DWREngine.setPreHook(function() {
  889. var disabledZone = $('disabledZone');
  890. if (!disabledZone) {
  891. disabledZone = document.createElement('div');
  892. disabledZone.setAttribute('id', 'disabledZone');
  893. disabledZone.style.position = "absolute";
  894. disabledZone.style.zIndex = "1000";
  895. disabledZone.style.left = "0px";
  896. disabledZone.style.top = "0px";
  897. disabledZone.style.width = "100%";
  898. disabledZone.style.height = "100%";
  899. document.body.appendChild(disabledZone);
  900. var messageZone = document.createElement('div');
  901. messageZone.setAttribute('id', 'messageZone');
  902. messageZone.style.position = "absolute";
  903. messageZone.style.top = "0px";
  904. messageZone.style.right = "0px";
  905. messageZone.style.background = "#EEEECC";
  906. messageZone.style.color = "#123";
  907. messageZone.style.fontFamily = "Arial,Helvetica,sans-serif";
  908. messageZone.style.padding = "4px";
  909. disabledZone.appendChild(messageZone);
  910. var text = document.createTextNode(loadingMessage);
  911. messageZone.appendChild(text);
  912. }
  913. else {
  914. $('messageZone').innerHTML = loadingMessage;
  915. disabledZone.style.visibility = 'visible';
  916. // window.clearInterval(instance.intervalId);
  917. }
  918. });
  919. js.dwr.core.DWREngine.setPostHook(function() {
  920. $('disabledZone').style.visibility = 'hidden';
  921. });
  922. } catch (E) {
  923. alert(E.description);
  924. }
  925. }