class HTML::Selector
def nth_child(a, b, of_type, reverse)
* +of_type+ -- True to test only elements of this type (of-type).
* +b+ -- Value of b part.
* +a+ -- Value of a part.
pseudo class, given the following arguments:
Returns a lambda that can match an element against the nth-child
def nth_child(a, b, of_type, reverse) # a = 0 means select at index b, if b = 0 nothing selected return lambda { |element| false } if a == 0 && b == 0 # a < 0 and b < 0 will never match against an index return lambda { |element| false } if a < 0 && b < 0 b = a + b + 1 if b < 0 # b < 0 just picks last element from each group b -= 1 unless b == 0 # b == 0 is same as b == 1, otherwise zero based lambda do |element| # Element must be inside parent element. return false unless element.parent && element.parent.tag? index = 0 # Get siblings, reverse if counting from last. siblings = element.parent.children siblings = siblings.reverse if reverse # Match element name if of-type, otherwise ignore name. name = of_type ? element.name : nil found = false for child in siblings # Skip text nodes/comments. if child.tag? && (name == nil || child.name == name) if a == 0 # Shortcut when a == 0 no need to go past count if index == b found = child.equal?(element) break end elsif a < 0 # Only look for first b elements break if index > b if child.equal?(element) found = (index % a) == 0 break end else # Otherwise, break if child found and count == an+b if child.equal?(element) found = (index % a) == b break end end index += 1 end end found end end