class Watir::Element

Base class for HTML elements.

Public Class Methods

new(parent, selector) click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 25
def initialize(parent, selector)
  @parent   = parent
  @selector = selector
  @element  = nil

  unless @selector.kind_of? Hash
    raise ArgumentError, "invalid argument: #{selector.inspect}"
  end
end

Public Instance Methods

==(other) click to toggle source

Returns true if two elements are equal.

@example

browser.text_field(name: "new_user_first_name") == browser.text_field(name: "new_user_first_name")
#=> true
# File lib/watir-webdriver/elements/element.rb, line 65
def ==(other)
  other.is_a?(self.class) && wd == other.wd
end
Also aliased as: eql?
attribute_value(attribute_name) click to toggle source

Returns given attribute value of element.

@example

browser.a(id: "link_2").attribute_value "title"
#=> "link_title_2"

@param [String] attribute_name @return [String, nil]

# File lib/watir-webdriver/elements/element.rb, line 270
def attribute_value(attribute_name)
  assert_exists
  element_call { @element.attribute attribute_name }
end
browser() click to toggle source

Returns browser.

@return [Watir::Browser]

# File lib/watir-webdriver/elements/element.rb, line 492
def browser
  @parent.browser
end
click(*modifiers) click to toggle source

Clicks the element, optionally while pressing the given modifier keys. Note that support for holding a modifier key is currently experimental, and may not work at all.

@example Click an element

browser.element(name: "new_user_button").click

@example Click an element with shift key pressed

browser.element(name: "new_user_button").click(:shift)

@example Click an element with several modifier keys pressed

browser.element(name: "new_user_button").click(:shift, :control)

@param [:shift, :alt, :control, :command, :meta] Modifier key(s) to press while clicking.

# File lib/watir-webdriver/elements/element.rb, line 113
def click(*modifiers)
  assert_exists
  assert_enabled

  element_call do
    if modifiers.any?
      assert_has_input_devices_for "click(#{modifiers.join ', '})"

      action = driver.action
      modifiers.each { |mod| action.key_down mod }
      action.click @element
      modifiers.each { |mod| action.key_up mod }

      action.perform
    else
      @element.click
    end
  end

  browser.after_hooks.run
end
double_click() click to toggle source

Double clicks the element. Note that browser support may vary.

@example

browser.element(name: "new_user_button").double_click
# File lib/watir-webdriver/elements/element.rb, line 143
def double_click
  assert_exists
  assert_has_input_devices_for :double_click

  element_call { driver.action.double_click(@element).perform }
  browser.after_hooks.run
end
drag_and_drop_by(right_by, down_by) click to toggle source

Drag and drop this element by the given offsets. Note that browser support may vary.

@example

browser.div(id: "draggable").drag_and_drop_by 100, -200

@param [Fixnum] right_by @param [Fixnum] down_by

# File lib/watir-webdriver/elements/element.rb, line 215
def drag_and_drop_by(right_by, down_by)
  assert_exists
  assert_has_input_devices_for :drag_and_drop_by

  element_call do
    driver.action.
           drag_and_drop_by(@element, right_by, down_by).
           perform
  end
end
drag_and_drop_on(other) click to toggle source

Drag and drop this element on to another element instance. Note that browser support may vary.

@example

a = browser.div(id: "draggable")
b = browser.div(id: "droppable")
a.drag_and_drop_on b
# File lib/watir-webdriver/elements/element.rb, line 192
def drag_and_drop_on(other)
  assert_is_element other
  assert_exists
  assert_has_input_devices_for :drag_and_drop_on

  element_call do
    driver.action.
           drag_and_drop(@element, other.wd).
           perform
  end
end
driver() click to toggle source

@api private

# File lib/watir-webdriver/elements/element.rb, line 382
def driver
  @parent.driver
end
enabled?() click to toggle source

Returns true if this element is present and enabled on the page.

@return [Boolean]

# File lib/watir-webdriver/elements/element.rb, line 412
def enabled?
  assert_exists
  element_call { @element.enabled? }
