Signatur
Beschreibung
document.execCommand() führt einen benannten Bearbeitungsbefehl auf der aktuellen Auswahl oder an der Cursorposition aus. Das funktioniert nur, wenn das Dokument im Modus designMode = "on" ist oder der Fokus in einem Element mit contenteditable bzw. in einem <input>/<textarea> liegt. Zu den typischen Befehlen gehören bold, italic, underline, createLink, insertHTML, insertText, formatBlock, undo, redo, copy und cut.
Früher war die Methode die Grundlage für viele Rich-Text-Editoren (WYSIWYG) und für die Funktion „In die Zwischenablage kopieren“. Inzwischen gilt sie offiziell als veraltet: Es gibt keinen verbindlichen Standard, und die Browser erzeugen teilweise unterschiedliches HTML (zum Beispiel <b> statt <strong> oder <span style>).
Einen praktischen Vorteil hat sie trotzdem noch: Mit execCommand vorgenommene Änderungen landen im nativen Rückgängig-Stapel des Browsers, sodass Strg+Z sie zurücknehmen kann. Deshalb wird insertText heute noch gern verwendet, um Text in Eingabefelder einzufügen, ohne dass die Undo-Historie verloren geht. Für neuen Code solltest du die Clipboard API, die Selection/Range-APIs und das Ereignis beforeinput verwenden.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $commandName Pflicht | string | Name des Befehls, z. B. "bold", "insertText", "createLink", "foreColor", "formatBlock", "copy", "undo". |
|
| $showDefaultUI | boolean | false | Gibt an, ob eine Standard-Benutzeroberfläche angezeigt werden soll. Wird von modernen Browsern ignoriert, deshalb immer false übergeben. |
| $valueArgument | string | null | null | Zusätzlicher Wert für Befehle, die einen brauchen, z. B. die URL bei createLink, die Farbe bei foreColor, den Text bei insertText oder "<h2>" bei formatBlock. |
Rückgabewert
true, wenn der Befehl unterstützt und ausgeführt wurde, sonst false (etwa bei unbekanntem Befehl, fehlendem bearbeitbarem Kontext oder bei copy/cut ohne Benutzeraktion).Beispiele
Einfache Formatierungs-Toolbar für contenteditable
// HTML: <div id="editor" contenteditable="true">Text hier…</div>
// <button data-cmd="bold">B</button> <button data-cmd="italic">I</button>
const editor = document.querySelector('#editor');
document.querySelectorAll('[data-cmd]').forEach((btn) => {
// mousedown verhindern, damit die Auswahl im Editor erhalten bleibt
btn.addEventListener('mousedown', (e) => e.preventDefault());
btn.addEventListener('click', () => {
const ok = document.execCommand(btn.dataset.cmd, false, null);
console.log(`${btn.dataset.cmd}:`, ok);
editor.focus();
});
});
Link und Überschrift einfügen
const addLink = () => {
const url = prompt('URL eingeben:', 'https://');
if (url && /^https?:\/\//.test(url)) {
document.execCommand('createLink', false, url);
}
};
const makeHeading = () => {
// Den aktuellen Block in eine h2 umwandeln
document.execCommand('formatBlock', false, '<h2>');
};
document.querySelector('#link-btn').addEventListener('click', addLink);
document.querySelector('#h2-btn').addEventListener('click', makeHeading);
Text einfügen, ohne die Undo-Historie zu verlieren
const textarea = document.querySelector('textarea');
const insertEmoji = (emoji) => {
textarea.focus();
// Mit insertText bleibt Strg+Z funktionsfähig – anders als bei textarea.value = …
const ok = document.execCommand('insertText', false, emoji);
if (!ok) {
// Rückfall für Umgebungen ohne Unterstützung
textarea.setRangeText(emoji, textarea.selectionStart, textarea.selectionEnd, 'end');
}
};
document.querySelector('#emoji-btn').addEventListener('click', () => insertEmoji('🙂'));
Kopieren mit modernem Weg und Rückfall
const copyText = async (text) => {
if (navigator.clipboard?.writeText) {
await navigator.clipboard.writeText(text);
return true;
}
// Alter Rückfall über ein temporäres Textfeld
const ta = document.createElement('textarea');
ta.value = text;
ta.setAttribute('readonly', '');
ta.style.position = 'fixed';
ta.style.opacity = '0';
document.body.append(ta);
ta.select();
const ok = document.execCommand('copy');
ta.remove();
return ok;
};
document.querySelector('#copy-btn').addEventListener('click', async () => {
console.log('Kopiert:', await copyText('Hallo Zwischenablage'));
});
// Wichtig · Fallstricke
- Veraltet: Die Methode ist nicht standardisiert (es gibt nur einen unvollständigen W3C-Entwurf). Sie funktioniert in allen aktuellen Browsern, kann sich aber je nach Browser unterschiedlich verhalten und soll in neuem Code nicht verwendet werden.
- Uneinheitliches Markup: Chrome, Firefox und Safari erzeugen für denselben Befehl unterschiedliches HTML. Mit
document.execCommand('styleWithCSS', false, true)lässt sich steuern, obstyle-Attribute oder Tags wie<b>entstehen. - Sicherheit (XSS):
insertHTMLfügt das übergebene HTML ungefiltert ein. Benutzereingaben musst du vorher bereinigen (z. B. mit DOMPurify). Das gilt auch für den Inhalt einescontenteditable-Bereichs, bevor du ihn speicherst oder an anderer Stelle ausgibst. BeicreateLinksolltest dujavascript:-URLs abweisen. - Benutzeraktion nötig:
copyundcutfunktionieren nur innerhalb eines durch den Nutzer ausgelösten Ereignisses (z. B.click).pasteist in Webseiten fast immer gesperrt und gibtfalsezurück. - Der Fokus bzw. die Auswahl muss beim Aufruf im bearbeitbaren Bereich liegen. Wenn du auf einen Button klickst, geht die Auswahl oft verloren. Abhilfe schafft
preventDefault()immousedown-Handler. - Mit
document.queryCommandState(),queryCommandValue()undqueryCommandSupported()lassen sich Zustand und Unterstützung abfragen. Diese Methoden sind ebenfalls veraltet. - Ersatz:
navigator.clipboardfür die Zwischenablage,Selection/Rangefür DOM-Manipulationen,beforeinput/InputEventfür eigene Editor-Logik,setRangeText()für Eingabefelder.