[Laszlo-checkins] r10847 - openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml
bargull@openlaszlo.org
bargull at openlaszlo.org
Tue Sep 2 11:16:37 PDT 2008
Author: bargull
Date: 2008-09-02 11:16:09 -0700 (Tue, 02 Sep 2008)
New Revision: 10847
Modified:
openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzHTTPLoader.js
openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLParser.js
openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLTranslator.js
Log:
Change 20080901-bargull-M9C by bargull at dell--p4--2-53 on 2008-09-01 22:32:11
in /home/Admin/src/svn/openlaszlo/trunk
for http://svn.openlaszlo.org/openlaszlo/trunk
Summary: dhtml http-loader
New Features:
Bugs Fixed: LPP-6912
Technical Reviewer: hminsky
QA Reviewer: (pending)
Doc Reviewer: (pending)
Documentation:
Release Notes:
Details:
LzXMLParser:
- changed to a less verbose form
LzXMLTranslator:
- changed to a less verbose form
- removed slashPat, it wasn't referenced anywhere
- use now "localName" (resp. "baseName") instead of manually splitting the nsprefix
- removed debug-statements
LzHTTPLoader:
- moved all "static" properties to the beginning
- added local variable in translateXML (LPP-6912)
- fixed/added implementation of getResponseStatus(), getResponseHeaders(), getResponseHeader(), getElapsedTime()
- clear response-variables in "open" before doing a new request
- and some other trivial changes (e.g. renamed variables and moved functions for consistency)
Tests:
all-data passes
weather (uses nsprefix)
Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzHTTPLoader.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzHTTPLoader.js 2008-09-02 17:02:17 UTC (rev 10846)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzHTTPLoader.js 2008-09-02 18:16:09 UTC (rev 10847)
@@ -18,23 +18,33 @@
this.__loaderid = LzHTTPLoader.loaderIDCounter++;
}
+LzHTTPLoader.GET_METHOD = "GET";
+LzHTTPLoader.POST_METHOD = "POST";
+LzHTTPLoader.PUT_METHOD = "PUT";
+LzHTTPLoader.DELETE_METHOD = "DELETE";
+
+// holds list of outstanding data requests, to handle timeouts
+LzHTTPLoader.activeRequests = {};
+LzHTTPLoader.loaderIDCounter = 0;
+
// Default callback handlers
+LzHTTPLoader.prototype.loadSuccess = function (loader, data) {}
+LzHTTPLoader.prototype.loadError = function (loader, data) {}
+LzHTTPLoader.prototype.loadTimeout = function (loader, data) {}
+
LzHTTPLoader.prototype.loadContent = function (self, content) {
if (this.options['parsexml']) {
- this.translateXML(content);
+ this.translateXML();
} else {
this.loadSuccess(this, content);
}
}
-LzHTTPLoader.prototype.loadSuccess = function (loader, data) {}
-LzHTTPLoader.prototype.loadError = function (loader, data) {}
-LzHTTPLoader.prototype.loadTimeout = function (loader, data) {}
-
/* Parse response into XML data. */
-LzHTTPLoader.prototype.translateXML = function (content) {
+LzHTTPLoader.prototype.translateXML = function () {
var lzxdata = null;
if (this.responseXML != null) {
+ var elt;
var nodes = this.responseXML.childNodes;
// find first content (type == 1) child node
for (var i = 0; i < nodes.length; i++) {
@@ -52,7 +62,6 @@
this.loadSuccess(this, lzxdata);
}
-
/* Returns the response as a string */
LzHTTPLoader.prototype.getResponse = function () {
return this.responseText;
@@ -60,20 +69,19 @@
/* Returns numeric status code (200, 404, 500, etc...) */
LzHTTPLoader.prototype.getResponseStatus = function () {
- // nyi
+ return this.responseStatus;
}
-// TODO [hqm 2007-02] this is not very useful now because we are
-// immediately null'ing out the req field as soon as the request
-// returns, in order to assist IE in garbage collecting.
-
-/* Returns an array of response headers */
+/* Returns an object of response headers */
LzHTTPLoader.prototype.getResponseHeaders = function () {
- // [todo hqm 2006-07] this returns a string at the moment, needs to be parsed into
- // a hash table
- return this.req.getAllResponseHeaders();
+ //return this.req.getAllResponseHeaders();
+ return this.responseHeaders;
}
+LzHTTPLoader.prototype.getResponseHeader = function (key) {
+ //return this.req.getResponseHeader(key);
+ return this.responseHeaders[key];
+}
/* @param Object obj: A hash table of headers for the HTTP request
@access public
@@ -86,20 +94,10 @@
@param String val: header value
@access public
*/
-
LzHTTPLoader.prototype.setRequestHeader = function (key, val) {
this.requestheaders[key] = val;
}
-LzHTTPLoader.prototype.abort = function () {
- if (this.req) {
- this.__abort = true;
- this.req.abort();
- this.req = null;
- this.removeTimeout(this);
- }
-}
-
/* @public */
LzHTTPLoader.prototype.setOption = function (key, val) {
this.options[key] = val;
@@ -110,20 +108,17 @@
return this.options[key];
}
-
/* @public */
LzHTTPLoader.prototype.setProxied = function (proxied) {
this.setOption('proxied', proxied);
}
-/* @public
- */
+/* @public */
LzHTTPLoader.prototype.setQueryParams = function (qparams) {
this.queryparams = qparams;
}
-/* @public
- */
+/* @public */
LzHTTPLoader.prototype.setQueryString = function (qstring) {
this.querystring = qstring;
}
@@ -137,34 +132,45 @@
// [todo hqm 2006-07] NYI
}
-// TODO [hqm 2007-02] this is not useful right now because we are
-// null'ing out the req field as soon as the request returns, in order
-// to assist IE in garbage collecting.
-LzHTTPLoader.prototype.getResponseHeader = function (key) {
- return this.req.getResponseHeader(key);
+LzHTTPLoader.prototype.abort = function () {
+ if (this.req) {
+ this.__abort = true;
+ this.req.abort();
+ this.req = null;
+ this.removeTimeout(this);
+ }
}
-LzHTTPLoader.GET_METHOD = "GET";
-LzHTTPLoader.POST_METHOD = "POST";
-LzHTTPLoader.PUT_METHOD = "PUT";
-LzHTTPLoader.DELETE_METHOD = "DELETE";
-
-// headers can be a hashtable or null
-
LzHTTPLoader.prototype.open = function (method, url, username, password) {
- if (this.req) {
- Debug.warn("pending request for id=%s", this.__loaderid);
+ if ($debug) {
+ if (this.req) {
+ // TODO: what is the expected behaviour?
+ // ignore the new request or cancel the previous one?
+ Debug.warn("pending request for id=%s", this.__loaderid);
+ }
}
{
#pragma "passThrough=true"
- this.req = window.XMLHttpRequest? new XMLHttpRequest(): new ActiveXObject("Microsoft.XMLHTTP");
+ this.req = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP");
}
+ this.responseStatus = 0;
+ this.responseHeaders = null;
+ this.responseText = null;
+ this.responseXML = null;
+
this.__abort = false;
this.__timeout = false;
this.requesturl = url;
this.requestmethod = method;
+}
+LzHTTPLoader.prototype.send = function (content) {
+ this.loadXMLDoc(/* method */ this.requestmethod,
+ /* url */ this.requesturl,
+ /* headers */ this.requestheaders,
+ /* postbody */ content,
+ /* ignorewhite */ true);
}
// @access public
@@ -191,66 +197,44 @@
return lz.Browser.makeProxiedURL(params);
}
-LzHTTPLoader.prototype.send = function (content) {
- this.loadXMLDoc(/* method */ this.requestmethod,
- /* url */ this.requesturl,
- /* headers */ this.requestheaders,
- /* postbody */ content,
- /* ignorewhite */ true);
-}
-
-// holds list of outstanding data requests, to handle timeouts
-//LzHTTPLoader.activeRequests = [];
-LzHTTPLoader.activeRequests = {};
-LzHTTPLoader.loaderIDCounter = 0;
-
// Default infinite timeout
LzHTTPLoader.prototype.timeout = Infinity;
LzHTTPLoader.prototype.setTimeout = function (timeout) {
this.timeout = timeout;
- // [todo hqm 2006-07] Should we have an API method for setting LzLoader timeout?
+ // [todo hqm 2006-07] Should we have an API method for setting LzLoader timeout?
}
// Set up a pending timeout for a loader.
-/*
-LzHTTPLoader.prototype.setupTimeout = function (obj, duration) {
+LzHTTPLoader.prototype.setupTimeout = function (loader, duration) {
var endtime = (new Date()).getTime() + duration;
- LzHTTPLoader.activeRequests.push(obj, endtime);
- setTimeout("LzHTTPLoader.__LZcheckXMLHTTPTimeouts()", duration);
-}
-*/
-LzHTTPLoader.prototype.setupTimeout = function (obj, duration) {
- var endtime = (new Date()).getTime() + duration;
- //obj.__loaderid = LzHTTPLoader.loaderIDCounter++;//uncomment to give LzHTTPLoader-instance a new loader-id
- var lid = obj.__loaderid;
+ var lid = loader.__loaderid;
- LzHTTPLoader.activeRequests[lid] = [obj, endtime];
+ LzHTTPLoader.activeRequests[lid] = [loader, endtime];
var timeoutid = setTimeout("LzHTTPLoader.__LZcheckXMLHTTPTimeouts(" + lid + ")", duration);
LzHTTPLoader.activeRequests[lid][2] = timeoutid;
}
-
+
// Remove a loader from the timeouts list.
-LzHTTPLoader.prototype.removeTimeout = function (target) {
- var lid = target.__loaderid;
+LzHTTPLoader.prototype.removeTimeout = function (loader) {
+ var lid = loader.__loaderid;
//Debug.write("remove timeout for id=%s", lid);
if (lid != null) {
var reqarr = LzHTTPLoader.activeRequests[lid];
- if (reqarr && reqarr[0] === target) {
+ if (reqarr && reqarr[0] === loader) {
clearTimeout(reqarr[2]);
delete LzHTTPLoader.activeRequests[lid];
}
}
}
-
-
+
// Check if any outstanding requests have timed out.
LzHTTPLoader.__LZcheckXMLHTTPTimeouts = function (lid) {
- var req = LzHTTPLoader.activeRequests[lid];
- if (req) {
+ var reqarr = LzHTTPLoader.activeRequests[lid];
+ if (reqarr) {
var now = (new Date()).getTime();
- var loader = req[0];
- var dstimeout = req[1];
+ var loader = reqarr[0];
+ var dstimeout = reqarr[1];
//Debug.write("diff %d", now - dstimeout);
if (now >= dstimeout) {
//Debug.write("timeout for %s", lid);
@@ -265,16 +249,16 @@
// if it hasn't timed out, add it back to the list for the future
//Debug.write("recheck timeout");
var timeoutid = setTimeout("LzHTTPLoader.__LZcheckXMLHTTPTimeouts(" + lid + ")", now - dstimeout);
- req[2] = timeoutid;
+ reqarr[2] = timeoutid;
}
}
}
LzHTTPLoader.prototype.getElapsedTime = function () {
- return ((new Date()).getTime() - this.gstart);
+ return ((new Date()).getTime() - this.gstart);
}
-
+// headers can be a hashtable or null
LzHTTPLoader.prototype.__setRequestHeaders = function (xhr, headers) {
if (headers != null) {
for (var key in headers) {
@@ -285,58 +269,68 @@
}
}
+LzHTTPLoader.prototype.__getAllResponseHeaders = function (xhr) {
+ var re = new RegExp("^([-\\w]+):\\s*(\\S(?:.*\\S)?)\\s*$", "mg");
+ var respheader = xhr.getAllResponseHeaders();
+
+ var allheaders = {};
+ var header;
+ while ((header = re.exec(respheader)) != null) {
+ allheaders[header[1]] = header[2];
+ }
+
+ return allheaders;
+}
+
// public
// parsexml flag : if true, translate native XML tree into LzDataNode tree,
// if false, don't attempt to translate the XML (if it exists)
-
LzHTTPLoader.prototype.loadXMLDoc = function (method, url, headers, postbody, ignorewhite) {
- if(this.req) {
+ if (this.req) {
// we can't close over "this", so use another variable name.
var self = this;
this.req.onreadystatechange = function () {
- if (self.req == null) { return; }
- //Debug.write("readyState=%d", self.req.readyState);
- if (self.req.readyState == 4) {
+ var xhr = self.req;
+ if (xhr == null) { return; }
+ //Debug.write("readyState=%d", xhr.readyState);
+ if (xhr.readyState == 4) {
if (self.__timeout) {
- //Debug.write("timeout for id=%s, xhr=%w", self.__loaderid, self.req);
+ // request has timed out, ignore ready-state
} else if (self.__abort) {
- //Debug.write("abort for id=%s, xhr=%w", self.__loaderid, self.req);
+ // request was cancelled, ignore ready-state
} else {
+ self.removeTimeout(self);
+ self.req = null;
+
var status = -1;
try {
- status = self.req.status;
+ status = xhr.status;
} catch (e) {
//if you abort a request, readyState will be set to 4,
//but reading status will result in an exception (at least in Firefox).
- //Debug.write("catched error: %s", e);
}
// only if "OK"
- //Debug.write("status=%d", status);
+ self.responseStatus = status;
if (status == 200 || status == 304) {
- var elt = null;
- var xml = self.req.responseXML;
- self.responseXML = xml;
- self.responseText = self.req.responseText;
- self.removeTimeout(self);
-
- /**** DEBUGGING
- var xmlSerializer = new XMLSerializer();
- var markup = xmlSerializer.serializeToString(elt);
- Debug.write("loadXMLDoc", elt, markup, d.serialize());
- *** /DEBUGGING
- */
- self.req = null;
+ self.responseXML = xhr.responseXML;
+ self.responseText = xhr.responseText;
+ self.responseHeaders = self.__getAllResponseHeaders(xhr);
+
+ //DEBUGGING:
+ //var xmlSerializer = new XMLSerializer();
+ //var markup = xmlSerializer.serializeToString(self.responseXML);
+ //Debug.write("loadXMLDoc", markup);
+
// Callback with raw text string
self.loadContent(self, self.responseText);
} else {
- self.removeTimeout(self);
- self.req = null;
self.loadError(self, null);
}
}
}
};
+
this.req.open(method, url, true);
// If no content-type for POST was explicitly specified,
// use "application/x-www-form-urlencoded"
@@ -344,11 +338,12 @@
headers['content-type'] = 'application/x-www-form-urlencoded';
}
this.__setRequestHeaders(this.req, headers);
+ this.gstart = (new Date()).getTime();
this.req.send(postbody);
+
+ // Set up the timeout
+ if (isFinite(this.timeout)) {
+ this.setupTimeout(this, this.timeout);
+ }
}
- // Set up the timeout
- if (isFinite(this.timeout)) {
- this.setupTimeout(this, this.timeout);
- }
}
-
Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLParser.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLParser.js 2008-09-02 17:02:17 UTC (rev 10846)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLParser.js 2008-09-02 18:16:09 UTC (rev 10847)
@@ -1,7 +1,7 @@
/**
* LzXMLParser.js
*
- * @copyright Copyright 2006 Laszlo Systems, Inc. All Rights Reserved.
+ * @copyright Copyright 2006, 2008 Laszlo Systems, Inc. All Rights Reserved.
* Use is subject to license terms.
*
* @topic Kernel
@@ -12,9 +12,8 @@
* @shortdesc Utility for parsing text into native XML DOM object
*/
-var LzXMLParser = new Object;
-
-LzXMLParser.parseXML = function( str, trimwhitespace, nsprefix ){
+var LzXMLParser = {
+parseXML: function (str, trimwhitespace, nsprefix) {
#pragma "passThrough=true"
// TODO [hqm 05-2006] need to add third arg, NSPREFIX, to
// this method, and to the node copy routine , see the SWF
@@ -22,9 +21,9 @@
// to both swf and DHTML, with a conditionalized version for IE probably.
var parser = new DOMParser();
var doc = parser.parseFromString(str, "text/xml");
- //Debug.write("LzXMLParser.parseXML", doc.childNodes[0], str);
return doc.childNodes[0];
}
+} // end of LzXMLParser
// DOMparser for IE and safari
// http://erik.eae.net/archives/2005/07/03/20.19.18/
Modified: openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLTranslator.js
===================================================================
--- openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLTranslator.js 2008-09-02 17:02:17 UTC (rev 10846)
+++ openlaszlo/trunk/WEB-INF/lps/lfc/kernel/dhtml/LzXMLTranslator.js 2008-09-02 18:16:09 UTC (rev 10847)
@@ -1,7 +1,7 @@
/**
* LzXMLTranslator.js
*
- * @copyright Copyright 2006-2007 Laszlo Systems, Inc. All Rights Reserved.
+ * @copyright Copyright 2006-2008 Laszlo Systems, Inc. All Rights Reserved.
* Use is subject to license terms.
*
* @topic Kernel
@@ -12,95 +12,69 @@
* @shortdesc Utility for converting native XML DOM object into LzDataNode tree
*/
-var LzXMLTranslator = new Object;
+var LzXMLTranslator = {
-LzXMLTranslator.copyXML = function (xmldoc, trimwhitespace, nsprefix) {
- var lfcnode = LzXMLTranslator.copyBrowserXML(xmldoc, true, trimwhitespace, nsprefix);
- return lfcnode;
-}
+whitespacePat: new RegExp("^\\s*$"),
+stringTrimPat: new RegExp("^\\s+|\\s+$", "g"),
+copyXML: function (xmldoc, trimwhitespace, nsprefix) {
+ return this.copyBrowserXML(xmldoc, true, trimwhitespace, nsprefix);
+},
-LzXMLTranslator.whitespacePat = new RegExp("^[\t\n\r ]*$");
-LzXMLTranslator.stringTrimPat = new RegExp("(^[\t\n\r ]*|[\t\n\r ]*$)", "g");
-LzXMLTranslator.slashPat = new RegExp("/", "g");
-
-LzXMLTranslator.copyBrowserXML = function (node, ignorewhite, trimwhite, nsprefix) {
- if (! node) return node;
- var nv = node.nodeValue;
- var lfcnode = null;
- // text node?
- if (node.nodeType == 3 || node.nodeType == 4) {
- // text node
-
+copyBrowserXML: function (node, ignorewhite, trimwhite, nsprefix) {
+ if (! node) {
+ return node;
+ } else if (node.nodeType == 3 || node.nodeType == 4) {
+ // text node (3: TEXT_NODE, 4: CDATA_SECTION_NODE)
+ var nv = node.nodeValue;
+
// If ignorewhite is true, discard a text node which is all whitespace
- if (ignorewhite && LzXMLTranslator.whitespacePat.test(nv)) {
- //Debug.debug('found text whitespace', nv);
+ if (ignorewhite && this.whitespacePat.test(nv)) {
return null;
}
if (trimwhite) {
- var nvo = nv;
- nv = nv.replace(LzXMLTranslator.stringTrimPat, "");
+ nv = nv.replace(this.stringTrimPat, "");
}
- lfcnode = new LzDataText(nv);
- //Debug.debug('found text node', nv, 'lfcnode=', lfcnode);
- return lfcnode;
+
+ return new LzDataText(nv);
} else if (node.nodeType == 1 || node.nodeType == 9) {
- // element or document node
-
- // slow but sure way to copy attributes
+ // element or document node (1: ELEMENT_NODE, 9: DOCUMENT_NODE)
- var nattrs = node.attributes;
var cattrs = {};
-
+ var nattrs = node.attributes;
if (nattrs) {
+ // slow but sure way to copy attributes
for (var k = 0; k < nattrs.length; k++) {
var attrnode = nattrs.item(k);
if (attrnode) {
- var attrname = attrnode.name;
- var attrval = attrnode.value;
- var nattrname = attrname;
-
- if (!nsprefix) {
- // strip namespace prefixes
- var colpos = attrname.indexOf(':');
- if (colpos >= 0) {
- nattrname = attrname.substring(colpos+1);
- }
- }
-
- cattrs[nattrname] = attrval;
+ //older IE's use "baseName" instead of DOM Level2 property "localName"
+ var attrname = (!nsprefix && (attrnode.localName || attrnode.baseName)) || attrnode.name;
+ cattrs[attrname] = attrnode.value;
}
}
}
- var nname = node.nodeName;
- if (nname && !nsprefix) {
- // strip namespace prefix
- var npos = nname.indexOf(':');
- if (npos >= 0) {
- nname = nname.substring(npos+1);
+ //older IE's use "baseName" instead of DOM Level2 property "localName"
+ var nname = (!nsprefix && (node.localName || node.baseName)) || node.nodeName;
+ var lfcnode = new LzDataElement(nname, cattrs);
+
+ if (node.hasChildNodes()) {
+ var newchildren = [];
+ var children = node.childNodes;
+ for (var i = 0; i < children.length; i++) {
+ var lfcchild = this.copyBrowserXML(children[i], ignorewhite, trimwhite, nsprefix);
+ if (lfcchild != null) {
+ newchildren.push(lfcchild);
+ }
}
+
+ lfcnode.setChildNodes(newchildren);
}
-
-
- lfcnode = new LzDataElement(nname, cattrs);
- var children = node.childNodes;
- var newchildren = [];
- for (var i = 0; i < children.length; i++ ) {
- var child = children[i];
- var lfcchild = LzXMLTranslator.copyBrowserXML(child, ignorewhite, trimwhite, nsprefix);
- //Debug.debug('lfcchild = ', lfcchild);
- if (lfcchild != null) {
- newchildren.push(lfcchild);
- }
- }
-
- lfcnode.setChildNodes(newchildren);
return lfcnode;
} else {
// ignore all other node types
return null;
}
}
-
+} // end of LzXMLTranslator
More information about the Laszlo-checkins
mailing list