Live Rechtschreibprüfung im tinyMCE (spellcheck Plugin)
Für ein Sportnachrichten-Portal wurde kürzlich für den tinyMCE eine Möglichkeit benötigt die Rechtschreibprüfung direkt während der Eingabe zu aktualisieren.
Nach einiger Suche im Internet stieß ich hierbei auf folgenden Blogeintrag (in englischer Sprache): Background spell check in TinyMCE.
Das Problem
Der Lösungsansatz des Blogs gefiel mir schon sehr gut, allerdings hat der hier vorgestellte Lösungsweg für mich zwei Nachteile:
- Die Aktualisierung erfolgt maximal alle 3 Sekunden.
- Die Aktualisierung erfolgt 3 Sekunden nach dem letzten Tastendruck (egal welche Taste), wenn kein weiterer Tastendruck erfolgt.
Hier der originale Code aus dem Blogbeitrag mit übersetzten und ergänzten Kommentaren:
[pastacode lang=“javascript“ message=“JavaScript“ highlight=““ provider=“manual“]
tinyMCE.init({
//...
// sonstige tinyMCE Konfigurationen hier
//...
plugins : "spellchecker", // Rechtschreibprüfungs-Plugin aktivieren
theme_advanced_buttons1 : "spellchecker", // Button einfügen
spellchecker_languages : "+Deutsch=de,English=en", // verfügbare Sprachen festlegen
// setup funktion definieren, dies muss gegebenenfalls in eigene Funktionen integriert werden, sofern schon ein setup-Block existiert
setup: function(ed) {
ed.addCommand('mceSpellCheckRuntime', function() {
t = ed.plugins.spellchecker; // Editor spellchecker-Plugin-Element
if (t.mceSpellCheckRuntimeTimer) { // wenn schon ein Timer ausgelöst wurde diesen zurücksetzen
window.clearTimeout(t.mceSpellCheckRuntimeTimer);
}
t.mceSpellCheckRuntimeTimer = window.setTimeout(function() { // neuen Timer mit 3 Sekunden Verzögerung anlegen
t._done(); // Rechtschreibfehler-Markierungen zurücksetzen
t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { // checkWords (Prüfungsfunktion) des Plugins aufrufen -> Fehlerhafte Worte markieren
if (r.length > 0) { // wenn falsche Worte gefunden
t.active = 1; // Rechtschreibprüfung auf aktiv setzen
t._markWords(r); // Worte markieren
ed.nodeChanged(); // Änderungs-Trigger an tinyMCE senden
}
});
}, 3000); // 3000 Millisek. = 3 Sekunden
});
ed.onKeyUp.add(function(ed, e) { // Bei Tastendruck
ed.execCommand('mceSpellCheckRuntime'); // Oben definierte Funktion mit 3 Sek.-Timer aufrufen
});
}
});
[/pastacode]
Nun galt es die von mir angesprochenen Probleme lösen.
Problemlösung
Ansatz 1: Reduzierung der Zeit für den Timer
Grundsätzlich könnte ich hier einfach die Timeout Zeit von 3000 Millisekunden auf beispielsweise 500 reduzieren. Da jedoch in der Regel nicht alle Menschen schnell tippen können und man immer mal Zwischendurch auch kleine Denkpausen macht, schien mir das nicht günstig.
Es würde bedeuten, dass im Extremfall, der gesamte Text zweimal pro Sekunde an den Server gesendet wird um die Rechtschreibung zu prüfen. Bei langen Texten eigentlich nicht praktikabel.
Ansatz 2: Auslösen des Timers nur bei bestimmten Tasten
Der 1. Ansatz (Reduzierung der Timer-Zeit) hat nur Sinn, wenn im Gegenzug der Timer nicht bei jeder Taste ausgelöst wird. Meine Idee war es nun, dass der Timer nur bei bestimmten Zeichen gestartet wird. Ich habe mich hierbei vorerst für einige Satzzeichen, Sonderzeichen und die Leertaste entschieden, da diese in der Regel ein Wort-Ende markieren, nach dem es Sinn hat die Prüfung laufen zu lassen.
Modifizierter Code
Hier nun der modifizierte Code (ausschließlich der Setup-Block) mit Kommentaren:
[pastacode lang=“javascript“ message=“JavaScript“ highlight=““ provider=“manual“]
// hier die sonstigen Start-Optionen des tinyMCE
setup : function(ed) {
ed.addCommand('mceSpellCheckRuntime', function() {
t = ed.plugins.spellchecker; // Editor spellchecker-Plugin-Element
// an dieser Stelle wurde die Timer-Zurücksetzung entfernt und in die Tastendruck Funktion verschoben
t.mceSpellCheckRuntimeTimer = window.setTimeout(function() {
t._done(); // Rechtschreibfehler-Markierungen zurücksetzen
t._sendRPC('checkWords', [t.selectedLang, t._getWords()], function(r) { // checkWords (Prüfungsfunktion) des Plugins aufrufen -> Fehlerhafte Worte
if (r.length > 0) { // wenn falsche Worte gefunden
t.active = 1; // Rechtschreibprüfung auf aktiv setzen
t._markWords(r); // falsche Worte markieren
ed.nodeChanged(); // Änderungs-Trigger an tinyMCE senden
}
});
}, 500); // Timeout auf 500 Millisek = 0,5 Sekunden reduziert
});
ed.onKeyUp.add(function(ed, e) {
t = ed.plugins.spellchecker; // Editor spellchecker-Plugin-Element
if (t.mceSpellCheckRuntimeTimer) { // Wenn ein Timeout existiert, dieses zurücksetzen
window.clearTimeout(t.mceSpellCheckRuntimeTimer);
}
if(e.keyCode == 9 || e.keyCode == 13 || e.keyCode == 32 || (e.keyCode >= 109 && e.keyCode < = 111) || (e.keyCode >= 186 && e.keyCode < = 191) || (e.keyCode >= 219 && e.keyCode < = 222)) { // nur wenn eine der definierten Tasten gedrückt wurde neuen Timer starten
ed.execCommand('mceSpellCheckRuntime');
}
});
},
// hier der weitere Code des tinyMCE
[/pastacode]
Mit dieser Lösung werden die Aufrufe der Rechtschreibprüfung deutlich reduziert und dennoch steht eine Echtzeitprüfung zur Verfügung. Sobald eines der definierten Zeichen, wie z. B. ein Punkt oder Leerzeichen oder Enter gedrückt wurde, startet ein 500 Millisekunden Timer und – sofern in dieser Zeit keine weitere Taste gedrückt wird, wird die Prüfung gestartet. Die Liste der Zeichen kann man natürlich beliebig erweitern.
Selbstverständlich kann die Prüfung bei Bedarf auch immer noch manuell über das Icon angestoßen werden.
Füge diese URL in deine WordPress-Website ein, um sie einzubetten
Füge diesen Code in deine Website ein, um ihn einzubinden