// (C) Benutzer:Jowereit 2007-2012
//
// Dokumentation siehe ]
//
// Getestet unter Firefox 2 (Linux) und Opera 9 (Linux); Internet Explorer 7 (Windows) funktioniert nicht ganz problemlos (siehe FIXME).
//
// In Konqueror 3.5 gibt es noch ein paar Probleme (Bugs?) beim Einfügen von Text.
// Autokorrektur komplett ausschalten: var typo_autokorrektur_an = false;
if (typeof typo_autokorrektur_an == "undefined") var typo_autokorrektur_an = true;
// Autokorrektur auch auf der Benutzer-E-Mail-Seite/auf der Hochlade-Seite aktivieren
if (typeof typo_auch_benutzer_email == "undefined") var typo_auch_benutzer_email = true;
if (typeof typo_auch_upload_form == "undefined") var typo_auch_upload_form = true;
// Immer doppelte Anführungszeichen verwenden
if (typeof typo_immer_doppelte_anfuehrungszeichen == "undefined") var typo_immer_doppelte_anfuehrungszeichen = false;
// Zwei Bindestriche bei der Signatur nicht zu einem Gedankenstrich machen.
if (typeof typo_kein_gedankenstrich_bei_signatur == "undefined") var typo_kein_gedankenstrich_bei_signatur = true;
// Falls man seine Signatur mit einem Leerzeichen zwischen Bindestrichen und Tilden schreibt (wie ich), diese
// Variable auf true setzen.
if (typeof typo_signatur_mit_leerzeichen == "undefined") var typo_signatur_mit_leerzeichen = false;
// Bei typo_signatur_mit_leerzeichen ein geschütztes Leerzeichen zwischen Bindestrichen und Tilden einfügen
if (typeof typo_signatur_mit_leerzeichen_nbsp == "undefined") var typo_signatur_mit_leerzeichen_nbsp = true;
// Zeige in der Bearbeitungsleiste eine Checkbox zum temporären Ausschalten der Autokorrektur.
if (typeof typo_zeige_checkbox == "undefined") var typo_zeige_checkbox = true;
// Autokorrektur bei CSS/JS-Unterseiten von Benutzerseiten deaktivieren
var typo_is_css_js_subpage = (mw.config.get('wgCanonicalNamespace') == "User" && mw.config.get('wgTitle').match(/\/+\.(css|js)/));
// QuickEdit-Integration aktivieren.
if (typeof typo_quickedit == "undefined") var typo_quickedit = true;
// Umschließen der Auswahl mit ] bei Eingabe einer öffnenden eckigen Klammer aktivieren.
if (typeof typo_link_mit_eckiger_klammer == "undefined") var typo_link_mit_eckiger_klammer = true;
if (typo_is_css_js_subpage) {
typo_autokorrektur_an = false;
typo_zeige_checkbox = false;
}
// Ist der wikEd-Editor gerade aktiv?
var typo_wiked_aktiv = false;
// Das Bearbeitungs-Textfeld
var typo_textbox = null;
if (!typo_is_css_js_subpage && typo_zeige_checkbox) {
if (typeof(wikEd) === 'undefined') {
wikEd = { };
}
if (typeof(wikEd.config) === 'undefined') {
wikEd.config = { };
}
if (typeof(wikEd.config.button) === 'undefined') {
wikEd.config.button = { };
}
if (typeof(wikEd.config.buttonBar) === 'undefined') {
wikEd.config.buttonBar = { };
}
// Benutzerdefinierter wikEd-Button
// define custom buttons
wikEd.config.button = ;
wikEd.config.buttonBar = ];
}
//-------------------------------------------------------------------------------------------------------------
// Im Internet Explorer ist es gar nicht so einfach, die Position des Cursors herauszufinden. Folgender
// Workaround stammt von
// http://the-stickman.com/web-development/javascript/finding-selection-cursor-position-in-a-textarea-in-internet-explorer/
function ie_getSelection(element) {
var range = document.selection.createRange(); // We'll use this as a 'dummy'
var stored_range = range.duplicate(); // Select all text
stored_range.moveToElementText(element); // Now move 'dummy' end point to end point of original range
stored_range.setEndPoint('EndToEnd', range); // Now we can calculate start and end points
// Setze die Eigenschaften "selectionStart" und "selectionEnd" der Textbox, sodass auf sie
// wie in Firefox zugegriffen werden kann.
element.selectionStart = stored_range.text.length - range.text.length;
element.selectionEnd = element.selectionStart + range.text.length;
}
// Setzt im wikEd-Editorfenster die Eigenschaften selectionStart, selectionEnd, curLine und curLineOffset
function wiked_getSelection(element) {
var obj = {};
WikEdGetText(obj, 'selection');
wikEd.ParseDOM(obj, wikEd.frameBody);
element.value = obj.plain;
element.selectionStart = obj.plainFocus;
element.selectionEnd = obj.plainFocus;
getCurLine(element);
}
// Schreibt den aktuellen Absatz in die Eigenschaft curLine des angegebenen Textfelds. (Müsste also eigentlich
// curParagraph oder so heißen).
function getCurLine(textarea) {
var anfang = textarea.value.slice(0, textarea.selectionStart).lastIndexOf("\n") + 1;
var ende = textarea.value.slice(textarea.selectionStart).indexOf("\n");
if (ende == -1) {
textarea.curLine = textarea.value.slice(anfang);
} else {
textarea.curLine = textarea.value.slice(anfang, textarea.selectionStart + ende);
}
textarea.curLineOffset = anfang;
}
// Setzt den Cursor im Textfeld "textarea" an die Position "pos".
function setcursor(textarea, pos) {
if (document.selection && document.selection.createRange && !is_opera) { // Internet Explorer
var range = textarea.createTextRange();
range.collapse(true);
var anzahlZeilenumbrueche = textarea.value.slice(0, textarea.selectionStart).split('\r').length - 1;
range.moveStart("character", pos - anzahlZeilenumbrueche);
range.moveEnd("character", 0);
range.select();
} else {
textarea.selectionStart = pos;
textarea.selectionEnd = pos;
}
}
// Erstellt eine Checkbox am rechten Rand der Bearbeitungsleiste, die die Autokorrektur an- oder ausschaltet.
// FIXME: Wird im Internet Explorer über der Bearbeitungsleiste angezeigt.
function createCheckbox() {
var container = document.createElement("div");
container.setAttribute("style", "float: right");
container.id = "typo_autokorrektur_an_container";
container.innerHTML = '<input type="checkbox" id="typo_autokorrektur_an" '
+ (typo_autokorrektur_an ? 'checked="checked"' : "") + ' />'
+ '<label for="typo_autokorrektur_an">Autokorrektur</label>';
container.childNodes.onchange = function() {
typo_autokorrektur_an = this.checked;
typo_textbox.focus();
}
return container;
}
// -----
// Prüft, ob die letzte Eingabe im Textfeld "element" (textarea oder wikEd) gleich dem String "vergleich" ist.
function letzteEingabe(element, vergleich) {
return (element.curLine.slice(element.selectionStart - vergleich.length - element.curLineOffset, element.selectionStart - element.curLineOffset) == vergleich);
}
// -----
// Fügt im Textfeld "element" den Text "text" ein und löscht dabei zunächst "anzahlLoeschen" Zeichen vor dem Cursor
function einfuegen(element, text, anzahlLoeschen) {
var selStart = element.selectionStart; // Anfang der Auswahl zwischenspeichern, da sie in der nächsten Anweisung verändert wird.
var scrollPos = element.scrollTop;
element.value = element.value.slice(0, element.selectionStart - anzahlLoeschen) + text + element.value.slice(element.selectionEnd);
setcursor(element, selStart - anzahlLoeschen + text.length);
element.scrollTop = scrollPos;
}
// Das Gleiche für wikEd.
function einfuegenWikEd(element, text, anzahlLoeschen) {
var obj = {};
WikEdGetText(obj, 'selection');
if (anzahlLoeschen > 0) {
obj.selection.range.setStart(obj.sel.focusNode, obj.sel.focusOffset - anzahlLoeschen);
wikEd.FrameExecCommand('delete');
}
wikEd.FrameExecCommand('inserthtml', text);
}
// -----
function charAt(element, position) {
return element.value.charAt(position);
}
function charAtWikEd(element, position) {
return element.curLine.charAt(position);
}
// -----
// Gibt das letzte Vorkommen des Strings "text" im aktuellen Absatz des Textfelds "element" bis zur
// Startposition der Auswahl zurück.
function letztesVorkommen(element, text) {
return element.curLine.slice(0, element.selectionStart - element.curLineOffset).lastIndexOf(text);
}
// -----
// Prüft, ob ein Zeichen eine Zahl ist
function isNumeric(c) {
return (c != "") && ("0123456789".indexOf(c) != -1);
}
// -----
// Wird aufgerufen, wenn der wikEd-Editor aktiviert wurde.
function wikEdAktiviert() {
if ((typo_zeige_checkbox) && document.getElementById("typo_autokorrektur_an_container") != null) {
document.getElementById("typo_autokorrektur_an_container").style.display = "none";
}
typo_wiked_aktiv = true;
}
// Wird aufgerufen, wenn der wikEd-Editor deaktiviert wurde.
function wikEdDeaktiviert() {
if (typo_zeige_checkbox) {
if (document.getElementById("typo_autokorrektur_an_container") != null) {
document.getElementById("typo_autokorrektur_an_container").style.display = "block";
}
if (document.getElementById("typo_autokorrektur_an") != null) {
document.getElementById("typo_autokorrektur_an").checked = typo_autokorrektur_an;
}
}
typo_wiked_aktiv = false;
}
// Richtet benutzerdefinierte DOM-Funktionen und Ereignis-Handler im wikEd-Editor ein.
function setupForWikEd() {
if (!wikEd.addEventListener) {
return;
}
wikEd.addEventListener(wikEd.frameDocument, 'keypress', autokorrektur, true);
wikEd.frameDocument.letzteEingabe = function(vergleich) { return letzteEingabe(this, vergleich) };
wikEd.frameDocument.einfuegen = function(text, anzahlLoeschen) { return einfuegenWikEd(this, text, anzahlLoeschen) };
wikEd.frameDocument.letztesVorkommen = function(text) { return letztesVorkommen(this, text) };
wikEd.frameDocument.charAt = function(position) { return charAtWikEd(this, position) };
document.getElementById("wikEdAutokorrekturJowereit").className = (typo_autokorrektur_an ? "wikEdButtonChecked" : "wikEdButtonUnchecked");
document.getElementById("wikEdAutokorrekturJowereit").setAttribute("checked", typo_autokorrektur_an);
wikEdAktiviert();
}
//-------------------------------------------------------------------------------------------------------------
// Diese Funktion wird beim Drücken einer Taste (onkeypress) im Bearbeitungs-Textfeld aufgerufen.
function autokorrektur(evt) {
if (!typo_autokorrektur_an) return true;
// Bei manchen Tastatureingaben (z.B. Tilde) ist der Wert des übergebenen Zeichens in event.charCode
// statt in event.keyCode gespeichert. In diesem Fall enthält die Variable keyCode trotzdem den
// Zeichencode.
if (document.selection && document.selection.createRange && !is_opera) { // Internet Explorer
// Im Internet Explorer darf das "event"-Objekt nicht als Parameter übergeben werden, sondern
// steht der Funktion global zur Verfügung. Außerdem bedarf es eines kleinen Tricks, um die
// aktuelle Position des Cursors herauszufinden.
ie_getSelection(this);
var keyCode = event.keyCode;
if (keyCode == 0) {
keyCode = event.charCode;
}
} else {
var keyCode = evt.which;
if (keyCode == 0) {
keyCode = evt.charCode;
}
}
// Das Holen der aktuellen Auswahl in wikEd ist ziemlich ressourcenfressend, deshalb lieber vorher
// abbrechen, falls sowieso nichts korrigiert werden muss.
if (!(keyCode == 34 || keyCode == 45 || keyCode == 46 || keyCode == 39 || keyCode == 126 || keyCode == 62 || keyCode == 91)) {
return true;
}
if (typo_wiked_aktiv) {
wiked_getSelection(this);
}
var selStart = this.selectionStart;
var selEnde = this.selectionEnd;
if (!typo_wiked_aktiv) {
getCurLine(this);
}
// Wenn cancel = true, wird das eingegebene Zeichen nicht in das Textfeld eingefügt.
var cancel = false;
switch (keyCode) {
case 91: // öffnende eckige Klammer
// Wenn Text markiert ist, dann umschließt die Eingabe einer öffnenden eckigen
// Klammer ihn mit den Zeichen ].
if (selEnde - selStart > 0 && typo_link_mit_eckiger_klammer) {
insertTags("]", "");
cancel = true;
}
break;
case 34: // Zollzeichen
// Zollzeichen (") werden in typografische Anführungszeichen umgewandelt. Dabei wird
// ein öffendes Anführungszeichen gesetzt, wenn sich der Cursor am Anfang der Textbox
// befindet oder das Zeichen vor dem Cursor ein Leerzeichen, ein Zeilenumbruch oder
// eine Klammer ist. Falls das Zeichen vor dem Cursor eine Zahl ist, wird das Zeichen
// in ein typografisch korrektes Zollzeichen umgewandelt.
// FIXME: Der Internet Explorer ignoriert Zeilenumbrüche und gibt beim Cursor am
// Anfang der Zeile den Wert des letzten Zeichens in der Zeile darüber aus; deshalb
// funktioniert dort das Einfügen von öffnenden Anführungszeichen am Anfang der Zeile
// nicht.
// Bei der Eingabe von HTML-Attributen sollen ebenfalls keine typografischen
// Anführungszeichen verwendet werden. Die Ersetzung wird dann nicht vorgenommen,
// wenn direkt am Cursor ein Gleichheitszeichen steht oder sich der Cursor innerhalb
// eines HTML-Tags befindet und ein Gleichheitszeichen + Anführungszeichen schon
// eingegeben wurde.
if (selEnde - selStart > 0) {
// Wenn Text ausgewählt ist, diesen immer mit Anführungszeichen umgeben.
insertTags("„", "“", "");
cancel = true;
} else if (this.letzteEingabe("=") || this.letztesVorkommen("=\"") > this.letztesVorkommen(">") || this.letztesVorkommen("=\"") > this.letztesVorkommen("|}")) {
return true;
} else if (selStart - this.curLineOffset == 0 || this.letzteEingabe("\n") || this.letzteEingabe(" ")
|| this.letzteEingabe("(") || this.letzteEingabe("[") || this.letzteEingabe("{") || this.letzteEingabe("|")) {
// Ein einfaches öffnendes Anführungszeichen wird eingefügt, wenn ein doppeltes
// noch "offen" ist, d.h. wenn die Position eines öffnenden doppelten
// Anführungszeichens im Text größer ist als die eines schließenden doppelten
// Anführungszeichens.
if (!typo_immer_doppelte_anfuehrungszeichen && this.letztesVorkommen("„") > this.letztesVorkommen("“")) {
this.einfuegen("‚", 0);
} else {
this.einfuegen("„", 0);
}
} else {
// Ein typografisch korrektes Zollzeichen/Gradsekundenzeichen wird eingefügt, wenn das
// Zeichen am Cursor eine Zahl ist und der Cursor sich nicht innerhalb von Anführungszeichen
// befindet (in diesem Fall ist es wahrscheinlicher, dass ein schließendes
// Anführungszeichen eingegeben werden soll).
if (isNumeric(this.charAt(this.selectionStart - 1)) && this.letztesVorkommen("„") <= this.letztesVorkommen("“")) {
this.einfuegen("″", 0);
// Ein einfaches schließendes Anführungszeichen wird eingefügt, wenn ein einfaches
// Anführungszeichen noch "offen" ist (s.o.)
} else if (!typo_immer_doppelte_anfuehrungszeichen && this.letztesVorkommen("‚") > this.letztesVorkommen("‘")) {
this.einfuegen("‘", 0);
} else {
this.einfuegen("“", 0);
}
}
cancel = true;
break;
case 45: // Bindestrich
// Wenn schon ein Bindestrich davor steht, beide zu einem Gedanken- oder Bis-Strich
// zusammenfügen.
// Wenn aber mehrere Bindestriche davor stehen, soll wahrscheinlich eine horizontale
// Linie eingegeben werden; die Ersetzung wird dann rückgängig gemacht.
// Wenn ein HTML-Kommentar eingegeben werden soll ("<!--"), wird die Ersetzung nicht
// vorgenommen
if (this.letzteEingabe("–")) {
this.einfuegen("--", 1);
} else if (this.letzteEingabe("-") && !this.letzteEingabe("--") && !this.letzteEingabe("<!-")) {
this.einfuegen("–", 1);
cancel = true;
}
break;
case 46: // Punkt
// Drei aufeinanderfolgende Punkte werden in ein Auslassungszeichen (…) umgewandelt.
if (this.letzteEingabe("..")) {
this.einfuegen("…", 2);
cancel = true;
}
break;
case 39: // Apostroph
// Das Zeichen ' wird in einen typografischen Apostroph (’) umgewandelt, außer es steht
// davor schon ein ' (Auszeichnung "kursiv" oder "fett"). Wenn ein typografischer
// Apostroph davor steht, wird er ebenfalls durch ein ' ersetzt.
// Wenn als letztes eine Zahl eingegeben wurde (isNumeric), wird ein Gradminuten- bzw.
// Fußzeichen eingefügt.
if (this.letzteEingabe("’") || this.letzteEingabe("′")) {
this.einfuegen("''", 1);
cancel = true;
} else if (isNumeric(this.charAt(this.selectionStart - 1))) {
this.einfuegen("′", 0);
cancel = true;
} else if (!this.letzteEingabe("'")) {
this.einfuegen("’", 0);
cancel = true;
}
break;
case 126: // Tilde
if (typo_kein_gedankenstrich_bei_signatur) {
// Bei der Signatur sollen zwei Bindestriche nicht durch einen Gedankenstrich ersetzt
// werden. Deshalb wird bei der Eingabe einer Tilde diese Ersetzung ggf. wieder rück-
// gängig gemacht:
// - bei Signatur ohne Leerzeichen zwischen Bindestrichen und Tilden
if (!typo_signatur_mit_leerzeichen && this.letzteEingabe("–")) {
this.einfuegen("--", 1);
// - bei Signatur mit Leerzeichen
} else if (typo_signatur_mit_leerzeichen && this.letzteEingabe("– ")) {
if (typo_signatur_mit_leerzeichen_nbsp) {
if (typo_wiked_aktiv) {
this.einfuegen("--&nbsp;", 2);
} else {
this.einfuegen("-- ", 2);
}
} else {
this.einfuegen("-- ", 2);
}
}
} else {
// Der Gedankenstrich soll so bleiben, nicht ersetzt werden. Eventuell soll aber
// das Leerzeichen durch ein geschütztes Leerzeichen ersetzt werden.
if (typo_signatur_mit_leerzeichen && typo_signatur_mit_leerzeichen_nbsp && this.letzteEingabe("– ")) {
if (typo_wiked_aktiv) {
this.einfuegen("&nbsp;", 1);
} else {
this.einfuegen(" ", 1);
}
}
}
break;
case 62: // schließende eckige Klammer (>)
// Beim schließenden Tag eines HTML-Kommentars ("-->") sollen zwei Bindestriche nicht
// durch einen Gedankenstrich ersetzt werden.
if (this.letzteEingabe("–")) {
this.einfuegen("--", 1);
} else if (this.letzteEingabe("-") && !this.letzteEingabe("--")) {
this.einfuegen("→", 1);
cancel = true;
}
break;
}
// Wenn cancel = true, weitere Ereignisbehandlung abbrechen
if (typo_wiked_aktiv && cancel) {
evt.preventDefault();
return true;
} else {
return !cancel;
}
}
function typo_find_textbox() {
if (typo_is_css_js_subpage) {
return null;
} else if (document.getElementById("wpTextbox1")) {
if (!document.getElementById("wpTextbox1").readOnly) {
return document.getElementById("wpTextbox1");
}
} else if (typo_auch_benutzer_email && document.getElementById("wpText")) {
return document.getElementById("wpText");
} else if (typo_auch_upload_form && document.getElementById("wpUploadDescription")) {
return document.getElementById("wpUploadDescription");
}
return null;
}
function typo_textbox_init() {
typo_textbox.onkeypress = autokorrektur;
typo_textbox.letzteEingabe = function(vergleich) { return letzteEingabe(this, vergleich); }
typo_textbox.einfuegen = function(text, anzahlLoeschen) { return einfuegen(this, text, anzahlLoeschen); }
typo_textbox.letztesVorkommen = function(text) { return letztesVorkommen(this, text); }
typo_textbox.charAt = function(position) { return charAt(this, position); }
if (typo_zeige_checkbox) {
var checkbox = createCheckbox();
if (document.getElementById("toolbar")) {
document.getElementById("toolbar").appendChild(checkbox);
} else if (document.getElementById("wikiEditor-ui-toolbar")) {
document.getElementById("wikiEditor-ui-toolbar").appendChild(checkbox);
} else {
if (typo_quickedit && typeof qeNodes !== 'undefined') { // Workaround
var frm = qeNodes.Form;
frm.parentNode.insertBefore(checkbox, frm);
} else {
typo_textbox.parentNode.insertBefore(checkbox, typo_textbox);
}
}
}
}
function typo_init() {
typo_textbox = typo_find_textbox();
if (typo_textbox != null) {
typo_textbox_init();
}
}
function typo_qe_init() {
typo_textbox = qeNodes.Form.firstChild.childNodes;
if (typo_textbox != null) {
typo_textbox_init();
}
}
$(typo_init);
if (!typo_is_css_js_subpage) {
// Ereignis-Handler für das Aktivieren und Deaktivieren von wikEd registrieren
if (typeof(wikEd) == 'undefined') { wikEd = {}; }
if (typeof(wikEd.config) == 'undefined') { wikEd.config = {}; }
if (typeof(wikEd.config.setupHook ) == 'undefined') { wikEd.config.setupHook = ; }
if (typeof(wikEd.config.onHook ) == 'undefined') { wikEd.config.onHook = ; }
if (typeof(wikEd.config.offHook ) == 'undefined') { wikEd.config.offHook = ; }
wikEd.config.setupHook.push(setupForWikEd);
wikEd.config.onHook.push(wikEdAktiviert);
wikEd.config.offHook.push(wikEdDeaktiviert);
// Ereignis-Handler für das Aktivieren von QuickEdit (Benutzer:ASM) registrieren.
if (typo_quickedit) {
if (typeof qeAddHook !== 'undefined') {
qeAddHook("qeMakeForm", typo_qe_init);
}
}
}