Selecting "unfriendly" DOM elements

I consider a DOM element as “unfriendly” (hard to be selected), if it fills 5 terms:

  1. It doesn’t have any identifiers whatsoever (ID’s, Classes or unique attributes).

  2. Its Xpath is created dynamically in each server creation of a webpage.

  3. It’s one of many elements of the same tag (say, div), and the number of these is also dynamic, so a specific item reference like document.querySelector('div')[322], will be principally ineffective.

  4. It is a bit frustrating to target by the HTML alone given that the trail or track from a parent element with an ID is quite large (like 20-30 elements).

  5. Other elements share the same textContent of the element (though these will appear on viewport only if you’ll open accordions that contain them).

What’s left?

I understand that the only thing left in such rare case is to do such conditioning:

if textContent includes SOMETHING.
if item is available on viewport.

Out of curiosity. What else can be done to target that element, besides the condition set I just described?

Hey there! I guess you can’t change the original HTML? What kind of content is there?
It really depends on what you want to do. Depending on the situation, you can apply different tricks and tactics to select the desired element. Do you need a specific text you are looking for?

From what you explain, I could imagine the html looks a little like this:

<div>
    <div>same content</div>
    <div>same content</div>
    <div>same content</div>
    <div>same content</div>
    <div>same content</div>
</div>

What is the point of selecting a specific element, if they are all the same? Please let me know what you are trying to achieve, this might help a lot to help you :smiley:

Best,
Martin

HI @MartinMuzatko

This is the Xpath of the button I want to click

#js_n6 > div > ul > li:nth-child(4) > a > span > span

I would gladly use it for document.querySelector, the problem is that the #js_n6 ID is created dynamically in each bootstrapping:

Sometimes it #js-x1, #js_v9, #js z4, #js k1 and so forth.

Using a CSS wildcard for the ID seems to be ineffective because it closes the modal in which my button sits… It seems to target other, earlier elements with the similar ID’s found by the wildcard.

A direct example is Facebook.com’s conversations page. Go to the page with all conversations, run in console:

document.querySelector(‘._5blh._4-0h’).click();

And then inspect the “Delete” button to see what I mean too.

 
 
< off topic >
    
    If people would only learn how to code for themselves,
    rather than relying on third party frameworks to do it for
    them, then they would not experience all the extremely
    silly problems that they invariably do. :rofl:
 
 
< / off topic >

coothead

If it was towards me for some odd reason, you are mistaken - I code only with Vanilla (and I’m to learn Node.JS to work in server side).

Did you post this in the wrong thread?

I just read and re-read the conversation here and can’t see how it relates to anything posted.

2 Likes

Methinks he went off this statement…

I immediately thought of the Bootstrap framework myself, which is obviously not vanilla javascript

1 Like

By bootstrapping I meant — Each loading or refreshing of the page…

If you’re running vanilla JS, why are you shooting yourself in the foot by getting different results each time?

See my response to @MartinMuzatko, it’s not my site and I can’t control over the face the ID changes each fresh/refresh…

Ah, that explains a lot.

Unfortunately, if you are dealing with someone else’s DOM there often isn’t an “easy” way that I know of. In the past I’ve needed to write custom code (user scripts and browser extensions) to fix invalid markup, then write a literal mess of code to get the elements I was interested in. Then if the other site changed its DOM, it was back to the drawing board. Fun, not.

Hi there Pullo,

as @DaveMaxwell pointed out it was
bootstapping, that rang my bell. :biggrin:

coothead

Well fb is using React under the hood; there’s no static content served from the backend but a message to activate JS and a logout button. So given the complexity of the site, it’s basically impossible to tell where exactly a certain element will appear; and unique identifiers in the DOM are simply not required (other than for styling), as React handles the element references itself while constantly diffing and updating the DOM on each change of state.

For instance, when you have a dynamic list, then each item will have a unique key prop; but this key never even appears in the DOM. React just needs it to internally keep track of the list items, and decide which items to update at a given point.

Now modifying sites with user scripts and bookmarklets (are these still a thing?) sure can be fun, but I think targeting an SPA like fb is a bit like tilting at windmills. :-/ Just that you keep that in mind… it’s simply how this site works.

2 Likes

@m3g4p0p The element I try to select is always in the same place (always the third button in a menu) so I guess there is a little bit more hope in this case.

Hey Coothead.

Fair enough, but as the OP pointed out, bootstrapping is basically just a process where a simple set of instructions activates a more complicated system. You often talk about bootstrapping Angular apps, for example.

2 Likes

I solved the problem by combining selection of a parent element with a CSS ID wildcard, then using the rest of the Xpath. Here’s an example:

document.querySelector('.idElementParent > [id^="js"] > div > ul > li:nth-child(4)').someMethod();
3 Likes

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.