Posted about 5 years ago. Visible to the public.

Find the innermost DOM element that contains a given string

Let's say you want to find the element with the text hello in the following DOM tree:

Copy
<html> <body> <article> <strong>hello</strong> <strong>world</strong> </article> </body> </html>

You might think of using jQuery's :contains selector:

Copy
$(":contains('hello')")

Unfortunately that returns a lot more elements than you expect:

Copy
[ <html>...<html>, <body>...</body>, <article>...</article>, <strong>hello</strong> ]

The reason for this is that all of these elements contain the word hello!

What you need to do instead is to find all elements containing "hello" which don't have a descendant containing "hello":

Copy
$(":contains('hello'):not(:has(:contains('hello')))")

Note that :contains and :has are non-standard selectors that are available in jQuery's selector engine only. You can't use them in other libraries that match CSS selectors, such as Nokogiri or Capybara.

You can do the same with an XPath expression, though. So e.g. in Capybara:

Copy
page.find(:xpath, ".//*[contains(text(), 'hello') and not (./*[contains(text(), 'hello'])]")

By refactoring problematic code and creating automated tests, makandra can vastly improve the maintainability of your Rails application.

Owner of this card:

Avatar
Henning Koch
Last edit:
almost 5 years ago
by Martin Straub
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses short-lived cookies to improve usability.
Accept or learn more