/*! NicEdit - Micro Inline WYSIWYG
 * Copyright 2007-2008 Brian Kirchoff
 *
 * NicEdit is distributed under the terms of the MIT license
 * For more information visit http://nicedit.com/
 * Do not remove this copyright message
 */

 /*
 *This is a modified version of nicedit	Version 0.9.0b (March 20th, 2008)
 *There are few modified parts which have been modified to be compatible with the rootscript.js (validation and field submission)
 *When doing an update of that file you should probably reuse the modification I did in the past.
 *To access my modification look for the following string :  [HACK_START]
 *@author : Ben
 */
jCore.nedit=true;

var bkExtend=function(){
	var A=arguments;
	if(A.length==1){
		A=[this,A[0]]
	}
	for(var B in A[1]){
		A[0][B]=A[1][B]
	}
	return A[0]
};

//main class which contains prototype and class extension system and definition
function bkClass(){}

//prototype(W3C) function to add a property to an object
//we add the constructor to it
bkClass.prototype.construct=function(){};

//extend function contains class definition and variables storage
//def is an array of property and methods
bkClass.extend=function(C){

	var A=function(){
		if(arguments[0]!==bkClass){
			return this.construct.apply(this,arguments)
		}
	};

	var B=new this(bkClass);
	bkExtend(B,C);
	A.prototype=B;
	A.extend=this.extend;

	return A
};

var bkElement=bkClass.extend({

	//constructor
	construct:function(A){
		if(typeof (A)=="string"){
			A=document.createElement(A)
		}
		A=$BK(A);
		return A
	},

	appendTo:function(A){
		A.appendChild(this);
		return this
	},

	appendBefore:function(A){
		A.parentNode.insertBefore(this,A);
		return this
	},

	addEvent:function(B,A){
		bkLib.addEvent(this,B,A);
		return this
	},

	setContent:function(A){
		this.innerHTML=A;
		return this
	},

	//get some offset value
	pos:function(){
		var C=curtop=0;
		var B=obj=this;
		if(obj.offsetParent){
			do{
				C+=obj.offsetLeft;
				curtop+=obj.offsetTop
			}
			while(obj=obj.offsetParent)
		}
		var A=(!window.opera)?parseInt(this.getStyle("border-width")||this.style.border)||0:0;
		return[C+A,curtop+A+this.offsetHeight]
	},

	noSelect:function(){
		bkLib.noSelect(this);
		return this
	},

	parentTag:function(A){
		var B=this;
		do{
			if(B&&B.nodeName&&B.nodeName.toUpperCase()==A){
				return B
			}
			B=B.parentNode
		}
		while(B);
		return false
	},

	hasClass:function(A){
		return this.className.match(new RegExp("(\\s|^)nicEdit-"+A+"(\\s|$)"))
	},

	addClass:function(A){
		if(!this.hasClass(A)){
			this.className+=" nicEdit-"+A
		}
		return this
	},

	removeClass:function(A){
		if(this.hasClass(A)){
			this.className=this.className.replace(new RegExp("(\\s|^)nicEdit-"+A+"(\\s|$)")," ")
		}
		return this
	},

	//set style of an element based on an array of elements
	setStyle:function(A){
		var B=this.style;

		//foreach in javascript A is array and C is each entry of the array
		for(var C in A){
			switch(C){
				case"float":
					B.cssFloat=B.styleFloat=A[C];
					break;
				case"opacity":
					B.opacity=A[C];
					B.filter="alpha(opacity="+Math.round(A[C]*100)+")";
					break;
				case"className":
					this.className=A[C];
					break;
				default:
					B[C]=A[C]
			}
		}
		return this
	},

	//get style of an element based on a param C
	//return
	getStyle:function(A,C){
		var B=(!C)?document.defaultView:C;
		if(this.nodeType==1){
			return(B&&B.getComputedStyle)?B.getComputedStyle(this,null).getPropertyValue(A):this.currentStyle[bkLib.camelize(A)]
		}
	},

	remove:function(){
		this.parentNode.removeChild(this);
		return this
	},

	setAttributes:function(A){
		for(var B in A){
			this[B]=A[B]
		}
		return this
	}

});


var bkLib={

	isMSIE:(navigator.appVersion.indexOf("MSIE")!=-1),

	//??
	addEvent:function(C,B,A){
		(C.addEventListener)?C.addEventListener(B,A,false):C.attachEvent("on"+B,A)
	},

	//to convert a string to an array probably
	toArray:function(C){
		var B=C.length,A=new Array(B);
		while(B--){
			A[B]=C[B]
		}
		return A
	},

	//to set an element to unselectable so that it is not possible to copy
	//warning though the setAttribute function probably needs to be replaced on some other browsers
	noSelect:function(B){
		if(B.setAttribute&&B.nodeName.toLowerCase()!="input"&&B.nodeName.toLowerCase()!="textarea"){
			B.setAttribute("unselectable","on")
		}
		//we set as unselectables the child element of the main one "element"
		for(var A=0;A<B.childNodes.length;A++){
			bkLib.noSelect(B.childNodes[A])
		}
	},

	camelize:function(A){
		return A.replace(/\-(.)/g,function(B,C){return C.toUpperCase()})
	},

	//in array function pretty handy
	//check for a value in one array
	inArray:function(A,B){
		return(bkLib.search(A,B)!=null)
	},

	search:function(A,C){
		for(var B=0;B<A.length;B++){
			if(A[B]==C){return B}
		}
		return null
	},

	//??
	cancelEvent:function(A){
		A=A||window.event;
		if(A.preventDefault&&A.stopPropagation){
			A.preventDefault();
			A.stopPropagation()
		}
		return false
	},

	//??
	domLoad:[],
	//??
	domLoaded:function(){
		if(arguments.callee.done){return }
		arguments.callee.done=true;
		for(i=0;i<bkLib.domLoad.length;i++){
			bkLib.domLoad[i]()
		}
	},

	//we increment an array of event to fire on domloaded
	onDomLoaded:function(A){
		this.domLoad.push(A);

		//to know when the DOM is loaded on mozilla
		if(document.addEventListener){
			document.addEventListener("DOMContentLoaded",bkLib.domLoaded,null)
		}
		else{
			//??
			if(bkLib.isMSIE){
				document.write("<script id=__ie_onload defer "+((location.protocol=="https:")?"src='javascript:void(0)'":"src=//0")+"><\/script>");
				$BK("__ie_onload").onreadystatechange=function(){
					if(this.readyState=="complete"){bkLib.domLoaded()}
				}
			}
		}
		window.onload=bkLib.domLoaded
	}

};

//a quick function to get element by id
function $BK(A){

	if(typeof (A)=="string"){
		A=document.getElementById(A)
	}

	return(A&&!A.appendTo)?bkExtend(A,bkElement.prototype):A
}

