[kupu-checkins] r33999 - in kupu/trunk/kupu: common tests

duncan at codespeak.net duncan at codespeak.net
Wed Nov 1 11:51:55 CET 2006


Author: duncan
Date: Wed Nov  1 11:51:49 2006
New Revision: 33999

Modified:
   kupu/trunk/kupu/common/kupueditor.js
   kupu/trunk/kupu/common/sarissa.js
   kupu/trunk/kupu/common/sarissa_ieemu_xpath.js
   kupu/trunk/kupu/tests/run_tests.html
   kupu/trunk/kupu/tests/test_kupubasetools.js
   kupu/trunk/kupu/tests/test_kupueditor.js
   kupu/trunk/kupu/tests/test_kupuhelpers.js
   kupu/trunk/kupu/tests/test_xhtml.js
Log:
Update to latest sarissa.js/sarissa_ieemu_xpath.js: 0.9.7.4+fixes (will switch to 0.9.7.5 when it becomes available).
kupueditor.js no longer uses Sarissa.serialize (since that has vapourised).
Tests no long use Sarissa.serialize.
Tests reference Node.TEXT_NODE and Node.ELEMENT_NODE since Opera couldn't handle node.TEXT_NODE &c.
Tests are now more forgiving when comparing output since Opera does weird things like adding attributes to <html> tag and closing <img/> in innerHTML.
Fixed a real bug in the tests: calling createRange on wrong document.
Opera still failing 15 unit tests and messing up the style pulldown.

Modified: kupu/trunk/kupu/common/kupueditor.js
==============================================================================
--- kupu/trunk/kupu/common/kupueditor.js	(original)
+++ kupu/trunk/kupu/common/kupueditor.js	Wed Nov  1 11:51:49 2006
@@ -92,6 +92,7 @@
     this.log = logger; // simple logger object
     this.tools = {}; // mapping id->tool
     this.filters = new Array(); // contentfilters
+    this.serializer = new XMLSerializer();
     
     this._designModeSetAttempts = 0;
     this._initialized = false;
@@ -624,7 +625,7 @@
         var bodies = transform.getElementsByTagName('body');
         var data = '';
         for (var i = 0; i < bodies.length; i++) {
-            data += Sarissa.serialize(bodies[i]);
+            data += this.serializer.serializeToString(bodies[i]);
         }
         return this.escapeEntities(data);
     };
@@ -746,13 +747,13 @@
             var contents =  '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" ' + 
                             '"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n' + 
                             '<html xmlns="http://www.w3.org/1999/xhtml">' +
-                            Sarissa.serialize(transform.getElementsByTagName("head")[0]) +
-                            Sarissa.serialize(transform.getElementsByTagName("body")[0]) +
+                            this.serializer.serializeToString(transform.getElementsByTagName("head")[0]) +
+                            this.serializer.serializeToString(transform.getElementsByTagName("body")[0]) +
                             '</html>';
         } else {
             var contents = '<html>' + 
-                            Sarissa.serialize(transform.getElementsByTagName("head")[0]) +
-                            Sarissa.serialize(transform.getElementsByTagName("body")[0]) +
+                            this.serializer.serializeToString(transform.getElementsByTagName("head")[0]) +
+                            this.serializer.serializeToString(transform.getElementsByTagName("body")[0]) +
                             '</html>';
         };
 

Modified: kupu/trunk/kupu/common/sarissa.js
==============================================================================
--- kupu/trunk/kupu/common/sarissa.js	(original)
+++ kupu/trunk/kupu/common/sarissa.js	Wed Nov  1 11:51:49 2006
@@ -1,66 +1,54 @@
-/*****************************************************************************
- *
- * Sarissa XML library version 0.9.6
- * Copyright (c) 2003 Manos Batsis, 
- * mailto: mbatsis at users full stop sourceforge full stop net
- * This software is distributed under the Kupu License. See
- * LICENSE.txt for license text. See the Sarissa homepage at
- * http://sarissa.sourceforge.net for more information.
- *
- *****************************************************************************
-
+/**
  * ====================================================================
  * About
  * ====================================================================
- * Sarissa cross browser XML library 
- * @version 0.9.6
- * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
- *
  * Sarissa is an ECMAScript library acting as a cross-browser wrapper for native XML APIs.
  * The library supports Gecko based browsers like Mozilla and Firefox,
- * Internet Explorer (5.5+ with MSXML3.0+) and, last but not least, KHTML based browsers like
- * Konqueror and Safari.
- *
+ * Internet Explorer (5.5+ with MSXML3.0+), Konqueror, Safari and a little of Opera
+ * @version @sarissa.version@
+ * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
+ * ====================================================================
+ * Licence
+ * ====================================================================
+ * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher, 
+ * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher 
+ * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If 
+ * you make modifications under the ASL, i would appreciate it if you submitted those.
+ * In case your copy of Sarissa does not include the license texts, you may find
+ * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
+ * <a href="http://www.apache.org">http://www.apache.org</a>.
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
+ * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 /**
- * <p>Sarissa is a utility class. Provides static methods for DOMDocument and 
- * XMLHTTP objects, DOM Node serializatrion to XML strings and other goodies.</p>
+ * <p>Sarissa is a utility class. Provides "static" methods for DOMDocument, 
+ * DOM Node serialization to XML strings and other utility goodies.</p>
  * @constructor
  */
 function Sarissa(){};
-/** @private */
 Sarissa.PARSED_OK = "Document contains no parsing errors";
-/**
- * Tells you whether transformNode and transformNodeToObject are available. This functionality
- * is contained in sarissa_ieemu_xslt.js and is deprecated. If you want to control XSLT transformations
- * use the XSLTProcessor
- * @deprecated
- * @type boolean
- */
-Sarissa.IS_ENABLED_TRANSFORM_NODE = false;
-/**
- * tells you whether XMLHttpRequest (or equivalent) is available
- * @type boolean
- */
-Sarissa.IS_ENABLED_XMLHTTP = false;
-/**
- * tells you whether selectNodes/selectSingleNode is available
- * @type boolean
- */
-Sarissa.IS_ENABLED_SELECT_NODES = false;
+Sarissa.PARSED_EMPTY = "Document is empty";
+Sarissa.PARSED_UNKNOWN_ERROR = "Not well-formed or other error";
 var _sarissa_iNsCounter = 0;
 var _SARISSA_IEPREFIX4XSLPARAM = "";
 var _SARISSA_HAS_DOM_IMPLEMENTATION = document.implementation && true;
 var _SARISSA_HAS_DOM_CREATE_DOCUMENT = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.createDocument;
 var _SARISSA_HAS_DOM_FEATURE = _SARISSA_HAS_DOM_IMPLEMENTATION && document.implementation.hasFeature;
 var _SARISSA_IS_MOZ = _SARISSA_HAS_DOM_CREATE_DOCUMENT && _SARISSA_HAS_DOM_FEATURE;
