When a browser navigates to an URL like http://example.com/#foo
, it scrolls to the element identified by #foo
; this element of the URI is called a fragment identifier. Suppose I have a fragment identifier for an element on the current page, which I have not yet navigated to. How can I find out which DOM node would have been targeted by it?
- It’s not enough to use
document.getElementById
, because a fragment identifier#foo
can also target an old-style anchor,<a name="foo">
, which this method misses. - It’s not correct to use
document.getElementsByName
either, because that would find non-anchors like<input>
or<textarea>
nodes, and miss elements identified by theid=
attribute. - Since I have not navigated at the fragment, I cannot use
document.querySelector(':target')
either.
Is there a reliable way to find which DOM node would have been targeted by fragment identifier that catches all cases? If the solution uses querySelector
, I would of course like it to be robust against unusual characters found within identifiers, however deprecated they may be.
CodePudding user response:
A selector is the easiest way to say "An element with an ID or an a
element with a name".
CSS.escape
will handle special characters for you.
const fragment_id = `fdfd""fewf"`; // The test string I used for this
const escaped_fragment_id = CSS.escape(fragment_id);
const element = document.querySelector(`#${escaped_fragment_id}, a[name="${escaped_fragment_id}"`)
Note that you might also need to use decodeURIComponent
if the source of fragment_id
has been escaped.