//to manage events
var bkEvent={

	//we add the event to the event array if the function to trigger is defined
	addEvent:function(A,B){
		if(B){
			this.eventList=this.eventList||{};
			this.eventList[A]=this.eventList[A]||[];
			this.eventList[A].push(B)
		}
		return this
	},

	//we trigger the event of this type with the following arguments
	fireEvent:function(){
		var A=bkLib.toArray(arguments),C=A.shift();
		if(this.eventList&&this.eventList[C]){
			for(var B=0;B<this.eventList[C].length;B++){
				this.eventList[C][B].apply(this,A)
			}
		}
	}

};

function __(A){return A}

//??
Function.prototype.closure=function(){

	var A=this,B=bkLib.toArray(arguments),C=B.shift();

	return function(){
		if(typeof (bkLib)!="undefined"){
			return A.apply(C,B.concat(bkLib.toArray(arguments)))
		}
	}

};

//??
Function.prototype.closureListener=function(){

	var A=this,C=bkLib.toArray(arguments),B=C.shift();

	return function(E){
		E=E||window.event;
		if(E.target){
			var D=E.target
		}
		else{
			var D=E.srcElement
		}
		return A.apply(B,[E,D].concat(C))
	}
};


var nicEditorConfig = bkClass.extend({
	buttons : {
		'bold' : {name : __('Click to Bold'), command : 'Bold', tags : ['B','STRONG'], css : {'font-weight' : 'bold'}, key : 'b'},
		'italic' : {name : __('Click to Italic'), command : 'Italic', tags : ['EM','I'], css : {'font-style' : 'italic'}, key : 'i'},
		'underline' : {name : __('Click to Underline'), command : 'Underline', tags : ['U'], css : {'text-decoration' : 'underline'}, key : 'u'},
		'left' : {name : __('Left Align'), command : 'justifyleft', noActive : true},
		'center' : {name : __('Center Align'), command : 'justifycenter', noActive : true},
		'right' : {name : __('Right Align'), command : 'justifyright', noActive : true},
		'ol' : {name : __('Insert Ordered List'), command : 'insertorderedlist', tags : ['OL']},
		'ul' : 	{name : __('Insert Unordered List'), command : 'insertunorderedlist', tags : ['UL']},
		'subscript' : {name : __('Click to Subscript'), command : 'subscript', tags : ['SUB']},
		'superscript' : {name : __('Click to Superscript'), command : 'superscript', tags : ['SUP']},
		'strikethrough' : {name : __('Click to Strike Through'), command : 'strikeThrough', css : {'text-decoration' : 'line-through'}},
		'indent' : {name : __('Indent Text'), command : 'indent', noActive : true},
		'outdent' : {name : __('Remove Indent'), command : 'outdent', noActive : true},
		'hr' : {name : __('Horizontal Rule'), command : 'insertHorizontalRule', noActive : true}
	},
	iconsPath : '../nicEditorIcons.gif',
	buttonList : ['bold','italic','underline','left','center','right','ol','ul','fontSize','fontFamily','fontFormat','indent','outdent','link','image'],
	iconList : {"xhtml":1,"bgcolor":2,"forecolor":3,"bold":4,"center":5,"hr":6,"indent":7,"italic":8,"justify":9,"left":10,"ol":11,"outdent":12,"right":13,"save":14,"strikethrough":15,"subscript":16,"superscript":17,"ul":18,"underline":19,"image":20,"link":21,"unlink":22,"close":23,"arrow":24}

});
;

var nicEditors={

	nicPlugins:[],
	editors:[],

	registerPlugin:function(B,A){
		this.nicPlugins.push({p:B,o:A})
	},

	//to convert all the textareas on a page with nicedit
	allTextAreas:function(C){
		var A=document.getElementsByTagName("textarea");
		for(var B=0;B<A.length;B++){
			nicEditors.editors.push(new nicEditor(C).panelInstance(A[B]))
		}
		return nicEditors.editors
	},

	findEditor:function(C){
		var B=nicEditors.editors;
		for(var A=0;A<B.length;A++){
			if(B[A].instanceById(C)){
				return B[A]
			}
		}
	}
};

//the class that describe the niceditor creation
//it extends bkClass to have all of its functionalities
var nicEditor=bkClass.extend({

	//constructor
	construct:function(C){
		this.options=new nicEditorConfig();
		bkExtend(this.options,C);
		this.nicInstances=new Array();
		this.loadedPlugins=new Array();
		var A=nicEditors.nicPlugins;
		for(var B=0;B<A.length;B++){
			this.loadedPlugins.push(new A[B].p(this,A[B].o))
		}
		nicEditors.editors.push(this);

		//add an event to the library on mousedown we check that this element is selected or something
		//im not sure about the way this is written selectCheck is a function but it looks like an object the way its called
		//??
		bkLib.addEvent(document.body,"mousedown",this.selectCheck.closureListener(this))
	},

	//create an instance of nicEditor for a textarea based on an id
	panelInstance:function(B,C){
		//[HACK_START]
		//for current compatibility with our library
		//we need to record each element id of the textareas
		if(typeof(B) == "string") {
			jareaids.push(B);
		}
		//[HACK_END]
		B=this.checkReplace($BK(B));
		var A=new bkElement("DIV").setStyle({width:(parseInt(B.getStyle("width"))||B.clientWidth)+"px"}).appendBefore(B);
		this.setPanel(A);
		return this.addInstance(B,C)
	},

	checkReplace:function(B){
		var A=nicEditors.findEditor(B);
		if(A){
			A.removeInstance(B);
			A.removePanel()
		}
		return B
	},

	//this add the instance based on the browser
	addInstance:function(B,C){
		B=this.checkReplace($BK(B));
		if(B.contentEditable||!!window.opera){
			//this create a div within the webpage but then it's all not possible to edit
			//the content
			var A=new nicEditorInstance(B,C,this)
		}
		else{
			//this is how it works on mozilla and ie it generates an iframe
			//which is like a totally new webpage
			var A=new nicEditorIFrameInstance(B,C,this)
		}
		this.nicInstances.push(A);
		this.fireEvent("add",A);
		return this
	},

	removeInstance:function(C){
		C=$BK(C);
		var B=this.nicInstances;
		for(var A=0;A<B.length;A++){
			if(B[A].e==C){
				B[A].remove();
				this.nicInstances.splice(A,1)
			}
		}
	},

	removePanel:function(A){
		if(this.nicPanel){
			this.nicPanel.remove();
			this.nicPanel=null
		}
	},

	instanceById:function(C){
		C=$BK(C);
		var B=this.nicInstances;
		for(var A=0;A<B.length;A++){
			if(B[A].e==C){
				return B[A]
			}
		}
	},

	//i guess it create the top part of the editor with all the buttons
	setPanel:function(A){
		this.nicPanel=new nicEditorPanel($BK(A),this.options,this);
		this.fireEvent("panel",this.nicPanel);
		return this
	},

	//this may be a key element to develop more buttons for that editor
	nicCommand:function(B,A){
		if(this.selectedInstance){
			this.selectedInstance.nicCommand(B,A)
		}
	},

	getIcon:function(D,A){
		var C=this.options.iconList[D];
		var B=(A.iconFiles)?A.iconFiles[D]:"";
		return{backgroundImage:"url('"+((C)?this.options.iconsPath:B)+"')",backgroundPosition:((C)?((C-1)*-18):0)+"px 0px"}
	},

	//what's the C doing here ??
	//A looks like an element on which we check that the class name contains nicEdit i think
	//A could be the document
	selectCheck:function(C,A){
		var B=false;
		do{
			if(A.className&&A.className.indexOf("nicEdit")!=-1){return false}
		}
		while(A=A.parentNode);
		this.fireEvent("blur",this.selectedInstance,A);
		this.lastSelectedInstance=this.selectedInstance;
		this.selectedInstance=null;
		return false
	}
});

