diff --git a/YACOSWeb/WebContent/dwr/engine.js b/YACOSWeb/WebContent/dwr/engine.js new file mode 100644 index 0000000..a846555 --- /dev/null +++ b/YACOSWeb/WebContent/dwr/engine.js @@ -0,0 +1,1281 @@ +/* + * Copyright 2005 Joe Walker + * + * 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. + */ + +/** + * Declare an object to which we can add real functions. + */ +if (dwr == null) var dwr = {}; +if (dwr.engine == null) dwr.engine = {}; +if (DWREngine == null) var DWREngine = dwr.engine; + +/** + * Set an alternative error handler from the default alert box. + * @see getahead.org/dwr/browser/engine/errors + */ +dwr.engine.setErrorHandler = function(handler) { + dwr.engine._errorHandler = handler; +}; + +/** + * Set an alternative warning handler from the default alert box. + * @see getahead.org/dwr/browser/engine/errors + */ +dwr.engine.setWarningHandler = function(handler) { + dwr.engine._warningHandler = handler; +}; + +/** + * Setter for the text/html handler - what happens if a DWR request gets an HTML + * reply rather than the expected Javascript. Often due to login timeout + */ +dwr.engine.setTextHtmlHandler = function(handler) { + dwr.engine._textHtmlHandler = handler; +}; + +/** + * Set a default timeout value for all calls. 0 (the default) turns timeouts off. + * @see getahead.org/dwr/browser/engine/errors + */ +dwr.engine.setTimeout = function(timeout) { + dwr.engine._timeout = timeout; +}; + +/** + * The Pre-Hook is called before any DWR remoting is done. + * @see getahead.org/dwr/browser/engine/hooks + */ +dwr.engine.setPreHook = function(handler) { + dwr.engine._preHook = handler; +}; + +/** + * The Post-Hook is called after any DWR remoting is done. + * @see getahead.org/dwr/browser/engine/hooks + */ +dwr.engine.setPostHook = function(handler) { + dwr.engine._postHook = handler; +}; + +/** + * Custom headers for all DWR calls + * @see getahead.org/dwr/???? + */ +dwr.engine.setHeaders = function(headers) { + dwr.engine._headers = headers; +}; + +/** + * Custom parameters for all DWR calls + * @see getahead.org/dwr/???? + */ +dwr.engine.setParameters = function(parameters) { + dwr.engine._parameters = parameters; +}; + +/** XHR remoting type constant. See dwr.engine.set[Rpc|Poll]Type() */ +dwr.engine.XMLHttpRequest = 1; + +/** XHR remoting type constant. See dwr.engine.set[Rpc|Poll]Type() */ +dwr.engine.IFrame = 2; + +/** XHR remoting type constant. See dwr.engine.setRpcType() */ +dwr.engine.ScriptTag = 3; + +/** + * Set the preferred remoting type. + * @param newType One of dwr.engine.XMLHttpRequest or dwr.engine.IFrame or dwr.engine.ScriptTag + * @see getahead.org/dwr/browser/engine/options + */ +dwr.engine.setRpcType = function(newType) { + if (newType != dwr.engine.XMLHttpRequest && newType != dwr.engine.IFrame && newType != dwr.engine.ScriptTag) { + dwr.engine._handleError(null, { name:"dwr.engine.invalidRpcType", message:"RpcType must be one of dwr.engine.XMLHttpRequest or dwr.engine.IFrame or dwr.engine.ScriptTag" }); + return; + } + dwr.engine._rpcType = newType; +}; + +/** + * Which HTTP method do we use to send results? Must be one of "GET" or "POST". + * @see getahead.org/dwr/browser/engine/options + */ +dwr.engine.setHttpMethod = function(httpMethod) { + if (httpMethod != "GET" && httpMethod != "POST") { + dwr.engine._handleError(null, { name:"dwr.engine.invalidHttpMethod", message:"Remoting method must be one of GET or POST" }); + return; + } + dwr.engine._httpMethod = httpMethod; +}; + +/** + * Ensure that remote calls happen in the order in which they were sent? (Default: false) + * @see getahead.org/dwr/browser/engine/ordering + */ +dwr.engine.setOrdered = function(ordered) { + dwr.engine._ordered = ordered; +}; + +/** + * Do we ask the XHR object to be asynchronous? (Default: true) + * @see getahead.org/dwr/browser/engine/options + */ +dwr.engine.setAsync = function(async) { + dwr.engine._async = async; +}; + +/** + * Does DWR poll the server for updates? (Default: false) + * @see getahead.org/dwr/browser/engine/options + */ +dwr.engine.setActiveReverseAjax = function(activeReverseAjax) { + if (activeReverseAjax) { + // Bail if we are already started + if (dwr.engine._activeReverseAjax) return; + dwr.engine._activeReverseAjax = true; + dwr.engine._poll(); + } + else { + // Can we cancel an existing request? + if (dwr.engine._activeReverseAjax && dwr.engine._pollReq) dwr.engine._pollReq.abort(); + dwr.engine._activeReverseAjax = false; + } + // TODO: in iframe mode, if we start, stop, start then the second start may + // well kick off a second iframe while the first is still about to return + // we should cope with this but we don't +}; + +/** + * The default message handler. + * @see getahead.org/dwr/browser/engine/errors + */ +dwr.engine.defaultErrorHandler = function(message, ex) { + dwr.engine._debug("Error: " + ex.name + ", " + ex.message, true); + if (message == null || message == "") alert("A server error has occured."); + // Ignore NS_ERROR_NOT_AVAILABLE if Mozilla is being narky + else if (message.indexOf("0x80040111") != -1) dwr.engine._debug(message); + else alert(message); +}; + +/** + * The default warning handler. + * @see getahead.org/dwr/browser/engine/errors + */ +dwr.engine.defaultWarningHandler = function(message, ex) { + dwr.engine._debug(message); +}; + +/** + * For reduced latency you can group several remote calls together using a batch. + * @see getahead.org/dwr/browser/engine/batch + */ +dwr.engine.beginBatch = function() { + if (dwr.engine._batch) { + dwr.engine._handleError(null, { name:"dwr.engine.batchBegun", message:"Batch already begun" }); + return; + } + dwr.engine._batch = dwr.engine._createBatch(); +}; + +/** + * Finished grouping a set of remote calls together. Go and execute them all. + * @see getahead.org/dwr/browser/engine/batch + */ +dwr.engine.endBatch = function(options) { + var batch = dwr.engine._batch; + if (batch == null) { + dwr.engine._handleError(null, { name:"dwr.engine.batchNotBegun", message:"No batch in progress" }); + return; + } + dwr.engine._batch = null; + if (batch.map.callCount == 0) return; + + // The hooks need to be merged carefully to preserve ordering + if (options) dwr.engine._mergeBatch(batch, options); + + // In ordered mode, we don't send unless the list of sent items is empty + if (dwr.engine._ordered && dwr.engine._batchesLength != 0) { + dwr.engine._batchQueue[dwr.engine._batchQueue.length] = batch; + } + else { + dwr.engine._sendData(batch); + } +}; + +/** @deprecated */ +dwr.engine.setPollMethod = function(type) { dwr.engine.setPollType(type); }; +dwr.engine.setMethod = function(type) { dwr.engine.setRpcType(type); }; +dwr.engine.setVerb = function(verb) { dwr.engine.setHttpMethod(verb); }; +dwr.engine.setPollType = function() { dwr.engine._debug("Manually setting the Poll Type is not supported"); }; + +//============================================================================== +// Only private stuff below here +//============================================================================== + +/** The original page id sent from the server */ +dwr.engine._origScriptSessionId = "${scriptSessionId}"; + +/** The session cookie name */ +dwr.engine._sessionCookieName = "${sessionCookieName}"; // JSESSIONID + +/** Is GET enabled for the benefit of Safari? */ +dwr.engine._allowGetForSafariButMakeForgeryEasier = "${allowGetForSafariButMakeForgeryEasier}"; + +/** The script prefix to strip in the case of scriptTagProtection. */ +dwr.engine._scriptTagProtection = "${scriptTagProtection}"; + +/** The default path to the DWR servlet */ +dwr.engine._defaultPath = "${defaultPath}"; + +/** Do we use XHR for reverse ajax because we are not streaming? */ +dwr.engine._pollWithXhr = "${pollWithXhr}"; + +/** The read page id that we calculate */ +dwr.engine._scriptSessionId = null; + +/** The function that we use to fetch/calculate a session id */ +dwr.engine._getScriptSessionId = function() { + if (dwr.engine._scriptSessionId == null) { + dwr.engine._scriptSessionId = dwr.engine._origScriptSessionId + Math.floor(Math.random() * 1000); + } + return dwr.engine._scriptSessionId; +}; + +/** A function to call if something fails. */ +dwr.engine._errorHandler = dwr.engine.defaultErrorHandler; + +/** For debugging when something unexplained happens. */ +dwr.engine._warningHandler = dwr.engine.defaultWarningHandler; + +/** A function to be called before requests are marshalled. Can be null. */ +dwr.engine._preHook = null; + +/** A function to be called after replies are received. Can be null. */ +dwr.engine._postHook = null; + +/** An map of the batches that we have sent and are awaiting a reply on. */ +dwr.engine._batches = {}; + +/** A count of the number of outstanding batches. Should be == to _batches.length unless prototype has messed things up */ +dwr.engine._batchesLength = 0; + +/** In ordered mode, the array of batches waiting to be sent */ +dwr.engine._batchQueue = []; + +/** What is the default rpc type */ +dwr.engine._rpcType = dwr.engine.XMLHttpRequest; + +/** What is the default remoting method (ie GET or POST) */ +dwr.engine._httpMethod = "POST"; + +/** Do we attempt to ensure that calls happen in the order in which they were sent? */ +dwr.engine._ordered = false; + +/** Do we make the calls async? */ +dwr.engine._async = true; + +/** The current batch (if we are in batch mode) */ +dwr.engine._batch = null; + +/** The global timeout */ +dwr.engine._timeout = 0; + +/** ActiveX objects to use when we want to convert an xml string into a DOM object. */ +dwr.engine._DOMDocument = ["Msxml2.DOMDocument.6.0", "Msxml2.DOMDocument.5.0", "Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]; + +/** The ActiveX objects to use when we want to do an XMLHttpRequest call. */ +dwr.engine._XMLHTTP = ["Msxml2.XMLHTTP.6.0", "Msxml2.XMLHTTP.5.0", "Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]; + +/** Are we doing comet or polling? */ +dwr.engine._activeReverseAjax = false; + +/** The iframe that we are using to poll */ +dwr.engine._outstandingIFrames = []; + +/** The xhr object that we are using to poll */ +dwr.engine._pollReq = null; + +/** How many milliseconds between internal comet polls */ +dwr.engine._pollCometInterval = 200; + +/** How many times have we re-tried to poll? */ +dwr.engine._pollRetries = 0; +dwr.engine._maxPollRetries = 0; + +/** Do we do a document.reload if we get a text/html reply? */ +dwr.engine._textHtmlHandler = null; + +/** If you wish to send custom headers with every request */ +dwr.engine._headers = null; + +/** If you wish to send extra custom request parameters with each request */ +dwr.engine._parameters = null; + +/** Undocumented interceptors - do not use */ +dwr.engine._postSeperator = "\n"; +dwr.engine._defaultInterceptor = function(data) { return data; }; +dwr.engine._urlRewriteHandler = dwr.engine._defaultInterceptor; +dwr.engine._contentRewriteHandler = dwr.engine._defaultInterceptor; +dwr.engine._replyRewriteHandler = dwr.engine._defaultInterceptor; + +/** Batch ids allow us to know which batch the server is answering */ +dwr.engine._nextBatchId = 0; + +/** A list of the properties that need merging from calls to a batch */ +dwr.engine._propnames = [ "rpcType", "httpMethod", "async", "timeout", "errorHandler", "warningHandler", "textHtmlHandler" ]; + +/** Do we stream, or can be hacked to do so? */ +dwr.engine._partialResponseNo = 0; +dwr.engine._partialResponseYes = 1; +dwr.engine._partialResponseFlush = 2; + +/** + * @private Send a request. Called by the Javascript interface stub + * @param path part of URL after the host and before the exec bit without leading or trailing /s + * @param scriptName The class to execute + * @param methodName The method on said class to execute + * @param func The callback function to which any returned data should be passed + * if this is null, any returned data will be ignored + * @param vararg_params The parameters to pass to the above class + */ +dwr.engine._execute = function(path, scriptName, methodName, vararg_params) { + var singleShot = false; + if (dwr.engine._batch == null) { + dwr.engine.beginBatch(); + singleShot = true; + } + var batch = dwr.engine._batch; + // To make them easy to manipulate we copy the arguments into an args array + var args = []; + for (var i = 0; i < arguments.length - 3; i++) { + args[i] = arguments[i + 3]; + } + // All the paths MUST be to the same servlet + if (batch.path == null) { + batch.path = path; + } + else { + if (batch.path != path) { + dwr.engine._handleError(batch, { name:"dwr.engine.multipleServlets", message:"Can't batch requests to multiple DWR Servlets." }); + return; + } + } + // 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._mergeBatch(batch, callData); + batch.handlers[batch.map.callCount] = { + exceptionHandler:callData.exceptionHandler, + callback:callData.callback + }; + + // 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; + for (i = 0; i < args.length; i++) { + dwr.engine._serializeAll(batch, [], args[i], prefix + "param" + i); + } + + // Now we have finished remembering the call, we incr the call count + batch.map.callCount++; + if (singleShot) dwr.engine.endBatch(); +}; + +/** @private Poll the server to see if there is any data waiting */ +dwr.engine._poll = function(overridePath) { + if (!dwr.engine._activeReverseAjax) return; + + var batch = dwr.engine._createBatch(); + batch.map.id = 0; // TODO: Do we need this?? + batch.map.callCount = 1; + batch.isPoll = true; + if (dwr.engine._pollWithXhr == "true") { + batch.rpcType = dwr.engine.XMLHttpRequest; + batch.map.partialResponse = dwr.engine._partialResponseNo; + } + else { + if (navigator.userAgent.indexOf("Gecko/") != -1) { + batch.rpcType = dwr.engine.XMLHttpRequest; + batch.map.partialResponse = dwr.engine._partialResponseYes; + } + // else if (navigator.userAgent.indexOf("; MSIE")) { + // batch.rpcType = dwr.engine.IFrame; + // batch.map.partialResponse = dwr.engine._partialResponseYes; + // } + else if (navigator.userAgent.indexOf("Safari/")) { + batch.rpcType = dwr.engine.XMLHttpRequest; + batch.map.partialResponse = dwr.engine._partialResponseYes; + } + else { + batch.rpcType = dwr.engine.XMLHttpRequest; + batch.map.partialResponse = dwr.engine._partialResponseNo; + } + } + batch.httpMethod = "POST"; + batch.async = true; + batch.timeout = 0; + batch.path = (overridePath) ? overridePath : dwr.engine._defaultPath; + batch.preHooks = []; + batch.postHooks = []; + batch.errorHandler = dwr.engine._pollErrorHandler; + batch.warningHandler = dwr.engine._pollErrorHandler; + batch.handlers[0] = { + callback:function(pause) { + dwr.engine._pollRetries = 0; + setTimeout("dwr.engine._poll()", pause); + } + }; + + // Send the data + dwr.engine._sendData(batch); + if (batch.rpcType == dwr.engine.XMLHttpRequest && batch.map.partialResponse == dwr.engine._partialResponseYes) { + dwr.engine._checkCometPoll(); + } +}; + +/** Try to recover from polling errors */ +dwr.engine._pollErrorHandler = function(msg, ex) { + // if anything goes wrong then just silently try again (up to 3x) after 10s + dwr.engine._pollRetries++; + dwr.engine._debug("Reverse Ajax poll failed (pollRetries=" + dwr.engine._pollRetries + "): " + ex.name + " : " + ex.message); + if (dwr.engine._pollRetries < dwr.engine._maxPollRetries) { + setTimeout("dwr.engine._poll()", 10000); + } + else { + dwr.engine._activeReverseAjax = false; + dwr.engine._debug("Giving up."); + } +}; + +/** @private Generate a new standard batch */ +dwr.engine._createBatch = function() { + var batch = { + map:{ + callCount:0, + page:window.location.pathname + window.location.search, + httpSessionId:dwr.engine._getJSessionId(), + scriptSessionId:dwr.engine._getScriptSessionId() + }, + charsProcessed:0, paramCount:0, + parameters:{}, headers:{}, + isPoll:false, handlers:{}, preHooks:[], postHooks:[], + rpcType:dwr.engine._rpcType, + httpMethod:dwr.engine._httpMethod, + async:dwr.engine._async, + 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); + var propname, data; + if (dwr.engine._headers) { + for (propname in dwr.engine._headers) { + data = dwr.engine._headers[propname]; + if (typeof data != "function") batch.headers[propname] = data; + } + } + if (dwr.engine._parameters) { + for (propname in dwr.engine._parameters) { + data = dwr.engine._parameters[propname]; + if (typeof data != "function") batch.parameters[propname] = data; + } + } + return batch; +}; + +/** @private Take further options and merge them into */ +dwr.engine._mergeBatch = 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; + } + } +}; + +/** @private What is our session id? */ +dwr.engine._getJSessionId = function() { + var cookies = document.cookie.split(';'); + for (var i = 0; i < cookies.length; i++) { + var cookie = cookies[i]; + while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length); + if (cookie.indexOf(dwr.engine._sessionCookieName + "=") == 0) { + return cookie.substring(dwr.engine._sessionCookieName.length + 1, cookie.length); + } + } + return ""; +}; + +/** @private Check for reverse Ajax activity */ +dwr.engine._checkCometPoll = function() { + for (var i = 0; i < dwr.engine._outstandingIFrames.length; i++) { + var text = ""; + var iframe = dwr.engine._outstandingIFrames[i]; + try { + text = dwr.engine._getTextFromCometIFrame(iframe); + } + catch (ex) { + dwr.engine._handleWarning(iframe.batch, ex); + } + if (text != "") dwr.engine._processCometResponse(text, iframe.batch); + } + if (dwr.engine._pollReq) { + var req = dwr.engine._pollReq; + var text = req.responseText; + if (text != null) dwr.engine._processCometResponse(text, req.batch); + } + + // If the poll resources are still there, come back again + if (dwr.engine._outstandingIFrames.length > 0 || dwr.engine._pollReq) { + setTimeout("dwr.engine._checkCometPoll()", dwr.engine._pollCometInterval); + } +}; + +/** @private Extract the whole (executed an all) text from the current iframe */ +dwr.engine._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;
+};
+
+/** @private Some more text might have come in, test and execute the new stuff */
+dwr.engine._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);
+
+ dwr.engine._receivedBatch = batch;
+ dwr.engine._eval(exec);
+ dwr.engine._receivedBatch = null;
+};
+
+/** @private Actually send the block of data in the batch object. */
+dwr.engine._sendData = function(batch) {
+ batch.map.batchId = dwr.engine._nextBatchId;
+ dwr.engine._nextBatchId++;
+ dwr.engine._batches[batch.map.batchId] = batch;
+ dwr.engine._batchesLength++;
+ batch.completed = false;
+
+ 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._abortRequest(batch); }, batch.timeout);
+ }
+ // Get setup for XMLHttpRequest if possible
+ if (batch.rpcType == dwr.engine.XMLHttpRequest) {
+ if (window.XMLHttpRequest) {
+ batch.req = new XMLHttpRequest();
+ }
+ // IE5 for the mac claims to support window.ActiveXObject, but throws an error when it's used
+ else if (window.ActiveXObject && !(navigator.userAgent.indexOf("Mac") >= 0 && navigator.userAgent.indexOf("MSIE") >= 0)) {
+ batch.req = dwr.engine._newActiveXObject(dwr.engine._XMLHTTP);
+ }
+ }
+
+ var prop, request;
+ if (batch.req) {
+ // Proceed using XMLHttpRequest
+ if (batch.async) {
+ batch.req.onreadystatechange = function() {
+ if (typeof dwr != 'undefined') dwr.engine._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;
+ }
+ // 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") batch.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;
+ request = dwr.engine._constructRequest(batch);
+ try {
+ batch.req.open(batch.httpMethod, request.url, batch.async);
+ try {
+ for (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._stateChange(batch);
+ }
+ catch (ex) {
+ dwr.engine._handleError(batch, ex);
+ }
+ }
+ else if (batch.rpcType != dwr.engine.ScriptTag) {
+ var idname = batch.isPoll ? "dwr-if-poll-" + batch.map.batchId : "dwr-if-" + batch.map["c0-id"];
+ // on IE try to use the htmlfile activex control
+ if (batch.isPoll && window.ActiveXObject) {
+ batch.htmlfile = new window.ActiveXObject("htmlfile");
+ batch.htmlfile.open();
+ batch.htmlfile.write("");
+ //batch.htmlfile.write("");
+ batch.htmlfile.write("");
+ batch.htmlfile.write("");
+ batch.htmlfile.close();
+ batch.htmlfile.parentWindow.dwr = dwr;
+ batch.document = batch.htmlfile;
+ }
+ else {
+ 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;
+ }
+ 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);
+ request = dwr.engine._constructRequest(batch);
+ if (batch.httpMethod == "GET") {
+ batch.iframe.setAttribute("src", request.url);
+ }
+ else {
+ batch.form = batch.document.createElement("form");
+ batch.form.setAttribute("id", "dwr-form");
+ batch.form.setAttribute("action", request.url);
+ batch.form.setAttribute("target", idname);
+ batch.form.target = idname;
+ batch.form.setAttribute("method", batch.httpMethod);
+ for (prop in batch.map) {
+ var value = batch.map[prop];
+ if (typeof value != "function") {
+ 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();
+ }
+ }
+ else {
+ batch.httpMethod = "GET"; // There's no such thing as ScriptTag using POST
+ batch.mode = batch.isPoll ? dwr.engine._ModePlainPoll : dwr.engine._ModePlainCall;
+ request = dwr.engine._constructRequest(batch);
+ batch.script = document.createElement("script");
+ batch.script.id = "dwr-st-" + batch.map["c0-id"];
+ batch.script.src = request.url;
+ document.body.appendChild(batch.script);
+ }
+};
+
+dwr.engine._ModePlainCall = "/call/plaincall/";
+dwr.engine._ModeHtmlCall = "/call/htmlcall/";
+dwr.engine._ModePlainPoll = "/call/plainpoll/";
+dwr.engine._ModeHtmlPoll = "/call/htmlpoll/";
+
+/** @private Work out what the URL should look like */
+dwr.engine._constructRequest = function(batch) {
+ // A quick string to help people that use web log analysers
+ var request = { url:batch.path + batch.mode, body:null };
+ if (batch.isPoll == true) {
+ request.url += "ReverseAjax.dwr";
+ }
+ else if (batch.map.callCount == 1) {
+ request.url += batch.map["c0-scriptName"] + "." + batch.map["c0-methodName"] + ".dwr";
+ }
+ else {
+ request.url += "Multiple." + batch.map.callCount + ".dwr";
+ }
+ // Play nice with url re-writing
+ var sessionMatch = location.href.match(/jsessionid=([^?]+)/);
+ if (sessionMatch != null) {
+ request.url += ";jsessionid=" + sessionMatch[1];
+ }
+
+ var prop;
+ if (batch.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;
+ request.url += "?";
+ for (prop in batch.map) {
+ if (typeof batch.map[prop] != "function") {
+ request.url += encodeURIComponent(prop) + "=" + encodeURIComponent(batch.map[prop]) + "&";
+ }
+ }
+ request.url = request.url.substring(0, request.url.length - 1);
+ }
+ else {
+ // PERFORMANCE: for iframe mode this is thrown away.
+ request.body = "";
+ for (prop in batch.map) {
+ if (typeof batch.map[prop] != "function") {
+ request.body += prop + "=" + batch.map[prop] + dwr.engine._postSeperator;
+ }
+ }
+ request.body = dwr.engine._contentRewriteHandler(request.body);
+ }
+ request.url = dwr.engine._urlRewriteHandler(request.url);
+ return request;
+};
+
+/** @private Called by XMLHttpRequest to indicate that something has happened */
+dwr.engine._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._clearUp(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();
+ }
+ 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._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 propogate normally:
+ dwr.engine._receivedBatch = batch;
+ if (toEval != null) toEval = toEval.replace(dwr.engine._scriptTagProtection, "");
+ dwr.engine._eval(toEval);
+ dwr.engine._receivedBatch = null;
+ dwr.engine._validateBatch(batch);
+ dwr.engine._clearUp(batch);
+};
+
+/**
+ * @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).
+ */
+dwr.engine._validateBatch = 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;
+ }
+ }
+ }
+}
+
+/** @private Called from iframe onload, check batch using batch-id */
+dwr.engine._iframeLoadingComplete = function(batchId) {
+ // dwr.engine._checkCometPoll();
+ var batch = dwr.engine._batches[batchId];
+ if (batch) dwr.engine._validateBatch(batch);
+}
+
+/** @private Called by the server: Execute a callback */
+dwr.engine._remoteHandleCallback = function(batchId, callId, reply) {
+ var batch = dwr.engine._batches[batchId];
+ if (batch == null) {
+ dwr.engine._debug("Warning: batch == null in remoteHandleCallback for batchId=" + batchId, true);
+ return;
+ }
+ // Error handlers inside here indicate an error that is nothing to do
+ // with DWR so we handle them differently.
+ try {
+ var handlers = batch.handlers[callId];
+ batch.handlers[callId] = null;
+ if (!handlers) {
+ dwr.engine._debug("Warning: Missing handlers. callId=" + callId, true);
+ }
+ else if (typeof handlers.callback == "function") handlers.callback(reply);
+ }
+ catch (ex) {
+ dwr.engine._handleError(batch, ex);
+ }
+};
+
+/** @private Called by the server: Handle an exception for a call */
+dwr.engine._remoteHandleException = function(batchId, callId, ex) {
+ var batch = dwr.engine._batches[batchId];
+ if (batch == null) { dwr.engine._debug("Warning: null batch in remoteHandleException", true); return; }
+ var handlers = batch.handlers[callId];
+ batch.handlers[callId] = null;
+ if (handlers == null) { dwr.engine._debug("Warning: null handlers in remoteHandleException", true); return; }
+ if (ex.message == undefined) ex.message = "";
+ if (typeof handlers.exceptionHandler == "function") handlers.exceptionHandler(ex.message, ex);
+ else if (typeof batch.errorHandler == "function") batch.errorHandler(ex.message, ex);
+};
+
+/** @private Called by the server: The whole batch is broken */
+dwr.engine._remoteHandleBatchException = function(ex, batchId) {
+ var searchBatch = (dwr.engine._receivedBatch == null && batchId != null);
+ if (searchBatch) {
+ dwr.engine._receivedBatch = dwr.engine._batches[batchId];
+ }
+ if (ex.message == undefined) ex.message = "";
+ dwr.engine._handleError(dwr.engine._receivedBatch, ex);
+ if (searchBatch) {
+ dwr.engine._receivedBatch = null;
+ dwr.engine._clearUp(dwr.engine._batches[batchId]);
+ }
+};
+
+/** @private Called by the server: Reverse ajax should not be used */
+dwr.engine._remotePollCometDisabled = function(ex, batchId) {
+ dwr.engine.setActiveReverseAjax(false);
+ var searchBatch = (dwr.engine._receivedBatch == null && batchId != null);
+ if (searchBatch) {
+ dwr.engine._receivedBatch = dwr.engine._batches[batchId];
+ }
+ if (ex.message == undefined) ex.message = "";
+ dwr.engine._handleError(dwr.engine._receivedBatch, ex);
+ if (searchBatch) {
+ dwr.engine._receivedBatch = null;
+ dwr.engine._clearUp(dwr.engine._batches[batchId]);
+ }
+};
+
+/** @private Called by the server: An IFrame reply is about to start */
+dwr.engine._remoteBeginIFrameResponse = function(iframe, batchId) {
+ if (iframe != null) dwr.engine._receivedBatch = iframe.batch;
+ dwr.engine._callPostHooks(dwr.engine._receivedBatch);
+};
+
+/** @private Called by the server: An IFrame reply is just completing */
+dwr.engine._remoteEndIFrameResponse = function(batchId) {
+ dwr.engine._clearUp(dwr.engine._receivedBatch);
+ dwr.engine._receivedBatch = null;
+};
+
+/** @private This is a hack to make the context be this window */
+dwr.engine._eval = function(script) {
+ if (script == null) return null;
+ if (script == "") { dwr.engine._debug("Warning: blank script", true); return null; }
+ // dwr.engine._debug("Exec: [" + script + "]", true);
+ return eval(script);
+};
+
+/** @private Called as a result of a request timeout */
+dwr.engine._abortRequest = function(batch) {
+ if (batch && !batch.completed) {
+ clearInterval(batch.interval);
+ dwr.engine._clearUp(batch);
+ if (batch.req) batch.req.abort();
+ dwr.engine._handleError(batch, { name:"dwr.engine.timeout", message:"Timeout" });
+ }
+};
+
+/** @private call all the post hooks for a batch */
+dwr.engine._callPostHooks = function(batch) {
+ if (batch.postHooks) {
+ for (var i = 0; i < batch.postHooks.length; i++) {
+ batch.postHooks[i]();
+ }
+ batch.postHooks = null;
+ }
+};
+
+/** @private A call has finished by whatever means and we need to shut it all down. */
+dwr.engine._clearUp = function(batch) {
+ if (!batch) { dwr.engine._debug("Warning: null batch in dwr.engine._clearUp()", true); return; }
+ if (batch.completed == "true") { dwr.engine._debug("Warning: Double complete", true); return; }
+
+ // IFrame tidyup
+ if (batch.div) batch.div.parentNode.removeChild(batch.div);
+ if (batch.iframe) {
+ // If this is a poll frame then stop comet polling
+ for (var i = 0; i < dwr.engine._outstandingIFrames.length; i++) {
+ if (dwr.engine._outstandingIFrames[i] == batch.iframe) {
+ dwr.engine._outstandingIFrames.splice(i, 1);
+ }
+ }
+ batch.iframe.parentNode.removeChild(batch.iframe);
+ }
+ if (batch.form) batch.form.parentNode.removeChild(batch.form);
+
+ // 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;
+ }
+
+ if (batch.map && batch.map.batchId) {
+ delete dwr.engine._batches[batch.map.batchId];
+ dwr.engine._batchesLength--;
+ }
+
+ batch.completed = true;
+
+ // 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._sendData(sendbatch);
+ }
+};
+
+/** @private Generic error handling routing to save having null checks everywhere */
+dwr.engine._handleError = function(batch, ex) {
+ if (typeof ex == "string") ex = { name:"unknown", message:ex };
+ if (ex.message == null) ex.message = "";
+ if (ex.name == null) ex.name = "unknown";
+ if (batch && typeof batch.errorHandler == "function") batch.errorHandler(ex.message, ex);
+ else if (dwr.engine._errorHandler) dwr.engine._errorHandler(ex.message, ex);
+ if (batch) dwr.engine._clearUp(batch);
+};
+
+/** @private Generic error handling routing to save having null checks everywhere */
+dwr.engine._handleWarning = function(batch, ex) {
+ if (typeof ex == "string") ex = { name:"unknown", message:ex };
+ if (ex.message == null) ex.message = "";
+ if (ex.name == null) ex.name = "unknown";
+ if (batch && typeof batch.warningHandler == "function") batch.warningHandler(ex.message, ex);
+ else if (dwr.engine._warningHandler) dwr.engine._warningHandler(ex.message, ex);
+ if (batch) dwr.engine._clearUp(batch);
+};
+
+/**
+ * @private Marshall a data item
+ * @param batch A map of variables to how they have been marshalled
+ * @param referto An array of already marshalled variables to prevent recurrsion
+ * @param data The data to be marshalled
+ * @param name The name of the data being marshalled
+ */
+dwr.engine._serializeAll = function(batch, referto, data, name) {
+ if (data == null) {
+ batch.map[name] = "null:null";
+ return;
+ }
+
+ switch (typeof data) {
+ case "boolean":
+ batch.map[name] = "boolean:" + data;
+ break;
+ case "number":
+ batch.map[name] = "number:" + data;
+ break;
+ case "string":
+ batch.map[name] = "string:" + encodeURIComponent(data);
+ break;
+ case "object":
+ if (data instanceof String) batch.map[name] = "String:" + encodeURIComponent(data);
+ else if (data instanceof Boolean) batch.map[name] = "Boolean:" + data;
+ else if (data instanceof Number) batch.map[name] = "Number:" + data;
+ else if (data instanceof Date) batch.map[name] = "Date:" + data.getTime();
+ else if (data && data.join) batch.map[name] = dwr.engine._serializeArray(batch, referto, data, name);
+ else batch.map[name] = dwr.engine._serializeObject(batch, referto, data, name);
+ break;
+ case "function":
+ // We just ignore functions.
+ break;
+ default:
+ dwr.engine._handleWarning(null, { name:"dwr.engine.unexpectedType", message:"Unexpected type: " + typeof data + ", attempting default converter." });
+ batch.map[name] = "default:" + data;
+ break;
+ }
+};
+
+/** @private Have we already converted this object? */
+dwr.engine._lookup = function(referto, data, name) {
+ var lookup;
+ // Can't use a map: getahead.org/ajax/javascript-gotchas
+ for (var i = 0; i < referto.length; i++) {
+ if (referto[i].data == data) {
+ lookup = referto[i];
+ break;
+ }
+ }
+ if (lookup) return "reference:" + lookup.name;
+ referto.push({ data:data, name:name });
+ return null;
+};
+
+/** @private Marshall an object */
+dwr.engine._serializeObject = function(batch, referto, data, name) {
+ var ref = dwr.engine._lookup(referto, data, name);
+ if (ref) return ref;
+
+ // This check for an HTML is not complete, but is there a better way?
+ // Maybe we should add: data.hasChildNodes typeof "function" == true
+ if (data.nodeName && data.nodeType) {
+ return dwr.engine._serializeXml(batch, referto, data, name);
+ }
+
+ // treat objects as an associative arrays
+ var reply = "Object_" + dwr.engine._getObjectClassName(data) + ":{";
+ var element;
+ for (element in data) {
+ if (typeof data[element] != "function") {
+ batch.paramCount++;
+ var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
+ dwr.engine._serializeAll(batch, referto, data[element], childName);
+
+ reply += encodeURIComponent(element) + ":reference:" + childName + ", ";
+ }
+ }
+
+ if (reply.substring(reply.length - 2) == ", ") {
+ reply = reply.substring(0, reply.length - 2);
+ }
+ reply += "}";
+
+ return reply;
+};
+
+/** @private Returns the classname of supplied argument obj */
+dwr.engine._errorClasses = { "Error":Error, "EvalError":EvalError, "RangeError":RangeError, "ReferenceError":ReferenceError, "SyntaxError":SyntaxError, "TypeError":TypeError, "URIError":URIError };
+dwr.engine._getObjectClassName = function(obj) {
+ // Try to find the classname by stringifying the object's constructor
+ // and extract from "function ".
+ if (obj && obj.constructor && obj.constructor.toString)
+ {
+ var str = obj.constructor.toString();
+ var regexpmatch = str.match(/function\s+(\w+)/);
+ if (regexpmatch && regexpmatch.length == 2) {
+ return regexpmatch[1];
+ }
+ }
+
+ // Now manually test against the core Error classes, as these in some
+ // browsers successfully match to the wrong class in the
+ // Object.toString() test we will do later
+ if (obj && obj.constructor) {
+ for (var errorname in dwr.engine._errorClasses) {
+ if (obj.constructor == dwr.engine._errorClasses[errorname]) return errorname;
+ }
+ }
+
+ // Try to find the classname by calling Object.toString() on the object
+ // and extracting from "[object ]"
+ 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";
+};
+
+/** @private Marshall an object */
+dwr.engine._serializeXml = function(batch, referto, data, name) {
+ var ref = dwr.engine._lookup(referto, data, name);
+ if (ref) return ref;
+
+ var output;
+ if (window.XMLSerializer) output = new XMLSerializer().serializeToString(data);
+ else if (data.toXml) output = data.toXml;
+ else output = data.innerHTML;
+
+ return "XML:" + encodeURIComponent(output);
+};
+
+/** @private Marshall an array */
+dwr.engine._serializeArray = function(batch, referto, data, name) {
+ var ref = dwr.engine._lookup(referto, data, name);
+ if (ref) return ref;
+
+ var reply = "Array:[";
+ for (var i = 0; i < data.length; i++) {
+ if (i != 0) reply += ",";
+ batch.paramCount++;
+ var childName = "c" + dwr.engine._batch.map.callCount + "-e" + batch.paramCount;
+ dwr.engine._serializeAll(batch, referto, data[i], childName);
+ reply += "reference:";
+ reply += childName;
+ }
+ reply += "]";
+
+ return reply;
+};
+
+/** @private Convert an XML string into a DOM object. */
+dwr.engine._unserializeDocument = function(xml) {
+ var dom;
+ if (window.DOMParser) {
+ var parser = new DOMParser();
+ dom = parser.parseFromString(xml, "text/xml");
+ if (!dom.documentElement || dom.documentElement.tagName == "parsererror") {
+ var message = dom.documentElement.firstChild.data;
+ message += "\n" + dom.documentElement.firstChild.nextSibling.firstChild.data;
+ throw message;
+ }
+ return dom;
+ }
+ else if (window.ActiveXObject) {
+ dom = dwr.engine._newActiveXObject(dwr.engine._DOMDocument);
+ dom.loadXML(xml); // What happens on parse fail with IE?
+ return dom;
+ }
+ else {
+ var div = document.createElement("div");
+ div.innerHTML = xml;
+ return div;
+ }
+};
+
+/** @param axarray An array of strings to attempt to create ActiveX objects from */
+dwr.engine._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;
+};
+
+/** @private Used internally when some message needs to get to the programmer */
+dwr.engine._debug = function(message, stacktrace) {
+ var written = false;
+ try {
+ if (window.console) {
+ if (stacktrace && window.console.trace) window.console.trace();
+ window.console.log(message);
+ written = true;
+ }
+ else if (window.opera && window.opera.postError) {
+ window.opera.postError(message);
+ written = true;
+ }
+ }
+ catch (ex) { /* ignore */ }
+
+ if (!written) {
+ var debug = document.getElementById("dwr-debug");
+ if (debug) {
+ var contents = message + "
" + debug.innerHTML;
+ if (contents.length > 2048) contents = contents.substring(0, 2048);
+ debug.innerHTML = contents;
+ }
+ }
+};
diff --git a/YACOSWeb/WebContent/dwr/util.js b/YACOSWeb/WebContent/dwr/util.js
new file mode 100644
index 0000000..6687862
--- /dev/null
+++ b/YACOSWeb/WebContent/dwr/util.js
@@ -0,0 +1,1484 @@
+/*
+ * Copyright 2005 Joe Walker
+ *
+ * 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.
+ */
+
+/**
+ * Declare an object to which we can add real functions.
+ */
+if (dwr == null) var dwr = {};
+if (dwr.util == null) dwr.util = {};
+if (DWRUtil == null) var DWRUtil = dwr.util;
+
+/** @private The flag we use to decide if we should escape html */
+dwr.util._escapeHtml = true;
+
+/**
+ * Set the global escapeHtml flag
+ */
+dwr.util.setEscapeHtml = function(escapeHtml) {
+ dwr.util._escapeHtml = escapeHtml;
+};
+
+/** @private Work out from an options list and global settings if we should be esccaping */
+dwr.util._shouldEscapeHtml = function(options) {
+ if (options && options.escapeHtml != null) {
+ return options.escapeHtml;
+ }
+ return dwr.util._escapeHtml;
+};
+
+/**
+ * Return a string with &, <, >, ' and " replaced with their entities
+ * @see TODO
+ */
+dwr.util.escapeHtml = function(original) {
+ var div = document.createElement('div');
+ var text = document.createTextNode(original);
+ div.appendChild(text);
+ return div.innerHTML;
+};
+
+/**
+ * Replace common XML entities with characters (see dwr.util.escapeHtml())
+ * @see TODO
+ */
+dwr.util.unescapeHtml = function(original) {
+ var div = document.createElement('div');
+ div.innerHTML = original.replace(/<\/?[^>]+>/gi, '');
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
+};
+
+/**
+ * Replace characters dangerous for XSS reasons with visually similar characters
+ * @see TODO
+ */
+dwr.util.replaceXmlCharacters = function(original) {
+ original = original.replace("&", "+");
+ original = original.replace("<", "\u2039");
+ original = original.replace(">", "\u203A");
+ original = original.replace("\'", "\u2018");
+ original = original.replace("\"", "\u201C");
+ return original;
+};
+
+/**
+ * Return true iff the input string contains any XSS dangerous characters
+ * @see TODO
+ */
+dwr.util.containsXssRiskyCharacters = function(original) {
+ return (original.indexOf('&') != -1
+ || original.indexOf('<') != -1
+ || original.indexOf('>') != -1
+ || original.indexOf('\'') != -1
+ || original.indexOf('\"') != -1);
+};
+
+/**
+ * Enables you to react to return being pressed in an input
+ * @see http://getahead.org/dwr/browser/util/selectrange
+ */
+dwr.util.onReturn = function(event, action) {
+ if (!event) event = window.event;
+ if (event && event.keyCode && event.keyCode == 13) action();
+};
+
+/**
+ * Select a specific range in a text box. Useful for 'google suggest' type functions.
+ * @see http://getahead.org/dwr/browser/util/selectrange
+ */
+dwr.util.selectRange = function(ele, start, end) {
+ ele = dwr.util._getElementById(ele, "selectRange()");
+ if (ele == null) return;
+ if (ele.setSelectionRange) {
+ ele.setSelectionRange(start, end);
+ }
+ else if (ele.createTextRange) {
+ var range = ele.createTextRange();
+ range.moveStart("character", start);
+ range.moveEnd("character", end - ele.value.length);
+ range.select();
+ }
+ ele.focus();
+};
+
+/**
+ * Find the element in the current HTML document with the given id or ids
+ * @see http://getahead.org/dwr/browser/util/$
+ */
+if (document.getElementById) {
+ dwr.util.byId = function() {
+ var elements = new Array();
+ for (var i = 0; i < arguments.length; i++) {
+ var element = arguments[i];
+ if (typeof element == 'string') {
+ element = document.getElementById(element);
+ }
+ if (arguments.length == 1) {
+ return element;
+ }
+ elements.push(element);
+ }
+ return elements;
+ };
+}
+else if (document.all) {
+ dwr.util.byId = function() {
+ var elements = new Array();
+ for (var i = 0; i < arguments.length; i++) {
+ var element = arguments[i];
+ if (typeof element == 'string') {
+ element = document.all[element];
+ }
+ if (arguments.length == 1) {
+ return element;
+ }
+ elements.push(element);
+ }
+ return elements;
+ };
+}
+
+/**
+ * Alias $ to dwr.util.byId
+ * @see http://getahead.org/dwr/browser/util/$
+ */
+var $;
+if (!$) {
+ $ = dwr.util.byId;
+}
+
+/**
+ * This function pretty-prints simple data or whole object graphs, f ex as an aid in debugging.
+ * @see http://getahead.org/dwr/browser/util/todescriptivestring
+ */
+dwr.util.toDescriptiveString = function(data, showLevels, options) {
+ if (showLevels === undefined) showLevels = 1;
+ var opt = {};
+ if (dwr.util._isObject(options)) opt = options;
+ var defaultoptions = {
+ escapeHtml:false,
+ baseIndent: "",
+ childIndent: "\u00A0\u00A0",
+ lineTerminator: "\n",
+ oneLineMaxItems: 5,
+ shortStringMaxLength: 13,
+ propertyNameMaxLength: 30
+ };
+ for (var p in defaultoptions) {
+ if (!(p in opt)) {
+ opt[p] = defaultoptions[p];
+ }
+ }
+
+ var skipDomProperties = {
+ document:true, ownerDocument:true,
+ all:true,
+ parentElement:true, parentNode:true, offsetParent:true,
+ children:true, firstChild:true, lastChild:true,
+ previousSibling:true, nextSibling:true,
+ innerHTML:true, outerHTML:true,
+ innerText:true, outerText:true, textContent:true,
+ attributes:true,
+ style:true, currentStyle:true, runtimeStyle:true,
+ parentTextEdit:true
+ };
+
+ function recursive(data, showLevels, indentDepth, options) {
+ var reply = "";
+ try {
+ // string
+ if (typeof data == "string") {
+ var str = data;
+ if (showLevels == 0 && str.length > options.shortStringMaxLength)
+ str = str.substring(0, options.shortStringMaxLength-3) + "...";
+ if (options.escapeHtml) {
+ // Do the escape separately for every line as escapeHtml() on some
+ // browsers (IE) will strip line breaks and we want to preserve them
+ var lines = str.split("\n");
+ for (var i = 0; i < lines.length; i++) lines[i] = dwr.util.escapeHtml(lines[i]);
+ str = lines.join("\n");
+ }
+ if (showLevels == 0) { // Short format
+ str = str.replace(/\n|\r|\t/g, function(ch) {
+ switch (ch) {
+ case "\n": return "\\n";
+ case "\r": return "";
+ case "\t": return "\\t";
+ }
+ });
+ }
+ else { // Long format
+ str = str.replace(/\n|\r|\t/g, function(ch) {
+ switch (ch) {
+ case "\n": return options.lineTerminator + indent(indentDepth+1, options);
+ case "\r": return "";
+ case "\t": return "\\t";
+ }
+ });
+ }
+ reply = '"' + str + '"';
+ }
+
+ // function
+ else if (typeof data == "function") {
+ reply = "function";
+ }
+
+ // Array
+ else if (dwr.util._isArray(data)) {
+ if (showLevels == 0) { // Short format (don't show items)
+ if (data.length > 0)
+ reply = "[...]";
+ else
+ reply = "[]";
+ }
+ else { // Long format (show items)
+ var strarr = [];
+ strarr.push("[");
+ var count = 0;
+ for (var i = 0; i < data.length; i++) {
+ if (! (i in data)) continue;
+ var itemvalue = data[i];
+ if (count > 0) strarr.push(", ");
+ if (showLevels == 1) { // One-line format
+ if (count == options.oneLineMaxItems) {
+ strarr.push("...");
+ break;
+ }
+ }
+ else { // Multi-line format
+ strarr.push(options.lineTerminator + indent(indentDepth+1, options));
+ }
+ if (i != count) {
+ strarr.push(i);
+ strarr.push(":");
+ }
+ strarr.push(recursive(itemvalue, showLevels-1, indentDepth+1, options));
+ count++;
+ }
+ if (showLevels > 1) strarr.push(options.lineTerminator + indent(indentDepth, options));
+ strarr.push("]");
+ reply = strarr.join("");
+ }
+ }
+
+ // Objects except Date
+ else if (dwr.util._isObject(data) && !dwr.util._isDate(data)) {
+ if (showLevels == 0) { // Short format (don't show properties)
+ reply = dwr.util._detailedTypeOf(data);
+ }
+ else { // Long format (show properties)
+ var strarr = [];
+ if (dwr.util._detailedTypeOf(data) != "Object") {
+ strarr.push(dwr.util._detailedTypeOf(data));
+ if (typeof data.valueOf() != "object") {
+ strarr.push(":");
+ strarr.push(recursive(data.valueOf(), 1, indentDepth, options));
+ }
+ strarr.push(" ");
+ }
+ strarr.push("{");
+ var isDomObject = dwr.util._isHTMLElement(data);
+ var count = 0;
+ for (var prop in data) {
+ var propvalue = data[prop];
+ if (isDomObject) {
+ if (!propvalue) continue;
+ if (typeof propvalue == "function") continue;
+ if (skipDomProperties[prop]) continue;
+ if (prop.toUpperCase() == prop) continue;
+ }
+ if (count > 0) strarr.push(", ");
+ if (showLevels == 1) { // One-line format
+ if (count == options.oneLineMaxItems) {
+ strarr.push("...");
+ break;
+ }
+ }
+ else { // Multi-line format
+ strarr.push(options.lineTerminator + indent(indentDepth+1, options));
+ }
+ strarr.push(prop.length > options.propertyNameMaxLength ? prop.substring(0, options.propertyNameMaxLength-3) + "..." : prop);
+ strarr.push(":");
+ strarr.push(recursive(propvalue, showLevels-1, indentDepth+1, options));
+ count++;
+ }
+ if (showLevels > 1 && count > 0) strarr.push(options.lineTerminator + indent(indentDepth, options));
+ strarr.push("}");
+ reply = strarr.join("");
+ }
+ }
+
+ // undefined, null, number, boolean, Date
+ else {
+ reply = "" + data;
+ }
+
+ return reply;
+ }
+ catch(err) {
+ return (err.message ? err.message : ""+err);
+ }
+ }
+
+ function indent(count, options) {
+ var strarr = [];
+ strarr.push(options.baseIndent);
+ for (var i=0; i= 1) ele = nodes.item(0);
+ }
+
+ if (ele == null) {
+ dwr.util._debug("setValue() can't find an element with id/name: " + orig + ".");
+ return;
+ }
+
+ // All paths now lead to some update so we highlight a change
+ dwr.util.highlight(ele, options);
+
+ if (dwr.util._isHTMLElement(ele, "select")) {
+ if (ele.type == "select-multiple" && dwr.util._isArray(val)) dwr.util._selectListItems(ele, val);
+ else dwr.util._selectListItem(ele, val);
+ return;
+ }
+
+ if (dwr.util._isHTMLElement(ele, "input")) {
+ if (ele.type == "radio" || ele.type == "checkbox") {
+ if (nodes && nodes.length >= 1) {
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes.item(i);
+ if (node.type != ele.type) continue;
+ if (dwr.util._isArray(val)) {
+ node.checked = false;
+ for (var j = 0; j < val.length; j++)
+ if (val[j] == node.value) node.checked = true;
+ }
+ else {
+ node.checked = (node.value == val);
+ }
+ }
+ }
+ else {
+ ele.checked = (val == true);
+ }
+ }
+ else ele.value = val;
+
+ return;
+ }
+
+ if (dwr.util._isHTMLElement(ele, "textarea")) {
+ ele.value = val;
+ return;
+ }
+
+ // If the value to be set is a DOM object then we try importing the node
+ // rather than serializing it out
+ if (val.nodeType) {
+ if (val.nodeType == 9 /*Node.DOCUMENT_NODE*/) val = val.documentElement;
+ val = dwr.util._importNode(ele.ownerDocument, val, true);
+ ele.appendChild(val);
+ return;
+ }
+
+ // Fall back to innerHTML and friends
+ if (dwr.util._shouldEscapeHtml(options) && typeof(val) == "string") {
+ if (ele.textContent) ele.textContent = val;
+ else if (ele.innerText) ele.innerText = val;
+ else ele.innerHTML = dwr.util.escapeHtml(val);
+ }
+ else {
+ ele.innerHTML = val;
+ }
+};
+
+/**
+ * @private Find multiple items in a select list and select them. Used by setValue()
+ * @param ele The select list item
+ * @param val The array of values to select
+ */
+dwr.util._selectListItems = function(ele, val) {
+ // We deal with select list elements by selecting the matching option
+ // Begin by searching through the values
+ var found = false;
+ var i;
+ var j;
+ for (i = 0; i < ele.options.length; i++) {
+ ele.options[i].selected = false;
+ for (j = 0; j < val.length; j++) {
+ if (ele.options[i].value == val[j]) {
+ ele.options[i].selected = true;
+ }
+ }
+ }
+ // If that fails then try searching through the visible text
+ if (found) return;
+
+ for (i = 0; i < ele.options.length; i++) {
+ for (j = 0; j < val.length; j++) {
+ if (ele.options[i].text == val[j]) {
+ ele.options[i].selected = true;
+ }
+ }
+ }
+};
+
+/**
+ * @private Find an item in a select list and select it. Used by setValue()
+ * @param ele The select list item
+ * @param val The value to select
+ */
+dwr.util._selectListItem = function(ele, val) {
+ // We deal with select list elements by selecting the matching option
+ // Begin by searching through the values
+ var found = false;
+ var i;
+ for (i = 0; i < ele.options.length; i++) {
+ if (ele.options[i].value == val) {
+ ele.options[i].selected = true;
+ found = true;
+ }
+ else {
+ ele.options[i].selected = false;
+ }
+ }
+
+ // If that fails then try searching through the visible text
+ if (found) return;
+
+ for (i = 0; i < ele.options.length; i++) {
+ ele.options[i].selected = (ele.options[i].text == val);
+ }
+};
+
+/**
+ * Read the current value for a given HTML element.
+ * @see http://getahead.org/dwr/browser/util/getvalue
+ */
+dwr.util.getValue = function(ele, options) {
+ if (options == null) options = {};
+ var orig = ele;
+ if (typeof ele == "string") {
+ ele = dwr.util.byId(ele);
+ // We can work with names and need to sometimes for radio buttons, and IE has
+ // an annoying bug where getElementById() returns an element based on name if
+ // it doesn't find it by id. Here we don't want to do that, so:
+ if (ele && ele.id != orig) ele = null;
+ }
+ var nodes = null;
+ if (ele == null) {
+ // Now it is time to look by name
+ nodes = document.getElementsByName(orig);
+ if (nodes.length >= 1) ele = nodes.item(0);
+ }
+ if (ele == null) {
+ dwr.util._debug("getValue() can't find an element with id/name: " + orig + ".");
+ return "";
+ }
+
+ if (dwr.util._isHTMLElement(ele, "select")) {
+ // Using "type" property instead of "multiple" as "type" is an official
+ // client-side property since JS 1.1
+ if (ele.type == "select-multiple") {
+ var reply = new Array();
+ for (var i = 0; i < ele.options.length; i++) {
+ var item = ele.options[i];
+ if (item.selected) {
+ var valueAttr = item.getAttributeNode("value");
+ if (valueAttr && valueAttr.specified) {
+ reply.push(item.value);
+ }
+ else {
+ reply.push(item.text);
+ }
+ }
+ }
+ return reply;
+ }
+ else {
+ var sel = ele.selectedIndex;
+ if (sel != -1) {
+ var item = ele.options[sel];
+ var valueAttr = item.getAttributeNode("value");
+ if (valueAttr && valueAttr.specified) {
+ return item.value;
+ }
+ return item.text;
+ }
+ else {
+ return "";
+ }
+ }
+ }
+
+ if (dwr.util._isHTMLElement(ele, "input")) {
+ if (ele.type == "radio") {
+ if (nodes && nodes.length >= 1) {
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes.item(i);
+ if (node.type == ele.type) {
+ if (node.checked) return node.value;
+ }
+ }
+ }
+ return ele.checked;
+ }
+ if (ele.type == "checkbox") {
+ if (nodes && nodes.length >= 1) {
+ var reply = [];
+ for (var i = 0; i < nodes.length; i++) {
+ var node = nodes.item(i);
+ if (node.type == ele.type) {
+ if (node.checked) reply.push(node.value);
+ }
+ }
+ return reply;
+ }
+ return ele.checked;
+ }
+ return ele.value;
+ }
+
+ if (dwr.util._isHTMLElement(ele, "textarea")) {
+ return ele.value;
+ }
+
+ if (dwr.util._shouldEscapeHtml(options)) {
+ if (ele.textContent) return ele.textContent;
+ else if (ele.innerText) return ele.innerText;
+ }
+ return ele.innerHTML;
+};
+
+/**
+ * getText() is like getValue() except that it reads the text (and not the value) from select elements
+ * @see http://getahead.org/dwr/browser/util/gettext
+ */
+dwr.util.getText = function(ele) {
+ ele = dwr.util._getElementById(ele, "getText()");
+ if (ele == null) return null;
+ if (!dwr.util._isHTMLElement(ele, "select")) {
+ dwr.util._debug("getText() can only be used with select elements. Attempt to use: " + dwr.util._detailedTypeOf(ele) + " from id: " + orig + ".");
+ return "";
+ }
+
+ // This is a bit of a scam because it assumes single select
+ // but I'm not sure how we should treat multi-select.
+ var sel = ele.selectedIndex;
+ if (sel != -1) {
+ return ele.options[sel].text;
+ }
+ else {
+ return "";
+ }
+};
+
+/**
+ * Given a map, or a recursive structure consisting of arrays and maps, call
+ * setValue() for all leaf entries and use intermediate levels to form nested
+ * element ids.
+ * @see http://getahead.org/dwr/browser/util/setvalues
+ */
+dwr.util.setValues = function(data, options) {
+ var prefix = "";
+ if (options && options.prefix) prefix = options.prefix;
+ if (options && options.idPrefix) prefix = options.idPrefix;
+ dwr.util._setValuesRecursive(data, prefix);
+};
+
+/**
+ * @private Recursive helper for setValues()
+ */
+dwr.util._setValuesRecursive = function(data, idpath) {
+ // Array containing objects -> add "[n]" to prefix and make recursive call
+ // for each item object
+ if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) {
+ for (var i = 0; i < data.length; i++) {
+ dwr.util._setValuesRecursive(data[i], idpath+"["+i+"]");
+ }
+ }
+ // Object (not array) -> handle nested object properties
+ else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
+ for (var prop in data) {
+ var subidpath = idpath ? idpath+"."+prop : prop;
+ // Object (not array), or array containing objects -> call ourselves recursively
+ if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop])
+ || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) {
+ dwr.util._setValuesRecursive(data[prop], subidpath);
+ }
+ // Functions -> skip
+ else if (typeof data[prop] == "function") {
+ // NOP
+ }
+ // Only simple values left (or array of simple values, or empty array)
+ // -> call setValue()
+ else {
+ // Are there any elements with that id or name
+ if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) {
+ dwr.util.setValue(subidpath, data[prop]);
+ }
+ }
+ }
+ }
+};
+
+/**
+ * Given a map, or a recursive structure consisting of arrays and maps, call
+ * getValue() for all leaf entries and use intermediate levels to form nested
+ * element ids.
+ * Given a string or element that refers to a form, create an object from the
+ * elements of the form.
+ * @see http://getahead.org/dwr/browser/util/getvalues
+ */
+dwr.util.getValues = function(data, options) {
+ if (typeof data == "string" || dwr.util._isHTMLElement(data)) {
+ return dwr.util.getFormValues(data);
+ }
+ else {
+ var prefix = "";
+ if (options != null && options.prefix) prefix = options.prefix;
+ if (options != null && options.idPrefix) prefix = options.idPrefix;
+ dwr.util._getValuesRecursive(data, prefix);
+ return data;
+ }
+};
+
+/**
+ * Given a string or element that refers to a form, create an object from the
+ * elements of the form.
+ * @see http://getahead.org/dwr/browser/util/getvalues
+ */
+dwr.util.getFormValues = function(eleOrNameOrId) {
+ var ele = null;
+ if (typeof eleOrNameOrId == "string") {
+ ele = document.forms[eleOrNameOrId];
+ if (ele == null) ele = dwr.util.byId(eleOrNameOrId);
+ }
+ else if (dwr.util._isHTMLElement(eleOrNameOrId)) {
+ ele = eleOrNameOrId;
+ }
+ if (ele != null) {
+ if (ele.elements == null) {
+ alert("getFormValues() requires an object or reference to a form element.");
+ return null;
+ }
+ var reply = {};
+ var name;
+ var value;
+ for (var i = 0; i < ele.elements.length; i++) {
+ if (ele[i].type in {button:0,submit:0,reset:0,image:0,file:0}) continue;
+ if (ele[i].name) {
+ name = ele[i].name;
+ value = dwr.util.getValue(name);
+ }
+ else {
+ if (ele[i].id) name = ele[i].id;
+ else name = "element" + i;
+ value = dwr.util.getValue(ele[i]);
+ }
+ reply[name] = value;
+ }
+ return reply;
+ }
+};
+
+/**
+ * @private Recursive helper for getValues().
+ */
+dwr.util._getValuesRecursive = function(data, idpath) {
+ // Array containing objects -> add "[n]" to idpath and make recursive call
+ // for each item object
+ if (dwr.util._isArray(data) && data.length > 0 && dwr.util._isObject(data[0])) {
+ for (var i = 0; i < data.length; i++) {
+ dwr.util._getValuesRecursive(data[i], idpath+"["+i+"]");
+ }
+ }
+ // Object (not array) -> handle nested object properties
+ else if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
+ for (var prop in data) {
+ var subidpath = idpath ? idpath+"."+prop : prop;
+ // Object, or array containing objects -> call ourselves recursively
+ if (dwr.util._isObject(data[prop]) && !dwr.util._isArray(data[prop])
+ || dwr.util._isArray(data[prop]) && data[prop].length > 0 && dwr.util._isObject(data[prop][0])) {
+ dwr.util._getValuesRecursive(data[prop], subidpath);
+ }
+ // Functions -> skip
+ else if (typeof data[prop] == "function") {
+ // NOP
+ }
+ // Only simple values left (or array of simple values, or empty array)
+ // -> call getValue()
+ else {
+ // Are there any elements with that id or name
+ if (dwr.util.byId(subidpath) != null || document.getElementsByName(subidpath).length >= 1) {
+ data[prop] = dwr.util.getValue(subidpath);
+ }
+ }
+ }
+ }
+};
+
+/**
+ * Add options to a list from an array or map.
+ * @see http://getahead.org/dwr/browser/lists
+ */
+dwr.util.addOptions = function(ele, data/*, options*/) {
+ ele = dwr.util._getElementById(ele, "addOptions()");
+ if (ele == null) return;
+ var useOptions = dwr.util._isHTMLElement(ele, "select");
+ var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]);
+ if (!useOptions && !useLi) {
+ dwr.util._debug("addOptions() can only be used with select/ul/ol elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
+ return;
+ }
+ if (data == null) return;
+
+ var argcount = arguments.length;
+ var options = {};
+ var lastarg = arguments[argcount - 1];
+ if (argcount > 2 && dwr.util._isObject(lastarg)) {
+ options = lastarg;
+ argcount--;
+ }
+ var arg3 = null; if (argcount >= 3) arg3 = arguments[2];
+ var arg4 = null; if (argcount >= 4) arg4 = arguments[3];
+ if (!options.optionCreator && useOptions) options.optionCreator = dwr.util._defaultOptionCreator;
+ if (!options.optionCreator && useLi) options.optionCreator = dwr.util._defaultListItemCreator;
+
+ var text, value, li;
+ if (dwr.util._isArray(data)) {
+ // Loop through the data that we do have
+ for (var i = 0; i < data.length; i++) {
+ options.data = data[i];
+ options.text = null;
+ options.value = null;
+ if (useOptions) {
+ if (arg3 != null) {
+ if (arg4 != null) {
+ options.text = dwr.util._getValueFrom(data[i], arg4);
+ options.value = dwr.util._getValueFrom(data[i], arg3);
+ }
+ else options.text = options.value = dwr.util._getValueFrom(data[i], arg3);
+ }
+ else options.text = options.value = dwr.util._getValueFrom(data[i]);
+
+ if (options.text != null || options.value) {
+ var opt = options.optionCreator(options);
+ opt.text = options.text;
+ opt.value = options.value;
+ ele.options[ele.options.length] = opt;
+ }
+ }
+ else {
+ options.value = dwr.util._getValueFrom(data[i], arg3);
+ if (options.value != null) {
+ li = options.optionCreator(options);
+ if (dwr.util._shouldEscapeHtml(options)) {
+ options.value = dwr.util.escapeHtml(options.value);
+ }
+ li.innerHTML = options.value;
+ ele.appendChild(li);
+ }
+ }
+ }
+ }
+ else if (arg4 != null) {
+ if (!useOptions) {
+ alert("dwr.util.addOptions can only create select lists from objects.");
+ return;
+ }
+ for (var prop in data) {
+ options.data = data[prop];
+ options.value = dwr.util._getValueFrom(data[prop], arg3);
+ options.text = dwr.util._getValueFrom(data[prop], arg4);
+
+ if (options.text != null || options.value) {
+ var opt = options.optionCreator(options);
+ opt.text = options.text;
+ opt.value = options.value;
+ ele.options[ele.options.length] = opt;
+ }
+ }
+ }
+ else {
+ if (!useOptions) {
+ dwr.util._debug("dwr.util.addOptions can only create select lists from objects.");
+ return;
+ }
+ for (var prop in data) {
+ if (typeof data[prop] == "function") continue;
+ options.data = data[prop];
+ if (!arg3) {
+ options.value = prop;
+ options.text = data[prop];
+ }
+ else {
+ options.value = data[prop];
+ options.text = prop;
+ }
+ if (options.text != null || options.value) {
+ var opt = options.optionCreator(options);
+ opt.text = options.text;
+ opt.value = options.value;
+ ele.options[ele.options.length] = opt;
+ }
+ }
+ }
+
+ // All error routes through this function result in a return, so highlight now
+ dwr.util.highlight(ele, options);
+};
+
+/**
+ * @private Get the data from an array function for dwr.util.addOptions
+ */
+dwr.util._getValueFrom = function(data, method) {
+ if (method == null) return data;
+ else if (typeof method == 'function') return method(data);
+ else return data[method];
+};
+
+/**
+ * @private Default option creation function
+ */
+dwr.util._defaultOptionCreator = function(options) {
+ return new Option();
+};
+
+/**
+ * @private Default list item creation function
+ */
+dwr.util._defaultListItemCreator = function(options) {
+ return document.createElement("li");
+};
+
+/**
+ * Remove all the options from a select list (specified by id)
+ * @see http://getahead.org/dwr/browser/lists
+ */
+dwr.util.removeAllOptions = function(ele) {
+ ele = dwr.util._getElementById(ele, "removeAllOptions()");
+ if (ele == null) return;
+ var useOptions = dwr.util._isHTMLElement(ele, "select");
+ var useLi = dwr.util._isHTMLElement(ele, ["ul", "ol"]);
+ if (!useOptions && !useLi) {
+ dwr.util._debug("removeAllOptions() can only be used with select, ol and ul elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
+ return;
+ }
+ if (useOptions) {
+ ele.options.length = 0;
+ }
+ else {
+ while (ele.childNodes.length > 0) {
+ ele.removeChild(ele.firstChild);
+ }
+ }
+};
+
+/**
+ * Create rows inside a the table, tbody, thead or tfoot element (given by id).
+ * @see http://getahead.org/dwr/browser/tables
+ */
+dwr.util.addRows = function(ele, data, cellFuncs, options) {
+ ele = dwr.util._getElementById(ele, "addRows()");
+ if (ele == null) return;
+ if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
+ dwr.util._debug("addRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
+ return;
+ }
+ if (!options) options = {};
+ if (!options.rowCreator) options.rowCreator = dwr.util._defaultRowCreator;
+ if (!options.cellCreator) options.cellCreator = dwr.util._defaultCellCreator;
+ var tr, rowNum;
+ if (dwr.util._isArray(data)) {
+ for (rowNum = 0; rowNum < data.length; rowNum++) {
+ options.rowData = data[rowNum];
+ options.rowIndex = rowNum;
+ options.rowNum = rowNum;
+ options.data = null;
+ options.cellNum = -1;
+ tr = dwr.util._addRowInner(cellFuncs, options);
+ if (tr != null) ele.appendChild(tr);
+ }
+ }
+ else if (typeof data == "object") {
+ rowNum = 0;
+ for (var rowIndex in data) {
+ options.rowData = data[rowIndex];
+ options.rowIndex = rowIndex;
+ options.rowNum = rowNum;
+ options.data = null;
+ options.cellNum = -1;
+ tr = dwr.util._addRowInner(cellFuncs, options);
+ if (tr != null) ele.appendChild(tr);
+ rowNum++;
+ }
+ }
+
+ dwr.util.highlight(ele, options);
+};
+
+/**
+ * @private Internal function to draw a single row of a table.
+ */
+dwr.util._addRowInner = function(cellFuncs, options) {
+ var tr = options.rowCreator(options);
+ if (tr == null) return null;
+ for (var cellNum = 0; cellNum < cellFuncs.length; cellNum++) {
+ var func = cellFuncs[cellNum];
+ if (typeof func == 'function') options.data = func(options.rowData, options);
+ else options.data = func || "";
+ options.cellNum = cellNum;
+ var td = options.cellCreator(options);
+ if (td != null) {
+ if (options.data != null) {
+ if (dwr.util._isHTMLElement(options.data)) td.appendChild(options.data);
+ else {
+ if (dwr.util._shouldEscapeHtml(options) && typeof(options.data) == "string") {
+ td.innerHTML = dwr.util.escapeHtml(options.data);
+ }
+ else {
+ td.innerHTML = options.data;
+ }
+ }
+ }
+ tr.appendChild(td);
+ }
+ }
+ return tr;
+};
+
+/**
+ * @private Default row creation function
+ */
+dwr.util._defaultRowCreator = function(options) {
+ return document.createElement("tr");
+};
+
+/**
+ * @private Default cell creation function
+ */
+dwr.util._defaultCellCreator = function(options) {
+ return document.createElement("td");
+};
+
+/**
+ * Remove all the children of a given node.
+ * @see http://getahead.org/dwr/browser/tables
+ */
+dwr.util.removeAllRows = function(ele, options) {
+ ele = dwr.util._getElementById(ele, "removeAllRows()");
+ if (ele == null) return;
+ if (!options) options = {};
+ if (!options.filter) options.filter = function() { return true; };
+ if (!dwr.util._isHTMLElement(ele, ["table", "tbody", "thead", "tfoot"])) {
+ dwr.util._debug("removeAllRows() can only be used with table, tbody, thead and tfoot elements. Attempt to use: " + dwr.util._detailedTypeOf(ele));
+ return;
+ }
+ var child = ele.firstChild;
+ var next;
+ while (child != null) {
+ next = child.nextSibling;
+ if (options.filter(child)) {
+ ele.removeChild(child);
+ }
+ child = next;
+ }
+};
+
+/**
+ * dwr.util.byId(ele).className = "X", that we can call from Java easily.
+ */
+dwr.util.setClassName = function(ele, className) {
+ ele = dwr.util._getElementById(ele, "setClassName()");
+ if (ele == null) return;
+ ele.className = className;
+};
+
+/**
+ * dwr.util.byId(ele).className += "X", that we can call from Java easily.
+ */
+dwr.util.addClassName = function(ele, className) {
+ ele = dwr.util._getElementById(ele, "addClassName()");
+ if (ele == null) return;
+ ele.className += " " + className;
+};
+
+/**
+ * dwr.util.byId(ele).className -= "X", that we can call from Java easily
+ * From code originally by Gavin Kistner
+ */
+dwr.util.removeClassName = function(ele, className) {
+ ele = dwr.util._getElementById(ele, "removeClassName()");
+ if (ele == null) return;
+ var regex = new RegExp("(^|\\s)" + className + "(\\s|$)", 'g');
+ ele.className = ele.className.replace(regex, '');
+};
+
+/**
+ * dwr.util.byId(ele).className |= "X", that we can call from Java easily.
+ */
+dwr.util.toggleClassName = function(ele, className) {
+ ele = dwr.util._getElementById(ele, "toggleClassName()");
+ if (ele == null) return;
+ var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
+ if (regex.test(ele.className)) {
+ ele.className = ele.className.replace(regex, '');
+ }
+ else {
+ ele.className += " " + className;
+ }
+};
+
+/**
+ * Clone a node and insert it into the document just above the 'template' node
+ * @see http://getahead.org/dwr/???
+ */
+dwr.util.cloneNode = function(ele, options) {
+ ele = dwr.util._getElementById(ele, "cloneNode()");
+ if (ele == null) return null;
+ if (options == null) options = {};
+ var clone = ele.cloneNode(true);
+ if (options.idPrefix || options.idSuffix) {
+ dwr.util._updateIds(clone, options);
+ }
+ else {
+ dwr.util._removeIds(clone);
+ }
+ ele.parentNode.insertBefore(clone, ele);
+ return clone;
+};
+
+/**
+ * @private Update all of the ids in an element tree
+ */
+dwr.util._updateIds = function(ele, options) {
+ if (options == null) options = {};
+ if (ele.id) {
+ ele.setAttribute("id", (options.idPrefix || "") + ele.id + (options.idSuffix || ""));
+ }
+ var children = ele.childNodes;
+ for (var i = 0; i < children.length; i++) {
+ var child = children.item(i);
+ if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
+ dwr.util._updateIds(child, options);
+ }
+ }
+};
+
+/**
+ * @private Remove all the Ids from an element
+ */
+dwr.util._removeIds = function(ele) {
+ if (ele.id) ele.removeAttribute("id");
+ var children = ele.childNodes;
+ for (var i = 0; i < children.length; i++) {
+ var child = children.item(i);
+ if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
+ dwr.util._removeIds(child);
+ }
+ }
+};
+
+/**
+ * Clone a template node and its embedded template child nodes according to
+ * cardinalities (of arrays) in supplied data.
+ */
+dwr.util.cloneNodeForValues = function(templateEle, data, options) {
+ templateEle = dwr.util._getElementById(templateEle, "cloneNodeForValues()");
+ if (templateEle == null) return null;
+ if (options == null) options = {};
+ var idpath;
+ if (options.idPrefix != null)
+ idpath = options.idPrefix;
+ else
+ idpath = templateEle.id || "";
+ return dwr.util._cloneNodeForValuesRecursive(templateEle, data, idpath, options);
+};
+
+/**
+ * @private Recursive helper for cloneNodeForValues().
+ */
+dwr.util._cloneNodeForValuesRecursive = function(templateEle, data, idpath, options) {
+ // Incoming array -> make an id for each item and call clone of the template
+ // for each of them
+ if (dwr.util._isArray(data)) {
+ var clones = [];
+ for (var i = 0; i < data.length; i++) {
+ var item = data[i];
+ var clone = dwr.util._cloneNodeForValuesRecursive(templateEle, item, idpath + "[" + i + "]", options);
+ clones.push(clone);
+ }
+ return clones;
+ }
+ else
+ // Incoming object (not array) -> clone the template, add id prefixes, add
+ // clone to DOM, and then recurse into any array properties if they contain
+ // objects and there is a suitable template
+ if (dwr.util._isObject(data) && !dwr.util._isArray(data)) {
+ var clone = templateEle.cloneNode(true);
+ if (options.updateCloneStyle && clone.style) {
+ for (var propname in options.updateCloneStyle) {
+ clone.style[propname] = options.updateCloneStyle[propname];
+ }
+ }
+ dwr.util._replaceIds(clone, templateEle.id, idpath);
+ templateEle.parentNode.insertBefore(clone, templateEle);
+ dwr.util._cloneSubArrays(data, idpath, options);
+ return clone;
+ }
+
+ // It is an error to end up here so we return nothing
+ return null;
+};
+
+/**
+ * @private Substitute a leading idpath fragment with another idpath for all
+ * element ids tree, and remove ids that don't match the idpath.
+ */
+dwr.util._replaceIds = function(ele, oldidpath, newidpath) {
+ if (ele.id) {
+ var newId = null;
+ if (ele.id == oldidpath) {
+ newId = newidpath;
+ }
+ else if (ele.id.length > oldidpath.length) {
+ if (ele.id.substr(0, oldidpath.length) == oldidpath) {
+ var trailingChar = ele.id.charAt(oldidpath.length);
+ if (trailingChar == "." || trailingChar == "[") {
+ newId = newidpath + ele.id.substr(oldidpath.length);
+ }
+ }
+ }
+ if (newId) {
+ ele.setAttribute("id", newId);
+ }
+ else {
+ ele.removeAttribute("id");
+ }
+ }
+ var children = ele.childNodes;
+ for (var i = 0; i < children.length; i++) {
+ var child = children.item(i);
+ if (child.nodeType == 1 /*Node.ELEMENT_NODE*/) {
+ dwr.util._replaceIds(child, oldidpath, newidpath);
+ }
+ }
+};
+
+/**
+ * @private Finds arrays in supplied data and uses any corresponding template
+ * node to make a clone for each item in the array.
+ */
+dwr.util._cloneSubArrays = function(data, idpath, options) {
+ for (prop in data) {
+ var value = data[prop];
+ // Look for potential recursive cloning in all array properties
+ if (dwr.util._isArray(value)) {
+ // Only arrays with objects are interesting for cloning
+ if (value.length > 0 && dwr.util._isObject(value[0])) {
+ var subTemplateId = idpath + "." + prop;
+ var subTemplateEle = dwr.util.byId(subTemplateId);
+ if (subTemplateEle != null) {
+ dwr.util._cloneNodeForValuesRecursive(subTemplateEle, value, subTemplateId, options);
+ }
+ }
+ }
+ // Continue looking for arrays in object properties
+ else if (dwr.util._isObject(value)) {
+ dwr.util._cloneSubArrays(value, idpath + "." + prop, options);
+ }
+ }
+};
+
+/**
+ * @private Helper to turn a string into an element with an error message
+ */
+dwr.util._getElementById = function(ele, source) {
+ var orig = ele;
+ ele = dwr.util.byId(ele);
+ if (ele == null) {
+ dwr.util._debug(source + " can't find an element with id: " + orig + ".");
+ }
+ return ele;
+};
+
+/**
+ * @private Is the given node an HTML element (optionally of a given type)?
+ * @param ele The element to test
+ * @param nodeName eg "input", "textarea" - check for node name (optional)
+ * if nodeName is an array then check all for a match.
+ */
+dwr.util._isHTMLElement = function(ele, nodeName) {
+ if (ele == null || typeof ele != "object" || ele.nodeName == null) {
+ return false;
+ }
+ if (nodeName != null) {
+ var test = ele.nodeName.toLowerCase();
+ if (typeof nodeName == "string") {
+ return test == nodeName.toLowerCase();
+ }
+ if (dwr.util._isArray(nodeName)) {
+ var match = false;
+ for (var i = 0; i < nodeName.length && !match; i++) {
+ if (test == nodeName[i].toLowerCase()) {
+ match = true;
+ }
+ }
+ return match;
+ }
+ dwr.util._debug("dwr.util._isHTMLElement was passed test node name that is neither a string or array of strings");
+ return false;
+ }
+ return true;
+};
+
+/**
+ * @private Like typeOf except that more information for an object is returned other than "object"
+ */
+dwr.util._detailedTypeOf = function(x) {
+ var reply = typeof x;
+ if (reply == "object") {
+ reply = Object.prototype.toString.apply(x); // Returns "[object class]"
+ reply = reply.substring(8, reply.length-1); // Just get the class bit
+ }
+ return reply;
+};
+
+/**
+ * @private Object detector. Excluding null from objects.
+ */
+dwr.util._isObject = function(data) {
+ return (data && typeof data == "object");
+};
+
+/**
+ * @private Array detector. Note: instanceof doesn't work with multiple frames.
+ */
+dwr.util._isArray = function(data) {
+ return (data && data.join);
+};
+
+/**
+ * @private Date detector. Note: instanceof doesn't work with multiple frames.
+ */
+dwr.util._isDate = function(data) {
+ return (data && data.toUTCString) ? true : false;
+};
+
+/**
+ * @private Used by setValue. Gets around the missing functionallity in IE.
+ */
+dwr.util._importNode = function(doc, importedNode, deep) {
+ var newNode;
+
+ if (importedNode.nodeType == 1 /*Node.ELEMENT_NODE*/) {
+ newNode = doc.createElement(importedNode.nodeName);
+
+ for (var i = 0; i < importedNode.attributes.length; i++) {
+ var attr = importedNode.attributes[i];
+ if (attr.nodeValue != null && attr.nodeValue != '') {
+ newNode.setAttribute(attr.name, attr.nodeValue);
+ }
+ }
+
+ if (typeof importedNode.style != "undefined") {
+ newNode.style.cssText = importedNode.style.cssText;
+ }
+ }
+ else if (importedNode.nodeType == 3 /*Node.TEXT_NODE*/) {
+ newNode = doc.createTextNode(importedNode.nodeValue);
+ }
+
+ if (deep && importedNode.hasChildNodes()) {
+ for (i = 0; i < importedNode.childNodes.length; i++) {
+ newNode.appendChild(dwr.util._importNode(doc, importedNode.childNodes[i], true));
+ }
+ }
+
+ return newNode;
+};
+
+/** @private Used internally when some message needs to get to the programmer */
+dwr.util._debug = function(message, stacktrace) {
+ var written = false;
+ try {
+ if (window.console) {
+ if (stacktrace && window.console.trace) window.console.trace();
+ window.console.log(message);
+ written = true;
+ }
+ else if (window.opera && window.opera.postError) {
+ window.opera.postError(message);
+ written = true;
+ }
+ }
+ catch (ex) { /* ignore */ }
+
+ if (!written) {
+ var debug = document.getElementById("dwr-debug");
+ if (debug) {
+ var contents = message + "
" + debug.innerHTML;
+ if (contents.length > 2048) contents = contents.substring(0, 2048);
+ debug.innerHTML = contents;
+ }
+ }
+};