Start · Sprachen · JavaScript · Referenz · TextFormat

TextFormat

Schnittstelle

Beschreibt ein Format wie Unterstreichungsstil und -stärke, das eine Eingabemethode (IME) auf einen Textbereich in einem <code>EditContext</code> anwenden möchte.

seit JavaScript Experimentell: Chrome/Edge 121+ (EditContext API), Kategorie: webapi

Signatur

interface TextFormat

Beschreibung

Die Schnittstelle TextFormat gehört zur EditContext API. Mit dieser API lassen sich eigene Texteditoren bauen, etwa auf Basis von <canvas> oder eigenen DOM-Strukturen, die trotzdem vollständig mit dem Eingabesystem des Betriebssystems zusammenarbeiten. Dazu gehören IMEs für Chinesisch, Japanisch oder Koreanisch, Bildschirmtastaturen und Diktierfunktionen.

Während einer Texteingabe mit Komposition (Composition) will die IME bestimmte Abschnitte des noch nicht bestätigten Textes hervorheben, meist durch eine Unterstreichung. Der Browser löst dann auf dem EditContext das Ereignis textformatupdate aus. Über event.getTextFormats() bekommt man ein Array von TextFormat-Objekten. Jedes Objekt gibt einen Bereich an (rangeStart bis rangeEnd, als Zeichenpositionen im Text des EditContext) und legt fest, wie dieser Bereich dargestellt werden soll.

Die Instanzeigenschaften sind alle schreibgeschützt:

  • rangeStart (number): Anfangsposition des Bereichs, inklusive.
  • rangeEnd (number): Endposition des Bereichs, exklusive.
  • underlineStyle (string): "none", "solid", "dotted", "dashed" oder "wavy".
  • underlineThickness (string): "none", "thin" oder "thick".

Der Browser zeichnet diese Formate nicht selbst. Die Anwendung muss sie selbst darstellen, zum Beispiel über die CSS Custom Highlight API oder durch Zeichnen auf einem Canvas. Mit dem Konstruktor new TextFormat(options) lassen sich außerdem eigene Instanzen erzeugen, etwa für Tests.

Parameter

Name Typ Default Beschreibung
$options Object {} Optionales Objekt für den Konstruktor new TextFormat(options).
$options.rangeStart number 0 Anfangsposition des formatierten Bereichs, inklusive.
$options.rangeEnd number 0 Endposition des formatierten Bereichs, exklusive.
$options.underlineStyle "none" | "solid" | "dotted" | "dashed" | "wavy" "none" Stil der Unterstreichung.
$options.underlineThickness "none" | "thin" | "thick" "none" Stärke der Unterstreichung.

Rückgabewert

Typ
TextFormat
Beschreibung
Der Konstruktor liefert eine neue TextFormat-Instanz. Im normalen Einsatz bekommt man die Objekte jedoch über TextFormatUpdateEvent.getTextFormats() als Array.

Beispiele

Formate beim textformatupdate-Ereignis auslesen

// <div id="editor"></div> im HTML
const editor = document.getElementById('editor');

if ('EditContext' in window) {
  const editContext = new EditContext();
  editor.editContext = editContext;

  editContext.addEventListener('textformatupdate', (event) => {
    const formats = event.getTextFormats();
    for (const format of formats) {
      console.log(
        `Bereich ${format.rangeStart}–${format.rangeEnd}:`,
        format.underlineStyle,
        format.underlineThickness
      );
    }
  });
} else {
  console.warn('EditContext API wird nicht unterstützt.');
}
Bereich 0–3: solid thin Bereich 3–6: solid thick

IME-Formate mit der CSS Custom Highlight API darstellen

/* CSS:
  ::highlight(ime-thin)  { text-decoration: underline 1px; }
  ::highlight(ime-thick) { text-decoration: underline 3px; }
  ::highlight(ime-wavy)  { text-decoration: underline wavy; }
*/
const editor = document.getElementById('editor');
const editContext = new EditContext();
editor.editContext = editContext;

// Text selbst rendern (vereinfacht: ein einziger Textknoten)
editContext.addEventListener('textupdate', () => {
  editor.textContent = editContext.text;
});

editContext.addEventListener('textformatupdate', (event) => {
  const textNode = editor.firstChild;
  const groups = { 'ime-thin': new Highlight(), 'ime-thick': new Highlight(), 'ime-wavy': new Highlight() };

  if (textNode) {
    for (const f of event.getTextFormats()) {
      if (f.underlineStyle === 'none') continue;
      const range = new Range();
      range.setStart(textNode, f.rangeStart);
      range.setEnd(textNode, f.rangeEnd);
      const key = f.underlineStyle === 'wavy'
        ? 'ime-wavy'
        : f.underlineThickness === 'thick' ? 'ime-thick' : 'ime-thin';
      groups[key].add(range);
    }
  }

  for (const [name, highlight] of Object.entries(groups)) {
    CSS.highlights.set(name, highlight);
  }
});

// Nach Ende der Komposition Hervorhebungen entfernen
editContext.addEventListener('compositionend', () => {
  ['ime-thin', 'ime-thick', 'ime-wavy'].forEach((n) => CSS.highlights.delete(n));
});

Eigene TextFormat-Instanz erzeugen (z. B. für Tests)

const format = new TextFormat({
  rangeStart: 2,
  rangeEnd: 5,
  underlineStyle: 'dashed',
  underlineThickness: 'thin'
});

console.log(format.rangeStart, format.rangeEnd);
console.log(format.underlineStyle, format.underlineThickness);
2 5 dashed thin

// Wichtig · Fallstricke

  • Experimentell: Die EditContext API und damit TextFormat gibt es bisher nur in Chromium-Browsern (Chrome/Edge ab 121). Prüfe die Unterstützung vorher mit 'EditContext' in window und sieh eine Ausweichlösung vor, etwa contenteditable oder <textarea>.
  • Keine automatische Darstellung: Der Browser liefert die Formate nur als Daten. Wenn deine Anwendung sie nicht selbst zeichnet, sieht der Nutzer während der IME-Komposition keine Hervorhebung.
  • Positionen beziehen sich auf editContext.text, nicht auf DOM-Knoten. Sie zählen in UTF-16-Codeeinheiten. Wenn du den Text auf mehrere Knoten verteilst, musst du die Positionen selbst in DOM-Bereiche umrechnen.
  • Die Werte können sich unterscheiden: Frühe Entwürfe der Spezifikation hatten zusätzlich Eigenschaften wie textColor, backgroundColor und underlineColor. Diese wurden wieder entfernt. Einige frühe Chromium-Versionen lieferten die Werte außerdem großgeschrieben (z. B. "Solid"). Vergleiche zur Sicherheit ohne Beachtung der Groß-/Kleinschreibung, etwa mit value.toLowerCase().
  • Die Formate gelten nur für die laufende Komposition. Entferne deine Hervorhebungen bei compositionend oder beim nächsten textformatupdate.