nicEditor=nicEditor.extend(bkEvent);


//the nicEditorInstance class which extends the lib class
//this is not used on mozilla or firefox
var nicEditorInstance=bkClass.extend({

	isSelected:false,

	//parameters passed are element id:F , D:options(buttonlist ,etc..):o , C:nicEditor instance
	construct:function(F,D,C){
		this.ne=C;
		this.elm=this.e=F;
		this.options=D||{};
		newX=parseInt(F.getStyle("width"))||F.clientWidth;newY=parseInt(F.getStyle("height"))||F.clientHeight;
		this.initialHeight=newY-8;
		var G=(F.nodeName.toLowerCase()=="textarea");

		if(G||this.options.hasPanel){

			//we create divs to which we assign the value of the textarea, and style the divs
			this.editorContain=new bkElement("DIV").setStyle({
				width:newX+"px",border:"1px solid #ccc",borderTop:0,overflowY:"auto",overflowX:"hidden",maxHeight:(this.ne.options.maxHeight)?this.ne.options.maxHeight+"px":null
			}).appendBefore(F);

			var A=new bkElement("DIV").setStyle({
				width:(newX-8)+"px",margin:"4px",minHeight:newY+"px"
			}).addClass("main").appendTo(this.editorContain);

			//we hide the textarea
			F.setStyle({display:"none"});

			if(G){
				//we look for forms and add an event on submit to trigger
				A.setContent(F.value);
				this.copyElm=F;
				while(F=F.parentNode){
					if(F.nodeName=="FORM"){
						bkLib.addEvent(F,"submit",this.saveContent.closure(this))
					}
				}
			}
			else{
				A.innerHTML=F.innerHTML
			}

			//we style a bit more depending on the browser
			var B=(bkLib.isMSIE&&!((typeof document.body.style.maxHeight!="undefined")&&document.compatMode=="CSS1Compat"));
			A.setStyle((B)?{height:newY+"px"}:{overflow:"hidden"});
			this.elm=A
		}

		this.ne.addEvent("blur",this.blur.closure(this));
		this.init();this.blur();
		try{
			this.nicCommand("styleWithCSS",true)
		}
		catch(E){}
	},

	//the initialising function
	init:function(){
		//we set it as editable whatever it is
		this.elm.setAttribute("contentEditable","true");

		//we need to record each iframe with those textarea into an array
		//[HACK_START]
		//we need to record each iframe with those textarea into an array
		jnedinst.push(this.elm);
		//jnedfd.push(this.frameDoc);
		//[HACK_END]

		//i guess it doesn't work if we dont have anything in the div
		//so we put some br
		if(this.getContent()==""){
			this.setContent("<br />")
		}
		this.instanceDoc=document.defaultView;
		this.elm.addEvent("mousedown",this.selected.closureListener(this)).addEvent("keypress",this.keyDown.closureListener(this)).addEvent("focus",this.selected.closure(this)).addEvent("blur",this.blur.closure(this)).addEvent("keyup",this.selected.closure(this))
	},

	remove:function(){
		this.saveContent();
		if(this.copyElm||this.options.hasPanel){
			this.editorContain.remove();
			this.e.setStyle({
				display:"block"
			});
			this.ne.removePanel()
		}
		this.disable();
		this.ne.fireEvent("removeInstance",this)
	},

	disable:function(){
		this.elm.setAttribute("contentEditable","false")
	},

	//returns the element which is selected maybe
	//probably used for the undo/redo
	getSel:function(){
		return(window.getSelection)?window.getSelection():document.selection
	},

	//get range ???
	//probably used for the undo/redo
	getRng:function(){
		var A=this.getSel();
		if(!A){
			return null
		}
		return(A.rangeCount>0)?A.getRangeAt(0):A.createRange()
	},

	//select range ???
	//probably used for the undo/redo
	selRng:function(A,B){
		if(window.getSelection){
			B.removeAllRanges();
			B.addRange(A)
		}
		else{
			A.select()
		}
	},

	selElm:function(){
		var C=this.getRng();
		if(C.startContainer){
			var D=C.startContainer;
			if(C.cloneContents().childNodes.length==1){
				for(var B=0;B<D.childNodes.length;B++){
					var A=D.childNodes[B].ownerDocument.createRange();A.selectNode(D.childNodes[B]);
					if(C.compareBoundaryPoints(Range.START_TO_START,A)!=1&&C.compareBoundaryPoints(Range.END_TO_END,A)!=-1){
						return $BK(D.childNodes[B])
					}
				}
			}
			return $BK(D)
		}
		else{
			return $BK((this.getSel().type=="Control")?C.item(0):C.parentElement())
		}
	},

	//???
	//probably used for the undo/redo
	saveRng:function(){
		this.savedRange=this.getRng();
		this.savedSel=this.getSel()
	},

	//??
	//probably used for the undo/redo
	restoreRng:function(){
		if(this.savedRange){
			this.selRng(this.savedRange,this.savedSel)
		}
	},

	keyDown:function(C,B){
		if(C.keyCode==13){
			if(bkLib.isMSIE){
				var A=this.getRng();
				A.pasteHTML("<br />");
				A.collapse(false);
				A.select();
				return false
			}
		}
		if(C.ctrlKey){
			this.ne.fireEvent("key",this,C);
			if(C.preventDefault){
				C.preventDefault()
			}
			return false
		}
	},

	//switch the state of the instance if selected
	selected:function(C,A){
		if(!A){
			A=this.selElm()
		}
		if(!C.ctrlKey){
			var B=this.ne.selectedInstance;
			if(B!=this){
				if(B){
					this.ne.fireEvent("blur",B,A)
				}
				this.ne.selectedInstance=this;
				this.ne.fireEvent("focus",B,A)
			}
			this.ne.fireEvent("selected",B,A);
			this.isFocused=true;
			this.elm.addClass("selected")
		}
		return false
	},

	blur:function(){
		this.isFocused=false;
		this.elm.removeClass("selected")
	},

	saveContent:function(){
		if(this.copyElm||this.options.hasPanel){
			this.ne.fireEvent("save",this);
			(this.copyElm)?this.copyElm.value=this.getContent():this.e.innerHTML=this.getContent()
		}
	},

	getElm:function(){
		return this.elm
	},

	//return the content of the div
	getContent:function(){
		this.content=this.getElm().innerHTML;
		this.ne.fireEvent("get",this);
		return this.content
	},

	//set the content of the div
	setContent:function(A){
		this.content=A;
		this.ne.fireEvent("set",this);
		this.elm.innerHTML=this.content
	},

	//the method execCommand is accepted on ie and mozilla and is for the rich text formatting option
	nicCommand:function(B,A){
		document.execCommand(B,false,A)
	}
});

