class method self.new

Ruby on Rails 4.0.13

Since v2.2.3 Last seen in v4.1.16

Available in: v2.2.3 v2.3.18 v3.0.20 v3.1.12 v3.2.22.5 v4.0.13 v4.1.16

Signature

Selector.new(string, [values ...]) => selector

Creates a new selector from a CSS 2 selector expression.

The first argument is the selector expression. All other arguments are used for value substitution.

Throws InvalidSelectorError is the selector expression is invalid.

Parameters

selector req
values rest
Source
# File actionpack/lib/action_view/vendor/html-scanner/html/selector.rb, line 241
    def initialize(selector, *values)
      raise ArgumentError, "CSS expression cannot be empty" if selector.empty?
      @source = ""
      values = values[0] if values.size == 1 && values[0].is_a?(Array)

      # We need a copy to determine if we failed to parse, and also
      # preserve the original pass by-ref statement.
      statement = selector.strip.dup

      # Create a simple selector, along with negation.
      simple_selector(statement, values).each { |name, value| instance_variable_set("@#{name}", value) }

      @alternates = []
      @depends = nil

      # Alternative selector.
      if statement.sub!(/^\s*,\s*/, "")
        second = Selector.new(statement, values)
        @alternates << second
        # If there are alternate selectors, we group them in the top selector.
        if alternates = second.instance_variable_get(:@alternates)
          second.instance_variable_set(:@alternates, [])
          @alternates.concat alternates
        end
        @source << " , " << second.to_s
      # Sibling selector: create a dependency into second selector that will
      # match element immediately following this one.
      elsif statement.sub!(/^\s*\+\s*/, "")
        second = next_selector(statement, values)
        @depends = lambda do |element, first|
          if element = next_element(element)
            second.match(element, first)
          end
        end
        @source << " + " << second.to_s
      # Adjacent selector: create a dependency into second selector that will
      # match all elements following this one.
      elsif statement.sub!(/^\s*~\s*/, "")
        second = next_selector(statement, values)
        @depends = lambda do |element, first|
          matches = []
          while element = next_element(element)
            if subset = second.match(element, first)
              if first && !subset.empty?
                matches << subset.first
                break
              else
                matches.concat subset
              end
            end
          end
          matches.empty? ? nil : matches
        end
        @source << " ~ " << second.to_s
      # Child selector: create a dependency into second selector that will
      # match a child element of this one.
      elsif statement.sub!(/^\s*>\s*/, "")
        second = next_selector(statement, values)
        @depends = lambda do |element, first|
          matches = []
          element.children.each do |child|
            if child.tag? && subset = second.match(child, first)
              if first && !subset.empty?
                matches << subset.first
                break
              else
                matches.concat subset
              end
            end
          end
          matches.empty? ? nil : matches
        end
        @source << " > " << second.to_s
      # Descendant selector: create a dependency into second selector that
      # will match all descendant elements of this one. Note,
      elsif statement =~ /^\s+\S+/ && statement != selector
        second = next_selector(statement, values)
        @depends = lambda do |element, first|
          matches = []
          stack = element.children.reverse
          while node = stack.pop
            next unless node.tag?
            if subset = second.match(node, first)
              if first && !subset.empty?
                matches << subset.first
                break
              else
                matches.concat subset
              end
            elsif children = node.children
              stack.concat children.reverse
            end
          end
          matches.empty? ? nil : matches
        end
        @source << " " << second.to_s
      else
        # The last selector is where we check that we parsed
        # all the parts.
        unless statement.empty? || statement.strip.empty?
          raise ArgumentError, "Invalid selector: #{statement}"
        end
      end
    end

Defined in actionpack/lib/action_view/vendor/html-scanner/html/selector.rb line 241 · View on GitHub · Improve this page · Find usages on GitHub

Defined in HTML::Selector

Type at least 2 characters to search.

↑↓ navigate · open · esc close