var Editer ={
	instances:{},
	Base:Class.create(
		{
			initialize:function(id){
				if(!this.constructor.instances)
					this.constructor.instances={};
				this.constructor.instances[id]=this;
				Editer.instances[id]=this;
				this.id=id;
			},
			destroy:function(){
				delete this.constructor.instances[this.id];
			}
		}
	)
};


var sel, rng, papa, trail ;
var JunEditer = Editer.Base.createSubClass(
{
	options:{},
	initialize:function(options){
		this.imgpath = 'http://img.ohpy.com/opimg/common/editor/img/';
		this.language = new Array();
		this.language['undo'] = "취소";
		this.language['redo'] = "재실행";
		this.language['number'] = "번호 매기기";
		this.language['bullet'] = "글머리 기호";
		this.language['indent'] = "들여쓰기";
		this.language['outdent'] = "내어쓰기";
		this.language['rule'] = "수평선 삽입";
		this.language['table'] = "표 삽입";
		this.language['link'] = "링크 삽입";
		this.language['clean'] = "스타일 지우기";
		this.language['bold'] = "굵게";
		this.language['italic'] = "기울임꼴";
		this.language['underline'] = "밑줄";
		this.language['strikethrough'] = "취소선";
		this.language['color'] = "글자 색상";
		this.language['hilite'] = "배경 색상";
		this.language['left'] = "왼쪽 정렬";
		this.language['center'] = "가운데 정렬";
		this.language['right'] = "오른쪽 정렬";
		this.language['right'] = "오른쪽 정렬";
		this.sels = 'fontname fontsize';
		this.buts1 = ' undo redo | number bullet | indent outdent | rule  table link clean ';
		this.buts2 = ' | bold italic underline strikethrough | color hilite | left center right ';
		this.colorstatus = false;
		this.heightResize = false;
		this.heightResizeDown = false;
		
		this.options = Object.extend({
			textarea:'',
			iframe:'',
			row:15,
			color:'#060',
			zIndex:'2',
			form:'',
			div:'',
			height:150,
			editmode:'TEXT',
			status:false},options);
	},
	goEditMode : function(editmode) {	
		switch(editmode) {
			case "TEXT" : this.Text(); break;
			case "HTML" : this.Html(); break;
			case "EDIT" : this.Edit(); break;
		}
		this.makeResize();
	},
	Text:function() {	
		if(this.options.editmode == "EDIT"){
			if(this.options.status){
				frame = $(this.options.iframe).contentWindow;
				var content	=	(window.get_xhtml) ? get_xhtml(frame.document.body) : frame.document.body.innerHTML;
				$(this.options.textarea).value = this.conversion(content);
				Element.show(this.options.textarea);
				Element.hide(this.options.div);
			}else{
				Element.show(this.options.textarea);
				Element.hide(this.options.div);		
			}
		}else{
			Element.show(this.options.textarea);
			Element.hide(this.options.div);
		}

		this.options.editmode	= 'TEXT';
		this.selected('tab-text');
	},
	Html:function() {	
		if(this.options.editmode == "EDIT"){
			if(this.options.status){
				frame = $(this.options.iframe).contentWindow;
				content	=	(window.get_xhtml) ? get_xhtml(frame.document.body) : frame.document.body.innerHTML;
				$(this.options.textarea).value = this.conversion(content);
				Element.show(this.options.textarea);
				Element.hide(this.options.div);
			}else{
				Element.show(this.options.textarea);
				Element.hide(this.options.div);		
			}
		}else{
			Element.show(this.options.textarea);
			Element.hide(this.options.div);
		}

		this.options.editmode	= 'HTML';
		this.selected('tab-html');
	},
	Edit:function() {
		try{
		if(this.options.editmode != 'EDIT'){
			Element.show(this.options.div);
			if(!this.options.status){
				this.makeEditHtml();
				this.options.status = true;			
			}else{
				if(this.goediter != undefined){
				Element.hide(this.options.textarea);
				Element.hide(this.goediter);
				Element.show(this.controls);
				Element.show(this.options.iframe);
				}
			}
			content = this.decodeTagStr(this.replace($F(this.options.textarea)));
			this.frameHtml(content);
			Element.hide(this.options.textarea);
		}

		this.options.editmode	= 'EDIT';
		this.selected('tab-editor');
		}catch(e){
			alert(e);
		}
	},
	selected:function(selectedClass){
		if($(this.options.form) != undefined){
			element = Element.getDescendantByClassName($(this.options.form),'tab');
			for(var i=0;i<element.childNodes.length;i++){
				var elem=element.childNodes[i];
				if(elem.nodeType!=1)continue;
				
				if(Element.hasClassName(elem,'selected')){
					Element.removeClassName(elem, "selected");
				}
				if(Element.hasClassName(elem,selectedClass)){
					Element.addClassName(elem, "selected");
				}
			}				
		}
		if(/html/i.test(this.buts1) && this.goediter == undefined){
			$(this.options.div).appendChild(this.editerHtml());
			Element.show(this.options.div);
		}
				
	},
	frameHtml : function(str){
			html = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n";
			html += "<html><head>";
			html += "<meta http-equiv=\"content-type\" content=\"text/html; charset=utf-8\" />\n";
			html += "<style type='text/css'>body { font-size:9pt;font-family:돋움;overflow:auto}; blockquote{border : 1px dashed #DFDFDF;padding : 5px;}; P {margin-top:3px;margin-bottom:3px;margin-left:3;margin-right:3;white-space: -moz-pre-wrap;word-break:break-all;}</style></head>\n";
			html += "<body>";
			html += str;
			html += "</body>\n";
			html += "</html>";
			oHtml = $(this.options.iframe).contentWindow;
			oHtml.document.open();
			oHtml.document.write(html);
			oHtml.document.close();
			
			try{
				$(this.options.iframe).contentWindow.document.designMode = "On";
			}catch(e){}
			
	},
	// editor Html
	makeEditHtml : function (){
		// link
		$(this.options.div).appendChild( this.linkHtml());
		// table
		$(this.options.div).appendChild(this.tableHtml());
		// control
		$(this.options.div).appendChild(this.facultyHtml());
		// iframe
		$(this.options.div).appendChild(this.iframeHtml());
		// html sorce view
		if(/html/i.test(this.buts1)){
			if(this.goediter == undefined){
				$(this.options.div).appendChild(this.editerHtml());
			}
			Element.hide(this.goediter);
		}
	},
	Resiter : function(input){
		$(input).value = this.options.editmode;
		if(this.options.editmode != "EDIT"){
			if(this.options.status){
				this.frameHtml(this.replace($F(this.options.textarea)));
				frame = $(this.options.iframe).contentWindow;
				content	= (window.get_xhtml) ? get_xhtml(frame.document.body) : frame.document.body.innerHTML;
				$(this.options.textarea).value = content;
			}else{
				$(this.options.textarea).value =  $F(this.options.textarea);
			}
		}else{
			frame = $(this.options.iframe).contentWindow;
			content	=	(window.get_xhtml) ? get_xhtml(frame.document.body) : frame.document.body.innerHTML;
			$(this.options.textarea).value = content;
		}
	},
	conversion : function(str){ 
		if (/^<br[ ]*\/?>$/i.test(str)) str = '';
		//...but <B>,<I> deprecated
		str = str.replace(/(<\/?)[Bb]>/g, "$1strong>");
		str = str.replace(/(<\/?)[Ii]>/g, "$1em>");
		str = str.replace(/(<\/?)[Bb](\s+[^>]*)>/g, "$1strong$2>");
		str = str.replace(/(<\/?)[Ii](\s+[^>]*)>/g, "$1em$2>");
		str = this.replaceaTag(str); // A태그의 target 삽입.
		str = str.replace(location.href+'#','#'); //IE anchor bug
		return str;
	},
	replaceaTag : function(str){ 
		// A태그 가져오는 정규식.	
		var aReg = /<[aA][^<]+>/g;
		// a태그 전체 가져오기.

		while ( szOrgTag = aReg.exec(str)) {
			// ajax 가 있을시에는 제외.
			if(szOrgTag[0].indexOf('ajax=') > 0) { 
				continue;
			}
			// target이 있는지 검사.
			// target이 없을시에는 뒤에 추가
			if(szOrgTag[0].indexOf(' target') < 0) {
				szTarget = szOrgTag[0].replace(/>/," target=_blank>");
				str = str.replace(szOrgTag[0],szTarget);	
			}
		}
		return str;
	},
	replace:function(str){ 
		str = str.replace(/<(\/?)strong([^>]*)>/gi, "<$1B$2>"); 
		str = str.replace(/<(\/?)em>>/gi, "<$1I>");
		return str;
	},
	makeObj : function(id,name){
		var classname;
		switch (name) {
			case "color": case "link" :classname = "link_form"; break;
			case "table" : classname = "table_form"; break;
			default: break;
		}
		var div = document.createElement('div');
		Element.addClassName(div,classname);
		div.style.display = 'none';
		return div;
	},
	// editer sorce view
	editerHtml : function (){
		var oEditer = document.createElement('div');
		Element.addClassName(oEditer,'ctrl');
//		oEditer.setStyle({display: 'none' });
		
		var atag = document.createElement('a');
		Element.addClassName(atag,'wg-btn-editor');
		atag.setAttribute('href' , '#//');
		atag.onclick = this.goEdit.bindAsEventListener(this);	
	
		var img = document.createElement('img');
		img.setAttribute('src' , this.imgpath+'go_editor.gif');
		img.setAttribute('alt' , '에디터');
		atag.appendChild(img);
		oEditer.appendChild(atag);
	
		this.goediter =  oEditer;
		return oEditer;
	},
	// link
	linkHtml : function (){
		var oLink = document.createElement('div');
		Element.addClassName(oLink,'link_form');
		oLink.setStyle({position: 'absolute' });
		Element.hide(oLink);
	
		// 1단
		var div = document.createElement('div');
		Element.addClassName(div,'editorbox-top');
		var h1 = document.createElement('h1');
		Element.addClassName(h1,'editorbox-h');
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');	
		atag.appendChild(document.createTextNode('링크 걸기'));
		h1.appendChild(atag);
		div.appendChild(h1);
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');
		atag.onclick = function(){ Element.hide(oLink);};
		Element.addClassName(atag,'btn-close');
		atag.appendChild(document.createTextNode('닫기'));
		div.appendChild(atag);
		oLink.appendChild(div);	
		
		// 2단
		var div1 = document.createElement('div');
		Element.addClassName(div1,'editorbox-middle');
	
		var div2 = document.createElement('div');
		Element.addClassName(div2,'link-set');
		var h2 = document.createElement('h2');
		Element.addClassName(h2,'editorbox-h');
		h2.appendChild(document.createTextNode('URL입력'));
		div2.appendChild(h2);
		
		var select = document.createElement('select');
		var option = document.createElement('option');
		option.setAttribute('value' , 'http://');
		option.appendChild(document.createTextNode('http://'));
		select.appendChild(option);
		var option = document.createElement('option');
		option.setAttribute('value' , 'mailto:');
		option.appendChild(document.createTextNode('mailto:'));
		select.appendChild(option);
		var option = document.createElement('option');
		option.setAttribute('value' , '');
		option.appendChild(document.createTextNode('기타'));
		select.appendChild(option);	
		div2.appendChild(select);
		this.linkselect = select;
		
		var inputurl = document.createElement('input');
		inputurl.setAttribute('type' , 'text');
		inputurl.setAttribute('size' , '60');
		Element.addClassName(inputurl,'lf_url');
		div2.appendChild(inputurl);
		this.linkurl = inputurl;	
		
		var div3 = document.createElement('div');
		Element.addClassName(div3,'new-window');
		var input = document.createElement('input');
		input.setAttribute('type' , 'checkbox');
		input.setAttribute('defaultChecked','checked');
		div3.appendChild(input);
		this.linkcheck = input;
		
		var span = document.createElement('span');
		span.appendChild(document.createTextNode('새 창으로 열기'));
		div3.appendChild(span);
		div2.appendChild(div3);
		div1.appendChild(div2);
	
		var div2 = document.createElement('div');
		Element.addClassName(div2,'link-set-btn');
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');
		Element.addClassName(atag,'button3');
		atag.appendChild(document.createTextNode('확인'));
		atag.onclick = this.insertLink.bindAsEventListener(this);
		div2.appendChild(atag);
		div1.appendChild(div2);
		oLink.appendChild(div1);
	
		// 3단
		var div1 = document.createElement('div');
		Element.addClassName(div1,'editorbox-bottom');
		oLink.appendChild(div1);
	
		this.linkTit = h1;
		this.link = oLink;
		return oLink;
	},
	insertLink : function(){
		if (document.selection) rng.select();
		frame = $(this.options.iframe).contentWindow;
		szHeader = $F(this.linkselect);
		szUrl	= $F(this.linkurl);
		target	= (this.linkcheck.checked)?'target="_blank"':'target="_self"';
		if (szUrl) {
			this.insHTML('<a href="'+ szHeader + szUrl+'" '+target+'>');
			Element.hide(this.link);
		} else {
			frame.document.execCommand('Unlink', false,null);
		}
	},
	insHTML : function(html) {
		frame = $(this.options.iframe).contentWindow;
		if (!html) return;
		if (html.indexOf('js:') == 0){ eval(html.replace(/^js:/,'')); return;}
		if (!html) html = prompt("Enter some HTML to insert:", "");
		if (document.selection) {
			rng.select(); 
			html = html + rng.htmlText;
			frame.document.selection.createRange().pasteHTML(html);
		} else {
			if (sel) 	html = html + sel;
			var fragment = frame.document.createDocumentFragment();
			var div = frame.document.createElement("div");
			div.innerHTML = html;
			while (div.firstChild) {
				fragment.appendChild(div.firstChild);
			}
			sel.removeAllRanges();
			rng.deleteContents();
			var node = rng.startContainer;
			var pos = rng.startOffset;
			switch (node.nodeType) {
			case 3: 
				if (fragment.nodeType == 3) {
					node.insertData(pos, fragment.data);
					rng.setEnd(node, pos + fragment.length);
					rng.setStart(node, pos + fragment.length);
				} else {
				    node = node.splitText(pos);
					node.parentNode.insertBefore(fragment, node);
					rng.setEnd(node, pos + fragment.length);
					rng.setStart(node, pos + fragment.length);
				}
				break;
			case 1: 
				if(node.hasChildNodes()) {
					if(node.childNodes[pos].nodeName == "HEAD")	{
						node = node.childNodes[pos+1];
						node.appendChild(fragment);
					} else {
						node = node.childNodes[pos];
						node.parentNode.insertBefore(fragment, node);	
					}
				}else{
					node.appendChild(fragment);
				}
				rng.setEnd(node, pos + fragment.length);
				rng.setStart(node, pos + fragment.length);
				break;
			}
			sel.addRange(rng);
			frame.document.body.innerHTML = frame.document.body.innerHTML.replace(/\n/gi, "<br />");
		}
		frame.focus();
	},
	tableHtml : function (){
		var oTable = document.createElement('div');
		Element.addClassName(oTable,'table_form');
		oTable.setStyle({position: 'absolute' });
		Element.hide(oTable);
	
		// 1단
		var div = document.createElement('div');
		Element.addClassName(div,'editorbox-top');
	
		var h1 = document.createElement('h1');
		Element.addClassName(h1,'editorbox-h');
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');	
		atag.appendChild(document.createTextNode('표 그리기'));
		atag.onfocus = function(){ this.blur(); };
		h1.appendChild(atag);
		div.appendChild(h1);
		this.tableTit = atag;
		
		
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');
		atag.onclick = function(){ Element.hide(oTable);};
		Element.addClassName(atag,'btn-close');
		atag.appendChild(document.createTextNode('닫기'));
		div.appendChild(atag);
		
		oTable.appendChild(div);
		
		// 2단
		var div = document.createElement('div');
		Element.addClassName(div,'editorbox-middle');
		
		var div1 = document.createElement('div');
		Element.addClassName(div1,'table-set');
		
		var div2 = document.createElement('div');
		Element.addClassName(div2,'table-set-rowcol');
	
		var h2 = document.createElement('h2');
		Element.addClassName(h2,'editorbox-h');
		h2.appendChild(document.createTextNode('표 설정:'));
		div2.appendChild(h2);
	
		var input = document.createElement('input');
		input.setAttribute('type' , 'text');
		input.setAttribute('size','2');
		input.setAttribute('value','3');
		this.tablerow = input;
		div2.appendChild(input);
		
		var span = document.createElement('span');
		span.appendChild(document.createTextNode('열'));
		div2.appendChild(span);
	
		var input = document.createElement('input');
		input.setAttribute('type' , 'text');
		input.setAttribute('size','2');
		input.setAttribute('value','3');
		this.tablecol = input;
		div2.appendChild(input);
		
		var span = document.createElement('span');
		span.appendChild(document.createTextNode('행'));
		div2.appendChild(span);
		div1.appendChild(div2);
	
		var div2 = document.createElement('div');
		Element.addClassName(div2,'table-set-border');
		
		var h2 = document.createElement('h2');
		Element.addClassName(h2,'editorbox-h');
		h2.appendChild(document.createTextNode('표 테두리 굵기:'));
		div2.appendChild(h2);
	
		var input = document.createElement('input');
		input.setAttribute('type' , 'text');
		input.setAttribute('size','2');
		input.setAttribute('value','1');
		this.tableborderl = input;
		div2.appendChild(input);
		
		var span = document.createElement('span');
		span.appendChild(document.createTextNode('px'));
		div2.appendChild(span);
		div1.appendChild(div2);
			
		var div2 = document.createElement('div');
		Element.addClassName(div2,'table-set-btn');
	
		var atag = document.createElement('a');
		atag.setAttribute('href' , '#//');
		atag.setAttribute('value' , 'table');
		Element.addClassName(atag,'button7');
		atag.appendChild(document.createTextNode('확인'));
		atag.onclick = this.makeTable.bindAsEventListener(this);
		div2.appendChild(atag);
		div1.appendChild(div2);
		div.appendChild(div1);
		oTable.appendChild(div);
		
		// 3단
		var div = document.createElement('div');
		Element.addClassName(div,'editorbox-bottom');	
		oTable.appendChild(div);
		
		this.table = oTable;
		return oTable;
	},
	makeColor : function (){
		this.oPlugColor = new App.Plugin.ColorPicker(this, {id : this.options.color_form});

		var obj = document.createElement('div');
		Element.addClassName(obj,'color_form');
	
		obj.innerHTML = this.oPlugColor.getOutput();
			
		this.color = obj;
		return obj;
	},
	makeTable : function (){
		var rows = this.tablerow.value;
		var cols = this.tablecol.value;
		var border = this.tableborderl.value;
		if ((rows > 0) && (cols > 0)) {
			var table = '<table border="' + border + '">';
			for (var i=1; i <= cols; i++) {
				table = table + "<tr>";
				for (var j=1; j <= rows; j++) {
					if (i==1) {
						table += "<td>&nbsp;</td>";
					} else if (j==1) { 
						table += "<td>&nbsp;</td>";
					} else {
						table += "<td>&nbsp;</td>";
					}
				}
				table += "</tr>";
			}
			table += " </table>";
			frame = $(this.options.iframe).contentWindow;
			frame.focus();
			if(BrowserInfo.isIE) {
				this.selectiframe();
				rng.select();
				frame.document.selection.createRange().pasteHTML(table);
			}else{
				frame.document.execCommand("inserthtml",false,table);
			}
			Element.hide(this.table);
		}
	},
	cleanUp : function (){
		frame = $(this.options.iframe).contentWindow;
		gentleClean = false;
		frame.document.execCommand("removeformat",false,null);
		this.selectiframe();
		var h = frame.document.body.innerHTML;
		if (!gentleClean)
			h = h.replace(/<\/?(SPAN|DEL|INS|DIR)[^>]*>/gi, "").replace(/\b(CLASS|STYLE)=\"?[^\"]*\"?/gi,"");
		h = h.replace(/<\/?(FONT|SHAPE|V:|O:|F:|F |PATH|LOCK|IMAGEDATA|STROKE|FORMULAS)[^>]*>/gi, "");
		h = h.replace(/\bCLASS=\"?MSO\w*\"?/gi, "");
		h = h.replace(/<(TABLE|TD)(.*)(WIDTH|HEIGHT)[^A-Za-z>]*/gi, "<$1$2");
		h = h.replace(/<([^>]+)>\s*<\/\1>/gi, ""); 
		frame.document.body.innerHTML = h;
	},
	facultyHtml : function (){
		controls = this.buts1 + ' newline ' + this.sels + this.buts2;
		gizmos = controls.split(' ');
		var div1 = document.createElement('div');
		Element.addClassName(div1,'controls');	
		var div2 = document.createElement('div');
		Element.addClassName(div2,'control-container');
		var div3 = document.createElement('div');
		Element.addClassName(div3,'control-set01');
		for (var i = 0; i < gizmos.length; i++) {
			if (gizmos[i]){
				if (gizmos[i] == '|'){
					var img = document.createElement('img');
					Element.addClassName(img,'btn-wall');
					img.setAttribute('src' , this.imgpath+'btn_wall.gif');
					div3.appendChild(img);
				}else if (gizmos[i] == 'newline'){
					div2.appendChild(div3);
					div2.appendChild(document.createElement('br'));
					div3 = document.createElement('div');
					Element.addClassName(div3,'control-set02');
				}else if (this.sels.indexOf(gizmos[i]) != -1){
					select = this.actionSelect(gizmos[i]);
					div3.appendChild(select);
					div3.appendChild(document.createTextNode('\n'));
				} else if (this.buts1.indexOf(gizmos[i]) != -1){
					div3.appendChild(this.makeButton(gizmos[i]));
				}else if (this.buts2.indexOf(gizmos[i]) != -1) {
					div3.appendChild(this.makeButton(gizmos[i]));
				}
			}
		}
		div2.appendChild(div3);
		div1.appendChild(div2);
		this.controls = div1;
		return div1;
	},
	iframeHtml : function (){
		var div = document.createElement('div');
		var iframe = document.createElement('iframe');
		iframe.setAttribute('id', this.options.iframe);
		iframe.setAttribute('name', this.options.iframe);
		iframe.setAttribute('height' ,this.options.height);
		Element.addClassName(iframe,'r_whizzywig');
		div.appendChild(iframe);
		return div;
	},
	decodeTagStr : function(szStr) {
	    szStr = szStr.replace(/&llt;/gi,"&lt;");
	    szStr = szStr.replace(/&ggt;/gi,"&gt;");
		return szStr;
	},
	selectiframe : function(){
		oFrame = $(this.options.iframe);
		frame = oFrame.contentWindow;
		frame.focus();
	
		if (frame.getSelection) {
			sel = frame.getSelection();
			if (sel != null) rng = sel.getRangeAt(sel.rangeCount - 1).cloneRange();
			papa = sel.anchorNode;
		} else { 
			sel = frame.document.selection;
			rng = sel.createRange();
			switch (sel.type) {
			case "Text":case "None":
				papa = rng.parentElement(); break;
			case "Control":
				papa = rng.item(0); break;
			default:
				papa = frame.document.body;
			}
		}
		var paNode = papa;
		trail = papa.nodeName; 
		while (!paNode.nodeName.match(/^(HTML|BODY)/)) {
			paNode = paNode.parentNode;
			trail = paNode.nodeName + '>' + trail;
		}	
	},
	makeButton : function (button){
		var aTag = document.createElement('a');
		Element.addClassName(aTag,'wg-btn-'+button);
		aTag.owner = this;
		aTag.onclick = function(){ this.owner.actionEditer(arguments[0], button); };
		var img = document.createElement('img');
		img.setAttribute('src' ,this.imgpath+button);
		img.setAttribute('alt' ,this.lanKey(button));
		aTag.appendChild(img);	
		return aTag;
	},
	actionEditer : function(evt, command) {
		oFrame = $(this.options.iframe);
		frame = oFrame.contentWindow;
		this.selectiframe();
		option = '';
		
		try {
			if (!BrowserInfo.isIE){
				option = false;
				frame.document.execCommand('useCSS',false, false);
			}
		} catch(e) {
		}
		
		if ("leftrightcenterjustify".indexOf(command) !=-1) command = "justify" + command;
		else if (command == "number") command = "insertorderedlist";
		else if (command == "bullet") command = "insertunorderedlist";
		else if (command == "rule") command = "inserthorizontalrule";
		switch (command) {
			case "color": 
				if(!this.colorstatus){
					$(this.options.div).appendChild(this.makeColor());
					this.oPlugColor.setEvent();
				}
				this.hideAllLayer();
				this.colorstatus = true;
				arr = this.position(evt);
				this.color.setStyle({left: arr['left']+"px", top: arr['top']+"px" });
				Element.show(this.color);
				this.colormethod = "forecolor";
				break;
			case "hilite" :
				if(!this.colorstatus){
					$(this.options.div).appendChild(this.makeColor());
					this.oPlugColor.setEvent();
				}
				this.hideAllLayer();
				this.colorstatus = true;
				arr = this.position(evt);
				this.color.setStyle({left: arr['left']+"px", top: arr['top']+"px" });
				Element.show(this.color);
				this.colormethod = "backcolor";
				break;
			case "link" :
				if (this.textsel()){
					this.hideAllLayer();
					arr = this.position(evt);
					this.link.setStyle({left: arr['left']+"px", top: arr['top']+"px" }); 
					Element.show(this.link);
					Drag.init(this.linkTit,this.link);
				}
				break;
			case "table" :
				this.hideAllLayer();
				arr = this.position(evt);
				this.table.setStyle({left: arr['left']+"px", top: arr['top']+"px" });
				Element.show(this.table);
				Drag.init(this.tableTit,this.table);
				break;
			case "clean" :
				this.cleanUp();
				break;
			case "html" :
				this.goText(); 
				break;
			default :
				frame.document.execCommand(command,false,option);
				break;
		}
		return;
	},
	goText : function() {
		$(this.options.textarea).setStyle({width : this.controls.clientWidth});

		if(frame == undefined) frame = $(this.options.iframe).contentWindow;
		var content	=	(window.get_xhtml) ? get_xhtml(frame.document.body) : frame.document.body.innerHTML;
		$(this.options.textarea).value = (!this.conversion(content))? '' : this.conversion(content);
		Element.show(this.options.textarea);
		Element.show(this.goediter);
		Element.hide(this.controls);
		Element.hide(this.options.iframe);
		$(this.options.textarea).focus();

		if($('edit_mode') != undefined){
			$('edit_mode').setAttribute('value' , 'TEXT');
		}
		if(this.goediter == undefined){
			$(this.options.div).appendChild(this.editerHtml());
		}
		
	
		this.options.editmode	= 'TEXT';
	},
	goEdit : function() {
		if($(this.options.iframe)==undefined){
		
			Element.show(this.options.div);
			this.makeEditHtml();
			this.options.status = true;			
			content = this.decodeTagStr(this.replace($F(this.options.textarea)));
			this.frameHtml(content);
			Element.hide(this.options.textarea);
			frame = $(this.options.iframe).contentWindow;
		}else{
			frame = $(this.options.iframe).contentWindow;
			frame.document.body.innerHTML = this.conversion($(this.options.textarea).value); 
			Element.hide(this.options.textarea);
			Element.hide(this.goediter);
			Element.show(this.controls);
			Element.show(this.options.iframe);
		}
		
		frame.focus();

		if($('edit_mode') != undefined){
			$('edit_mode').setAttribute('value' , 'EDIT');
		}
		
		this.options.editmode	= 'EDIT';
	},
	textsel : function() {
		if (sel != "" && sel.type != "None") return true; 
		else {alert("링크 영역을 지정해주세요"); return false;}
	},
	position : function(obj) {
		if (BrowserInfo.isIE) { 
	    	if (!document.documentElement.scrollLeft) {
				scrollX = document.body.scrollLeft;
			}else {
				scrollX = document.documentElement.scrollLeft;
	        }
	        if (!document.documentElement.scrollTop) {
	           scrollY = document.body.scrollTop;
	        } else {
	           scrollY = document.documentElement.scrollTop;
	        }
			nleft = event.clientX + scrollX;
			ntop = event.clientY + scrollY;
		}else {
			nleft  = obj.pageX;
	        ntop = obj.pageY;
		}
		return {left : nleft, top : ntop};
	},
	lanKey : function (key){
		return (this.language[key])?this.language[key] :  key;
	},
	changeSelect : function(obj, select) {
		frame = $(this.options.iframe).contentWindow;
		this.selectiframe();
		if(select == "fontname"){
			var sel = this.fontname;
		}else{
			var sel = this.fontsize;
		}
		var idx = sel.selectedIndex;
		var selected = sel.options[idx].value;
		var cmd = select.replace(/[0-9]*/g,"");
		frame.document.execCommand(cmd, false, selected);
		sel.selectedIndex = 0;
		frame.focus();
	},
	actionSelect : function (select){
		var color = document.createElement('select');
		if (select == 'fontname') {
			Element.addClassName(color,'fontname');
			var values = ["돋움","돋움", "굴림", "바탕", "궁서","Verdana","Arial","times"];
			var options = [this.lanKey("글자체"), "돋움", "굴림", "바탕", "궁서","Verdana","Arial","times"];
			this.fontname = color;
		 } else if (select == 'fontsize') {
			 Element.addClassName(color,'fontsize');
			var values = ["3", "1", "2", "3", "4", "5", "6", "7"];
			var options = [this.lanKey("크기"), "1 "+this.lanKey("Small"), "2", "3", "4", "5", "6", "7 "+this.lanKey("Big")];
			this.fontsize = color;
		} 
		for (var i = 0; i < values.length; i++) {
			var opt = document.createElement('option');
			opt.setAttribute('value',values[i]);
			opt.appendChild(document.createTextNode(options[i]));
			color.appendChild(opt);
		}
		color.onchange = this.changeSelect.bindAsEventListener(this, select);
		return color;
	},
	hideAllLayer :function() {
		if(this.colorstatus) {
			Element.hide(this.color);	
		}
		Element.hide(this.table);
		Element.hide(this.link);
	},
	getOffsetTop : function(obj) {
		return obj ? obj.offsetTop + this.getOffsetTop(obj.offsetParent) : 0;
	},
	makeResize : function () {
		obj = $(this.options.div + '_resize');
		this.resize_ondown = this.resizeOnDown.bindAsEventListener(this);
		this.resize_onmove = this.resizeOnMove.bindAsEventListener(this);
		this.resize_onup   = this.resizeOnUp.bindAsEventListener(this);
	
		obj.onmousedown = this.resize_ondown;
		obj.onmouseup   = this.resize_onup;
	},
	resizeOnDown : function(e) {
		 if(this.options.editmode == "EDIT"){
			Event.observe($(this.options.iframe).contentWindow.document, 'mousemove',this.resize_onmove);
			Event.observe($(this.options.iframe).contentWindow.document, 'mouseup', this.resize_onup);
		 }
		 
		Event.observe(document, 'mousemove', this.resize_onmove);
		Event.observe(document, 'mouseup', this.resize_onup);
		Event.stop(e);
	},
	resizeOnMove : function(e) {
		if(BrowserInfo.isIE) 
			e.target = e.srcElement;
		var targetOffset = (this.options.editmode == "EDIT") ? $(this.options.iframe) : $(this.options.textarea);
		var pageY = parseInt(e.clientY);
	
		if(BrowserInfo.isIE6){
			hideSelectBoxes();
		}
		
		if(e.target.tagName != "BODY" && e.target.tagName != "HTML") {
			pageY += BrowserInfo.getScrollTop();
			pageY -= this.getOffsetTop(targetOffset);
		} 
		try { 
			var height = this.options.height;
			targetOffset.style.height = Math.min(50000, Math.max(height , pageY)) + 'px';
		} catch(e) {
		}
	
		Event.stop(e);
	},
	resizeOnUp : function(e){
		if(BrowserInfo.isIE6){
			showSelectBoxes();
		}
		if(this.options.editmode == "EDIT"){
			Event.stopObserving($(this.options.iframe).contentWindow.document, 'mousemove',this.resize_onmove);
			Event.stopObserving($(this.options.iframe).contentWindow.document, 'mouseup', this.resize_onup);
		}
		 
		Event.stopObserving(document, 'mousemove', this.resize_onmove);
		Event.stopObserving(document, 'mouseup', this.resize_onup);
		Event.stop(e);
	}		
});
		
var B_JunEditer=JunEditer.createSubClass({
		options:{},
		// 초기 실행되는값
		initialize:function(options){
			JunEditer.prototype.initialize.apply(this,arguments);
			if((BrowserInfo.isSafari) || !document.getElementById || !document.designMode ) {//no designMode (Safari lies)
				alert("해당 브라우져에서 위즈윅 에디터 기능을 제공하지 않습니다.");
				Element.show(this.options.textarea);
				return;
			}
			this.buts1= this.buts1 + "html ";
			var input_editmode = document.createElement('input');

			//저장된 edit_mode를 사용하기 위한 변수 셋팅.
			if($('editor_area') != undefined){
				input_editmode.setAttribute('type' , 'hidden');
				input_editmode.setAttribute('id' , 'edit_mode');
				input_editmode.setAttribute('name' , 'edit_mode');
				input_editmode.setAttribute('value' , this.options.set_mode);
				$('editor_area').appendChild(input_editmode);
			}
			this.goEditMode(this.options.set_mode);
			this.makeResize();
		},	
		makeWhizzyWig : function (){

		},
		insertExecHtml : function (value){
			if(this.options.editmode == "EDIT"){
				frame = $(this.options.iframe).contentWindow;
				frame.focus();
				if(BrowserInfo.isIE) {
					this.selectiframe();
					rng.select(); //else IE gets lost
					frame.document.selection.createRange().pasteHTML(value);
				}
				else {
					frame.document.execCommand("inserthtml",false,value);
				}				
			}else{
				$(this.options.textarea).value = $(this.options.textarea).value + value;
			}
		},
		showHTML : function () {
			frame = ($(this.options.iframe) != null) ? $(this.options.iframe).contentWindow : null;
			value = (this.options.editmode == "EDIT") ? this.replaceaTag(frame.document.body.innerHTML) : this.replaceaTag($(this.options.textarea).value) ;
			// iframe이  null이면 에디터가 없음.
			if(frame == null && $('edit_mode') != undefined && $('edit_mode').value != 'TEXT') {
				value = value.replace(/\n/g,"<BR>"); // 개행문자를 <BR>로 출력
			} else {
		//		value = value.replace(/\\/g,"\\\\"); // \을 출력하기 위해서 변환.
			}
			return value;
		}		
	
	}
);


if(!App) var App = {};
if(!App.Plugin) App.Plugin = {};

App.Plugin.ColorPicker=Class.create();

App.Plugin.ColorPicker.prototype={
	initialize:function(obj, options){
		this.oEditer = obj;
		
		this.setOptions(options);

		this.setOutput();

		this.initialize = true;
	},
	setOptions:function(options){
		this.options = {minWidth:140,  id : "editer2"};
		this.options.aTableColor1 = new Array("#ff0000", "#ff6c00", "#ffaa00", "#ffef00", "#a6cf00", "#009e25", "#00b0a2", "#0075c8", "#3a32c3", "#7820b9", "#ef007c", "#ff33ff", "#cc00ff", "#0099ff", "#00ccff", "#33cc33", "#d6ed7b");
		this.options.aTableColor2 = new Array("#ffabab", "#ffcfab", "#ffe3ab", "#fffaab", "#e2efab", "#abdfb7", "#abe5e0", "#abd2ed", "#bebbeb", "#d3b6e8", "#faabd4", "#ffbcff", "#eeabff", "#abddff", "#abeeff", "#bceebc", "#f1f9d4");
		this.options.aTableColor3 = new Array("#e97d81", "#e19b73", "#d1b274", "#cfcca2", "#cfcca2", "#61b977", "#53aea8", "#518fbb", "#6a65bb", "#9a54ce", "#e573ae", "#cc29cc", "#a300cc", "#007acc", "#00a3cc", "#29a329", "#abbe62");
		this.options.aTableColor4 = new Array("#000000", "#151515", "#111111", "#222222", "#333333", "#444444", "#555555", "#666666", "#777777", "#888888", "#999999", "#aaaaaa", "#bbbbbb", "#cccccc", "#dddddd", "#eeeeee", "#ffffff");
		
		Object.extend(this.options,options||{});
	}, 
	setOutput:function() {

	var szHtml  = 
'<div class="layer-m color-picker"  style="width:227px" >'
	+ '<div class="layer-m-top">'
	+ '<div class="layer-top-h1">색상 선택</div>'
	+ '<div class="btn-close"><a href="#//" id="' + this.options.id + '_close">닫기</a></div>'
	+ '</div>'
	+ '<div class="layer-m-middle">'
		+ '<table cellspacing="1" cellpadding="0" class="color-picker-sample" id="' + this.options.id + '_tbl">\n'
			+ '<tr>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[0] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[1] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[2] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[3] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[4] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[5] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[6] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[7] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[8] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[9] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[10] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[11] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[12] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[13] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[14] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[15] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor1[16] +'></td>\n'
			+ '</tr>\n'
			+ '<tr>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[0] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[1] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[2] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[3] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[4] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[5] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[6] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[7] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[8] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[9] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[10] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[11] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[12] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[13] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[14] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[15] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor2[16] +'></td>\n'
			+ '</tr>\n'
			+ '<tr>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[0] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[1] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[2] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[3] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[4] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[5] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[6] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[7] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[8] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[9] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[10] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[11] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[12] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[13] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[14] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[15] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor3[16] +'></td>\n'
			+ '</tr>\n'
			+ '<tr>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[0] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[1] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[2] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[3] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[4] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[5] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[6] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[7] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[8] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[9] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[10] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[11] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[12] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[13] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[14] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[15] +'></td>\n'
				+ '<td bgcolor=' + this.options.aTableColor4[16] +' background="http://img.ohpy.com/opimg/common/editor/img/color_picker_white.gif"></td>\n'
			+ '</tr>\n'
		+ '</table>\n'
		+ '<div class="color-picker-preview">\n'
			+ '<div class="picker-preview-content"><span style="background-color:#ffaa00;" id="' + this.options.id + '_tdcolor"></span></div>\n'
			+ '<input type="text" class="picker-input" id="' + this.options.id + '_input" />\n'
			+ '<div class="picker-btn-confirm"><a href="#//" id="' + this.options.id + '_ok">확인</a></div>\n'
		+ '</div>\n'
	
		+ '<div class="picker-btn-more" id="' + this.options.id + '_more"><a href="#//" >더보기</a></div>\n'
		+ '<div class="picker-btn-folding" style="display:none" id="' + this.options.id + '_folding"><a href="#//">접기</a></div>\n'
	
		+ '<div class="color-picker-palette" style="display:none" id="' + this.options.id + '_cpp">\n'
		+ '</div><!--#color-picker-palette-->\n'
	
	+ '</div><!--.layer-m-middle-->\n'
	
	+ '<div class="layer-m-bottom">\n'
	+ '</div>\n'
+ '</div>';

		this.output = szHtml;
	}, 
	setEvent : function(obj, color) {
		var color_tbl = $(this.options.id + "_tbl");

		var color_cells =	color_tbl.getElementsByTagName('td');

		for(var i=0; i<color_cells.length; i++){
			cell = color_cells[i];
			bgColor = cell.bgColor.replace('#','');

			if(bgColor != ""){
				cell.onmouseover = this.overColor.bindAsEventListener(this, bgColor);
				cell.onclick = this.selectColor.bindAsEventListener(this);
			}
		}

		$(this.options.id + "_ok").onclick = this.selectColor.bindAsEventListener(this);
		
		$(this.options.id + "_close").onclick = function(){ 
			$(this.oEditer.color).style.display = "none"; 
		}.bindAsEventListener(this);
		
		
		$(this.options.id + "_more").onmousedown = function(){
			$(this.options.id + "_cpp").style.display = "block";

			$(this.options.id + "_more").style.display = "none";
			$(this.options.id + "_folding").style.display = "block";
			
			if(this.cpCreated){
				this.drawColBox(0,100,100);
			}else{
				this.cpCreated = true;
				this.drawPicker({id : this.options.id + "_cpp"});
			}
		}.bindAsEventListener(this);


		$(this.options.id + "_folding").onmousedown = function(){
			$(this.options.id + "_cpp").style.display = "none";

			$(this.options.id + "_more").style.display = "block";
			$(this.options.id + "_folding").style.display = "none";
		}.bindAsEventListener(this);	
	},
	selectColor : function(obj){
		var color = $(this.options.id + "_input").value;
	
		frame = $(this.oEditer.options.iframe).contentWindow;
	
		if (document.selection) rng.select();
	
		if(BrowserInfo.isIE) {
			frame.document.execCommand(this.oEditer.colormethod,false,color);
		} else {
			if(this.oEditer.colormethod=="backcolor") {
				frame.document.execCommand("styleWithCSS",false,true);
				frame.document.execCommand("hilitecolor",false,color);
			} else {
				frame.document.execCommand(this.oEditer.colormethod,false,color);
			}
		}
		Element.hide(this.oEditer.color);
		frame.focus();
	},
	overColor : function(obj, color) {
		$(this.options.id + '_input').value = "#"+color;
		$(this.options.id + '_tdcolor').style.backgroundColor = "#"+color;	
	},
	makeTdObj : function (bgcolor){
		var td = document.createElement('td');
		td.setAttribute('bgColor',bgcolor);
		td.setAttribute('height' , 11);
		td.setAttribute('width' , 11);
		return td;
	},
	getOutput: function() {
		return this.output;
	}, 
	drawPicker:function(attributes){

		var e = this._element = $(attributes.id);

		//느낌표 두 개는  거짓이면 true 를 반환, 참이면 false를 반환한다.
		//IE를 사용하면 this.useFilter 에 true 가 assign 되고, gekco 기반 브라우져(FF,사파리 등등)면 this.useCanvas 에 true 가 assign된다.
		//getContext는 canvas tag를 지원하는 브라우져에서 사용할 수 있는 자바스크립트 명령이다.  canvas tag부위에 draw를 시작할 수 있도록 해준다.
		this.useFilter = !!(this._element.filters);
		this.useCanvas = !!(document.createElement('canvas').getContext);

		this.fontcolor_options = Object.extend(attributes,{
			width : 201,
			huePanelHeight : 12,
			colPanelHeight : 170,
			onChange : function(id, c) {
							$(id + '_tdcolor').style.backgroundColor = '#'+c;
							$(id + '_input').value = '#'+c;
						}
		});

		// 비 호환 브라우저는 보이지 않고 끝낸다.
		if (!this.useFilter && !this.useCanvas) {
			Element.hide(this._element);
			return false;
		}

		//위 옵션에서 정했듯이 201 픽셀이 된다.
		e.style.width = this.fontcolor_options.width+'px';
	
		// 컬러 패널를 만들어 준다.
		// h (hue패널)가 아래의 풍부한 컬러, c (col 패널)가 큰 사각형의 명도차에 의한 세세한 컬러다)
		var c = this._col_panel = this.useCanvas?document.createElement('canvas'):document.createElement('div');
		var h = this._hue_panel = this.useCanvas?document.createElement('canvas'):document.createElement('div');				
	
		// 각 패널의 스타일을 지정해준다.
		Element.setStyle(e.appendChild(this._col_panel), {
			border : '1px solid #C5CAD0',
			background : 'white',
			cursor : 'crosshair',
			zIndex : 0
		});
			
		Element.setStyle(e.appendChild(this._hue_panel), {
			marginTop : '6px',
			border : '1px solid #C5CAD0',
			background : 'white',
			cursor : 'crosshair',
			position : 'relative',
			zIndex : 0
		});
	
		//각 브라우져별 패널에 크기지정을 해준다.
		if (this.useCanvas) { //canvas 태그 지원용 (Gekco 기반 브라우져)
			this._col_panel.width = this._hue_panel.width = this.fontcolor_options.width;
			this._col_panel.height = this.fontcolor_options.colPanelHeight;
			this._hue_panel.height = this.fontcolor_options.huePanelHeight;
		} else { // IE 용
			Element.addClassName(this._col_panel,'picker-palette-detail');
			Element.addClassName(this._hue_panel,'picker-palette-whole');		
			this._col_panel.style.width = this._hue_panel.style.width = this.fontcolor_options.width+'px';
			this._col_panel.style.height = this.fontcolor_options.colPanelHeight+'px';
			this._hue_panel.style.height = this.fontcolor_options.huePanelHeight+'px';
			this._col_panel.style.position = this._hue_panel.style.position = 'relative';
			this._hue_panel.style.overflow = 'hidden';
		}

		// col 패널에서 이동시, 마우스 클릭시의 이벤트를 위한 핸들러 함수 추가,
		Event.observe(this._col_panel, 'mousedown',  this.ondownCol.bindAsEventListener(this));
		Event.observe(this._col_panel, 'mousemove', this.onmoveCol.bindAsEventListener(this));

		// hue 패널에서 이동시, 마우스 클릭시의 이벤트를 위한 핸들러 함수 추가,
		Event.observe(this._hue_panel, 'mousedown', this.ondownHue.bindAsEventListener(this));
		Event.observe(this._hue_panel, 'mousemove', this.onmoveHue.bindAsEventListener(this));

		//마우스 버튼을 뗄 때 이벤트 핸들러 함수 IE에서는 이 이벤트가 없으면 마우스 down 상태가 아니어도 색상이 변한다.
//			Event.observe(document.body, 'mouseup', this.onup.bindAsEventListener(this));
		Event.observe(this._col_panel, 'mouseup', this.onup.bindAsEventListener(this));
		Event.observe(this._hue_panel, 'mouseup', this.onup.bindAsEventListener(this));
		// hue 사각형을 그려준다.
		this.drawHueBox();

		// col 사각형을 그려준다. 
		this.drawColBox(0,100,100);

	}, //init 클래스가 끝나고..

	//주어진 HSV 값으로 col 패널를 그려준다.
	drawColBox : function(h,s,v) {

		//정해진 값을  rgb hex 값으로 구한다.
		var sRGB = this.hsv2rgb_hex(h,s,v);
	
		//빈 사각형을 그려준다.
		this.clear();

		//첫번째 gradFill은 col 패널를 가로로 흰색에서 지정된 rgb 색상으로 칠해주고 (두번째 param이 가로를 뜻 함)
		this.gradFill('#'+sRGB,1);
		//두번째 gradFill은 col 패널를 세로로 아래로 갈수록 점점 어둡게 칠해준다.
		this.gradFill('#000000',0);

		//현재의 hsv 값을 들고 있는다.
		this._curHSV = {h:h,s:s,v:v};
	},
	
	//Hue 패널에서 마우스 왼쪽 버튼을 눌렀을 때 onmoveHue를 실행시킨다.
	ondownHue : function(e) {
		//button은 IE, which 는 gekco
		if (e.button || e.which) {
			this.movingHue = true;
			this.onmoveHue(e);
		}
	},

	//마우스 위치 정보를 받아서 col 패널를 만들어준다.
	onmoveHue : function(e) {
		if (!this.movingHue) return;
		
		//포지션을 잡아온다.
		var pos = this._getOffsetXY(e);
		
		// 좌표를 계산해서 hsv에 들어갈 컬러값을 구한다.
		var h = (pos.x/(this._hue_panel.offsetWidth-1))*360;
		h = Math.min(Math.max(h, 0), 360);
	
		// 구해진 값을 셋팅한다.
		this.drawColBox(h, this._curHSV.s, this._curHSV.v);
	},

	//col 패널에 뭔가 눌렸다면..		
	ondownCol : function(e) {
		if (e.button || e.which) {

			//onmoveCol(e)를 수행한다.
			this.movingCol = true;
			this.onmoveCol(e);
		}
	},

	//이 함수는 현재 위치를 잡아서 계산 후, 선택된 색상을 브라우져에 리턴한다.
	onmoveCol : function(e) {

		if (!this.movingCol) return;

		//위치를 구한다.
		var pos = this._getOffsetXY(e);
	
		// calculate
		var s = (pos.x/(this._col_panel.offsetWidth-1))*100;
		var v = (1 - pos.y/(this._col_panel.offsetWidth-1))*100;

		s = Math.min(Math.max(s, 0), 100);
		v = Math.min(Math.max(v, 0), 100);
	
		var sRGB = this.hsv2rgb_hex(this._curHSV.h,s,v);
		this.fontcolor_options.onChange(this.options.id, sRGB);
	},

	//이벤트가 일어났던 것을 전부 false 로 만들어 버린다.
		onup : function() {
		this.movingCol = false;
		this.movingHue = false;
	},
	
	//현재 마우스 커서의 위치를 구한다.
	_getOffsetXY : function(e) {

		//IE에서는 srcElement 를 알아듣고, FF 에서는 target 을 알아듣는다. 왜 차이가 있는지는 확실히는 모르겠다.
		if(!e.target) { e.element = e.srcElement;}
		else{  e.element = e.target;  }

		//이벤트가 일어난 layer의 수평값(layerX)에서 객체의 왼쪽 위치값(offsetLeft)을 빼서 X 값을 구한다.
		if (!e.offsetX && e.layerX) e.offsetX = e.layerX - e.element.offsetLeft;
		//같은 방법으로 Y 값을 구한다.
		if (!e.offsetY && e.layerY) e.offsetY = e.layerY - e.element.offsetTop;

		var x = e.offsetX, y = e.offsetY;

		//위에서 구한 offsetX 값과 0 중 큰 수를 element의 레이아웃 너비(element.offsetWidth)중 작은 넘으로 선택한다. 그것이 최종적인 위치.
		x = Math.min(Math.max(x,0), e.element.offsetWidth-1);
		//Y도 같은 방법으로 구한다.
		y = Math.min(Math.max(y,0), e.element.offsetHeight-1);

		return {x : x, y : y};
	},
						
	//col 패널 내부에서 색상을 없앨때(흰색으로 바꿀 때) 그릴 때 사용.
	clear : function() {
		//Gekco 기반 브라우져에서는...
		if (this.useCanvas)  {
			//흰색으로 사각형을 그려준다.
			var ctx = this._col_panel.getContext('2d');
			ctx.fillStyle = '#FFFFFF';
			ctx.fillRect(0,0,this._col_panel.width,this._col_panel.height);
		} else {
			this._col_panel.innerHTML = '';
		}
	},
	
	//col 패널에 그라데이션 효과를 넣는다.
	gradFill : function(rgb,orient) { // orient : (0)top->down, (1)left->right

		//Canvas 태그를 지원하는 브라우져
		//참고 튜토리얼 : http://developer.mozilla.org/ko/docs/Canvas_tutorial
		if (this.useCanvas) {
			
			//ctx는 canvas tag를 getElementByID해준 것.
			// 2d는 모든 캔버스 엘리먼트는 그리기 함수에 접근하기 위한 getContext라고 하는 DOM 메소드를 가지고 있는데, getContext는 항상 그리기 문맥의 종류를 나타내는 한 개의 인자를 받는다. 현재는 2d만 받는다.
			//때문에 ctx는 context 의 이니셜이다.
			var ctx = this._col_panel.getContext('2d');
			//createLinearGradient 는 단 방향으로 그라데이션 효과를 주는데 영역을 지정해주는 함수다.
			var linegradation = ctx.createLinearGradient(0,0,orient?this._col_panel.offsetWidth:0,orient?0:this._col_panel.offsetHeight);
			rgb = this.hex2rgb2(rgb);

			//addColorStop은 위에서 만들어진 영역 안에 그라데이션을 줄 색상을 설정하게 된다.
			//첫 인자는 0 ~ 1의 숫자가 들어가는데, 0이 top, 1이 bottom이다. 0.2 , 0.4 등에 컬러를 넣으면 몇가지 색이 겹쳐진 그라데이션 효과를 볼 수 있다.
			//rgba는 rgb에 알파값을 넣은 것으로 0 이 투명해짐을 의미한다. 1는 불투명한 것이다.
			linegradation.addColorStop(0, 'rgba('+rgb.r+','+rgb.g+','+rgb.b+',0)');
			linegradation.addColorStop(1, 'rgba('+rgb.r+','+rgb.g+','+rgb.b+',1)');

			//사각형을 그릴 스타일을 assign 해준다.
			ctx.fillStyle = linegradation;
			ctx.fillRect(0,0,this._col_panel.offsetWidth,this._col_panel.offsetHeight);
		} else {
			//rgb값이 제대로 넘어왔는지 정규식으로 체크해주고, 제일 앞에 있는 #을 제거한다.
			var rgb= rgb.replace('#','');

			//style을 지정해준다.
			Element.setStyle(this._col_panel.appendChild(document.createElement('div')), {
				top : 0,
				left : 0,
				width : '100%',
				height : this._col_panel.offsetHeight+'px',
				position : 'absolute',
				//MS 에서 지원하는 것으로, 객체의 배경과 웹 켄텐트 사이에 색상을 표현할 때 사용한다.
				//GradientType 은 1이 디폴트 값이고, 가로 그라데이션 효과에 사용하며, 0은 세로 효과에 사용한다.
				//각 컬러 셋팅은 #AARRGGBB 구조이고, AA 가 00이면 투명, FF면 불투명하다.
				filter : "progid:DXImageTransform.Microsoft.Gradient(GradientType="+orient+", StartColorStr='#00"+rgb+"', EndColorStr='#FF"+rgb+"')"
			});
		}
	},

	//hue 패널에 그라데이션 효과를 넣는다.
	drawHueBox : function() {
		var r=0, g=0, b=0, rgb, p;

		//Gekco 기반 브라우져라면...
		if (this.useCanvas) {
			var ctx = this._hue_panel.getContext('2d');
			
			//가로로 수평하게 그린다.
			var linGrad = ctx.createLinearGradient(0,0,this._hue_panel.offsetWidth,0);
			
			//7번의 색상 변화를 속성으로 만든다.
			for (var i=0; i < 7; i++) {
				//rgb = this.hsv2rgb(i/6*360, 100, 100);
				linGrad.addColorStop(i/6, '#'+this.hsv2rgb_hex(i/6*360, 100, 100));
			}
			
			//만든 속성을 그릴 사각형의 스타일로 넣는다.
			ctx.fillStyle = linGrad;
			
			//스타일대로 사각형을 그린다.
			ctx.fillRect(0,0,this._hue_panel.offsetWidth,this._hue_panel.offsetHeight);
		} else {
			var div, sp, ep, s_rgb, e_rgb;
			for (var i=1; i < 7; i++) {
				
				//Math.floor는 내림함수다.
				sp = Math.floor(((i-1)/6) * (this._hue_panel.offsetWidth-1));
				ep = Math.floor(i/6 * (this._hue_panel.offsetWidth-1));
				div   = document.createElement('div');						
				
				Element.setStyle(div, {
					position : 'absolute',
					height   : '100%',
					top      : '0',
					left     : sp+'px',
					width    : ep-sp,
					filter   : 'progid:DXImageTransform.Microsoft.Gradient(GradientType=1,StartColorStr="#FF'+this.hsv2rgb_hex((i-1)/6*360, 100, 100)+'",EndColorStr="#FF'+this.hsv2rgb_hex(i/6*360, 100, 100)+'")'
				});
				this._hue_panel.appendChild(div);
			}
		}
	},
	hex2rgb2 : function(hex)	{
	var hex= hex.replace('#','');

		if(hex.length == 3){
			hex = hex.match(/./g);
			hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
		}
				
		hex = hex.match(/../g);
				
		return{
			r : Number("0x"+hex[0]),
			g : Number("0x"+hex[1]),
			b : Number("0x"+hex[2])
		}
	},
	hsv2rgb_hex : function(h, s, v) {

	var br=Math.round(v/100*255);
		if(s==0){
			return br+br+br;
		}else{
			var hue=h%360;
			var f=hue%60;
			//round는 반올림 해주는 함수.
			var p=Math.round((v*(100-s))/10000*255);
			var q=Math.round((v*(6000-s*f))/600000*255);
			var t=Math.round((v*(6000-s*(60-f)))/600000*255);
					
			//10진수에서 hex 값으로 바꾼다.
			br = br.toString(16); if (br.length==1) br = '0'+br;
			p = p.toString(16); if (p.length==1) p = '0'+p;
			q = q.toString(16); if (q.length==1) q = '0'+q;
			t = t.toString(16); if (t.length==1) t = '0'+t;

			//floor 는 내림함수. 
			switch(Math.floor(hue/60)){
				case 0:	return br+t+p;
				case 1:	return q+br+p; 
				case 2:	return p+br+t; 
				case 3:	return p+q+br;
				case 4:return t+p+br;
				case 5:return br+p+q;
			}	
		}	
		return false;
	}
};