//the one that interest us i think..
// used under mozilla and ie
var nicEditorIFrameInstance=nicEditorInstance.extend({

	savedStyles:[],init:function(){
		var B=this.elm.innerHTML.replace(/^\s+|\s+$/g,"");
		this.elm.innerHTML="";
		(!B)?B="<br />":B;
		this.initialContent=B;
		this.elmFrame=new bkElement("iframe").setAttributes({src:"javascript:;",frameBorder:0,allowTransparency:"true",scrolling:"no"}).setStyle({height:"100px",width:"100%"}).addClass("frame").appendTo(this.elm);
		if(this.copyElm){
			this.elmFrame.setStyle({width:(this.elm.offsetWidth-4)+"px"})
		}
		var A={fontSize:"font-size",fontFamily:"font-family",fontWeight:"font-weight",color:"color"};
		for(itm in A){
			this.savedStyles[itm]=this.elm.getStyle(A[itm])
		}
		setTimeout(this.initFrame.closure(this),50)
	},

	disable:function(){
		this.elm.innerHTML=this.getContent()
	},

	//to init the iframe
	initFrame:function(){
		this.frameDoc=$BK(this.elmFrame.contentWindow.document);

		//Enabling Rich Text Editing in your iframe
		//this work on ie and mozilla
		this.frameDoc.designMode="on";
		this.frameDoc.open();
		this.frameDoc.write('<html><head></head><body id="nicEditContent" style="margin: 0 !important; background-color: transparent !important;">'+this.initialContent+"</body></html>");
		this.frameDoc.close();
		this.frameWin=$BK(this.elmFrame.contentWindow);
		this.frameContent=$BK(this.frameWin.document.body).setStyle(this.savedStyles);

		//we need to record each iframe with those textarea into an array
		//[HACK_START]
		//we need to record each iframe with those textarea into an array
		jnedinst.push(this.frameContent);
		jnedfd.push(this.frameDoc);
		//[HACK_END]

		this.instanceDoc=this.frameWin.document.defaultView;
		this.heightUpdate(true);
		this.frameDoc.addEvent("mousedown",this.selected.closureListener(this)).addEvent("keyup",this.heightUpdate.closureListener(this)).addEvent("keydown",this.keyDown.closureListener(this)).addEvent("keyup",this.selected.closure(this))
	},

	//get the content of the iframe
	getElm:function(){
		return this.frameContent
	},

	//set the content of the iframe
	setContent:function(A){
		this.content=A;this.ne.fireEvent("set",this);
		this.frameContent.innerHTML=this.content;this.heightUpdate()
	},

	//get selected element ??
	getSel:function(){
		return(this.frameWin)?this.frameWin.getSelection():this.frameDoc.selection
	},

	//update the height of the frame dynamically if the text goes wildy big
	heightUpdate:function(onInit){

		if(onInit===true){
				A=(this.frameContent.offsetHeight < 400) ? this.frameContent.offsetHeight:400;
			}else{
				A=this.frameContent.offsetHeight;
			}

		this.elmFrame.style.height=Math.max(A,this.initialHeight)+"px";
	},

	//need further investigation
	nicCommand:function(B,A){
		this.frameDoc.execCommand(B,false,A);
		setTimeout(this.heightUpdate.closure(this),100)
	}
});

//that is the classe to create the buttons panel it extends the bkClass
var nicEditorPanel=bkClass.extend({

	//the E:element to which we add the B:panel options(all the buttons required) the instance of the editor A
	construct:function(E,B,A){
		this.elm=E;
		this.options=B;
		this.ne=A;

		//array of buttons
		this.panelButtons=new Array();
		this.buttonList=bkExtend([],this.ne.options.buttonList);

		//need to create some div container and value, set some style
		this.panelContain=new bkElement("DIV").setStyle({overflow:"hidden",width:"100%",border:"1px solid #cccccc",backgroundColor:"#efefef"}).addClass("panelContain");
		this.panelElm=new bkElement("DIV").setStyle({margin:"2px",marginTop:"0px",zoom:1,overflow:"hidden"}).addClass("panel").appendTo(this.panelContain);

		this.panelContain.appendTo(E);
		var C=this.ne.options;
		var D=C.buttons;
		for(button in D){
			this.addButton(button,C,true)
		}
		this.reorder();
		E.noSelect()
	},

	//this is how we add a button to the array panelButtons
	addButton:function(buttonName,options,noOrder){
		var button=options.buttons[buttonName];
		var type=(button.type)?eval("(typeof("+button.type+') == "undefined") ? null : '+button.type+";"):nicEditorButton;
		var hasButton=bkLib.inArray(this.buttonList,buttonName);
		if(type&&(hasButton||this.ne.options.fullPanel)){
			this.panelButtons.push(new type(this.panelElm,buttonName,options,this.ne));
			if(!hasButton){
				this.buttonList.push(buttonName)
			}
		}
	},

	findButton:function(B){
		for(var A=0;A<this.panelButtons.length;A++){
			if(this.panelButtons[A].name==B){
				return this.panelButtons[A]
			}
		}
	},

	reorder:function(){
		var C=this.buttonList;
		for(var B=0;B<C.length;B++){
			var A=this.findButton(C[B]);
			if(A){
				this.panelElm.appendChild(A.margin)
			}
		}
	},

	remove:function(){
		this.elm.remove()
	}

});

