Доброго времени суток.

Потребовался мне простенький редактор для моего сайта. Главная задача была — поддержка табуляции. Искал в интернете, но так и не нашёл того, что мне нужно и решил написать сам.


Так как в своих проектах я использую jQuery, то решил сделать простенький плагин для этой библиотеки.

В javascript'e я не силён, так что код получился немного корявым:).
В общем, если кому-нибудь понадобиться, то прошу.

Рабочий пример можно посмотреть тут.

html:
<textarea id="redactor" cols="" rows=""></textarea>
<script type="text/javascript">$("#redactor").redactorpp();</script>


Собственно сам плагин:
jQuery.fn.redactorpp = function() {
	var obj=document.getElementById(jQuery(this).attr('id'));
	var jobj=jQuery(this);
  
	return this.each(function(){
	 $.browser.opera ? jobj.keypress(function(e){return keys(e)}) : jobj.keydown(function(e){return keys(e)});
	});
	
	function keys(e){
	if (e.which == 9 || e.which==0) return addTab();
	else if(e.which==13) return enterKey();
	else return true;
	}
	
	function enterKey(){
	obj.focus();
	var scrollHeightBefore=obj.scrollHeight;
	var scrollTop=obj.scrollTop;
	if (obj.selectionStart || obj.selectionStart == '0'){
		var cursor = getCaretPos();
		var before = obj.value.substr(0,cursor);
		var after = obj.value.substr(cursor,obj.value.length)
		var res=getTabs(before);
		obj.value=before;
		scrollHeightAfter=obj.scrollHeight;
		obj.value+="\r\n"+res+after;
		$.browser.opera ? cursor+=res.length+2 : cursor+=res.length+1;
		obj.setSelectionRange(cursor,cursor);
		obj.focus();
		}
	else if (document.selection){
		var before=ieStartEnd(true);
		var after=ieStartEnd(false);
		var res=getTabs(before);
		var s = document.selection.createRange();
		s.text = "\r\n"+res;
		scrollHeightAfter=obj.scrollHeight;
		s.select();
		}
	scrollHeightAfter==scrollHeightBefore ? obj.scrollTop=scrollTop+100 : obj.scrollTop=scrollTop;
	return false;
	}
	
	function getTabs(before){
	var res='';
	myArray = /(?:\r\n)?([\t ]*)\S?.*$/.exec(before);
		if (myArray != null)
			for ( i = 1; i < myArray.length; i++ ) res =res + myArray[i];
	return res;
	}
	
	function ieStartEnd(isBefore){
		var s = document.selection.createRange(), r = s.duplicate()
		r.moveToElementText(obj)
		if (isBefore) r.setEndPoint('EndToStart', s)
		else r.setEndPoint('StartToEnd', s)
		var txt = r.text, old = s.text.length, cont = true
		do { s.moveStart('character', -1)} while ((s.text.length==old) && (txt+='\n'))
		return txt;
		}
	
	function addTab(){
	obj.focus();
	if (obj.selectionStart || obj.selectionStart == '0'){
		var cursor = getCaretPos();
		var before=obj.value.substr(0,cursor)
		var after=obj.value.substr(cursor,jobj.val().length);
		obj.value=before+"\t"+after;
		cursor++;
		obj.setSelectionRange(cursor,cursor);
		obj.focus();
		return false;
		}
	else if (document.selection){
		document.selection.createRange().text='\t';
		return false;
		}
	return false;
	}
	
	function getCaretPos(){
	obj.focus();
	if(obj.selectionStart || obj.selectionStart == '0')
		return obj.selectionStart;
	else if (document.selection){
		var sel = document.selection.createRange();
		var clone = sel.duplicate();
		sel.collapse(true);
		clone.moveToElementText(obj);
		clone.setEndPoint('EndToEnd', sel);
		return clone.text.length;
		}
	 return false;
	}
}