// ==UserScript==
// @name          BBCode Eingabevereinfachung fuer das CForum
// @namespace     http://jeenaparadies.net/t/
// @description   Fuegt BBCode Buttons ueber der Textarea ein
// @include       http://forum.de.selfhtml.org/*
// @exclude       http://forum.de.selfhtml.org/cgi-bin/user/fo_userconf
// ==/UserScript==

/**
 *         Titel: BBCode Eingabevereinfachung fuer das CForum <http://wwwtech.de/cforum/>
 *        Author: Jeena Paradies <http://jeenaparadies.net> <info@jeenaparadies.net>,
 *                J. Strübig <struebig@gmx.net> (Modifikationen )
 *       Version: 0.6.0-greasemonkey
 *         Datum: 21. November 2006
 *        Lizenz: GPL <http://gnu.org/licenses/gpl.txt>
 *  Beschreibung: Mit diesem JavaScript erscheinen ueber der Textarea des CForums
 *                [Link], [Bild] und verschiedene [code] Buttons. Diese Buttons
 *                erleichtern die Eingabe von BBCode indem sie ggf. den markierten
 *                Text mit einbeziehen und mit anderen Angaben aus der Eingabeaufforderung
 *                an Cursorposition einfuegen (falls es der Browser beherscht). Zum stylen
 *                haben die Buttons die CSS Klasse jeena_bbcode.
 *
 *  Installation: Greasemonkey <http://greasemonkey.mozdev.org/> muss installiert sein,
 *                danach einfach auf den Link klicken und installieren. Eventuell möchte
 *                man die @include Regel (siehe oben) noch für andere CForen erweitern,
 *                im Orginal wirkt es nur im SELFHTML-Forum.
 *
 *   Erweiterung: Ausser den voreingestellten Buttons kann man sich eigene Buttons erstellen.
 *
 *                = code =
 *                Das CForum bietet ein Syntaxhighlighting fuer verschiedene Sprachen an
 *                <http://vms.wwwtech.de/cgi-bin/viewcvs.cgi/svn/cforum/trunk/conf/patterns/>.
 *                Fuer jede einzelne kann man sich bei Bedarf einen Button selbst hinzufuegen.
 *                Und das geht so: Unter bbcode.createButton('Perl', 'code','perl'); fügt man
 *                je Button eine Zeile mit bbcode.createButton('BUTTONNAME', 'code', 'sprache');
 *                ein, wobei 'BUTTONNAME' innerhalb des Buttons angezeigt wird und 'sprache'
 *                der Anfangsname eines der zur Verfuegung stehenden Patterns sein muss, bei
 *                pascal.pat waere dass dann z.B. pascal und bei xml.pat waere es xml. 'code'
 *                zeigt dem Script an, dass es sich um einen Quellcode handelt der ausgezeichnet
 *                wird.
 *
 *                = weiterer BBCode =
 *                Auch wenn es normalerweise aus ist, bietet das cforum durchaus die Moeglichkeit
 *                BBCode wie [b], [i] und aehnliches anzubieten. Um einen solchen Button zu
 *                erstellen geht man aehnlich wie bei den Sprachenbuttons vor. Hier ein Beispiel:
 *                bbcode.createButton('BUTTONNAME', 'b'); wobei dann [b] vor den
 *                markierten Text eingefuegt wird und [/b] danach.
 */

