Get to know MDN better
Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.
Die EditContext-API kann verwendet werden, um Rich-Text-Editoren im Web zu erstellen, die erweiterte Texteingabemöglichkeiten unterstützen, wie z.B. Input Method Editor (IME)-Komposition, Emoji-Picker oder andere plattformspezifische UI-Oberflächen für die Bearbeitung.
Dieser Artikel zeigt die notwendigen Schritte zum Erstellen eines Texteditors mit der EditContext-API. In diesem Leitfaden überprüfen Sie die Hauptschritte, die beim Erstellen eines einfachen HTML-Code-Editors erforderlich sind, der die Syntax des Codes beim Tippen hervorhebt und die IME-Komposition unterstützt.
Um den abschließenden Code zu sehen, schauen Sie sich den Quellcode auf GitHub an. Es ist eine gute Idee, den Quellcode offen zu halten, während Sie lesen, da das Tutorial nur die wichtigsten Teile des Codes zeigt.
Der Quellcode ist in folgende Dateien gegliedert:
Um die Live-Demo zu nutzen, öffnen Sie Edit Context API: HTML-Editor-Demo in einem Browser, der die EditContext-API unterstützt.
Der erste Schritt besteht darin, die Nutzeroberfläche für den Editor zu erstellen. Der Editor ist ein <div>-Element mit dem spellcheck-Attribut, das auf false gesetzt ist, um die Rechtschreibprüfung zu deaktivieren:
Um das Editorelement zu gestalten, wird der folgende CSS-Code verwendet. Der Code lässt den Editor den gesamten Viewport ausfüllen und scrollt, wenn es zu viel Inhalt gibt, um hineinzupassen. Die white-space-Eigenschaft wird ebenfalls verwendet, um Leerraumzeichen im eingegebenen HTML-Text zu erhalten, und die tab-size-Eigenschaft wird verwendet, um Tabulatorzeichen als zwei Leerzeichen darzustellen. Schließlich werden einige Standardfarben für Hintergrund, Text und Kursor gesetzt:
Um ein Element im Web bearbeitbar zu machen, verwenden Sie meistens ein <input>-Element, ein <textarea>-Element oder das contenteditable-Attribut.
Mit der EditContext-API können Sie jedoch auch andere Arten von Elementen bearbeitbar machen, ohne ein Attribut zu verwenden. Um die Liste der Elemente zu sehen, die mit der EditContext-API verwendet werden können, sehen Sie sich Mögliche Elemente auf der Eigenschaftsseite editContext des HTMLElements an.
Um den Editor bearbeitbar zu machen, erstellt die Demo-App eine Instanz von EditContext, übergibt dem Konstruktor etwas initialen HTML-Text und setzt dann die editContext-Eigenschaft des Editorelements auf die EditContext-Instanz:
Diese Codezeilen machen das Editorelement fokussierbar. Das Eingeben von Text in das Element löst das textupdate-Ereignis auf der EditContext-Instanz aus.
Um den syntaxhervorgehobenen HTML-Code im Editor zu rendern, wenn der Benutzer Text eingibt, verwendet die Demo-App eine Funktion namens render(), die aufgerufen wird, wenn neuer Text eingegeben wird, wenn Zeichen gelöscht werden oder wenn die Auswahl geändert wird.
Eines der ersten Dinge, die die render()-Funktion macht, ist das Tokenisieren des HTML-Textinhalts. Das Tokenisieren des HTML-Textinhalts ist erforderlich, um die HTML-Syntax hervorzuheben, und beinhaltet das Lesen der HTML-Code-Zeichenfolge und das Bestimmen, wo jedes öffnende Tag, schließende Tag, Attribut, Kommentar-Knoten und Text-Knoten beginnt und endet.
Die Demo-App verwendet die Funktion tokenizeHTML(), um dies zu erreichen, die die Zeichenfolge Zeichen für Zeichen durchläuft und dabei eine Zustandmaschine aufrechterhält. Den Quellcode für die Funktion tokenizeHTML() finden Sie in tokenizer.js auf GitHub.
Die Funktion wird in die HTML-Datei der Demo-App wie folgt importiert:
Immer wenn die render()-Funktion aufgerufen wird, also wenn der Benutzer Text eingibt oder wenn sich die Auswahl ändert, entfernt die Funktion den Inhalt im Editorelement und rendert dann jedes Token als separates HTML-Element:
Die EditContext-API gibt die Möglichkeit, die Art und Weise zu steuern, wie der bearbeitete Text gerendert wird. Die obige Funktion rendert ihn durch die Verwendung von HTML-Elementen, aber es könnte auch in jeder anderen Weise gerendert werden, einschließlich indem es in ein <canvas>-Element gerendert wird.
Die Demo-App führt die render()-Funktion bei Bedarf aus. Dies beinhaltet einmal, wenn die App startet, und dann erneut, wenn der Benutzer Text eingibt, indem sie auf das textupdate-Ereignis hört:
Wie im vorherigen Codebeispiel zur render()-Funktion zu sehen, wird jedem Token ein Klassenname zugewiesen, der dem Typ des Tokens entspricht. Die Demo-App verwendet diesen Klassennamen, um die Tokens mit CSS wie unten gezeigt zu gestalten:
Obwohl die Demo-App ein <div>-Element für den Editor verwendet, das bereits die Anzeige eines blinkenden Textcursors und das Hervorheben von Benutzerauswahlen unterstützt, erfordert die EditContext-API dennoch das Rendern der Auswahl. Dies liegt daran, dass die EditContext-API mit anderen Arten von Elementen verwendet werden kann, die diese Verhaltensweisen nicht unterstützen. Das Rendern der Auswahl selbst gibt uns außerdem mehr Kontrolle darüber, wie die Auswahl angezeigt wird. Schließlich wird aufgrund der Tatsache, dass die render()-Funktion den HTML-Inhalt des Editorelements jedes Mal löscht, wenn sie ausgeführt wird, jede Auswahl, die der Benutzer gemacht haben könnte, das nächste Mal, wenn die render()-Funktion ausgeführt wird, verloren.
Um die Auswahl zu rendern, verwendet die Demo-App die Methode Selection.setBaseAndExtent() am Ende der render()-Funktion. Um die Methode setBaseAndExtent() zu verwenden, benötigen wir ein Paar von DOM-Knoten und Zeichenoffsets, die den Beginn und das Ende der Auswahl darstellen. Die EditContext-API speichert den Status für die aktuelle Auswahl jedoch nur als Paar von Start- und Endzeichenoffsets im gesamten Bearbeitungsspeicher. Der Demo-App-Code verwendet eine weitere Funktion namens fromOffsetsToSelection(), um diese Zeichenoffsets in vier Werte zu konvertieren:
Den Code für die Funktion fromOffsetsToSelection() finden Sie in der Datei converter.js.
Die EditContext-API bietet uns eine hohe Flexibilität, um unsere eigene Texteditor-Nutzeroberfläche zu definieren. Dies bedeutet jedoch auch, dass wir einige Dinge selbst handhaben müssen, die normalerweise vom Browser oder Betriebssystem (OS) gehandhabt werden.
Zum Beispiel müssen wir dem OS mitteilen, wo sich der bearbeitbare Textbereich auf der Seite befindet. Auf diese Weise kann das OS jede Texteingabe-Nutzeroberfläche, die der Benutzer zum Schreiben von Text verwendet, wie z.B. ein IME-Kompositionsfenster, korrekt positionieren.
Die Demo-App verwendet die Methode EditContext.updateControlBounds(), um ihr ein DOMRect-Objekt zu übergeben, das die Grenzen des bearbeitbaren Textbereichs darstellt. Die Demo-App ruft diese Methode auf, wenn der Editor initialisiert wird, und erneut, wenn das Fenster in der Größe verändert wird:
Das im vorherigen Abschnitt verwendete textupdate-Ereignis wird nicht ausgelöst, wenn der Benutzer die Tasten Tab oder Enter drückt, daher müssen wir diese Tasten separat behandeln.
Um sie zu handhaben, verwendet die Demo-App einen Ereignislistener für das keydown-Ereignis auf dem Editorelement und verwendet diesen Listener, um den Textinhalt und die Auswahl der EditContext-Instanz zu aktualisieren, wie unten gezeigt:
Der obige Code ruft auch die Funktion updateSelection() auf, um die Auswahl zu aktualisieren, nachdem der Textinhalt aktualisiert wurde. Siehe Aktualisieren des Auswahlstatus und der Auswahlgrenzen weiter unten für mehr Informationen.
Wir könnten den Code verbessern, indem wir andere Tastenkombinationen wie Strg+C und Strg+V zum Kopieren und Einfügen von Text oder Strg+Z und Strg+Y zum Rückgängigmachen und Wiederherstellen von Textänderungen behandeln.
Wie wir bereits gesehen haben, kümmert sich die render()-Funktion um das Rendern der aktuellen Benutzerauswahl im Editorelement. Aber die Demo-App muss den Auswahlstatus und die Grenzen auch aktualisieren, wenn der Benutzer die Auswahl ändert. Die EditContext-API macht dies nicht automatisch, da die Editor-Nutzeroberfläche möglicherweise auf andere Weise implementiert ist, z.B. durch die Verwendung eines <canvas>-Elements.
Um zu wissen, wann der Benutzer die Auswahl ändert, verwendet die Demo-App das selectionchange-Ereignis und die Document.getSelection()-Methode, die ein Selection-Objekt bereitstellt, das uns mitteilt, wo sich die Auswahl des Benutzers befindet. Mithilfe dieser Informationen aktualisiert die Demo-App den Auswahlstatus und die Auswahlgrenzen der EditContext-API, indem sie die Methoden EditContext.updateSelection() und EditContext.updateSelectionBounds() verwendet. Dies wird vom OS genutzt, um das IME-Kompositionsfenster korrekt zu positionieren.
Da die EditContext-API jedoch Zeichenoffsets verwendet, um die Auswahl darzustellen, verwendet die Demo-App auch eine Funktion fromSelectionToOffsets(), die DOM-Auswahlobjekte in Zeichenoffsets konvertiert.
Den Code für die Funktion fromSelectionToOffsets() finden Sie in der Datei converter.js.
Zusätzlich zur Verwendung der Methoden EditContext.updateControlBounds() und EditContext.updateSelectionBounds(), um dem OS bei der Positionierung einer Texteingabe-Nutzeroberfläche zu helfen, die der Benutzer möglicherweise verwendet, benötigt das OS noch eine weitere Information: die Position und Größe bestimmter Zeichen innerhalb des Editorelements.
Um dies zu tun, hört die Demo-App auf das characterboundsupdate-Ereignis, verwendet es, um die Begrenzungen einiger der Zeichen im Editorelement zu berechnen und verwendet dann die Methode EditContext.updateCharacterBounds(), um die Zeichenbegrenzungen zu aktualisieren.
Wie vorher gesehen, kennt die EditContext-API nur Zeichenoffsets, was bedeutet, dass das characterboundsupdate-Ereignis die Start- und Endoffsets für die Zeichen bereitstellt, für die es Begrenzungen benötigt. Die Demo-App verwendet eine weitere Funktion, fromOffsetsToRenderedTokenNodes(), um die DOM-Elemente zu finden, in denen diese Zeichen gerendert wurden, und verwendet diese Informationen, um die erforderlichen Begrenzungen zu berechnen.
Den Code für die Funktion fromOffsetsToRenderedTokenNodes() finden Sie in der Datei converter.js.
Die Demo-App durchläuft einen letzten Schritt, um die IME-Komposition vollständig zu unterstützen. Wenn der Benutzer Text mit einem IME komponiert, kann das IME entscheiden, dass bestimmte Teile des komponierten Textes anders formatiert werden sollen, um den Kompositionsstatus anzuzeigen. Zum Beispiel könnte das IME entscheiden, den Text zu unterstreichen.
Da es die Verantwortung der Demo-App ist, den Inhalt im bearbeitbaren Textbereich darzustellen, ist es auch ihre Verantwortung, die notwendige IME-Formatierung anzuwenden. Die Demo-App erreicht dies, indem sie das Ereignis textformatupdate anhört, um zu wissen, wann das IME Textformate anwenden möchte, wo und welche Formate angewendet werden sollen.
Wie im folgenden Code-Ausschnitt gezeigt, verwendet die Demo-App das textformatupdate-Ereignis und erneut die Funktion fromOffsetsToSelection(), um den Textbereich zu finden, den die IME-Komposition formatieren möchte:
Dieser oben erwähnte Ereignishandler ruft die Funktion addHighlight() auf, um den Text zu formatieren. Diese Funktion verwendet die CSS Custom Highlight API, um die Textformate darzustellen. Die CSS Custom Highlight API bietet einen Mechanismus zum Stilen von willkürlichen Textbereichen, indem JavaScript verwendet wird, um die Bereiche zu erstellen, und CSS, um sie zu gestalten. Um diese API zu verwenden, wird das ::highlight()-Pseudoelement verwendet, um die Hervorhebungsstile zu definieren:
Highlight-Instanzen werden ebenfalls erstellt, in einem Objekt gespeichert und im HighlightRegistry mithilfe der CSS.highlights-Eigenschaft registriert:
Mit diesen Grundlagen verwendet die Funktion addHighlight() Range-Objekte für die Bereiche, die gestaltet werden müssen, und fügt sie dem Highlight-Objekt hinzu:
Dieser Artikel zeigte Ihnen, wie Sie die EditContext-API verwenden können, um einen einfachen HTML-Code-Editor zu erstellen, der die IME-Komposition und die Syntaxhervorhebung unterstützt.
Den endgültigen Code und die Live-Demo finden Sie auf GitHub: Live-Demo und Quellcode.
Wichtiger ist, dass dieser Artikel Ihnen zeigte, dass die EditContext-API viel Flexibilität in Bezug auf die Benutzeroberfläche Ihres Editors bietet. Basierend auf dieser Demo könnten Sie einen ähnlichen Texteditor erstellen, der ein <canvas>-Element verwendet, um den syntaxhervorgehobenen HTML-Code anstelle des <div>, das die Demo verwendet, zu rendern. Sie könnten auch ändern, wie jedes Token gerendert wird oder wie die Auswahl gerendert wird.
Der Bauplan für ein besseres Internet.
Besuche die gemeinnützige Muttergesellschaft der Mozilla Corporation, die Mozilla Foundation.
Teile dieses Inhalts sind ©1998–2026 von einzelnen mozilla.org-Mitwirkenden. Inhalte sind verfügbar unter einer Creative-Commons-Lizenz.