Reputation: 469
My question is about this function: https://developer.mozilla.org/en-US/docs/Web/API/Selection/containsNode and I have created this sandbox: https://codesandbox.io/s/amazing-bartik-smjt2?file=/src/index.js
code:
document.getElementById("app").innerHTML = `
<h1>Hello Vanilla!</h1>
<div>
We use the same configuration.<s> <span id="_span"><img src="http://www.mandysam.com/img/random.jpg" id="_img" alt="🙂" aria-label="🙂" width="40"></span> as Parcel to bundle this </s> sandbox, you can find more
info about Parcel.
<h2 id="y" hidden=true>span selected</h2>
<h2 id="z" hidden=true>img selected</h2>
</div>
`;
document.addEventListener("selectionchange", () => {
const selection = window.getSelection();
let span = document.querySelector("#_span");
const foundSpan = selection.containsNode(span);
let img = document.querySelector("#_img");
const foundImg = selection.containsNode(img);
let y = document.querySelector("#y");
y.toggleAttribute("hidden", !foundSpan);
let z = document.querySelector("#z");
z.toggleAttribute("hidden", !foundImg);
});
I do not understand why I should select at least a character before and after the image so the containsNode
returns true
on the span
element. Is this the expected behavior; the span element supposed to be selected whenever the img
is selected, right?
Upvotes: 2
Views: 324
Reputation: 16354
This is the expected behavior.
From the specification for the Selection API:
containsNode()
methodThe method must return
false
if the context object is empty or if node's root is not the document associated with the context object.Otherwise, if
allowPartialContainment
isfalse
, the method must returntrue
if and only if start of its range is before or visually equivalent to the first boundary point in the node and end of its range is after or visually equivalent to the last boundary point in the node.If allowPartialContainment is
true
, the method must returntrue
if and only if start of its range is before or visually equivalent to the first boundary point in the node or end of its range is after or visually equivalent to the last boundary point in the node.
The interface for containsNode()
is defined as:
boolean containsNode(Node node, optional boolean allowPartialContainment = false);
You have to provide true
for the allowPartialContainment
argument if you also want to have nodes that are only partially contained considered part of the selection:
const foundSpan = selection.containsNode(span, true);
document.addEventListener("selectionchange", () => {
const selection = window.getSelection();
let span = document.querySelector("#_span");
const isFullyContained = selection.containsNode(span);
const isPartiallyContained = selection.containsNode(span, true);
let y = document.querySelector("#y");
y.toggleAttribute("hidden", !isPartiallyContained || isFullyContained);
let z = document.querySelector("#z");
z.toggleAttribute("hidden", !isFullyContained);
});
<h1>Select the text with the image</h1>
<div>
We use the same configuration.
<span id="_span"><img src="http://www.mandysam.com/img/random.jpg" width="40"></span>
as Parcel to bundle this sandbox, you can find more info about Parcel.
<h2 id="y" hidden=true>span partially contained</h2>
<h2 id="z" hidden=true>span fully contained</h2>
</div>
It works with the image because img
is is a void element (has no content) and therefore can't be only partially contained in a selection.
Upvotes: 4