//the class to define each button instance extending bkClass
var nicEditorButton=bkClass.extend({

	isDisabled:false,
	isHover:false,
	isActive:false,

	construct:function(D,A,C,B){
		this.options=C.buttons[A];
		this.name=A;this.ne=B;
		this.elm=D;

		//create some divs for the button, set their style
		this.margin=new bkElement("DIV").setStyle({"float":"left",marginTop:"2px"}).appendTo(D);
		this.contain=new bkElement("DIV").setStyle({width:"20px",height:"20px"}).addClass("buttonContain").appendTo(this.margin);
		this.border=new bkElement("DIV").setStyle({backgroundColor:"#efefef",border:"1px solid #efefef"}).appendTo(this.contain);
		this.button=new bkElement("DIV").setStyle({width:"18px",height:"18px",overflow:"hidden",zoom:1,cursor:"pointer"}).addClass("button").setStyle(this.ne.getIcon(A,C)).appendTo(this.border);

		//add some event to the main one
		//for the button to be reactive
		this.button.addEvent("mouseover",this.hoverOn.closure(this)).addEvent("mouseout",this.hoverOff.closure(this)).addEvent("mousedown",this.mouseClick.closure(this)).noSelect();

		//strange ... ??
		if(!window.opera){
			this.button.onmousedown=bkLib.cancelEvent;
			this.button.onclick=bkLib.cancelEvent
		}
		B.addEvent("selected",this.enable.closure(this)).addEvent("blur",this.disable.closure(this)).addEvent("key",this.key.closure(this));
		this.disable();
		this.init()
	},

	//nothing for now
	init:function(){},

	//hide the button
	hide:function(){
		this.contain.setStyle({display:"none"})
	},

	//upate state to change depending on if the mouse is own out if the control panel is disabled
	updateState:function(){
		if(this.isDisabled){
			this.setBg()
		}
		else{
			if(this.isHover){
				this.setBg("hover")
			}
			else{
				if(this.isActive){
					this.setBg("active")
				}
				else{
					this.setBg()
				}
			}
		}
	},

	//it sets the background depending on the state(A) of the button
	setBg:function(A){
		switch(A){
			case"hover":
				var B={border:"1px solid #666",backgroundColor:"#ddd"};
				break;
			case"active":
				var B={border:"1px solid #666",backgroundColor:"#ccc"};
				break;
			default:
				var B={border:"1px solid #efefef",backgroundColor:"#efefef"}
		}
		this.border.setStyle(B).addClass("button-"+A)
	},

	//??
	checkNodes:function(A){
		var B=A;
		do{
			if(this.options.tags&&bkLib.inArray(this.options.tags,B.nodeName)){
				this.activate();
				return true
			}
		}
		while(B=B.parentNode&&B.className!="nicEdit");
		B=$BK(A);
		while(B.nodeType==3){
			B=$BK(B.parentNode)
		}
		if(this.options.css){
			for(itm in this.options.css){
				if(B.getStyle(itm,this.ne.selectedInstance.instanceDoc)==this.options.css[itm]){
					this.activate();
					return true
				}
			}
		}
		this.deactivate();
		return false
	},

	//activate ??
	activate:function(){
		if(!this.isDisabled){
			this.isActive=true;
			this.updateState();
			this.ne.fireEvent("buttonActivate",this)
		}
	},

	//deactivate ??
	deactivate:function(){
		this.isActive=false;
		this.updateState();
		if(!this.isDisabled){
			this.ne.fireEvent("buttonDeactivate",this)
		}
	},

	//enable ??
	enable:function(A,B){
		this.isDisabled=false;
		this.contain.setStyle({opacity:1}).addClass("buttonEnabled");
		this.updateState();
		this.checkNodes(B)
	},

	//disable ??
	disable:function(A,B){
		this.isDisabled=true;
		this.contain.setStyle({opacity:0.6}).removeClass("buttonEnabled");
		this.updateState()
	},

	//what the hell is the difference between all those functions....
	toggleActive:function(){
		(this.isActive)?this.deactivate():this.activate()
	},

	//mouseover
	hoverOn:function(){
		if(!this.isDisabled){
			this.isHover=true;
			this.updateState();
			this.ne.fireEvent("buttonOver",this)
		}
	},

	//mouseout
	hoverOff:function(){
		this.isHover=false;
		this.updateState();
		this.ne.fireEvent("buttonOut",this)
	},

	//mouseclick trigger the command related to that button
	mouseClick:function(){
		if(this.options.command){
			this.ne.nicCommand(this.options.command,this.options.commandArgs);
			if(!this.options.noActive){
				this.toggleActive()
			}
		}
		this.ne.fireEvent("buttonClick",this)
	},

	key:function(A,B){
		if(this.options.key&&B.ctrlKey&&String.fromCharCode(B.keyCode).toLowerCase()==this.options.key){
			this.mouseClick()
		}
	}
});


var nicPlugin=bkClass.extend({

	construct:function(B,A){
		this.options=A;
		this.ne=B;
		this.ne.addEvent("panel",this.loadPanel.closure(this));
		this.init()
	},

	loadPanel:function(C){
		var B=this.options.buttons;
		for(var A in B){
			C.addButton(A,this.options)
		}
		C.reorder()
	},

	init:function(){}

});


var nicPaneOptions = { };


var nicEditorPane=bkClass.extend({

	construct:function(D,C,B,A){
		this.ne=C;
		this.elm=D;
		this.pos=D.pos();
		this.contain=new bkElement("div").setStyle({zIndex:"99999",overflow:"hidden",position:"absolute",left:this.pos[0]+"px",top:this.pos[1]+"px"});
		this.pane=new bkElement("div").setStyle({fontSize:"12px",border:"1px solid #ccc",overflow:"hidden",padding:"4px",textAlign:"left",backgroundColor:"#ffffc9"}).addClass("pane").setStyle(B).appendTo(this.contain);
		if(A&&!A.options.noClose){
			this.close=new bkElement("div").setStyle({"float":"right",height:"16px",width:"16px",cursor:"pointer"}).setStyle(this.ne.getIcon("close",nicPaneOptions)).addEvent("mousedown",A.removePane.closure(this)).appendTo(this.pane)
		}
		this.contain.noSelect().appendTo(document.body);
		this.position();
		this.init()
	},

	init:function(){},

	position:function(){
		if(this.ne.nicPanel){
			var B=this.ne.nicPanel.elm;
			var A=B.pos();
			var C=A[0]+parseInt(B.getStyle("width"))-(parseInt(this.pane.getStyle("width"))+8);
			if(C<this.pos[0]){
				this.contain.setStyle({left:C+"px"})
			}
		}
	},

	toggle:function(){
		this.isVisible=!this.isVisible;
		this.contain.setStyle({display:((this.isVisible)?"block":"none")})
	},

	remove:function(){
		if(this.contain){
			this.contain.remove();
			this.contain=null
		}
	},

	append:function(A){
		A.appendTo(this.pane)
	},

	setContent:function(A){
		this.pane.setContent(A)
	}
});