-var _SARISSA_IS_SAFARI = navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1;
+var _SARISSA_IS_SAFARI = (navigator.userAgent && navigator.vendor && (navigator.userAgent.toLowerCase().indexOf("applewebkit") != -1 || navigator.vendor.indexOf("Apple") != -1));
 var _SARISSA_IS_IE = document.all && window.ActiveXObject && navigator.userAgent.toLowerCase().indexOf("msie") > -1  && navigator.userAgent.toLowerCase().indexOf("opera") == -1;
-
-if(!window.Node || !window.Node.ELEMENT_NODE){
-    var Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5,  ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12};
+if(!window.Node || !Node.ELEMENT_NODE){
+    Node = {ELEMENT_NODE: 1, ATTRIBUTE_NODE: 2, TEXT_NODE: 3, CDATA_SECTION_NODE: 4, ENTITY_REFERENCE_NODE: 5,  ENTITY_NODE: 6, PROCESSING_INSTRUCTION_NODE: 7, COMMENT_NODE: 8, DOCUMENT_NODE: 9, DOCUMENT_TYPE_NODE: 10, DOCUMENT_FRAGMENT_NODE: 11, NOTATION_NODE: 12};
 };
 
+if( typeof XMLDocument == "undefined" && typeof Document != "undefined"){ XMLDocument = Document; }
+
 // IE initialization
 if(_SARISSA_IS_IE){
     // for XSLT parameter names, prefix needed by IE
@@ -68,13 +56,15 @@
     // used to store the most recent ProgID available out of the above
     var _SARISSA_DOM_PROGID = "";
     var _SARISSA_XMLHTTP_PROGID = "";
+    var _SARISSA_DOM_XMLWRITER = "";
     /**
      * Called when the Sarissa_xx.js file is parsed, to pick most recent
      * ProgIDs for IE, then gets destroyed.
+     * @private
      * @param idList an array of MSXML PROGIDs from which the most recent will be picked for a given object
      * @param enabledList an array of arrays where each array has two items; the index of the PROGID for which a certain feature is enabled
      */
-    pickRecentProgID = function (idList, enabledList){
+    Sarissa.pickRecentProgID = function (idList){
         // found progID flag
         var bFound = false;
         for(var i=0; i < idList.length && !bFound; i++){
@@ -82,50 +72,69 @@
                 var oDoc = new ActiveXObject(idList[i]);
                 o2Store = idList[i];
                 bFound = true;
-                for(var j=0;j<enabledList.length;j++)
-                    if(i <= enabledList[j][1])
-                        Sarissa["IS_ENABLED_"+enabledList[j][0]] = true;
             }catch (objException){
                 // trap; try next progID
             };
         };
-        if (!bFound)
+        if (!bFound) {
             throw "Could not retreive a valid progID of Class: " + idList[idList.length-1]+". (original exception: "+e+")";
+        };
         idList = null;
         return o2Store;
     };
     // pick best available MSXML progIDs
-    _SARISSA_DOM_PROGID = pickRecentProgID(["Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"], [["SELECT_NODES", 2],["TRANSFORM_NODE", 2]]);
-    _SARISSA_XMLHTTP_PROGID = pickRecentProgID(["Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"], [["XMLHTTP", 4]]);
-    _SARISSA_THREADEDDOM_PROGID = pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
-    _SARISSA_XSLTEMPLATE_PROGID = pickRecentProgID(["Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"], [["XSLTPROC", 2]]);
+    _SARISSA_DOM_PROGID = null;
+    _SARISSA_THREADEDDOM_PROGID = null;
+    _SARISSA_XSLTEMPLATE_PROGID = null;
+    _SARISSA_XMLHTTP_PROGID = null;
+    if(!window.XMLHttpRequest){
+        /**
+         * Emulate XMLHttpRequest
+         * @constructor
+         */
+        XMLHttpRequest = function() {
+            if(!_SARISSA_XMLHTTP_PROGID){
+                _SARISSA_XMLHTTP_PROGID = Sarissa.pickRecentProgID(["Msxml2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP"]);
+            };
+            return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);
+        };
+    };
     // we dont need this anymore
-    pickRecentProgID = null;
     //============================================
     // Factory methods (IE)
     //============================================
     // see non-IE version
     Sarissa.getDomDocument = function(sUri, sName){
+        if(!_SARISSA_DOM_PROGID){
+            _SARISSA_DOM_PROGID = Sarissa.pickRecentProgID(["Msxml2.DOMDocument.4.0", "Msxml2.DOMDocument.3.0", "MSXML2.DOMDocument", "MSXML.DOMDocument", "Microsoft.XMLDOM"]);
+        };
         var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
-        // if a root tag name was provided, we need to load it in the DOM
-        // object
+        // if a root tag name was provided, we need to load it in the DOM object
         if (sName){
-            // if needed, create an artifical namespace prefix the way Moz
-            // does
-            if (sUri){
-                oDoc.loadXML("<a" + _sarissa_iNsCounter + ":" + sName + " xmlns:a" + _sarissa_iNsCounter + "=\"" + sUri + "\" />");
-                // don't use the same prefix again
-                ++_sarissa_iNsCounter;
-            }
-            else
-                oDoc.loadXML("<" + sName + "/>");
+            // create an artifical namespace prefix 
+            // or reuse existing prefix if applicable
+            var prefix = "";
+            if(sUri){
+                if(sName.indexOf(":") > 1){
+                    prefix = sName.substring(0, sName.indexOf(":"));
+                    sName = sName.substring(sName.indexOf(":")+1); 
+                }else{
+                    prefix = "a" + (_sarissa_iNsCounter++);
+                };
+            };
+            // use namespaces if a namespace URI exists
+            if(sUri){
+                oDoc.loadXML('<' + prefix+':'+sName + " xmlns:" + prefix + "=\"" + sUri + "\"" + " />");
+            } else {
+                oDoc.loadXML('<' + sName + " />");
+            };
         };
         return oDoc;
     };
     // see non-IE version   
     Sarissa.getParseErrorText = function (oDoc) {
         var parseErrorText = Sarissa.PARSED_OK;
-        if(oDoc.parseError != 0){
+        if(oDoc.parseError.errorCode != 0){
             parseErrorText = "XML Parsing Error: " + oDoc.parseError.reason + 
                 "\nLocation: " + oDoc.parseError.url + 
                 "\nLine Number " + oDoc.parseError.line + ", Column " + 
@@ -136,6 +145,9 @@
                 parseErrorText += "-";
             };
             parseErrorText +=  "^\n";
+        }
+        else if(oDoc.documentElement == null){
+            parseErrorText = Sarissa.PARSED_EMPTY;
         };
         return parseErrorText;
     };
