[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