var nicEditorAdvancedButton=nicEditorButton.extend({

	init:function(){
		this.ne.addEvent("selected",this.removePane.closure(this)).addEvent("blur",this.removePane.closure(this))
	},

	mouseClick:function(){
		if(!this.isDisabled){
			if(this.pane&&this.pane.pane){
				this.removePane()
			}
			else{
				this.pane=new nicEditorPane(this.contain,this.ne,{width:(this.width||"270px"),backgroundColor:"#fff"},this);
				this.addPane();this.ne.selectedInstance.saveRng()
			}
		}
	},

	addForm:function(C,G){
		this.form=new bkElement("form").addEvent("submit",this.submit.closureListener(this));
		this.pane.append(this.form);
		this.inputs={};
		for(itm in C){
			var D=C[itm];
			var F="";
			if(G){F=G.getAttribute(itm)}
			if(!F){F=D.value||""}
			var A=C[itm].type;
			if(A=="title"){
				new bkElement("div").setContent(D.txt).setStyle({fontSize:"14px",fontWeight:"bold",padding:"0px",margin:"2px 0"}).appendTo(this.form)
			}
			else{
				var B=new bkElement("div").setStyle({overflow:"hidden",clear:"both"}).appendTo(this.form);
				if(D.txt){
					new bkElement("label").setAttributes({"for":itm}).setContent(D.txt).setStyle({margin:"2px 4px",fontSize:"13px",width:"50px",lineHeight:"20px",textAlign:"right","float":"left"}).appendTo(B)
				}
				switch(A){
					case"text":
						this.inputs[itm]=new bkElement("input").setAttributes({id:itm,value:F,type:"text"}).setStyle({margin:"2px 0",fontSize:"13px","float":"left",height:"20px",border:"1px solid #ccc",overflow:"hidden"}).setStyle(D.style).appendTo(B);
						break;
					case"select":
						this.inputs[itm]=new bkElement("select").setAttributes({id:itm}).setStyle({border:"1px solid #ccc","float":"left",margin:"2px 0"}).appendTo(B);
						for(opt in D.options){
							var E=new bkElement("option").setAttributes({value:opt,selected:(opt==F)?"selected":""}).setContent(D.options[opt]).appendTo(this.inputs[itm])
						}
						break;
					case"content":
						this.inputs[itm]=new bkElement("textarea").setAttributes({id:itm}).setStyle({border:"1px solid #ccc","float":"left"}).setStyle(D.style).appendTo(B);
						this.inputs[itm].value=F
				}
			}
		}
		new bkElement("input").setAttributes({type:"submit"}).setStyle({backgroundColor:"#efefef",border:"1px solid #ccc",margin:"3px 0","float":"left",clear:"both"}).appendTo(this.form);
		this.form.onsubmit=bkLib.cancelEvent
	},

	submit:function(){},

	findElm:function(B,A,E){
		var D=this.ne.selectedInstance.getElm().getElementsByTagName(B);
		for(var C=0;C<D.length;C++){
			if(D[C].getAttribute(A)==E){
				return $BK(D[C])
			}
		}
	},

	removePane:function(){
		if(this.pane){
			this.pane.remove();
			this.pane=null;
			this.ne.selectedInstance.restoreRng()
		}
	}

});

var nicButtonTips=bkClass.extend({construct:function(A){this.ne=A;A.addEvent("buttonOver",this.show.closure(this)).addEvent("buttonOut",this.hide.closure(this))},show:function(A){this.timer=setTimeout(this.create.closure(this,A),400)},create:function(A){this.timer=null;if(!this.pane){this.pane=new nicEditorPane(A.button,this.ne,{fontSize:"12px",marginTop:"5px"});this.pane.setContent(A.options.name)}},hide:function(A){if(this.timer){clearTimeout(this.timer)}if(this.pane){this.pane=this.pane.remove()}}});nicEditors.registerPlugin(nicButtonTips);


var nicSelectOptions = {
	buttons : {
		'fontSize' : {name : __('Select Font Size'), type : 'nicEditorFontSizeSelect', command : 'fontsize'},
		'fontFamily' : {name : __('Select Font Family'), type : 'nicEditorFontFamilySelect', command : 'fontname'},
		'fontFormat' : {name : __('Select Font Format'), type : 'nicEditorFontFormatSelect', command : 'formatBlock'}
	}
};

//i think this is the class for the dropdowns font size, font type font face..
var nicEditorSelect=bkClass.extend({

	construct:function(D,A,C,B){
		this.options=C.buttons[A];
		this.elm=D;
		this.ne=B;
		this.name=A;
		this.selOptions=new Array();

		//we create some divs, set their style
		this.margin=new bkElement("div").setStyle({"float":"left",margin:"2px 1px 0 1px"}).appendTo(this.elm);
		this.contain=new bkElement("div").setStyle({width:"90px",height:"20px",cursor:"pointer",overflow:"hidden"}).addClass("selectContain").addEvent("click",this.toggle.closure(this)).appendTo(this.margin);
		this.items=new bkElement("div").setStyle({overflow:"hidden",zoom:1,border:"1px solid #ccc",paddingLeft:"3px",backgroundColor:"#fff"}).appendTo(this.contain);this.control=new bkElement("div").setStyle({overflow:"hidden","float":"right",height:"18px",width:"16px"}).addClass("selectControl").setStyle(this.ne.getIcon("arrow",C)).appendTo(this.items);
		this.txt=new bkElement("div").setStyle({overflow:"hidden","float":"left",width:"66px",height:"14px",marginTop:"1px",fontFamily:"sans-serif",textAlign:"center",fontSize:"12px"}).addClass("selectTxt").appendTo(this.items);

		//create exceptions for opera
		if(!window.opera){
			this.contain.onmousedown=this.control.onmousedown=this.txt.onmousedown=bkLib.cancelEvent
		}
		this.margin.noSelect();
		this.ne.addEvent("selected",this.enable.closure(this)).addEvent("blur",this.disable.closure(this));
		this.disable();
		this.init()
	},

	//disable it..
	disable:function(){
		this.isDisabled=true;
		this.close();
		this.contain.setStyle({opacity:0.6})
	},

	//enable it..
	enable:function(A){
		this.isDisabled=false;
		this.close();
		this.contain.setStyle({opacity:1})
	},

	//set some value into the text div
	setDisplay:function(A){
		this.txt.setContent(A)
	},

	//toggle open close state
	toggle:function(){
		if(!this.isDisabled){
			(this.pane)?this.close():this.open()
		}
	},

	open:function(){
		this.pane=new nicEditorPane(this.items,this.ne,{width:"88px",padding:"0px",borderTop:0,borderLeft:"1px solid #ccc",borderRight:"1px solid #ccc",borderBottom:"0px",backgroundColor:"#fff"});
		for(var C=0;C<this.selOptions.length;C++){
			var B=this.selOptions[C];
			var A=new bkElement("div").setStyle({overflow:"hidden",borderBottom:"1px solid #ccc",width:"88px",textAlign:"left",overflow:"hidden",cursor:"pointer"});
			var D=new bkElement("div").setStyle({padding:"0px 4px"}).setContent(B[1]).appendTo(A).noSelect();
			D.addEvent("click",this.update.closure(this,B[0])).addEvent("mouseover",this.over.closure(this,D)).addEvent("mouseout",this.out.closure(this,D)).setAttributes("id",B[0]);
			this.pane.append(A);
			if(!window.opera){
				D.onmousedown=bkLib.cancelEvent
			}
		}
	},

	close:function(){
		if(this.pane){
			this.pane=this.pane.remove()
		}
	},

	over:function(A){
		A.setStyle({backgroundColor:"#ccc"})
	},

	out:function(A){
		A.setStyle({backgroundColor:"#fff"})
	},

	//add an element to the list
	add:function(B,A){
		this.selOptions.push(new Array(B,A))
	},

	update:function(A){
		this.ne.nicCommand(this.options.command,A);
		this.close()
	}
});

