Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 6476

Show
Ignore:
Timestamp:
03/27/07 18:14:53 (1 year ago)
Author:
madrobby
Message:

Fix issues with Selector an+b logic, performance improvements. Closes #7873. [Andrew Dupont]

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • spinoffs/prototype/trunk/CHANGELOG

    r6475 r6476  
    11*SVN* 
     2 
     3* Fix issues with Selector an+b logic, performance improvements.  Closes #7873.  [Andrew Dupont] 
    24 
    35* Fix an issue with Element.getDimensions with some element types on non IE-browsers.  Closes #7683.  [Andrew Dupont] 
  • spinoffs/prototype/trunk/src/selector.js

    r6391 r6476  
    163163        var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); 
    164164      }, 
    165       nth: function(predicate, m) { 
    166         var mm, formula = m[6]
     165      nth: function(fragment, m) { 
     166        var mm, formula = m[6], predicate
    167167        if (formula == 'even') formula = '2n+0'; 
    168168        if (formula == 'odd')  formula = '2n+1'; 
    169169        if (mm = formula.match(/^(\d+)$/)) // digit only 
    170           predicate += "= " + mm[1]; 
    171         if (mm = formula.match(/^(\d+)?n(\+(\d+))?/)) { // an+b 
     170          return '[' + fragment + "= " + mm[1] + ']'; 
     171        if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 
     172          if (mm[1] == "-") mm[1] = -1; 
    172173          var a = mm[1] ? Number(mm[1]) : 1; 
    173           var b = mm[3] ? Number(mm[3]) : 0; 
    174           predicate += "mod " + a + " = " + b; 
    175         } 
    176         return "[" + predicate + "]";         
     174          var b = mm[2] ? Number(mm[2]) : 0; 
     175          predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + 
     176          "((#{fragment} - #{b}) div #{a} >= 0)]"; 
     177          return new Template(predicate).evaluate({ 
     178            fragment: fragment, a: a, b: b }); 
     179        } 
    177180      } 
    178181    } 
     
    266269      var h = Selector.handlers; 
    267270      for (var i = 0, results = [], node; node = nodes[i]; i++) 
    268         h.concat(results, Element.descendants(node)); 
     271        h.concat(results, node.getElementsByTagName('*')); 
    269272      return results; 
    270273    }, 
     
    272275    child: function(nodes) { 
    273276      var h = Selector.handlers; 
    274       for (var i = 0, results = [], node; node = nodes[i]; i++) 
    275         h.concat(results, Element.immediateDescendants(node)); 
     277      for (var i = 0, results = [], node; node = nodes[i]; i++) { 
     278        for (var j = 0, children = [], child; child = node.childNodes[j]; j++) 
     279          if (child.nodeType == 1 && child.tagName != '!') results.push(child); 
     280      } 
    276281      return results; 
    277282    }, 
     
    433438    }, 
    434439     
     440    // handles the an+b logic 
     441    getIndices: function(a, b, total) { 
     442      if (a == 0) return b > 0 ? [b] : []; 
     443      return $R(1, total).inject([], function(memo, i) { 
     444        if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); 
     445        return memo; 
     446      }); 
     447    }, 
     448     
    435449    // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type 
    436450    nth: function(nodes, formula, root, reverse, ofType) { 
     451      if (nodes.length == 0) return []; 
    437452      if (formula == 'even') formula = '2n+0'; 
    438453      if (formula == 'odd')  formula = '2n+1'; 
     
    449464        for (var i = 0, node; node = nodes[i]; i++) 
    450465          if (node.nodeIndex == formula) results.push(node); 
    451       } else if (m = formula.match(/^(\d+)?n(\+(\d+))?$/)) { // an+b 
     466      } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b 
     467        if (m[1] == "-") m[1] = -1; 
    452468        var a = m[1] ? Number(m[1]) : 1; 
    453         var b = m[3] ? Number(m[3]) : 0; 
    454         for (var i = 0, node; node = nodes[i]; i++) 
    455           if (node.nodeIndex % a == b) results.push(node); 
     469        var b = m[2] ? Number(m[2]) : 0; 
     470        var indices = Selector.pseudos.getIndices(a, b, nodes.length); 
     471        for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { 
     472          for (var j = 0; j < l; j++) 
     473            if (node.nodeIndex == indices[j]) results.push(node); 
     474        } 
    456475      } 
    457476      h.unmark(nodes); 
  • spinoffs/prototype/trunk/test/unit/selector.html

    r6392 r6476  
    299299      assertEnumEqual([$('link_2')], $$('#p *:nth-child(3)'), 'nth-child'); 
    300300      assertEnumEqual([$('link_2')], $$('#p a:nth-child(3)'), 'nth-child'); 
     301      assertEnumEqual($('item_2', 'item_3'), $$('#list > li:nth-child(n+2)')); 
     302      assertEnumEqual($('item_1', 'item_2'), $$('#list > li:nth-child(-n+2)')); 
    301303      $RunBenchmarks && wait(500, function() { 
    302304        benchmark(function() { $$('#level1 *:first-child') }, 1000, ':first-child'); 
     
    347349      assertEnumEqual($$('ul > li:last-child'), $$('ul > li:nth-last-child(1)')); 
    348350      assertEnumEqual($$('#troubleForm *:enabled'), $$('#troubleForm *:not(:disabled)')); 
     351      assertEnumEqual($$('ul > li:nth-child(n-999)'), $$('ul > li')); 
    349352    }}, 
    350353