end
eql?(other)
Alias for: ==
exist?()
Alias for: exists?
exists?() click to toggle source

Returns true if element exists.

@return [Boolean]

# File lib/watir-webdriver/elements/element.rb, line 41
def exists?
  assert_exists
  true
rescue UnknownObjectException, UnknownFrameException
  false
end
Also aliased as: exist?
fire_event(event_name) click to toggle source

Simulates JavaScript events on element. Note that you may omit “on” from event name.

@example

browser.button(name: "new_user_button").fire_event :click
browser.button(name: "new_user_button").fire_event "mousemove"
browser.button(name: "new_user_button").fire_event "onmouseover"

@param [String, Symbol] event_name

# File lib/watir-webdriver/elements/element.rb, line 357
def fire_event(event_name)
  assert_exists
  event_name = event_name.to_s.sub(/^on/, '').downcase

  element_call { execute_atom :fireEvent, @element, event_name }
end
flash() click to toggle source

Flashes (change background color far a moment) element.

@example

browser.text_field(name: "new_user_first_name").flash
# File lib/watir-webdriver/elements/element.rb, line 233
def flash
  background_color = style("backgroundColor")
  element_color = driver.execute_script("arguments[0].style.backgroundColor", @element)

  10.times do |n|
    color = (n % 2 == 0) ? "red" : background_color
    driver.execute_script("arguments[0].style.backgroundColor = '#{color}'", @element)
  end

  driver.execute_script("arguments[0].style.backgroundColor = arguments[1]", @element, element_color)

  self
end
focus() click to toggle source

Focuses element. Note that Firefox queues focus events until the window actually has focus.

@see code.google.com/p/selenium/issues/detail?id=157

# File lib/watir-webdriver/elements/element.rb, line 329
def focus
  assert_exists
  element_call { driver.execute_script "return arguments[0].focus()", @element }
end
focused?() click to toggle source

Returns true if this element is focused.

@return [Boolean]

# File lib/watir-webdriver/elements/element.rb, line 340
def focused?
  assert_exists
  element_call { @element == driver.switch_to.active_element }
end
hash() click to toggle source
Calls superclass method
# File lib/watir-webdriver/elements/element.rb, line 70
def hash
  @element ? @element.hash : super
end
hover() click to toggle source

Moves the mouse to the middle of this element. Note that browser support may vary.

@example

browser.element(name: "new_user_button").hover
# File lib/watir-webdriver/elements/element.rb, line 175
def hover
  assert_exists
  assert_has_input_devices_for :hover

  element_call { driver.action.move_to(@element).perform }
end
html()
Alias for: outer_html
inner_html() click to toggle source

Returns inner HTML code of element.

@example

browser.div(id: 'foo').inner_html
#=> "<a href=\"#\">hello</a>"

@return [String]

# File lib/watir-webdriver/elements/element.rb, line 302
def inner_html
  assert_exists
  element_call { execute_atom(:getInnerHtml, @element) }.strip
end
inspect() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 49
def inspect
  if @selector.key?(:element)
    '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, '{element: (webdriver element)}']
  else
    '#<%s:0x%x located=%s selector=%s>' % [self.class, hash*2, !!@element, selector_string]
  end
end
outer_html() click to toggle source

Returns outer (inner + element itself) HTML code of element.

@example

browser.div(id: 'foo').outer_html
#=> "<div id=\"foo\"><a href=\"#\">hello</a></div>"

@return [String]

# File lib/watir-webdriver/elements/element.rb, line 285
def outer_html
  assert_exists
  element_call { execute_atom(:getOuterHtml, @element) }.strip
end
Also aliased as: html
parent() click to toggle source

Returns parent element of current element.

# File lib/watir-webdriver/elements/element.rb, line 368
def parent
  assert_exists

  e = element_call { execute_atom :getParentElement, @element }

  if e.kind_of?(Selenium::WebDriver::Element)
    Watir.element_class_for(e.tag_name.downcase).new(@parent, element: e)
  end