@@ -150,43 +162,113 @@
      * @constructor
      */
     XSLTProcessor = function(){
+        if(!_SARISSA_XSLTEMPLATE_PROGID){
+            _SARISSA_XSLTEMPLATE_PROGID = Sarissa.pickRecentProgID(["Msxml2.XSLTemplate.4.0", "MSXML2.XSLTemplate.3.0"]);
+        };
         this.template = new ActiveXObject(_SARISSA_XSLTEMPLATE_PROGID);
         this.processor = null;
     };
     /**
-     * Impoprts the given XSLT DOM and compiles it to a reusable transform
+     * Imports the given XSLT DOM and compiles it to a reusable transform
+     * <b>Note:</b> If the stylesheet was loaded from a URL and contains xsl:import or xsl:include elements,it will be reloaded to resolve those
      * @argument xslDoc The XSLT DOMDocument to import
      */
     XSLTProcessor.prototype.importStylesheet = function(xslDoc){
+        if(!_SARISSA_THREADEDDOM_PROGID){
+            _SARISSA_THREADEDDOM_PROGID = Sarissa.pickRecentProgID(["MSXML2.FreeThreadedDOMDocument.4.0", "MSXML2.FreeThreadedDOMDocument.3.0"]);
+            _SARISSA_DOM_XMLWRITER = Sarissa.pickRecentProgID(["Msxml2.MXXMLWriter.4.0", "Msxml2.MXXMLWriter.3.0", "MSXML2.MXXMLWriter", "MSXML.MXXMLWriter", "Microsoft.XMLDOM"]);
+        };
+        xslDoc.setProperty("SelectionLanguage", "XPath");
+        xslDoc.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
         // convert stylesheet to free threaded
-        var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID); 
-        converted.loadXML(xslDoc.xml);
+        var converted = new ActiveXObject(_SARISSA_THREADEDDOM_PROGID);
+        // make included/imported stylesheets work if exist and xsl was originally loaded from url
+        if(xslDoc.url && xslDoc.selectSingleNode("//xsl:*[local-name() = 'import' or local-name() = 'include']") != null){
+            converted.async = false;
+            converted.load(xslDoc.url);
+        } else {
+            converted.loadXML(xslDoc.xml);
+        };
+        converted.setProperty("SelectionNamespaces", "xmlns:xsl='http://www.w3.org/1999/XSL/Transform'");
+        var output = converted.selectSingleNode("//xsl:output");
+        this.outputMethod = output ? output.getAttribute("method") : "html";
         this.template.stylesheet = converted;
         this.processor = this.template.createProcessor();
         // (re)set default param values
         this.paramsSet = new Array();
     };
+
     /**
-     * Transform the given XML DOM
+     * Transform the given XML DOM and return the transformation result as a new DOM document
      * @argument sourceDoc The XML DOMDocument to transform
      * @return The transformation result as a DOM Document
      */
     XSLTProcessor.prototype.transformToDocument = function(sourceDoc){
-        this.processor.input = sourceDoc;
-        var outDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
-        this.processor.output = outDoc; 
-        this.processor.transform();
-        return outDoc;
+        // fix for bug 1549749
+        if(_SARISSA_THREADEDDOM_PROGID == "MSXML2.FreeThreadedDOMDocument.3.0"){
+            this.processor.input=sourceDoc;
+
+            var outDoc=new ActiveXObject(_SARISSA_DOM_PROGID);
+
+            this.processor.output=outDoc;
+
+            this.processor.transform();
+
+            return outDoc;
+        }
+        else{
+            this.processor.input = sourceDoc;
+
+            var outDoc = new ActiveXObject(_SARISSA_DOM_XMLWRITER);
+
+            this.processor.output = outDoc; 
+
+            this.processor.transform();
+
+            var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
+
+            oDoc.loadXML(outDoc.output+"");
+
+            return oDoc;
+        };
     };
+    
     /**
-     * Not sure if this works in IE. Maybe this will allow non-well-formed
-     * transformation results (i.e. with no single root element)
+     * Transform the given XML DOM and return the transformation result as a new DOM fragment.
+     * <b>Note</b>: The xsl:output method must match the nature of the owner document (XML/HTML).
      * @argument sourceDoc The XML DOMDocument to transform
-     * @return The transformation result as a DOM Fragment
+     * @argument ownerDoc The owner of the result fragment
+     * @return The transformation result as a DOM Document
      */
