Changeset 7883

Show
Ignore:
Timestamp:
03/31/07 18:52:28 (22 months ago)
Author:
alex
Message:

tests and correctness fixes for dojo.query(). This is something of a backslide on performance, but correctness trumps. Still need to find another week or so to spend on query(). Refs #2615.

Location:
dojo/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • dojo/trunk/tests/_base/query.html

    r7845 r7883  
    55                <script type="text/javascript"> 
    66                        dojo.require("tests.runner"); 
    7                         // dojo.require("dojo.query"); 
    87                        dojo.addOnLoad(function(){ 
    9                                 /* 
    10                                 tests.register("thinger", function blah(t){ 
    11                                         t.assertTrue(true); 
    12                                 }); 
    13                                 tests.register("thinger", function blah2(t){ 
    14                                         t.assertTrue(false); 
    15                                 }); 
    16                                 */ 
    178                                tests.register("t",  
    189                                        [ 
     10                                                "tests.assertEqual(4, (dojo.query('h3')).length);", 
    1911                                                "tests.assertEqual(4, (dojo.query('#t h3')).length);", 
    20                                                 "tests.assertEqual(3, (dojo.query('#t > h3')).length);" 
     12                                                "tests.assertEqual(1, (dojo.query('#t div > h3')).length);", 
     13                                                "tests.assertEqual(3, (dojo.query('#t > h3')).length);", 
     14                                                "tests.assertEqual(2, (dojo.query('.foo, .bar')).length);", 
     15                                                "tests.assertEqual(2, (dojo.query('.foo')).length);", 
     16                                                "tests.assertEqual(2, (dojo.query('.baz')).length);", 
     17                                                "tests.assertEqual(1, (dojo.query('span.baz')).length);", 
     18                                                // FIXME: need to support [foo="foo bar"]. We're incorrectly tokenizing! 
     19                                                "tests.assertEqual(2, (dojo.query('[foo~=\"bar\"]')).length);", 
     20                                                "tests.assertEqual(3, (dojo.query('[foo]')).length);", 
     21                                                "tests.assertEqual(1, (dojo.query('[foo$=\"thud\"]')).length);", 
     22                                                "tests.assertEqual(1, (dojo.query('[foo|=\"bar\"]')).length);", 
     23                                                "tests.assertEqual(1, (dojo.query('[foo|=\"bar-baz\"]')).length);", 
     24                                                "tests.assertEqual(0, (dojo.query('[foo|=\"baz\"]')).length);", 
     25                                                "tests.assertEqual(dojo.byId('_foo'), dojo.query('.foo:nth-child(2)')[0]);" 
    2126                                        ] 
    2227                                ); 
     
    2833                <h1>testing dojo.query()</h1> 
    2934                <div id="t"> 
    30                         <h3> 
    31                                 <h4>h4</h4> 
     35                        <h3>h3 <span>span</span> endh3 </h3> 
     36                        <!-- comment to throw things off --> 
     37                        <div class="foo bar" id="_foo"> 
    3238                                <h3>h3</h3> 
    33                         </h3> 
     39                                <span id="foo"></span> 
     40                                <span></span> 
     41                        </div> 
    3442                        <h3>h3</h3> 
    35                         <h3>h3</h3> 
     43                        <h3 class="baz">h3</h3> 
     44                        <span class="foobar baz foo"></span> 
     45                        <span foo="bar"></span> 
     46                        <span foo="baz bar thud"></span> 
     47                        <!-- FIXME: should foo="bar-baz-thud" match? [foo$=thud] ??? --> 
     48                        <span foo="bar-baz-thudish"></span> 
    3649                </div> 
    3750        </body> 
  • dojo/trunk/_base/query.js

    r7698 r7883  
    5454                }, 
    5555                { 
     56                        key: "~=", 
     57                        match: function(attr, value){ 
     58                                return "[contains(concat(' ',@"+attr+",' '), ' "+ value +" ')]"; 
     59                        } 
     60                }, 
     61                { 
    5662                        key: "^=", 
    5763                        match: function(attr, value){ 
     
    8591                } 
    8692        ]; 
     93 
     94        var strip = function(val){ 
     95                var re = /^\s+|\s+$/g; 
     96                return val.replace(re, "");     //      string 
     97        } 
    8798 
    8899        var handleAttrs = function(     attrList,  
     
    112123                                                        value = value.substring(1, value.length-1); 
    113124                                                } 
    114                                                 matcher = ta.match(attr, value); 
     125                                                matcher = ta.match(strip(attr), strip(value)); 
    115126                                                break; 
    116127                                        } 
     
    138149        var buildPath = function(query){ 
    139150                var xpath = ""; 
    140                 var qparts = query.split(" "); 
     151                var qparts = query.split(" "); // FIXME: this break on span[thinger = foo] 
    141152                while(qparts.length){ 
    142153                        var tqp = qparts.shift(); 
    143154                        var prefix; 
     155                        // FIXME: need to add support for ~ and + 
    144156                        if(tqp == ">"){ 
    145157                                prefix = "/"; 
     158                                // prefix = "/child::node()"; 
    146159                                tqp = qparts.shift(); 
    147160                        }else{ 
    148161                                prefix = "//"; 
    149                         } 
     162                                // prefix = "/descendant::node()" 
     163                        } 
     164 
    150165                        // get the tag name (if any) 
    151166                        var tagName = getTagName(tqp); 
     
    156171                        var id = getId(tqp); 
    157172                        if(id.length){ 
    158                                 xpath += "[@id='"+id+"']"; 
     173                                xpath += "[@id='"+id+"'][1]"; 
    159174                        } 
    160175 
     
    182197                        // FIXME: need to implement pseudo-class checks!! 
    183198                }; 
    184                 // dojo.debug(xpath); 
    185199                return xpath; 
    186200        }; 
     
    196210                // FIXME: don't need to memoize. The closure scope handles it for us. 
    197211                var xpath = buildPath(path); 
     212                // console.debug(xpath); 
    198213 
    199214                var tf = function(){ 
    200215                        // XPath query strings are memoized. 
    201216                        var ret = []; 
    202                         var xpathResult = doc.evaluate(xpath, parent, null,  
    203                                                                                         // XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); 
    204                                                                                         XPathResult.ANY_TYPE, null); 
     217                        try{ 
     218                                var xpathResult = doc.evaluate(xpath, parent, null,  
     219                                                                                                // XPathResult.UNORDERED_NODE_ITERATOR_TYPE, null); 
     220                                                                                                XPathResult.ANY_TYPE, null); 
     221                        }catch(e){ 
     222                                console.debug("failure in exprssion:", xpath, "under:", parent); 
     223                                console.debug(e); 
     224                        } 
    205225                        var result = xpathResult.iterateNext(); 
    206226                        while(result){ 
     
    628648                                        var ncount = pi(condition); 
    629649                                        return function(elem){ 
    630                                                 // removeChaffNodes(elem.parentNode); 
    631                                                 return (elem.parentNode.childNodes[ncount-1] === elem); 
     650                                                return (getNodeIndex(elem) == ncount); 
    632651                                        } 
    633652                                } 
     
    661680                } 
    662681 
     682                var matcher; 
     683 
    663684                // if there's a class in our query, generate a match function for it 
    664685                var className = getClassName(query); 
     
    674695                                return re.test(elem.className); 
    675696                        }); 
    676  
    677                 } 
    678                 // [ "#", ".", "[", ":" ]; 
    679                 var defaultGetter = (d.isIE) ? 
    680                         function(cond){ 
    681                                 return function(elem){ 
    682                                         return elem[cond]; 
    683                                 } 
    684                         } : function(cond){ 
    685                                 return function(elem){ 
    686                                         return elem.hasAttribute(cond); 
    687                                 } 
    688                         }; 
    689                 handleAttrs(attrs, query, defaultGetter, 
    690                         function(tmatcher){ 
    691                                 ff = agree(ff, tmatcher); 
    692                         } 
    693                 ); 
    694  
    695                 var matcher; 
     697                } 
     698 
    696699                if(i[3]>= 0){ 
    697700                        // NOTE: we count on the pseudo name being at the end 
     701                        // FIXME: this is clearly a bug!!! 
    698702                        var pseudoName = query.substr(i[3]+1); 
    699703                        var condition = ""; 
     
    723727                        } 
    724728                } 
     729 
     730                // [ "#", ".", "[", ":" ]; 
     731                var defaultGetter = (d.isIE) ? 
     732                        function(cond){ 
     733                                return function(elem){ 
     734                                        return elem[cond]; 
     735                                } 
     736                        } : function(cond){ 
     737                                return function(elem){ 
     738                                        return elem.hasAttribute(cond); 
     739                                } 
     740                        }; 
     741                handleAttrs(attrs, query, defaultGetter, 
     742                        function(tmatcher){ 
     743                                ff = agree(ff, tmatcher); 
     744                        } 
     745                ); 
    725746                if(!ff){ 
    726747                        ff = function(){ return true; }; 
     
    768789                        var tn = getTagName(query); 
    769790 
    770                         /* 
    771                         if(-1 != i[3]){ 
    772                                 var pseudoName = (0 <= i[3]) ? query.substr(i[3]+1) : ""; 
    773                                 switch(pseudoName){ 
    774                                         case "first": 
    775                                                 retFunc = function(root){ 
    776                                                         // for(var x=0, te; te = tret[x]; x++){ 
    777                                                         var te, x=0, tret = root.getElementsByTagName(tn); 
    778                                                         while(te=tret[x++]){ 
    779                                                                 if(filterFunc(te)){ 
    780                                                                         return [ te ]; 
    781                                                                 } 
    782                                                         } 
    783                                                         return []; 
    784                                                 } 
    785                                                 break; 
    786                                         case "last": 
    787                                                 retFunc = function(root){ 
    788                                                         var tret = root.getElementsByTagName(tn); 
    789                                                         var te, x=tret.length-1; 
    790                                                         while(te=tret[x--]){ 
    791                                                                 if(filterFunc(te)){ 
    792                                                                         return [ te ]; 
    793                                                                 } 
    794                                                         } 
    795                                                         return []; 
    796                                                 } 
    797                                                 break; 
    798                                         default: 
    799                                                 retFunc = function(root){ 
    800                                                         var ret = []; 
    801                                                         var te, x=0, tret = root.getElementsByTagName(tn); 
    802                                                         while(te=tret[x++]){ 
    803                                                                 if(filterFunc(te)){ 
    804                                                                         ret[ret.length] = te; 
    805                                                                         // ret.push(te); 
    806                                                                 } 
    807                                                         } 
    808                                                         return ret; 
    809                                                 } 
    810                                                 break; 
    811                                 } 
    812                         }else  
    813                         */ 
    814791                        if(isTagOnly(query)){ 
    815792                                // it's just a plain-ol elements-by-tag-name query from the root 
     
    851828 
    852829                var sqf = function(root){ 
    853                         var qparts = query.split(" "); 
    854  
     830                        var qparts = query.split(" "); // FIXME: this is an inaccurate tokenizer! 
     831 
     832                        /* 
    855833                        // FIXME: need to make root popping more explicit and cache it somehow 
    856834 
     
    868846                                partIndex++; 
    869847                        } 
     848                        // console.debug(qparts[partIndex], root); 
    870849                        if(qparts.length == partIndex){ 
    871850                                return [ root ]; 
     
    884863                        //              foo.bar span[blah="thonk"] div div span code.example 
    885864                        // in short, we need to move the look-ahead logic into _filterDown() 
     865                        // console.debug(qparts[partIndex]); 
    886866                        if( isTagOnly(qparts[partIndex]) &&  
    887867                                (qparts[partIndex+1] != ">") 
     
    914894                                } 
    915895                        }else{ 
     896                                // console.debug(qparts); 
    916897                                candidates = getElementsFunc(qparts.shift())(root); 
    917898                        } 
     899                        */ 
     900                        var candidates = getElementsFunc(qparts.shift())(root); 
    918901                        return filterDown(candidates, qparts); 
    919902                } 
     
    960943                                        return getXPathFunc(query); 
    961944                                } 
    962                                 // return getXPathFunc(query); 
    963                         } 
    964  
     945                        } 
     946 
     947                        // fallthrough 
    965948                        return getStepQueryFunc(query); 
    966949                } : getStepQueryFunc 
    967950        ); 
    968         // FIXME: disable XPath for testing and tuning the DOM path 
     951        // uncomment to disable XPath for testing and tuning the DOM path 
    969952        // _getQueryFunc = getStepQueryFunc; 
     953        // uncomment to disable DOM queries for testing and tuning XPath 
     954        // _getQueryFunc = getXPathFunc; 
    970955 
    971956        var getQueryFunc = function(query){ 
     
    1008993        */ 
    1009994 
     995        // FIXME:  
     996        //              Dean's new Base2 uses a system whereby queries themselves note if 
     997        //              they'll need duplicate filtering. We need to get on that plan!! 
     998 
    1010999        var _zipIdx = 0; 
    10111000        var _zip = function(arr){ 
    10121001                var ret = new d.NodeList(); 
    10131002                if(!arr){ return ret; } 
    1014                 ret.push(arr[0]); 
     1003                if(arr[0]){ 
     1004                        ret.push(arr[0]); 
     1005                } 
    10151006                if(arr.length < 2){ return ret; } 
    10161007                _zipIdx++;