Signatur
Beschreibung
Ein Highlight-Objekt aus der CSS Custom Highlight API verhält sich wie ein Set: Es speichert eine Menge von Bereichen (Range oder StaticRange), die sich über das Pseudoelement ::highlight(name) gestalten lassen, ohne dass der DOM verändert wird. Die Methode values() liefert einen Iterator über genau diese Bereiche in der Reihenfolge, in der sie hinzugefügt wurden.
Sinnvoll ist values(), wenn Sie vorhandene Markierungen auswerten wollen – zum Beispiel den markierten Text auslesen, Treffer einer Suche zählen oder einzelne Bereiche gezielt wieder entfernen. Weil Highlight set-artig ist, ist values() identisch mit keys() und mit Highlight.prototype[Symbol.iterator]. Deshalb funktionieren for...of und die Spread-Syntax auch direkt auf dem Highlight-Objekt.
Der zurückgegebene Iterator ist live: Bereiche, die während des Durchlaufs hinzugefügt werden, tauchen noch auf, wenn der Iterator sie noch nicht erreicht hat. Wer das Highlight während der Schleife verändert, sollte deshalb vorher mit [...highlight.values()] einen Schnappschuss erzeugen.
Rückgabewert
AbstractRange-Objekt (Range oder StaticRange) in Einfügereihenfolge liefert.Beispiele
Highlight anlegen und Bereiche durchlaufen
// HTML: <p id="text">Hallo Welt, hallo JavaScript</p>
const textNode = document.getElementById('text').firstChild;
const r1 = new Range();
r1.setStart(textNode, 0);
r1.setEnd(textNode, 5);
const r2 = new Range();
r2.setStart(textNode, 12);
r2.setEnd(textNode, 17);
const highlight = new Highlight(r1, r2);
CSS.highlights.set('treffer', highlight);
for (const range of highlight.values()) {
console.log(range.toString());
}
Suchtreffer markieren und zählen
// CSS: ::highlight(suche) { background: yellow; }
const markiereSuche = (root, begriff) => {
const highlight = new Highlight();
const walker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT);
const suche = begriff.toLowerCase();
while (walker.nextNode()) {
const node = walker.currentNode;
const text = node.textContent.toLowerCase();
let pos = text.indexOf(suche);
while (pos !== -1) {
const range = new StaticRange({
startContainer: node, startOffset: pos,
endContainer: node, endOffset: pos + suche.length
});
highlight.add(range);
pos = text.indexOf(suche, pos + suche.length);
}
}
CSS.highlights.set('suche', highlight);
return highlight;
};
const treffer = markiereSuche(document.body, 'javascript');
const alle = [...treffer.values()];
console.log(`${alle.length} Treffer gefunden`);
console.log(alle.map((r) => `${r.startOffset}–${r.endOffset}`));
Bereiche sicher entfernen (Schnappschuss)
const highlight = CSS.highlights.get('treffer');
if (highlight) {
// Kopie anlegen, da der Iterator live ist
for (const range of [...highlight.values()]) {
if (range.collapsed) {
highlight.delete(range);
}
}
console.log('Verbleibende Bereiche:', highlight.size);
}
// Wichtig · Fallstricke
- Browser-Kompatibilität: Die CSS Custom Highlight API gibt es in Chromium seit Version 105 und in Safari seit 17.2; Firefox unterstützt sie erst seit Version 140. Prüfen Sie die Unterstützung mit
if ('highlights' in CSS). values(),keys()und[Symbol.iterator]()sind dieselbe Funktion.entries()liefert dagegen Paare[range, range], genau wie beiSet.- Der Iterator ist live. Wenn Sie während der Iteration
add()oderdelete()aufrufen, kann das zu unerwartetem Verhalten führen. Arbeiten Sie deshalb besser mit einer Kopie ([...highlight.values()]). - Ein
StaticRangepasst sich nicht an DOM-Änderungen an. Nach Änderungen am DOM kann er ungültige Offsets enthalten. EinRangepasst sich dagegen automatisch an, kostet aber mehr Leistung, wenn es viele davon gibt. - Der Iterator liefert nur die Bereichsobjekte selbst. Der Name, unter dem das Highlight registriert ist, steht in
CSS.highlights(HighlightRegistry).