   # @param selector the Protractor CSS locator argument
   # @returns a promise resolving to the Table array
   findTables: (selectors...) ->
-    @findAll_(selectors...).then (tables) ->
+    @_findAll(selectors...).then (tables) ->
       # Add the Table prototype to each WebElement in the result.
       tables.map(addTableMixin)
+
+  # @param selector the search condition
+  # @returns the By locator object
+  _locatorFor: (selector) ->
+    # If the selector is a string, then make a By locator.
+    # Otherwise, the selector is assumed to already be a
+    # By locator.
+    if _.isString(selector)
+      # An xpath selector string has a slash or equals.
+      # An id selector starts with # and doesn't have a space.
+      # Anything else is assumed to be CSS.
+      if selector == '..' or '/' in selector
+        By.xpath(selector)
+      else if selector[0] == '#' and not ' ' in selector
+        By.id(selector[1..-1])
+      else if selector.match(/^\w[\w-]*$/)
+        By.tagName(selector)
+      else
+        By.css(selector)
+    else if selector?
+      # Pass through a non-string selector.
+      selector
+    else
+      throw new Error("The selector is not defined")
+
 
 #
 # Note - it would be preferable to define the following Table

  # * If the string contains a '/' or equals '..', then the
  #   string is assumed to be an xpath.
  #
  # * Otherwise, if the string starts with '#' the search
  #   is on the id following the hash.
  #
  # * Otherwise, the search argument is assumed to be CSS.
  #
  # For example,
  #

  # prototype/property funhouse have not resolved this anomaly.
  
  # @returns a promise which resolves to the [[cell, ...], ...]
  #   row x column Finder array
  body: ->
    # Chain the finder to preferably look for rows in a tbody tag,
    # otherwise look in the table itself.
    @find(By.tagName('tbody'))
      .then (body) ->
        # The parent element is the table child tbody, if it exists,
        # otherwise the table itself.
        if body? then body else this
      .then (parent) ->
        # Find the rows...
        parent.findAll(By.tagName('tr'))
      .then (rows) ->
        rows.map (row) ->
          # ...then find the cells...
          row.findAll(By.tagName('td'))
      .then (rows) ->
        webdriver.promise.all(rows)

  # @returns a promise which resolves to a header text array
  header: ->
    @findAll(By.tagName('th'))
      .then (headings) ->
        headings.map (heading) ->
          heading.text()
      .then (headings) ->
        webdriver.promise.all(headings)


#
# Findable utility functions.
#

# The following mix-ins return a new mix-in instance which
# delegates to the mixin argument, e.g.:
#   extended = addFindableMixin(result)
#   expect(extended).to.be.an.instanceOf(Findable)
#   expect(_.functionsIn(extended).to.include.members(_.functionsIn(result))
#

# @param mixin the mix-in class
# @param obj the source object
# @return an empty new mixin object which delegates to
#   the given object
addMixin = (mixin, obj) ->
  _.extend(new mixin(), obj)

  # Adds Findable methods to the given WebElement.
addFindableMixin = _.partial(addMixin, Findable)

# Adds Findable methods to the given WebElement.
addTableMixin = _.partial(addMixin, Table)

module.exports = Findable