//font size class extend the main dropdown class
//just has different configurations
var nicEditorFontSizeSelect=nicEditorSelect.extend({

	sel:{1:"1&nbsp;(8pt)",2:"2&nbsp;(10pt)",3:"3&nbsp;(12pt)",4:"4&nbsp;(14pt)",5:"5&nbsp;(18pt)",6:"6&nbsp;(24pt)"},

	init:function(){
		this.setDisplay("Font&nbsp;Size...");
		for(itm in this.sel){
			this.add(itm,'<font size="'+itm+'">'+this.sel[itm]+"</font>")
		}
	}
});

//font family class extend the main dropdown class
//just has different configurations
var nicEditorFontFamilySelect=nicEditorSelect.extend({

	sel:{arial:"Arial","comic sans ms":"Comic Sans","courier new":"Courier New",georgia:"Georgia",helvetica:"Helvetica",impact:"Impact","times new roman":"Times","trebuchet ms":"Trebuchet",verdana:"Verdana"},

	init:function(){
		this.setDisplay("Font&nbsp;Family...");
		for(itm in this.sel){
			this.add(itm,'<font face="'+itm+'">'+this.sel[itm]+"</font>")
		}
	}
});

//font format class extend the main dropdown class
//just has different configurations
var nicEditorFontFormatSelect=nicEditorSelect.extend({

	sel:{p:"Paragraph",pre:"Pre",h6:"Heading&nbsp;6",h5:"Heading&nbsp;5",h4:"Heading&nbsp;4",h3:"Heading&nbsp;3",h2:"Heading&nbsp;2",h1:"Heading&nbsp;1"},

	init:function(){
		this.setDisplay("Font&nbsp;Format...");
		for(itm in this.sel){
			var A=itm.toUpperCase();
			this.add("<"+A+">","<"+itm+' style="padding: 0px; margin: 0px;">'+this.sel[itm]+"</"+A+">")
		}
	}
});

nicEditors.registerPlugin(nicPlugin,nicSelectOptions);


var nicLinkOptions = {
	buttons : {
		'link' : {name : 'Add Link', type : 'nicLinkButton', tags : ['A']},
		'unlink' : {name : 'Remove Link',  command : 'unlink', noActive : true}
	}
};

//the link button class extending the nicLinkButton class
//exact same thins as image button
var nicLinkButton=nicEditorAdvancedButton.extend({

	addPane:function(){
		this.ln=this.ne.selectedInstance.selElm().parentTag("A");
		this.addForm({"":{type:"title",txt:"Add/Edit Link"},href:{type:"text",txt:"URL",value:"http://",style:{width:"150px"}},title:{type:"text",txt:"Title"},target:{type:"select",txt:"Open In",options:{"":"Current Window",_blank:"New Window"},style:{width:"100px"}}},this.ln)
	},

	submit:function(C){
		var A=this.inputs.href.value;
		if(A=="http://"||A==""){
			alert("You must enter a URL to Create a Link");
			return false
		}
		this.removePane();
		if(!this.ln){
			var B="javascript:nicTemp();";
			this.ne.nicCommand("createlink",B);
			this.ln=this.findElm("A","href",B)
		}
		if(this.ln){
			this.ln.setAttributes({href:this.inputs.href.value,title:this.inputs.title.value,target:this.inputs.target.options[this.inputs.target.selectedIndex].value})
		}
	}
});

nicEditors.registerPlugin(nicPlugin,nicLinkOptions);


var nicColorOptions = {
	buttons : {
		'forecolor' : {name : __('Change Text Color'), type : 'nicEditorColorButton', noClose : true},
		'bgcolor' : {name : __('Change Background Color'), type : 'nicEditorBgColorButton', noClose : true}
	}
};


var nicEditorColorButton=nicEditorAdvancedButton.extend({

	addPane:function(){
		var D={0:"00",1:"33",2:"66",3:"99",4:"CC",5:"FF"};
		//var D = {0 : '00',1 : '11',2 : '22',3 :'33',4 : '44',5 : '55',6 : '66',7 : '77',8 : '88',9 :'99',10 : 'AA',11 : 'BB',12 : 'CC',13 : 'DD',14 : 'EE' ,15 : 'FF'};


		var H=new bkElement("DIV").setStyle({width:"270px"});
		//that's the way we create a color panel in javascript
		for(var A in D){
			for(var F in D){
				for(var E in D){
					var I="#"+D[A]+D[E]+D[F];
					var C=new bkElement("DIV").setStyle({cursor:"pointer",height:"15px","float":"left"}).appendTo(H);
					var G=new bkElement("DIV").setStyle({border:"2px solid "+I}).appendTo(C);
					var B=new bkElement("DIV").setStyle({backgroundColor:I,overflow:"hidden",width:"11px",height:"11px"}).addEvent("click",this.colorSelect.closure(this,I)).addEvent("mouseover",this.on.closure(this,G)).addEvent("mouseout",this.off.closure(this,G,I)).appendTo(G);
					if(!window.opera){
						C.onmousedown=B.onmousedown=bkLib.cancelEvent
					}
				}
			}
		}
		this.pane.append(H.noSelect())
	},

	//run command on color select
	colorSelect:function(A){
		this.ne.nicCommand("foreColor",A);
		this.removePane()
	},

	//change the style of the current square
	on:function(A){
		A.setStyle({border:"2px solid #000"})
	},

	off:function(A,B){
		A.setStyle({border:"2px solid "+B})
	}

});


var nicEditorBgColorButton=nicEditorColorButton.extend({

	colorSelect:function(A){
		this.ne.nicCommand("hiliteColor",A);
		this.removePane()
	}

});


nicEditors.registerPlugin(nicPlugin,nicColorOptions);


var nicImageOptions = {
	buttons : {
		'image' : {name : 'Add Image', type : 'nicImageButton', tags : ['IMG']}
	}

};

