<commit_before>module Browser; module DOM

class Element < Node
  def self.create(*args)
    $document.create_element(*args)
  end

  include Event::Target

  alias_native :id, :id

  def add_class(name)
    `#@native.className = #{class_names.push(name).uniq.join ' '}`

    self
  end

  def remove_class(name)
    `#@native.className = #{class_names.delete(name).join ' '}`
  end

  alias_native :class_name, :className

  def class_names
    `#@native.className`.split(/\s+/)
  end

  def attr(name)
    attributes[name]
  end

  alias attribute attr

  def attribute_nodes
    Array(`#@native.attributes`, :item).map { |e| DOM(e) }
  end

  def attributes
    Attributes.new(self)
  end

  def [](name)
    `#@native.getAttribute(#{name.to_s}) || nil`
  end

  def []=(name, value)
    `#@native.setAttribute(#{name.to_s}, #{value.to_s})`
  end

  alias get []

  alias get_attribute attr

  alias set_attribute []=

  def key?(name)
    !!self[name]
  end

  def keys
    attributes.keys
  end

  def values
    attribute_nodes.map { |n| n.value }
  end

  def each
    attributes.each { |name, value| yield value }
  end

  def remove_attribute(name)
    `#@native.removeAttribute(name)`
  end

  Size     = Struct.new(:width, :height)
  Position = Struct.new(:x, :y)

  def size
    Size.new(`#@native.clientWidth`, `#@native.clientHeight`)
  end

  def position
    Size.new(`#@native.clientLeft`, `#@native.clientTop`)
  end

  def /(*paths)
    paths.map { |path| xpath(path) }.flatten.uniq
  end

  def at(path)
    xpath(path).first
  end

  def at_css(*rules)
    rules.each {|rule|
      found = css(rule).first

      return found if found
    }

    nil
  end

  def at_xpath(*paths)
    paths.each {|path|
      found = xpath(path).first

      return found if found
    }

    nil
  end

  def search(*selectors)
    NodeSet.new document, selectors.map {|selector|
      xpath(selector).to_a.concat(css(selector).to_a)
    }.flatten.uniq
  end

  def css(path)
    NodeSet.new(document, Array(`#@native.querySelectorAll(path)`))
  end

  def xpath(path)
    result = []

    %x{
      try {
        var tmp = (#@native.ownerDocument || #@native).evaluate(
          path, #@native, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

        result = #{Array(`tmp`, :snapshotItem, :snapshotLength)};
      } catch (e) { }
    }

    NodeSet.new(document, result)
  end

  def style(data = nil)
    style = Style::Definition.new(`#@native.style`)

    if data.is_a?(String)
      style.replace(data)

      self
    elsif data.is_a?(Enumerable)
      style.assign(data)

      self
    else
      style
    end
  end

  def inspect
    "#<DOM::Element: #{name}>"
  end

  class Attributes
    include Enumerable

    def initialize(element)
      @element = element
    end

    def each(&block)
      return enum_for :each unless block_given?

      @element.attribute_nodes.each {|attr|
        yield attr.name, attr.value
      }

      self
    end

    def [](name)
      @element[name]
    end

    def []=(name, value)
      @element[name] = value
    end

    def merge!(hash)
      hash.each {|name, value|
        @element[name] = value
      }
    end
  end
end

end; end<commit_msg>dom/element: more attributes improvements<commit_after>module Browser; module DOM

class Element < Node
  def self.create(*args)
    $document.create_element(*args)
  end

  include Event::Target

  alias_native :id, :id

  def add_class(name)
    `#@native.className = #{class_names.push(name).uniq.join ' '}`

    self
  end

  def remove_class(name)
    `#@native.className = #{class_names.delete(name).join ' '}`
  end

  alias_native :class_name, :className

  def class_names
    `#@native.className`.split(/\s+/)
  end

  alias attribute attr

  def attribute_nodes
    Array(`#@native.attributes`, :item).map { |e| DOM(e) }
  end

  def attributes(options = {})
    Attributes.new(self, options)
  end

  def get(name, options = {})
    if namespace = options[:namespace]
      `#@native.getAttributeNS(#{namespace.to_s}, #{name.to_s}) || nil`
    else
      `#@native.getAttribute(#{name.to_s}) || nil`
    end
  end

  def set(name, value, options = {})
    if namespace = options[:namespace]
      `#@native.setAttributeNS(#{namespace.to_s}, #{name.to_s}, #{value})`
    else
      `#@native.setAttribute(#{name.to_s}, #{value.to_s})`
    end
  end

  alias [] get
  alias []= set

  alias attr get
  alias attribute get

  alias get_attribute get
  alias set_attribute set

  def key?(name)
    !!self[name]
  end

  def keys
    attributes_nodesmap(&:name)
  end

  def values
    attribute_nodes.map(&:value)
  end

  def each(options = {}, &block)
    return enum_for :each, options unless block

    attributes(options).each(&block)
  end

  def remove_attribute(name)
    `#@native.removeAttribute(name)`
  end

  Size     = Struct.new(:width, :height)
  Position = Struct.new(:x, :y)

  def size
    Size.new(`#@native.clientWidth`, `#@native.clientHeight`)
  end

  def position
    Size.new(`#@native.clientLeft`, `#@native.clientTop`)
  end

  def /(*paths)
    paths.map { |path| xpath(path) }.flatten.uniq
  end

  def at(path)
    xpath(path).first
  end

  def at_css(*rules)
    rules.each {|rule|
      found = css(rule).first

      return found if found
    }

    nil
  end

  def at_xpath(*paths)
    paths.each {|path|
      found = xpath(path).first

      return found if found
    }

    nil
  end

  def search(*selectors)
    NodeSet.new document, selectors.map {|selector|
      xpath(selector).to_a.concat(css(selector).to_a)
    }.flatten.uniq
  end

  def css(path)
    NodeSet.new(document, Array(`#@native.querySelectorAll(path)`))
  end

  def xpath(path)
    result = []

    %x{
      try {
        var tmp = (#@native.ownerDocument || #@native).evaluate(
          path, #@native, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

        result = #{Array(`tmp`, :snapshotItem, :snapshotLength)};
      } catch (e) { }
    }

    NodeSet.new(document, result)
  end

  def style(data = nil)
    style = Style::Definition.new(`#@native.style`)

    if data.is_a?(String)
      style.replace(data)

      self
    elsif data.is_a?(Enumerable)
      style.assign(data)

      self
    else
      style
    end
  end

  def inspect
    "#<DOM::Element: #{name}>"
  end

  class Attributes
    include Enumerable

    attr_reader :namespace

    def initialize(element, options)
      @element   = element
      @namespace = options[:namespace]
    end

    def each(&block)
      return enum_for :each unless block_given?

      @element.attribute_nodes.each {|attr|
        yield attr.name, attr.value
      }

      self
    end

    def [](name)
      @element.get_attribute(name, namespace: @namespace)
    end

    def []=(name, value)
      @element.set_attribute(name, value, namespace: @namespace)
    end

    def merge!(hash)
      hash.each {|name, value|
        self[name] = value
      }

      self
    end
  end
end

end; end
{'fraction_non_alphanumeric': 0.1328191945158526, 'fraction_numerical': 0.0, 'mean_word_length': 2.6531038080333853, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1178758', 'n_tokens_mistral': 2470, 'n_tokens_neox': 2380, 'n_words': 539}