DomUtils =
  #
  # Runs :callback if the DOM has loaded, otherwise runs it on load
  #
  documentReady: (func) ->
    if document.readyState == "loading"
      window.addEventListener "DOMContentLoaded", func
    else
      func()
  #
  # Adds a list of elements to a page.
  # Note that adding these nodes all at once (via the parent div) is significantly faster than one-by-one.
  #
  addElementList: (els, overlayOptions) ->
    parent = document.createElement("div")
    parent.id = overlayOptions.id if overlayOptions.id?
    parent.className = overlayOptions.className if overlayOptions.className?
    parent.appendChild(el) for el in els
    document.documentElement.appendChild(parent)
    parent
  #
  # Remove an element from its DOM tree.
  #
  removeElement: (el) -> el.parentNode.removeChild el
  #
  # Test whether the current frame is the top/main frame.
  #
  isTopFrame: ->
    window.top == window.self
  #
  # Takes an array of XPath selectors, adds the necessary namespaces (currently only XHTML), and applies them
  # to the document root. The namespaceResolver in evaluateXPath should be kept in sync with the namespaces
  # here.
  #
  makeXPath: (elementArray) ->
    xpath = []
    for element in elementArray
      xpath.push(".//" + element, ".//xhtml:" + element)
    xpath.join(" | ")
  # Evaluates an XPath on the whole document, or on the contents of the fullscreen element if an element is
  # fullscreen.
  evaluateXPath: (xpath, resultType) ->
    contextNode =
      if document.webkitIsFullScreen then document.webkitFullscreenElement else document.documentElement
    namespaceResolver = (namespace) ->
      if (namespace == "xhtml") then "http://www.w3.org/1999/xhtml" else null
    document.evaluate(xpath, contextNode, namespaceResolver, resultType, null)
  #
  # Returns the first visible clientRect of an element if it exists. Otherwise it returns null.
  #
  # WARNING: If testChildren = true then the rects of visible (eg. floated) children may be returned instead.
  # This is used for LinkHints and focusInput, **BUT IS UNSUITABLE FOR MOST OTHER PURPOSES**.
  #
  getVisibleClientRect: (element, testChildren = false) ->
    # Note: this call will be expensive if we modify the DOM in between calls.
    clientRects = (Rect.copy clientRect for clientRect in element.getClientRects())
    for clientRect in clientRects
      # If the link has zero dimensions, it may be wrapping visible but floated elements. Check for this.
      if (clientRect.width == 0 or clientRect.height == 0) and testChildren
        for child in element.children
          computedStyle = window.getComputedStyle(child, null)
          # Ignore child elements which are not floated and not absolutely positioned for parent elements with
          # zero width/height
          # NOTE(mrmr1993): This ignores floated/absolutely positioned descendants nested within inline
          # children.
          continue if (computedStyle.getPropertyValue('float') == 'none' &&
            computedStyle.getPropertyValue('position') != 'absolute')
          childClientRect = @getVisibleClientRect child, true
          continue if childClientRect == null or childClientRect.width < 3 or childClientRect.height < 3
          return childClientRect
      else
        clientRect = @cropRectToVisible clientRect
        continue if clientRect == null or clientRect.width < 3 or clientRect.height < 3
        # eliminate invisible elements (see test_harnesses/visibility_test.html)
        computedStyle = window.getComputedStyle(element, null)
        continue if computedStyle.getPropertyValue('visibility') != 'visible'
        return clientRect
    null
  #
  # Bounds the rect by the current viewport dimensions. If the rect is offscreen or has a height or width < 3
  # then null is returned instead of a rect.
  #
  cropRectToVisible: (rect) ->
    boundedRect = Rect.create(
      Math.max(rect.left, 0)
      Math.max(rect.top, 0)
      rect.right
      rect.bottom
    )
    if boundedRect.top >= window.innerHeight - 4 or boundedRect.left >= window.innerWidth - 4
      null
    else
      boundedRect
  #
  # Get the client rects for the  elements in a