//the image button class extending the nicEditorButton class
var nicImageButton=nicEditorAdvancedButton.extend({

	addPane:function(){
		this.im=this.ne.selectedInstance.selElm().parentTag("IMG");
		this.addForm({"":{type:"title",txt:"Add/Edit Image"},src:{type:"text",txt:"URL",value:"http://",style:{width:"150px"}},alt:{type:"text",txt:"Alt Text",style:{width:"100px"}},align:{type:"select",txt:"Align",options:{left:"Left",right:"Right"}}},this.im)
		},

	//since we have a submit button we have a paneSubmit function run on submit
	submit:function(B){
		var C=this.inputs.src.value;
		if(C==""||C=="http://"){
			alert("You must enter a Image URL to insert");
			return false
		}
		this.removePane();
		if(!this.im){
			var A="javascript:nicImTemp();";
			this.ne.nicCommand("insertImage",A);
			this.im=this.findElm("IMG","src",A)
		}
		if(this.im){
			this.im.setAttributes({src:this.inputs.src.value,alt:this.inputs.alt.value,align:this.inputs.align.value})
		}
	}

});


nicEditors.registerPlugin(nicPlugin,nicImageOptions);


var nicXHTML=bkClass.extend({

	stripAttributes:["_moz_dirty","_moz_resizing","_extended"],noShort:["style","title","script","textarea","a"],cssReplace:{"font-weight:bold;":"strong","font-style:italic;":"em"},sizes:{1:"xx-small",2:"x-small",3:"small",4:"medium",5:"large",6:"x-large"},

	construct:function(A){
		this.ne=A;
		if(this.ne.options.xhtml){
			A.addEvent("get",this.cleanup.closure(this))
		}
	},

	cleanup:function(A){
		var B=A.getElm();
		var C=this.toXHTML(B);A.content=C
	},

	toXHTML:function(C,A,L){
		var G="";
		var O="";
		var P="";
		var I=C.nodeType;
		var Q=C.nodeName.toLowerCase();
		var N=C.hasChildNodes&&C.hasChildNodes();
		var B=new Array();
		switch(I){
			case 1:
				var H=C.attributes;
				switch(Q){
					case"b":
						Q="strong";
						break;
					case"i":
						Q="em";
						break;
					case"font":
						Q="span";
						break
				}
				if(A){
					for(var F=0;F<H.length;F++){
						var K=H[F];
						var M=K.nodeName.toLowerCase();
						var D=K.nodeValue;
						if(!K.specified||!D||bkLib.inArray(this.stripAttributes,M)||typeof (D)=="function"){
							continue
						}
						switch(M){
							case"style":
								var J=D.replace(/ /g,"");
								for(itm in this.cssReplace){
									if(J.indexOf(itm)!=-1){
										B.push(this.cssReplace[itm]);
										J=J.replace(itm,"")
									}
								}
								P+=J;D="";
								break;
							case"class":
								D=D.replace("Apple-style-span","");
								break;
							case"size":
								P+="font-size:"+this.sizes[D]+";";
								D="";
								break
						}
						if(D){
							O+=" "+M+'="'+D+'"'
						}
					}
					if(P){
						O+=' style="'+P+'"'
					}
					for(var F=0;F<B.length;F++){
						G+="<"+B[F]+">"
					}
					if(O==""&&Q=="span"){
						A=false
					}
					if(A){
						G+="<"+Q;
						if(Q!="br"){G+=O}
					}
				}
				if(!N&&!bkLib.inArray(this.noShort,M)){
					if(A){G+=" />"}
				}
				else{
					if(A){G+=">"}
					for(var F=0;F<C.childNodes.length;F++){
						var E=this.toXHTML(C.childNodes[F],true,true);
						if(E){G+=E}
					}
				}
				if(A&&N){
					G+="</"+Q+">"
				}
				for(var F=0;F<B.length;F++){
					G+="</"+B[F]+">"
				}
				break;
			case 3:
				G+=C.nodeValue;
				break
		}
		return G
	}

});


nicEditors.registerPlugin(nicXHTML);


var nicBBCode=bkClass.extend({

	construct:function(A){
		this.ne=A;
		if(this.ne.options.bbCode){
			A.addEvent("get",this.bbGet.closure(this));A.addEvent("set",this.bbSet.closure(this));
			var B=this.ne.loadedPlugins;
			for(itm in B){
				if(B[itm].toXHTML){
					this.xhtml=B[itm]
				}
			}
		}
	},

	bbGet:function(A){
		var B=this.xhtml.toXHTML(A.getElm());
		A.content=this.toBBCode(B)
	},

	bbSet:function(A){
		A.content=this.fromBBCode(A.content)
	},

	toBBCode:function(B){
		function A(D,C){B=B.replace(D,C)}A(/\n/gi,"");
		A(/<strong>(.*?)<\/strong>/gi,"[b]$1[/b]");
		A(/<em>(.*?)<\/em>/gi,"[i]$1[/i]");A(/<span.*?style="text-decoration:underline;">(.*?)<\/span>/gi,"[u]$1[/u]");
		A(/<ul>(.*?)<\/ul>/gi,"[list]$1[/list]");
		A(/<li>(.*?)<\/li>/gi,"[*]$1[]");
		A(/<ol>(.*?)<\/ol>/gi,"[list=1]$1[/list]");
		A(/<img.*?src="(.*?)".*?>/gi,"[img]$1[/img]");
		A(/<a.*?href="(.*?)".*?>(.*?)<\/a>/gi,"[url=$1]$2[/url]");
		A(/<br.*?>/gi,"\n");A(/<.*?>.*?<\/.*?>/gi,"");
		return B
	},

	fromBBCode:function(A){
		function B(D,C){A=A.replace(D,C)}B(/\[b\](.*?)\[\/b\]/gi,"<strong>$1</strong>");
		B(/\[i\](.*?)\[\/i\]/gi,"<em>$1</em>");
		B(/\[u\](.*?)\[\/u\]/gi,'<span style="text-decoration:underline;">$1</span>');
		B(/\[list\](.*?)\[\/list\]/gi,"<ul>$1</ul>");
		B(/\[list=1\](.*?)\[\/list\]/gi,"<ol>$1</ol>");
		B(/\[\*\](.*?)\[\/\*\]/gi,"<li>$1</li>");
		B(/\[img\](.*?)\[\/img\]/gi,'<img src="$1" />');
		B(/\[url=(.*?)\](.*?)\[\/url\]/gi,'<a href="$1">$2</a>');
		B(/\n/gi,"<br />");
		return A
	}

});

nicEditors.registerPlugin(nicBBCode);


var nicCodeOptions = {
	buttons : {
		'xhtml' : {name : 'Edit HTML', type : 'nicCodeButton'}
	}

};

var nicCodeButton=nicEditorAdvancedButton.extend({

	width:"350px",

	addPane:function(){
		this.addForm({"":{type:"title",txt:"Edit HTML"},code:{type:"content",value:this.ne.selectedInstance.getContent(),style:{width:"340px",height:"200px"}}})
	},

	submit:function(B){
		var A=this.inputs.code.value;
		this.ne.selectedInstance.setContent(A);
		this.removePane()
	}
});

nicEditors.registerPlugin(nicPlugin,nicCodeOptions);