window.onload = function() {
	if(!document.getElementsByTagName) return;
	var textarea = document.getElementsByTagName('textarea')[0];
	
	if(!textarea) return;
	
	var br = document.createElement("br");
	
	// Platz für die Buttons schaffen
	textarea.parentNode.insertBefore(br, textarea);
	
	// Die Buttons anlegen
	createButton('Link', 'link');
	createButton('Bild', 'image');
	createButton('HTML', 'code', 'html');
	createButton('CSS', 'code', 'css');
	createButton('JS', 'code', 'javascript');
	createButton('PHP', 'code', 'php');
	createButton('Perl', 'code', 'perl');
	
	/*
	createButton() - fügt den Button oberhalb der Textarea ein
	*/
	function createButton (titel, aTag, eTag) {
		var button = document.createElement("input");
		button.type = 'button';
		button.className = 'jeena_bbcode';
		button.onclick = function() { insert(aTag, eTag);  };
		button.value = titel;
		br.parentNode.insertBefore(button, br);
	}
	
	// Suchmuster
	var url  = new RegExp('^(http://|https://|www.|ftp://|news:|mailto:|nntp:|telnet:|gopher:).');
	var mail = new RegExp('^[^@]+@[^@]+\.[a-zA-Z]+$');
	var http = new RegExp('^(http://)');
	var nl = new RegExp('(\015\012|\015|\012)');
	
	// insert - die iegentliche Funktion zum, einfügen des Code
	function insert (aTag, eTag){
		textarea.focus();
		
		if(typeof document.selection != 'undefined') {
			/* fuer Internet Explorer und Opera >= 8 */
			var range = document.selection.createRange();
			var insText = getInsertText( range.text, aTag, eTag );
			if(!insText) return;
			range.text = insText;
			
			if (insText.length == 0) range.move('character', -1);
			else range.moveStart('character', insText.length);

		} else if(typeof textarea.selectionStart != 'undefined'){
			
			/* fuer neuere auf Gecko basierende Browser */
			var start = textarea.selectionStart;
			var end = textarea.selectionEnd;
			var insText = getInsertText( textarea.value.substring(start, end), aTag, eTag );
			if(!insText) return;
			textarea.value = textarea.value.substr(0, start) + insText  + textarea.value.substr(end);
			
			var pos;
			if (insText.length == 0) pos = start + aTag.length + 1;
			else pos = start + insText.length;
			
			textarea.selectionStart = pos;
			textarea.selectionEnd = pos;
    } else {
		/* fuer die uebrigen Browser */
		var insText = getInsertText( '', aTag, eTag);
		textarea.value += insText;
	}
	}
	
	// getInsertText - prüft ob die Funktion aTag existiert und formatiert den Text
	function getInsertText (insText, aTag, eTag) {
		if (typeof functions[aTag] == 'function')  return functions[aTag](insText, eTag);
		return bbcode( insText, aTag, eTag);
	}
	
	// newline - enthält der Text Newline Zeichen
	function newline (insText) {
		if(nl.test(insText)) {
			alert('Der markierte Text darf keine Zeilenumbrueche enthalten');
			return true;
		}
		return false;
	}
	
	// Die Liste der möglichen Funktionen.
	var functions = {
		image: function(insText){
			if(newline(insText)) return '';
			var href = insText;
			var node = '';
			if(url.test(insText)) {
				// Text ist ein Link
				node = prompt('Alternativtext eingeben:', '');
			} else {
				// Text ist ein Text
				node = insText;
				if(!node) node = prompt('Alternativtext eingeben:');
				href = prompt('Bild URL eingeben:', 'http://');
			}
			if (!http.test(href)) href = 'http://' + href;
			return href ? 
			'[image:' + href + (node ? '@alt=' + node : '') + ']'
			: insText;
		},
		// code() -
		code: function(insText, lang ) {
			return '[code lang=' + lang + ']' + insText + '[/code]';
		},
		// bbCode()
		bbcode: function(insText, aTag, eTag ) {
			return '[' + aTag + ']' + insText + '[/' + (eTag || aTag)  +']';
		},
		// link()
		link: function(insText) {
			if(newline(insText)) return '';
			var node;
			var href;
			if( url.test(insText) || mail.test(insText) ) {
				// Der Text ist ein Link
				href = insText || prompt('URL eingeben:', '');
				
				if (mail.test(href)) href = 'mailto:' + insText;
				else if (!http.test(href)) href = 'http://' + insText;
				
				node = prompt('Linktext eingeben:', '');
			} else {
				// Der Text ist der Titel
				node = insText || prompt('Linktext eingeben:', '')
				href = prompt('URL eingeben:', 'http://');
				if (!http.test(href)) href = 'http://' + href;
			}
			return href ? 
			'[link:' + href + (  node ? '@title=' + node : '' ) + ']'
			: insText
			;
		}
	};
}
