| Finding An Element By ID When Multiple Exist |

Issue

HTML fragment generations incorrectly result in duplicate IDs on the page. This makes using a conventional ID selector problematic.
fragment_art
The best way to solve this problem is not to have it. What I mean by that is changing HTML fragment generation logic – whether it be JSPs to AngularJS – is the optimal solution, rather than working around it. Element IDs are supposed to be unique across the entire page for it to be considered valid HTML. However, it’s not always possible to do the proper solution for a variety of reasons, so this can provide a stopgap.

Assumptions / Prerequisites

  • The duplicate IDs exist in a known structure (HTML fragment)
  • JQuery is either currently used or can be used

Examples

Rather than writing to the console, to denote what got selected, I chose to write to the “output” divs contained within the document. The results are under the “*** Output ***” text section.

Solution

JQuery’s robust selectors! These examples provide just a few, of many, ways to work around this problem. The first method, in example #1, is the descendant selector.

//syntax
$("ancestor desiredElement")


This is an effective way when you have a known ancestor. We drill down through the ancestor to find the desired element ID. As example #2 demonstrates – the level of nesting does not matter.


Another method, in example #2, is using the next sibling selector.

//syntax
$("startAtSibling ~ desiredElement")


This is a useful way when you have a known sibling. In this instance, we have a known class on a sibling that will differ in each section (fragment). Note, it does not have to be a class, it could be a sibling’s ID.


The final method, in example #2, uses a combination of selectors – the contains selector, the first selector, and the next sibling selector. The result is being able to find the desired ID with a known piece of text near it.

//syntax
$("elementType:contains('Some Text'):first ~ desiredElement)


This last example is the most elaborate of them all. It uses a combination of selectors. The “contains” selector returns multiple elements matching the criteria, but for our purposes we only want one. So we use the “first” selector which returns the first instance. Even if there is only one to be returned, we still need to use it, so the sibling operator can work on one element and not an array.

Conclusion

While it’s best to not even have this issue (and need to work around it) – JQuery’s selectors provide what is needed to accomplish the task.