-    XSLTProcessor.prototype.transformToFragment = function(sourceDoc, ownerDocument){
-        return this.transformToDocument(sourceDoc);
+    XSLTProcessor.prototype.transformToFragment = function (sourceDoc, ownerDoc) {
+        this.processor.input = sourceDoc;
+        this.processor.transform();
+        var s = this.processor.output;
+        var f = ownerDoc.createDocumentFragment();
+        if (this.outputMethod == 'text') {
+            f.appendChild(ownerDoc.createTextNode(s));
+        } else if (ownerDoc.body && ownerDoc.body.innerHTML) {
+            var container = ownerDoc.createElement('div');
+            container.innerHTML = s;
+            while (container.hasChildNodes()) {
+                f.appendChild(container.firstChild);
+            }
+        }
+        else {
+            var oDoc = new ActiveXObject(_SARISSA_DOM_PROGID);
+            if (s.substring(0, 5) == '<?xml') {
+                s = s.substring(s.indexOf('?>') + 2);
+            }
+            var xml = ''.concat('<my>', s, '</my>');
+            oDoc.loadXML(xml);
+            var container = oDoc.documentElement;
+            while (container.hasChildNodes()) {
+                f.appendChild(container.firstChild);
+            }
+        }
+        return f;
     };
+    
     /**
      * Set global XSLT parameter of the imported stylesheet
      * @argument nsURI The parameter namespace URI
@@ -214,102 +296,23 @@
      * @return The parameter value if reviously set by setParameter, null otherwise
      */
     XSLTProcessor.prototype.getParameter = function(nsURI, name){
-        if(this.paramsSet[""+nsURI] && this.paramsSet[""+nsURI][name])
-            return this.paramsSet[""+nsURI][name];
-        else
+        nsURI = nsURI || "";
+        if(this.paramsSet[nsURI] && this.paramsSet[nsURI][name]){
+            return this.paramsSet[nsURI][name];
+        }else{
             return null;
+        };
     };
-}
-else{ /* end IE initialization, try to deal with real browsers now ;-) */
-   if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){
-        if(window.XMLDocument){
-            /**
-            * <p>Emulate IE's onreadystatechange attribute</p>
-            */
-            XMLDocument.prototype.onreadystatechange = null;
-            /**
-            * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p>
-            * <ul><li>1 == LOADING,</li>
-            * <li>2 == LOADED,</li>
-            * <li>3 == INTERACTIVE,</li>
-            * <li>4 == COMPLETED</li></ul>
-            */
-            XMLDocument.prototype.readyState = 0;
-            /**
-            * <p>Emulate IE's parseError attribute</p>
-            */
-            XMLDocument.prototype.parseError = 0;
-
-            // NOTE: setting async to false will only work with documents
-            // called over HTTP (meaning a server), not the local file system,
-            // unless you are using Moz 1.4+.
-            // BTW the try>catch block is for 1.4; I haven't found a way to check if
-            // the property is implemented without
-            // causing an error and I dont want to use user agent stuff for that...
-            var _SARISSA_SYNC_NON_IMPLEMENTED = false;
-            try{
-                /**
-                * <p>Emulates IE's async property for Moz versions prior to 1.4.
-                * It controls whether loading of remote XML files works
-                * synchronously or asynchronously.</p>
-                */
-                XMLDocument.prototype.async = true;
-                _SARISSA_SYNC_NON_IMPLEMENTED = true;
-            }catch(e){/* trap */};
-            /**
-            * <p>Keeps a handle to the original load() method. Internal use and only
-            * if Mozilla version is lower than 1.4</p>
-            * @private
-            */
-            XMLDocument.prototype._sarissa_load = XMLDocument.prototype.load;
-
-            /**
-            * <p>Overrides the original load method to provide synchronous loading for
-            * Mozilla versions prior to 1.4, using an XMLHttpRequest object (if
-            * async is set to false)</p>
-            * @returns the DOM Object as it was before the load() call (may be  empty)
-            */
-            XMLDocument.prototype.load = function(sURI) {
-                var oDoc = document.implementation.createDocument("", "", null);
-                Sarissa.copyChildNodes(this, oDoc);
-                this.parseError = 0;
-                Sarissa.__setReadyState__(this, 1);
-                try {
-                    if(this.async == false && _SARISSA_SYNC_NON_IMPLEMENTED) {
-                        var tmp = new XMLHttpRequest();
-                        tmp.open("GET", sURI, false);
-                        tmp.send(null);
-                        Sarissa.__setReadyState__(this, 2);
-                        Sarissa.copyChildNodes(tmp.responseXML, this);
-                        Sarissa.__setReadyState__(this, 3);
-                    }
-                    else {
-                        this._sarissa_load(sURI);
-                    };
-                }
-                catch (objException) {
-                    this.parseError = -1;
-                }
-                finally {
-                    if(this.async == false){
-                        Sarissa.__handleLoad__(this);
-                    };
-                };
-                return oDoc;
-            };
-        };//if(window.XMLDocument)
-
+}else{ /* end IE initialization, try to deal with real browsers now ;-) */
+    if(_SARISSA_HAS_DOM_CREATE_DOCUMENT){
         /**
          * <p>Ensures the document was loaded correctly, otherwise sets the
          * parseError to -1 to indicate something went wrong. Internal use</p>
          * @private
          */
         Sarissa.__handleLoad__ = function(oDoc){
-            if (!oDoc.documentElement || oDoc.documentElement.tagName == "parsererror")
-                oDoc.parseError = -1;
             Sarissa.__setReadyState__(oDoc, 4);
         };
-        
         /**
         * <p>Attached by an event handler to the load event. Internal use.</p>
         * @private
@@ -317,7 +320,6 @@
         _sarissa_XMLDocument_onload = function(){
             Sarissa.__handleLoad__(this);
         };
-        
         /**
          * <p>Sets the readyState property of the given DOM Document object.
          * Internal use.</p>
@@ -328,80 +330,111 @@
          */
         Sarissa.__setReadyState__ = function(oDoc, iReadyState){
             oDoc.readyState = iReadyState;
+            oDoc.readystate = iReadyState;
             if (oDoc.onreadystatechange != null && typeof oDoc.onreadystatechange == "function")
                 oDoc.onreadystatechange();
         };
-        /**
-        * <p>Factory method to obtain a new DOM Document object</p>
-        * @argument sUri the namespace of the root node (if any)
-        * @argument sUri the local name of the root node (if any)
-        * @returns a new DOM Document
-        */
         Sarissa.getDomDocument = function(sUri, sName){
-            var oDoc = document.implementation.createDocument(sUri?sUri:"", sName?sName:"", null);
+            var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
+            if(!oDoc.onreadystatechange){
+            
+                /**
+                * <p>Emulate IE's onreadystatechange attribute</p>
+                */
+                oDoc.onreadystatechange = null;
+            };
+            if(!oDoc.readyState){
+                /**
+                * <p>Emulates IE's readyState property, which always gives an integer from 0 to 4:</p>
+                * <ul><li>1 == LOADING,</li>
+                * <li>2 == LOADED,</li>
+                * <li>3 == INTERACTIVE,</li>
+                * <li>4 == COMPLETED</li></ul>
+                */
+                oDoc.readyState = 0;
+            };
             oDoc.addEventListener("load", _sarissa_XMLDocument_onload, false);
             return oDoc;
-        };        
+        };
+        if(window.XMLDocument){
+        
+        //if(window.XMLDocument) , now mainly for opera  
+        }// TODO: check if the new document has content before trying to copynodes, check  for error handling in DOM 3 LS
+        else if(_SARISSA_HAS_DOM_FEATURE && !Document.prototype.load && document.implementation.hasFeature('LS', '3.0')){
+    		//Opera 9 may get the XPath branch which gives creates XMLDocument, therefore it doesn't reach here which is good
+            /**
+            * <p>Factory method to obtain a new DOM Document object</p>
+            * @argument sUri the namespace of the root node (if any)
+            * @argument sUri the local name of the root node (if any)
+            * @returns a new DOM Document
+            */
+            Sarissa.getDomDocument = function(sUri, sName){
+                var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
+                return oDoc;
+            };
+        }
+        else {
+            Sarissa.getDomDocument = function(sUri, sName){
+                var oDoc = document.implementation.createDocument(sUri?sUri:null, sName?sName:null, null);
+                // looks like safari does not create the root element for some unknown reason
+                if(oDoc && (sUri || sName) && !oDoc.documentElement){
+                    oDoc.appendChild(oDoc.createElementNS(sUri, sName));
+                };
+                return oDoc;
+            };
+        };
     };//if(_SARISSA_HAS_DOM_CREATE_DOCUMENT)
 };
 //==========================================
 // Common stuff
 //==========================================
 if(!window.DOMParser){
-    /** 
-    * DOMParser is a utility class, used to construct DOMDocuments from XML strings
-    * @constructor
-    */
-    DOMParser = function() {
-    };
-    /** 
-    * Construct a new DOM Document from the given XMLstring
-    * @param sXml the given XML string
-    * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). 
-    * @return a new DOM Document from the given XML string
-    */
-    DOMParser.prototype.parseFromString = function(sXml, contentType){
-        var doc = Sarissa.getDomDocument();
-        doc.loadXML(sXml);
-        return doc;
-    };
-    
-};
-
-if(window.XMLHttpRequest){
-    Sarissa.IS_ENABLED_XMLHTTP = true;
-}
-else if(_SARISSA_IS_IE){
-    /**
-     * Emulate XMLHttpRequest
-     * @constructor
-     */
-    XMLHttpRequest = function() {
-        return new ActiveXObject(_SARISSA_XMLHTTP_PROGID);
+    if(_SARISSA_IS_SAFARI){
+        /*
+         * DOMParser is a utility class, used to construct DOMDocuments from XML strings
+         * @constructor
+         */
+        DOMParser = function() { };
+        /** 
+        * Construct a new DOM Document from the given XMLstring
+        * @param sXml the given XML string
+        * @param contentType the content type of the document the given string represents (one of text/xml, application/xml, application/xhtml+xml). 
+        * @return a new DOM Document from the given XML string
+        */
+        DOMParser.prototype.parseFromString = function(sXml, contentType){
+            var xmlhttp = new XMLHttpRequest();
+            xmlhttp.open("GET", "data:text/xml;charset=utf-8," + encodeURIComponent(sXml), false);
+            xmlhttp.send(null);
+            return xmlhttp.responseXML;
+        };
+    }else if(Sarissa.getDomDocument && Sarissa.getDomDocument() && Sarissa.getDomDocument(null, "bar").xml){
+        DOMParser = function() { };
+        DOMParser.prototype.parseFromString = function(sXml, contentType){
+            var doc = Sarissa.getDomDocument();
+            doc.loadXML(sXml);
+            return doc;
+        };
     };
-    Sarissa.IS_ENABLED_XMLHTTP = true;
 };
 
-if(!window.document.importNode && _SARISSA_IS_IE){
+if(!document.importNode && _SARISSA_IS_IE){
     try{
         /**
-        * Implements importNode for the current window document in IE using innerHTML.
-        * Testing showed that DOM was multiple times slower than innerHTML for this,
-        * sorry folks. If you encounter trouble (who knows what IE does behind innerHTML)
-        * please gimme a call.
+        * Implementation of importNode for the context window document in IE
         * @param oNode the Node to import
         * @param bChildren whether to include the children of oNode
         * @returns the imported node for further use
         */
-        window.document.importNode = function(oNode, bChildren){
-            var importNode = document.createElement("div");
-            if(bChildren)
-                importNode.innerHTML = Sarissa.serialize(oNode);
-            else
-                importNode.innerHTML = Sarissa.serialize(oNode.cloneNode(false));
-            return importNode.firstChild;
+        document.importNode = function(oNode, bChildren){
+            var tmp = document.createElement("div");
+            if(bChildren){
+                tmp.innerHTML = oNode.xml ? oNode.xml : oNode.innerHTML;
+            }else{
+                tmp.innerHTML = oNode.xml ? oNode.cloneNode(false).xml : oNode.cloneNode(false).innerHTML;
+            };
+            return tmp.getElementsByTagName("*")[0];
         };
-        }catch(e){};
+    }catch(e){ };
 };
 if(!Sarissa.getParseErrorText){
     /**
@@ -415,17 +448,16 @@
      */
     Sarissa.getParseErrorText = function (oDoc){
         var parseErrorText = Sarissa.PARSED_OK;
-        if(oDoc.parseError != 0){
-            /*moz*/
-            if(oDoc.documentElement.tagName == "parsererror"){
-                parseErrorText = oDoc.documentElement.firstChild.data;
-                parseErrorText += "\n" +  oDoc.documentElement.firstChild.nextSibling.firstChild.data;
-            }/*konq*/
-            else if(oDoc.documentElement.tagName == "html"){
-                parseErrorText = Sarissa.getText(oDoc.documentElement.getElementsByTagName("h1")[0], false) + "\n";
-                parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("body")[0], false) + "\n";
-                parseErrorText += Sarissa.getText(oDoc.documentElement.getElementsByTagName("pre")[0], false);
-            };
+        if(!oDoc.documentElement){
+            parseErrorText = Sarissa.PARSED_EMPTY;
+        } else if(oDoc.documentElement.tagName == "parsererror"){
+            parseErrorText = oDoc.documentElement.firstChild.data;
+            parseErrorText += "\n" +  oDoc.documentElement.firstChild.nextSibling.firstChild.data;
+        } else if(oDoc.getElementsByTagName("parsererror").length > 0){
+            var parsererror = oDoc.getElementsByTagName("parsererror")[0];
+            parseErrorText = Sarissa.getText(parsererror, true)+"\n";
+        } else if(oDoc.parseError && oDoc.parseError.errorCode != 0){
+            parseErrorText = Sarissa.PARSED_UNKNOWN_ERROR;
         };
         return parseErrorText;
     };
@@ -438,8 +470,7 @@
         var nodeType = node.nodeType;
         if(nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE){
             s += node.data;
-        }
-        else if(deep == true
+        } else if(deep == true
                     && (nodeType == Node.ELEMENT_NODE
                         || nodeType == Node.DOCUMENT_NODE
                         || nodeType == Node.DOCUMENT_FRAGMENT_NODE)){
@@ -448,33 +479,20 @@
     };
     return s;
 };
-if(window.XMLSerializer){
+if(!window.XMLSerializer 
+    && Sarissa.getDomDocument 
+    && Sarissa.getDomDocument("","foo", null).xml){
     /**
-     * <p>Factory method to obtain the serialization of a DOM Node</p>
-     * @returns the serialized Node as an XML string
+     * Utility class to serialize DOM Node objects to XML strings
+     * @constructor
      */
-    Sarissa.serialize = function(oDoc){
-        return (new XMLSerializer()).serializeToString(oDoc);
-    };
-}else{
-    if((Sarissa.getDomDocument("","foo", null)).xml){
-        // see non-IE version
-        Sarissa.serialize = function(oDoc) {
-            // TODO: check for HTML document and return innerHTML instead
-            return oDoc.xml;
-        };
-        /**
-         * Utility class to serialize DOM Node objects to XML strings
-         * @constructor
-         */
-        XMLSerializer = function(){};
-        /**
-         * Serialize the given DOM Node to an XML string
-         * @param oNode the DOM Node to serialize
-         */
-        XMLSerializer.prototype.serializeToString = function(oNode) {
-            return oNode.xml;
-        };
+    XMLSerializer = function(){};
+    /**
+     * Serialize the given DOM Node to an XML string
+     * @param oNode the DOM Node to serialize
+     */
+    XMLSerializer.prototype.serializeToString = function(oNode) {
+        return oNode.xml;
     };
 };
 
@@ -489,7 +507,8 @@
  * @argument oNode the Node to empty
  */
 Sarissa.clearChildNodes = function(oNode) {
-    while(oNode.hasChildNodes()){
+    // need to check for firstChild due to opera 8 bug with hasChildNodes
+    while(oNode.firstChild) {
         oNode.removeChild(oNode.firstChild);
     };
 };
@@ -502,17 +521,19 @@
  * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false
  */
 Sarissa.copyChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {
+    if((!nodeFrom) || (!nodeTo)){
+        throw "Both source and destination nodes must be provided";
+    };
     if(!bPreserveExisting){
         Sarissa.clearChildNodes(nodeTo);
     };
     var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;
     var nodes = nodeFrom.childNodes;
-    if(ownerDoc.importNode && (!_SARISSA_IS_IE)) {
+    if(typeof(ownerDoc.importNode) != "undefined")  {
         for(var i=0;i < nodes.length;i++) {
             nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
         };
-    }
-    else{
+    } else {
         for(var i=0;i < nodes.length;i++) {
             nodeTo.appendChild(nodes[i].cloneNode(true));
         };
@@ -525,32 +546,34 @@
  * the move operation, unless you supply a true third parameter</p>
  * @argument nodeFrom the Node to copy the childNodes from
  * @argument nodeTo the Node to copy the childNodes to
- * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is false
- */
+ * @argument bPreserveExisting whether to preserve the original content of nodeTo, default is
+ */ 
 Sarissa.moveChildNodes = function(nodeFrom, nodeTo, bPreserveExisting) {
+    if((!nodeFrom) || (!nodeTo)){
+        throw "Both source and destination nodes must be provided";
+    };
     if(!bPreserveExisting){
         Sarissa.clearChildNodes(nodeTo);
     };
-    
     var nodes = nodeFrom.childNodes;
     // if within the same doc, just move, else copy and delete
     if(nodeFrom.ownerDocument == nodeTo.ownerDocument){
-        nodeTo.appendChild(nodes[i]);
-    }else{
+        while(nodeFrom.firstChild){
+            nodeTo.appendChild(nodeFrom.firstChild);
+        };
+    } else {
         var ownerDoc = nodeTo.nodeType == Node.DOCUMENT_NODE ? nodeTo : nodeTo.ownerDocument;
-         if(ownerDoc.importNode && (!_SARISSA_IS_IE)) {
-            for(var i=0;i < nodes.length;i++) {
-                nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
-            };
-        }
-        else{
-            for(var i=0;i < nodes.length;i++) {
-                nodeTo.appendChild(nodes[i].cloneNode(true));
-            };
+        if(ownerDoc.importNode) {
+           for(var i=0;i < nodes.length;i++) {
+               nodeTo.appendChild(ownerDoc.importNode(nodes[i], true));
+           };
+        }else{
+           for(var i=0;i < nodes.length;i++) {
+               nodeTo.appendChild(nodes[i].cloneNode(true));
+           };
         };
         Sarissa.clearChildNodes(nodeFrom);
     };
-    
 };
 
 /** 

Modified: kupu/trunk/kupu/common/sarissa_ieemu_xpath.js
==============================================================================
--- kupu/trunk/kupu/common/sarissa_ieemu_xpath.js	(original)
+++ kupu/trunk/kupu/common/sarissa_ieemu_xpath.js	Wed Nov  1 11:51:49 2006
@@ -1,19 +1,9 @@
-/*****************************************************************************
- *
- * Sarissa XML library version 0.9.6
- * Copyright (c) 2003 Manos Batsis, 
- * mailto: mbatsis at users full stop sourceforge full stop net
- * This software is distributed under the Kupu License. See
- * LICENSE.txt for license text. See the Sarissa homepage at
- * http://sarissa.sourceforge.net for more information.
- *
- *****************************************************************************
-
+/**
  * ====================================================================
  * About
  * ====================================================================
  * Sarissa cross browser XML library - IE XPath Emulation 
- * @version 0.9.6
+ * @version @sarissa.version@
  * @author: Manos Batsis, mailto: mbatsis at users full stop sourceforge full stop net
  *
  * This script emulates Internet Explorer's selectNodes and selectSingleNode
@@ -22,9 +12,28 @@
  * USers may also map a namespace prefix to a default (unprefixed) namespace in the
  * source document with Sarissa.setXpathNamespaces
  *
+ *
+ * ====================================================================
+ * Licence
+ * ====================================================================
+ * Sarissa is free software distributed under the GNU GPL version 2 (see <a href="gpl.txt">gpl.txt</a>) or higher, 
+ * GNU LGPL version 2.1 (see <a href="lgpl.txt">lgpl.txt</a>) or higher and Apache Software License 2.0 or higher 
+ * (see <a href="asl.txt">asl.txt</a>). This means you can choose one of the three and use that if you like. If 
+ * you make modifications under the ASL, i would appreciate it if you submitted those.
+ * In case your copy of Sarissa does not include the license texts, you may find
+ * them online in various formats at <a href="http://www.gnu.org">http://www.gnu.org</a> and 
+ * <a href="http://www.apache.org">http://www.apache.org</a>.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
+ * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
+ * WARRANTIES OF MERCHANTABILITY,FITNESS FOR A PARTICULAR PURPOSE 
+ * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 if(_SARISSA_HAS_DOM_FEATURE && document.implementation.hasFeature("XPath", "3.0")){
-    var xmldoc = window.XMLDocument || window.Document;
     /**
     * <p>SarissaNodeList behaves as a NodeList but is only used as a result to <code>selectNodes</code>,
     * so it also has some properties IEs proprietery object features.</p>
@@ -58,7 +67,9 @@
     */
     SarissaNodeList.prototype.expr = "";
     /** dummy, used to accept IE's stuff without throwing errors */
-    xmldoc.prototype.setProperty  = function(x,y){};
+    if(window.XMLDocument && (!XMLDocument.prototype.setProperty)){
+        XMLDocument.prototype.setProperty  = function(x,y){};
+    };
     /**
     * <p>Programmatically control namespace URI/prefix mappings for XPath
     * queries.</p>
@@ -92,7 +103,7 @@
             var ns = namespaces[i];
             var colonPos = ns.indexOf(":");
             var assignPos = ns.indexOf("=");
-            if(colonPos == 5 && assignPos > colonPos+2){
+            if(colonPos > 0 && assignPos > colonPos+1){
                 var prefix = ns.substring(colonPos+1, assignPos);
                 var uri = ns.substring(assignPos+2, ns.length-1);
                 oDoc._sarissa_xpathNamespaces[prefix] = uri;
@@ -105,9 +116,9 @@
     * @private Flag to control whether a custom namespace resolver should
     *          be used, set to true by Sarissa.setXpathNamespaces
     */
-    xmldoc.prototype._sarissa_useCustomResolver = false;
+    XMLDocument.prototype._sarissa_useCustomResolver = false;
     /** @private */
-    xmldoc.prototype._sarissa_xpathNamespaces = new Array();
+    XMLDocument.prototype._sarissa_xpathNamespaces = new Array();
     /**
     * <p>Extends the XMLDocument to emulate IE's selectNodes.</p>
     * @argument sExpr the XPath expression to use
@@ -116,24 +127,34 @@
     * @returns the result of the XPath search as a SarissaNodeList
     * @throws An error if no namespace URI is found for the given prefix.
     */
-    xmldoc.prototype.selectNodes = function(sExpr, contextNode){
+    XMLDocument.prototype.selectNodes = function(sExpr, contextNode, returnSingle){
         var nsDoc = this;
         var nsresolver = this._sarissa_useCustomResolver
-        ? function(prefix){
+            ? function(prefix){
             var s = nsDoc._sarissa_xpathNamespaces[prefix];
             if(s)return s;
             else throw "No namespace URI found for prefix: '" + prefix+"'";
-            }
+        }
         : this.createNSResolver(this.documentElement);
+        var result = null;
+        if(!returnSingle){
             var oResult = this.evaluate(sExpr,
-                    (contextNode?contextNode:this),
-                    nsresolver,
-                    XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
-        var nodeList = new SarissaNodeList(oResult.snapshotLength);
-        nodeList.expr = sExpr;
-        for(var i=0;i<nodeList.length;i++)
-            nodeList[i] = oResult.snapshotItem(i);
-        return nodeList;
+                (contextNode?contextNode:this),
+                nsresolver,
+                XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+            var nodeList = new SarissaNodeList(oResult.snapshotLength);
+            nodeList.expr = sExpr;
+            for(var i=0;i<nodeList.length;i++)
+                nodeList[i] = oResult.snapshotItem(i);
+            result = nodeList;
+        }
+        else {
+            result = oResult = this.evaluate(sExpr,
+                (contextNode?contextNode:this),
+                nsresolver,
+                XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
+        };
+        return result;      
     };
     /**
     * <p>Extends the Element to emulate IE's selectNodes</p>
@@ -151,23 +172,18 @@
             throw "Method selectNodes is only supported by XML Elements";
     };
     /**
-    * <p>Extends the XMLDocument to emulate IE's selectSingleNodes.</p>
+    * <p>Extends the XMLDocument to emulate IE's selectSingleNode.</p>
     * @argument sExpr the XPath expression to use
     * @argument contextNode this is for internal use only by the same
     *           method when called on Elements
     * @returns the result of the XPath search as an (Sarissa)NodeList
     */
-    xmldoc.prototype.selectSingleNode = function(sExpr, contextNode){
+    XMLDocument.prototype.selectSingleNode = function(sExpr, contextNode){
         var ctx = contextNode?contextNode:null;
-        sExpr = "("+sExpr+")[1]";
-        var nodeList = this.selectNodes(sExpr, ctx);
-        if(nodeList.length > 0)
-            return nodeList.item(0);
-        else
-            return null;
+        return this.selectNodes(sExpr, ctx, true);
     };
     /**
-    * <p>Extends the Element to emulate IE's selectNodes.</p>
+    * <p>Extends the Element to emulate IE's selectSingleNode.</p>
     * @argument sExpr the XPath expression to use
     * @returns the result of the XPath search as an (Sarissa)NodeList
     * @throws An error if invoked on an HTML Element as this is only be
@@ -181,5 +197,4 @@
             throw "Method selectNodes is only supported by XML Elements";
     };
     Sarissa.IS_ENABLED_SELECT_NODES = true;
-    xmldoc = undefined;
-};
+};
\ No newline at end of file

Modified: kupu/trunk/kupu/tests/run_tests.html
==============================================================================
--- kupu/trunk/kupu/tests/run_tests.html	(original)
+++ kupu/trunk/kupu/tests/run_tests.html	Wed Nov  1 11:51:49 2006
@@ -74,6 +74,27 @@
         iframe.style.display = 'none';
     };
 
+    // Mark a specific test as failing under Opera. When Opera is
+    // fixed (or the test rewritten to cope with it) the flagged test
+    // will then fail.
+    function opera_is_broken(self, fname) {
+        var fn = self[fname];
+        if (navigator.userAgent.toLowerCase().indexOf("opera") == -1) {
+            return; // Browser is not opera.
+        }
+        self.debug('Invert test '+fname+'for broken browser');
+        function test() {
+            try {
+                fn.call(self);
+            } catch(e) {
+                // The function threw an exception, which is what we
+                // expect.
+                return
+            };
+            self.assert(false, 'expected test '+fname+' to fail, but it passed!');
+        };
+        self[fname] = test;
+    }
 //]]>
 </script>
 </head>

Modified: kupu/trunk/kupu/tests/test_kupubasetools.js
==============================================================================
--- kupu/trunk/kupu/tests/test_kupubasetools.js	(original)
+++ kupu/trunk/kupu/tests/test_kupubasetools.js	Wed Nov  1 11:51:49 2006
@@ -71,11 +71,10 @@
 
         this.selection.selection.removeAllRanges();
         for(var i = 0; i < indices.length; i = i + 1) {
-            var range = document.createRange();
+            var range = this.doc.createRange();
             range.selectNode(cellNodes[indices[i]]);
             this.selection.selection.addRange(range);
         };
-
         this.assertEquals('"'+this.selection.toString().replace(/\r|\n/g, '')+'"',
                           '"'+verificationString+'"');
     };
@@ -268,7 +267,7 @@
         data = '<table><tbody><tr><td>foo</td><td>foz</td></tr><tr><td>bar</td><td>baz</td></tr></tbody></table>';
         expected = '<table><tbody><tr><td><h1 class="te st">foo</h1></td><td>foz</td></tr><tr><td><h1 class="te st">bar</h1></td><td>baz</td></tr></tbody></table>'
         if (!_SARISSA_IS_IE) {
-            this.body.innerHTML = data; 
+            this.body.innerHTML = data;
             this._selectTableCells(new Array(0,2),'foo\tbar');
             this.ui.setTextStyle('h1|te st');
             this.assertEquals(this._cleanHtml(this.body.innerHTML), expected);

Modified: kupu/trunk/kupu/tests/test_kupueditor.js
==============================================================================
--- kupu/trunk/kupu/tests/test_kupueditor.js	(original)
+++ kupu/trunk/kupu/tests/test_kupueditor.js	Wed Nov  1 11:51:49 2006
@@ -10,6 +10,13 @@
 
 // $Id$
 
+function serializeDocument(d) {
+    return serializeNode(d.documentElement);
+}
+function serializeNode(n) {
+    var serializer = new XMLSerializer();
+    return serializer.serializeToString(n);
+}
 function KupuEditorTestCase() {
     this.name = 'KupuEditorTestCase';
 
@@ -21,7 +28,7 @@
         var parser = new DOMParser();
         var xmlstring = '<p><a id="outer"><a id="inner"><b><span>some link</span></b> Even more</a></a></p>'
         var doc = parser.parseFromString(xmlstring, 'text/xml');
-        this.assertEquals(Sarissa.serialize(doc).strip(),xmlstring);
+        this.assertEquals(serializeDocument(doc).strip(),xmlstring);
 
         var span = doc.documentElement.firstChild.firstChild.firstChild.firstChild;
 
@@ -40,20 +47,20 @@
     this.testRemoveNearestParentOfType = function() {
         var xmlstring = '<p><a id="outer"><a id="inner"><b><span>some link</span></b> Even more</a></a></p>'
         var doc = (new DOMParser()).parseFromString(xmlstring, 'text/xml');
-        this.assertEquals(Sarissa.serialize(doc).strip(), xmlstring);
+        this.assertEquals(serializeDocument(doc).strip(), xmlstring);
 
         var span = doc.documentElement.firstChild.firstChild.firstChild.firstChild;
 
         // first try to remove a parent we don't have; we expect the
         // xml not to change.
         this.editor.removeNearestParentOfType(span, 'br');
-        this.assertEquals(Sarissa.serialize(doc).strip(), xmlstring);  
+        this.assertEquals(serializeDocument(doc).strip(), xmlstring);  
 
         // now remove a real parent; we expect it to be gone in the
         // resulting xml.
         this.editor.removeNearestParentOfType(span, 'a');
         var expected = '<p><a id="outer"><b><span>some link</span></b> Even more</a></p>';
-        this.assertEquals(Sarissa.serialize(doc).strip(), expected);
+        this.assertEquals(serializeDocument(doc).strip(), expected);
     };
 
     this.test_serializeOutputToString = function() {

Modified: kupu/trunk/kupu/tests/test_kupuhelpers.js
==============================================================================
--- kupu/trunk/kupu/tests/test_kupuhelpers.js	(original)
+++ kupu/trunk/kupu/tests/test_kupuhelpers.js	Wed Nov  1 11:51:49 2006
@@ -27,18 +27,18 @@
         // this does not skip invisible whitespace
         var node = element.firstChild;
         for (var i=0; i < element.childNodes.length; i++) {
-            if (node.nodeType == node.TEXT_NODE) {
+            if (node.nodeType == Node.TEXT_NODE) {
                 var endcounts = !node.nextSibling &&
                          blockElements.contains(element.tagName.toUpperCase());
-                if ((offset < node.length) ||
-                    ((offset == node.length) && (!lastnode || endcounts))) {
+                if ((offset < node.data.length) ||
+                    ((offset == node.data.length) && (!lastnode || endcounts))) {
                     return [node, offset];
                 };
                 if (endcounts) {
                     offset -= 1;
                 };
-                offset -= node.length;
-            } else if (node.nodeType == node.ELEMENT_NODE) {
+                offset -= node.data.length;
+            } else if (node.nodeType == Node.ELEMENT_NODE) {
                 if (visibleEmptyElements.contains(node.tagName.toUpperCase())) {
                     if (offset > 0 && !node.nextSibling) {
                         offset -= 1;
@@ -65,7 +65,7 @@
         endNextNode, verificationString, ieskew, endskew) {
         var element = this.body;
         var innerSelection = this.selection.selection;
-        if (_SARISSA_IS_IE) {
+        if (innerSelection.createRange) {
             if (ieskew) {
                 startOffset += ieskew;
                 if (endskew) {
@@ -83,13 +83,14 @@
             range.setEndPoint('EndToStart', endrange);
             range.select();
         } else {
-            var position = this._MozillaPosition(element, startOffset,
-                                                 startNextNode);
-            innerSelection.collapse(position[0], position[1]);
+            var position = this._MozillaPosition(element, startOffset, startNextNode);
+            var epos = null;
             if (startOffset != endOffset) {
-                var position = this._MozillaPosition(element, endOffset,
-                                                     endNextNode);
-                innerSelection.extend(position[0], position[1]);
+                var epos = this._MozillaPosition(element, endOffset, endNextNode);
+            }
+            innerSelection.collapse(position[0], position[1]);
+            if (epos) {
+                innerSelection.extend(epos[0], epos[1]);
             };
         };
         this.assertEquals('"'+this.selection.toString().replace(/(\r|\n|\t)+/g, '')+'"',
@@ -99,6 +100,7 @@
     this._cleanHtml = function(s) {
         s = s.toLowerCase().replace(/[\r\n]/g, "");
         s = s.replace(/\>[ ]+\</g, "><");
+        s = s.replace(/\/>/g, ">");
         return s;
     };
 
@@ -207,14 +209,18 @@
 KupuHelpersTestCase.prototype = new TestCase;
 
 function KupuSelectionTestCase() {
-
+    this.cleanbody = function() {
+        var s = this.body.innerHTML.toLowerCase();
+        s = s.replace(/<img([^\/>]*)\/>/g, '<img$1>');
+        return s;
+    }
     this.testReplaceWithNode = function() {
         this.body.innerHTML = '<p>foo bar baz</p>';
         // select                    |bar|
         this._setSelection(4, null, 7, null, 'bar');
         node = this.doc.createElement('img');
         this.selection.replaceWithNode(node, true);
-        this.assertEquals(this.body.innerHTML.toLowerCase(), '<p>foo <img> baz</p>');
+        this.assertEquals(this.cleanbody(), '<p>foo <img> baz</p>');
     };
 
     this.testReplaceWithNodeTwice = function() {
@@ -224,7 +230,7 @@
         node = this.doc.createElement('img');
         this.selection.replaceWithNode(node, true);
         this.selection.replaceWithNode(node, true);
-        this.assertEquals(this.body.innerHTML.toLowerCase(), '<p>foo <img> baz</p>');
+        this.assertEquals(this.cleanbody(), '<p>foo <img> baz</p>');
     };
 
     this.testParentElementMissing = function() {
@@ -237,9 +243,11 @@
     };
 
     this.testParentElementBold = function() {
-        this.body.innerHTML = '<p>foo <b>bar</b><img/><img/> baz</p>';
-        // select                       |bar|
-        this._setSelection(4, true, 7, false, 'bar');
+        this.body.innerHTML = '<p>foo <b>xbar!</b><img/><img/> baz</p>';
+        // select                        |bar|
+        // kludged for opera which cannot do a selection involving the
+        // first character of the <b> tag.
+        this._setSelection(5, true, 8, true, 'bar');
         node = this.doc.getElementsByTagName('b')[0];
         this.assertEquals(this.selection.parentElement(), node);
     };
@@ -272,7 +280,7 @@
     this.testParentElement_r9516 = function() {
         this.body.innerHTML = '<p>foo <b>bar</b><img/></p><p>baz</p>';
         // select                              |<img/></p><p>baz|
-        this._setSelection(7, true, 12, false, 'baz');
+        this._setSelection(6, true, 12, false, 'rbaz');
         node = this.doc.getElementsByTagName('body')[0];
         this.assertEquals(this.selection.parentElement(), node);
     };
@@ -288,7 +296,7 @@
         this.body.innerHTML = '<p>foo <b>bar</b> baz</p>';
         var selection = this.kupudoc.getSelection();
         selection.selectNodeContents(this.body);
-        this.assertEquals(selection.toString(), 'foo bar baz');
+        this.assertEquals('['+selection.toString()+']', '[foo bar baz]');
         selection.selectNodeContents(this.body.firstChild.childNodes[1]);
         this.assertEquals(selection.toString(), 'bar');
     };

Modified: kupu/trunk/kupu/tests/test_xhtml.js
==============================================================================
--- kupu/trunk/kupu/tests/test_xhtml.js	(original)
+++ kupu/trunk/kupu/tests/test_xhtml.js	Wed Nov  1 11:51:49 2006
@@ -18,14 +18,19 @@
     this.incontext = function(s) {
         return '<html><head><title>test</title></head><body>'+s+'</body></html>';
     }
+    this.serializeNode = function(n) {
+        var serializer = new XMLSerializer();
+        return serializer.serializeToString(n);
+    }
     this.verifyResult = function(newdoc, exp) {
         var expected = this.incontext(exp);
-        var actual = Sarissa.serialize(newdoc);
+        var actual = this.serializeNode(newdoc);
         actual = actual.replace('\xa0', '&nbsp;');
+        actual = actual.replace(/^<html[^>]*>/, '<html>');
         if (actual == expected)
             return;
 
-        var context = /<html><head><title>test<\/title><\/head><body>(.*)<\/body><\/html>/;
+        var context = /<html[^>]*><head><title>test<\/title><\/head><body>(.*)<\/body><\/html>/i;
         if (context.test(actual) && context.test(expected)) {
             var a = context.exec(actual)[1];
             var e = context.exec(expected)[1];


More information about the kupu-checkins mailing list