Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten.Erfahre mehr über dieses Experiment.
Dokument: caretPositionFromPoint() Methode
Baseline 2025 *Newly available
Since December 2025, this feature works across the latest devices and browser versions. This feature might not work in older devices or browsers.
* Some parts of this feature may have varying levels of support.
DiecaretPositionFromPoint()-Methode desDocument-Interfaces gibt einCaretPosition-Objekt zurück, das den DOM-Knoten zusammen mit dem Cursor und dem Zeichenoffset des Cursors innerhalb dieses Knotens enthält.
In diesem Artikel
Syntax
caretPositionFromPoint(x, y)caretPositionFromPoint(x, y, options)Parameter
xDie horizontale Koordinate eines Punkts.
yDie vertikale Koordinate eines Punkts.
optionsOptionalDie folgenden optionalen Eigenschaften können ebenfalls angegeben werden.
shadowRootsOptionalEin Array von
ShadowRoot-Objekten.Die Methode kann eine Cursorposition für einen Knoten zurückgeben, der innerhalb des Shadow DOMs einer bereitgestellten Shadow-Root definiert ist.Wenn die Cursorposition in eine nicht bereitgestellte Shadow-Root fällt, wird die zurückgegebeneCaretPositionauf den Knoten abgebildet, der der Host der Shadow-Root ist.
Rückgabewert
EinCaretPosition-Objekt odernull.
Der zurückgegebene Wert istnull, wenn kein Viewport mit dem Dokument verknüpft ist, wennx odery negativ oder außerhalb des Viewport-Bereichs liegen oder wenn die Koordinaten einen Punkt anzeigen, an dem kein Textinsertion-Punkt-Indikator eingefügt werden konnte.
Beispiele
>Textknoten an der Cursorposition im DOM aufteilen
Dieses Beispiel demonstriert, wie man die Cursorposition von einem ausgewählten DOM-Knoten erhält, die Position verwendet, um den Knoten zu teilen, und einen Zeilenumbruch zwischen den beiden Knoten einfügt.Das Beispiel nutztcaretPositionFromPoint(), um die Cursorposition zu erhalten, sofern unterstützt, mit der nicht standardmäßigenDocument.caretRangeFromPoint()-Methode als Fallback.
Beachten Sie, dass einige Teile des Codes ausgeblendet sind, einschließlich des Codes, der zum Protokollieren verwendet wird, da dies nicht zum Verständnis dieser Methode beiträgt.
HTML
Das HTML definiert einen Textabsatz.
<div> This browser supports neither document.caretRangeFromPoint nor document.caretPositionFromPoint</div><button type="button">Reset</button><p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet.</p><pre>Log</pre>#log { height: 30px; padding: 0.5rem; border: 1px solid black;}const logElement = document.querySelector("#log");function log(text) { logElement.innerText = text;}const reload = document.querySelector("#reset");reload.addEventListener("click", () => { window.location.reload(true);});#message { color: red; font-weight: bold;}#message.fallback { color: darkorange;}#message.supported { color: green;}JavaScript
Die Methode unten überprüft zuerst die Unterstützung vondocument.caretPositionFromPoint und verwendet sie, um den Textknoten und den Offset an der Cursorposition zu erhalten.Wenn der Browser diese Methode nicht unterstützt, prüft der Code als nächstesdocument.caretRangeFromPoint und verwendet diese stattdessen.
Wenn der Knoten an der Cursorposition ein Textknoten ist, teilt der Code den Knoten an dem ausgewählten Offset und fügt einen Zeilenumbruch zwischen den beiden Knoten ein.
function insertBreakAtPoint(e) { let range; let textNode; let offset; if (document.caretPositionFromPoint) { range = document.caretPositionFromPoint(e.clientX, e.clientY); textNode = range.offsetNode; offset = range.offset; } else if (document.caretRangeFromPoint) { // Use WebKit-proprietary fallback method range = document.caretRangeFromPoint(e.clientX, e.clientY); textNode = range.startContainer; offset = range.startOffset; } else { // Neither method is supported, do nothing return; } // Logging code (uses hidden method to get substring with ^ at offset) if (textNode?.nodeType === 3) { const caretInText = getSubstringAroundOffset(textNode.textContent, offset); log( `node: ${textNode.nodeName}, offset: ${offset}, insert: ${caretInText}`, ); } // Only split TEXT_NODEs if (textNode?.nodeType === 3) { let replacement = textNode.splitText(offset); let br = document.createElement("br"); textNode.parentNode.insertBefore(br, replacement); }}Die Methode wird dann als Klickereignis-Handler für beliebige Absatzelemente hinzugefügt.
const paragraphs = document.getElementsByTagName("p");for (const paragraph of paragraphs) { paragraph.addEventListener("click", insertBreakAtPoint);}// Inserts ^ at offset and gets a substring for logfunction getSubstringAroundOffset(text, offset, length = 10) { const start = Math.max(0, offset - length); const end = Math.min(text.length, offset + length + 1); // Insert the caret character at the offset const modifiedText = `${text.substring(0, offset)}^${text.substring(offset)}`; return `...${modifiedText.substring(start, end)}...`;}let message = document.getElementById("message");if (document.caretPositionFromPoint) { message.textContent = "This browser supports the standard document.caretPositionFromPoint"; message.classList.add("supported");} else if (document.caretRangeFromPoint) { message.textContent = "This browser supports the non-standard document.caretRangeFromPoint"; message.classList.add("supported");}Ergebnisse
Klicken Sie irgendwo imLorem ipsum ...-Absatz unten, um einen Zeilenumbruch an der Stelle einzufügen, an der Sie klicken.Beachten Sie, dass das Protokoll dennodeName, den Offset und ein Fragment des ausgewählten Knotens mit einem^-Zeichen am Offset anzeigt.
Textknoten an Cursorpositionen in einem Shadow DOM aufteilen
Dieses Beispiel zeigt, wie man die Cursorposition von einem ausgewählten Knoten innerhalb einer Shadow-Root erhält.Das Beispiel ist dem ausschließlich DOM-basierten Beispiel oben sehr ähnlich, außer dass ein Teil des Textes innerhalb einer Shadow-Root liegt.Wir stellen einen Button zur Verfügung, um Ihnen den Unterschied zu zeigen, wenn eine Shadow-Root zucaretPositionFromPoint() übergeben wird oder nicht.
Beachten Sie, dass einige Teile des Codes ausgeblendet sind, einschließlich des Codes, der zum Protokollieren verwendet wird, da dies nicht zum Verständnis dieser Methode beiträgt.
HTML
Das HTML definiert einen Textabsatz innerhalb eines<div>-Elements.Der Absatz enthält ein<span>-Element mit derid "host", das wir als Host für eine Shadow-Root verwenden werden.Es gibt auch einige Buttons, die wir verwenden werden, um das Beispiel zurückzusetzen und das Shadow-Root-Option-Argument zucaretPositionFromPoint() hinzuzufügen/entfernen.
<div> This browser supports neither document.caretRangeFromPoint nor document.caretPositionFromPoint</div><button type="button">Reset</button><button type="button">Add Shadow</button><div> <p> Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut <span></span> labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. </p></div><pre>Log</pre>CSS
Hier verwenden wir CSS, um das#host-Element rot und fett zu machen.Dies erleichtert das Unterscheiden zwischen Text im DOM und Text im Shadow DOM.
#host { color: red; font-weight: bold;}#log { height: 30px; padding: 0.5rem; border: 1px solid black;}#message { color: red; font-weight: bold;}#message.fallback { color: darkorange;}#message.supported { color: green;}JavaScript
const logElement = document.querySelector("#log");function log(text) { logElement.innerText = text;}const reload = document.querySelector("#reset");reload.addEventListener("click", () => { window.location.reload(true);});Zuerst haben wir etwas Code, um unser Shadow DOM zu befüllen.Wir verwenden JavaScript, um eine Shadow-Root dynamisch anzuhängen, da das MDN-Beispielsystem uns dies nicht deklarativ mit dem<template>-Element tun lässt.Der Inhalt des Shadow DOM ist ein<span>-Element, das den Text "I'm in the shadow DOM" enthält.
const host = document.querySelector("#host");const shadow = host.attachShadow({ mode: "open" });const shadowSpan = document.createElement("span");shadowSpan.textContent = "I'm in the shadow DOM";shadow.appendChild(shadowSpan);Als nächstes fügen wir einen Handler für unseren "Enable/Disable shadow"-Button hinzu.Dieser Code schaltet den Wert deruseShadows-Variable um und aktualisiert den Button-Text entsprechend.
let useShadows = false;const shadowButton = document.querySelector("#shadowButton");shadowButton.addEventListener("click", () => { useShadows = !useShadows; shadowButton.innerText = useShadows ? "Remove Shadow" : "Add Shadow";});Die Methode unten überprüft zuerst die Unterstützung vondocument.caretPositionFromPoint und verwendet sie, um den Textknoten und den Offset an der Cursorposition zu erhalten.Der Wert deruseShadows-Variable wird verwendet, um zu bestimmen, ob die im Text gehostete Shadow-Root ancaretPositionFromPoint() übergeben wird.
- Wenn der Browser diese Methode nicht unterstützt, prüft der Code als nächstes
document.caretRangeFromPointund verwendet diese stattdessen. - Wenn der Knoten an der Cursorposition ein Textknoten ist, teilt der Code dann den Knoten an dem ausgewählten Offset und fügt einen Zeilenumbruch zwischen ihnen ein.
- Wenn der Knoten ein Elementknoten ist, fügt der Code einen Zeilenumbruch-Elementknoten an dem Offset ein.
function insertBreakAtPoint(e) { let range; let textNode; let offset; if (document.caretPositionFromPoint) { range = document.caretPositionFromPoint( e.clientX, e.clientY, useShadows ? { shadowRoots: [shadow] } : null, ); textNode = range.offsetNode; offset = range.offset; } else if (document.caretRangeFromPoint) { // Use WebKit-proprietary fallback method range = document.caretRangeFromPoint(e.clientX, e.clientY); textNode = range.startContainer; offset = range.startOffset; } else { // Neither method is supported, do nothing return; } // Logging code (uses hidden method to get substring with ^ at offset) if (textNode) { if (textNode.nodeType === 3) { const caretInText = getSubstringAroundOffset( textNode.textContent, offset, ); log( `type: TEXT_NODE, name: ${textNode.nodeName}, offset: ${offset}:${caretInText}`, ); } else if (textNode.nodeType === 1) { log(`type: ELEMENT_NODE, name: ${textNode.nodeName}, offset: ${offset}`); } else { log( `type: ${textNode.nodeType}, name: ${textNode.nodeName}, offset: ${offset}`, ); } } // Insert line at caret if (textNode?.nodeType === 3) { // TEXT_NODE - split text at offset and add br let replacement = textNode.splitText(offset); let br = document.createElement("br"); textNode.parentNode.insertBefore(br, replacement); } else if (textNode?.nodeType === 1) { // ELEMENT_NODE - Add br node at offset node let br = document.createElement("br"); const targetNode = textNode.childNodes[offset]; textNode.insertBefore(br, targetNode); } else { // Do nothing }}Zum Schluss fügen wir zwei Klickereignis-Handler für Absatzelemente im DOM und im Shadow-Root hinzu.Beachten Sie, dass wir die Elemente innerhalb desshadowRoot spezifisch abfragen müssen, da sie für normale DOM-Abfragemethoden nicht sichtbar sind.
// Click event handler <p> elements in the DOMconst paragraphs = document.getElementsByTagName("p");for (const paragraph of paragraphs) { paragraph.addEventListener("click", insertBreakAtPoint);}// Click event handler <p> elements in the Shadow DOMconst shadowParagraphs = host.shadowRoot.querySelectorAll("p");for (const paragraph of shadowParagraphs) { console.log(paragraph); paragraph.addEventListener("click", insertBreakAtPoint);}// Inserts ^ at offset and gets a substring for logfunction getSubstringAroundOffset(text, offset, length = 10) { const start = Math.max(0, offset - length); const end = Math.min(text.length, offset + length + 1); // Insert the caret character at the offset const modifiedText = `${text.substring(0, offset)}^${text.substring(offset)}`; return `...${modifiedText.substring(start, end)}...`;}let message = document.getElementById("message");if (document.caretPositionFromPoint) { message.textContent = "This browser supports the standard document.caretPositionFromPoint"; message.classList.add("supported");} else if (document.caretRangeFromPoint) { message.textContent = "This browser supports the non-standard document.caretRangeFromPoint"; message.classList.add("supported");}Ergebnisse
Klicken Sie imLorem ipsum ...-Absatz vor oder nach dem Shadow DOM-Text, um einen Zeilenumbruch an der Stelle einzufügen, an der Sie klicken.Beachten Sie, dass in diesem Fall das Protokoll zeigt, dass Sie einenTEXT_NODE, den Offset und ein Fragment des ausgewählten Knotens mit einem^-Zeichen am Offset ausgewählt haben.
Anfangs wird die Shadow-Root nicht ancaretPositionFromPoint() übergeben, daher ist der zurückgegebene Cursorposition-Knoten beim Klicken auf den Text "I'm in the shadow DOM" der übergeordnete Knoten des Hosts, mit dem Offset der Shadow-Root.Der Zeilenumbruch wird daher vor dem Knoten hinzugefügt und nicht an dem ausgewählten Punkt.Beachten Sie, dass der Cursorposition-Knoten in diesem Fall den TypELEMENT_NODE hat.
Wenn Sie den "Add shadow"-Button klicken, wird die Shadow-Root ancaretPositionFromPoint() übergeben, sodass die zurückgegebene Cursorposition der spezifische ausgewählte Knoten innerhalb des Shadow DOMs ist.Dadurch verhält sich der Shadow DOM-Text wie der andere Absatztext.
Spezifikationen
| Specification |
|---|
| CSSOM View Module> # dom-document-caretpositionfrompoint> |