end
present?() click to toggle source

Returns true if the element exists and is visible on the page.

@return [Boolean] @see Watir::Wait

# File lib/watir-webdriver/elements/element.rb, line 424
def present?
  exists? && visible?
rescue Selenium::WebDriver::Error::StaleElementReferenceError, UnknownObjectException
  # if the element disappears between the exists? and visible? calls,
  # consider it not present.
  false
end
right_click() click to toggle source

Right clicks the element. Note that browser support may vary.

@example

browser.element(name: "new_user_button").right_click
# File lib/watir-webdriver/elements/element.rb, line 159
def right_click
  assert_exists
  assert_has_input_devices_for :right_click

  element_call { driver.action.context_click(@element).perform }
  browser.after_hooks.run
end
select_text(str) click to toggle source
# File lib/watir-webdriver/extensions/select_text.rb, line 5
def select_text(str)
  assert_exists
  execute_atom :selectText, @element, str
end
send_keys(*args) click to toggle source

Sends sequence of keystrokes to element.

@example

browser.text_field(name: "new_user_first_name").send_keys "Watir", :return

@param [String, Symbol] *args

# File lib/watir-webdriver/elements/element.rb, line 316
def send_keys(*args)
  assert_exists
  assert_writable
  element_call { @element.send_keys(*args) }
end
style(property = nil) click to toggle source

Returns given style property of this element.

@example

browser.button(value: "Delete").style           #=> "border: 4px solid red;"
browser.button(value: "Delete").style("border") #=> "4px solid rgb(255, 0, 0)"

@param [String] property @return [String]

# File lib/watir-webdriver/elements/element.rb, line 443
def style(property = nil)
  if property
    assert_exists
    element_call { @element.style property }
  else
    attribute_value("style").to_s.strip
  end
end
tag_name() click to toggle source

Returns tag name of the element.

@return [String]

# File lib/watir-webdriver/elements/element.rb, line 91
def tag_name
  assert_exists
  element_call { @element.tag_name.downcase }
end
text() click to toggle source

Returns the text of the element.

@return [String]

# File lib/watir-webdriver/elements/element.rb, line 80
def text
  assert_exists
  element_call { @element.text }
end
to_subtype() click to toggle source

Cast this Element instance to a more specific subtype.

@example

browser.element(xpath: "//input[@type='submit']").to_subtype
#=> #<Watir::Button>
# File lib/watir-webdriver/elements/element.rb, line 460
def to_subtype
  elem = wd()
  tag_name = elem.tag_name.downcase

  klass = nil

  if tag_name == "input"
    klass = case elem.attribute(:type)
      when *Button::VALID_TYPES
        Button
      when 'checkbox'
        CheckBox
      when 'radio'
        Radio
      when 'file'
        FileField
      else
        TextField
      end
  else
    klass = Watir.element_class_for(tag_name)
  end

  klass.new(@parent, element: elem)
end
value() click to toggle source

Returns value of the element.

@return [String]

# File lib/watir-webdriver/elements/element.rb, line 253
def value
  attribute_value('value') || ''
rescue Selenium::WebDriver::Error::InvalidElementStateError
  ''
end
visible?() click to toggle source

Returns true if this element is visible on the page.

@return [Boolean]

# File lib/watir-webdriver/elements/element.rb, line 401
def visible?
  assert_exists
  element_call { @element.displayed? }
end
wd() click to toggle source

@api private

# File lib/watir-webdriver/elements/element.rb, line 390
def wd
  assert_exists
  @element
end

Protected Instance Methods

assert_element_found() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 534
def assert_element_found
  unless @element
    raise UnknownObjectException, "unable to locate element, using #{selector_string}"
  end
end
assert_exists() click to toggle source

Ensure that the element exists, making sure that it is not stale and located if necessary

# File lib/watir-webdriver/elements/element.rb, line 499
def assert_exists
  @element ||= @selector[:element]

  if @element
    ensure_not_stale # ensure not stale
  else
    @element = locate
  end

  assert_element_found
end
ensure_not_stale() click to toggle source

Ensure that the element isn't stale, by relocating if it is (unless always_locate = false)

# File lib/watir-webdriver/elements/element.rb, line 512
def ensure_not_stale
  # Performance shortcut; only need recursive call to ensure context if stale in current context
  return unless stale?

  ensure_context
  if stale?
    if Watir.always_locate? && !@selector[:element]
      @element = locate
    else
      reset!
    end
  end
  assert_element_found
end
locate() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 544
def locate
  ensure_context

  element_validator = element_validator_class.new
  selector_builder = selector_builder_class.new(@parent, @selector, self.class.attribute_list)
  locator = locator_class.new(@parent, @selector, selector_builder, element_validator)

  locator.locate
end
reset!() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 540
def reset!
  @element = nil
end
stale?() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 527
def stale?
  @element.enabled? # any wire call will check for staleness
  false
rescue Selenium::WebDriver::Error::ObsoleteElementError
  true
end

Private Instance Methods

assert_enabled() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 594
def assert_enabled
  unless element_call { @element.enabled? }
    raise ObjectDisabledException, "object is disabled #{selector_string}"
  end
end
assert_has_input_devices_for(name) click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 608
def assert_has_input_devices_for(name)
  unless driver.kind_of? Selenium::WebDriver::DriverExtensions::HasInputDevices
    raise NotImplementedError, "#{self.class}##{name} is not supported by this driver"
  end
end
assert_is_element(obj) click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 614
def assert_is_element(obj)
  unless obj.kind_of? Watir::Element
    raise TypeError, "execpted Watir::Element, got #{obj.inspect}:#{obj.class}"
  end
end
assert_writable() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 600
def assert_writable
  assert_enabled

  if respond_to?(:readonly?) && readonly?
    raise ObjectReadOnlyException, "object is read only #{selector_string}"
  end
end
attribute?(attribute) click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 587
def attribute?(attribute)
  assert_exists
  element_call do
    !!execute_atom(:getAttribute, @element, attribute.to_s.downcase)
  end
end
element_call() { || ... } click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 620
def element_call
  yield
rescue Selenium::WebDriver::Error::StaleElementReferenceError
  if Watir.always_locate? && !@selector[:element]
    @element = locate
  else
    reset!
  end
  assert_element_found
  retry
end
element_class_name() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 574
def element_class_name
  self.class.name.split('::').last
end
element_validator_class() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 562
def element_validator_class
  Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::Validator")
rescue NameError
  Kernel.const_get("#{Watir.locator_namespace}::Element::Validator")
end
ensure_context() click to toggle source

Ensure the driver is in the desired browser context

# File lib/watir-webdriver/elements/element.rb, line 583
def ensure_context
  @parent.is_a?(IFrame) ? @parent.switch_to! : @parent.assert_exists
end
locator_class() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 556
def locator_class
  Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::Locator")
rescue NameError
  Kernel.const_get("#{Watir.locator_namespace}::Element::Locator")
end
method_missing(meth, *args, &blk) click to toggle source
Calls superclass method
# File lib/watir-webdriver/elements/element.rb, line 632
def method_missing(meth, *args, &blk)
  method = meth.to_s
  if method =~ Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE
    attribute_value(method.tr('_', '-'), *args)
  else
    super
  end
end
respond_to_missing?(meth, *) click to toggle source
Calls superclass method
# File lib/watir-webdriver/elements/element.rb, line 641
def respond_to_missing?(meth, *)
  Locators::Element::SelectorBuilder::WILDCARD_ATTRIBUTE === meth.to_s || super
end
selector_builder_class() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 568
def selector_builder_class
  Kernel.const_get("#{Watir.locator_namespace}::#{element_class_name}::SelectorBuilder")
rescue NameError
  Kernel.const_get("#{Watir.locator_namespace}::Element::SelectorBuilder")
end
selector_string() click to toggle source
# File lib/watir-webdriver/elements/element.rb, line 578
def selector_string
  @selector.inspect
end