/* ---------------------------------------------------------------- */
/*
/* richtestediter.js
/* ~~~~~~~~~~~~~~~~~~~~~
/*   history(yyyy.mm.dd author remarks):
/*     2008.12.18 kaneko タグ置換方法変更
/*     2008.12.10 kaneko タグ整形
/*     2008.09.17 kaneko styleタグ対応
/*     2008.02.22 kaneko ObjectタグFlashVars対応
/*     2007.09.29 kaneko 新規作成
/*
/* (c) BRAINSYNC, INC.
/*
/* assigned vars:
/*
/* ---------------------------------------------------------------- */
	function RichTextEditer(){
		this.debug   = false; //debug mode

		this.targetName   = null;
		this.styles 	  = null;
		this.isIE	= false;
		this.isGecko = false;
		this.isSafari = false;
		this.browserVersion = null;
		this.editRichMode = true;
		
		this.replaceObjectTagname = "img";
		this.replaceObjectAttribute = 'src="http://static.syncl.jp/img/admin/object.gif" ';
		this.replaceScriptAttribute = 'src="http://static.syncl.jp/img/admin/script.gif" ';
		this.replaceObjectText = "Objectタグ";
		
		this.infoName	= null;
		this.info	= 'ご利用のブラウザではプレビューモードで装飾機能はご利用できません。';
		this.rteElt		= null;
		this.rteOldValue = null;
		this.rteWin		= null;
		this.rte		= null;
		this.rteBody	= null;
		this.rteDoc		= null;
		this.targetElt	= null;
		this.targetEltHeight	= null;
		this.modeChangeValue	= {'tag':'リッチモードへ', 'rich':'タグモードへ'};
		this.modeChangeTextType = 'value';
		this.modeChangeName = null;
		this.modeChangeButton = null;
		this.modeChangeButtonEnabled = true;

		this.modeValue	= {'tag':'タグモード', 'rich':'リッチモード'};
		this.modeTextType = 'value';
		this.modeName = null;
		this.modeSpan = null;
		
		this.allowTags = new Array('img','br');

		this.imgTarget = new Object();
		
		this.mouse_down = false;
		this._img_draging = false;
		this._iframe_loaded = false;

		this.bookmark = null;

		if(navigator){
			if(navigator.userAgent){
				if(navigator.userAgent.indexOf("MSIE") != -1){
					this.isIE = true;
				}
				if(navigator.userAgent.indexOf("Gecko/") != -1){
					this.isGecko = true;
				}
				if(navigator.userAgent.indexOf("Safari/") != -1){
					this.isSafari = true;
					this.browserVersion = 3;
					var ver = navigator.userAgent.split("Version/");
					if(ver[1]){
						if(3 <= Number(ver[1].split(' ')[0])){
							this.browserVersion = 2;
						}
					}else{
						this.browserVersion = 2;
					}
				}
			}
		}

		this.pointer_size = (this.isIE) ? 7 : 6;

		this.init = function() {

			var obj = this;
			this.infoElt = (this.infoName) ? document.getElementById(obj.infoName) : null;

			this.targetElt = document.getElementById(this.targetName);
			this.targetEltHeight = this.targetElt.clientHeight;

			this.rteElt = document.createElement('iframe');
			this.rteElt.frameBorder = 0;
			this.rteElt.style.height = this.targetEltHeight + 'px';

			var isrc = 'javascript:;';
			if (this.isIE) {
				isrc = 'about:blank';
			}

			this.rteElt.setAttribute('src', isrc);

			for(var key in this.styles){
				this.rteElt.style[key] = this.styles[key];
			}

			this.rteElt.style.height = (obj.editRichMode) ? this.targetEltHeight + 'px' : '0px';

			if (this.isSafari) {
				this.rteElt.style.visibility = (obj.editRichMode) ? 'visible' : 'hidden';
				this.targetElt.style.visibility = (obj.editRichMode) ? (obj.debug) ? 'visible' : 'hidden' : 'visible';
			}else{
				this.rteElt.style.display = (obj.editRichMode) ? 'block' : 'none';
				this.targetElt.style.display = (obj.editRichMode) ? (obj.debug) ? 'block' : 'none' : 'block';
			}

			var parentElt = this.targetElt.parentNode;
			parentElt.insertBefore(this.rteElt, this.targetElt);

			if(this.modeChangeButtonEnabled){
				if(this.modeChangeName){
					this.modeChangeButton = document.getElementById(this.modeChangeName);
				}else{
					this.modeChangeButton = document.createElement('input');
					this.modeChangeButton.type = 'button';
					parentElt.appendChild(this.modeChangeButton, this.targetElt);
				}

				if(this.modeName){
					this.modeSpan = document.getElementById(this.modeName);
				}
				this.modeChangeButton[this.modeChangeTextType] = (this.editRichMode) ? this.modeChangeValue['rich'] : this.modeChangeValue['tag'];

				if(this.modeSpan){
					this.modeSpan[this.modeTextType] = (this.editRichMode) ? this.modeValue['rich'] : this.modeValue['tag'];
				}
				this.modeChangeButton.onclick = function(){
					obj.modeChangeButtonClick();
				}
			}

			this.rteWin = this.rteElt.contentWindow;
			if(this.isSafari){
				this.rteDoc = this.rteElt.contentDocument;
			}else{
				this.rteDoc = this.rteWin.document;
			}

			obj.RTELoaded();
		}

		this.modeChangeButtonClick = function(){
			var obj = this;
			if(obj.editRichMode){
				obj.editRichMode = false;
				if(!obj.debug){

					if (obj.isSafari) {
						obj.rteElt.style.height = '0px';
						obj.rteElt.style.visibility = 'hidden';

						obj.targetElt.style.height = obj.targetEltHeight + 'px';
						obj.targetElt.style.visibility = 'visible';
					}else{
						obj.rteElt.style.display = 'none';
						obj.targetElt.style.display = 'block';
					}
				}
				obj.textChange(obj.rteElt);
				obj.targetElt.focus();
			}else{
				obj.editRichMode = true;

				if(!obj.debug){
					if (obj.isSafari) {
						obj.targetElt.style.height = '0px';
						obj.targetElt.style.visibility = 'hidden';

						obj.rteElt.style.height = obj.targetEltHeight + 'px';
						obj.rteElt.style.visibility = 'visible';
					}else{
						obj.targetElt.style.display = 'none';
						obj.rteElt.style.display = 'block';
					}
				}else{
					
				}
				obj.textChange(obj.targetElt);
				obj.rteWin.focus();

			}
			obj.modeChangeButton[obj.modeChangeTextType] = (obj.editRichMode) ? obj.modeChangeValue['rich'] : obj.modeChangeValue['tag'];
			if(obj.modeSpan){
				obj.modeSpan[obj.modeTextType] = (obj.editRichMode) ? obj.modeValue['rich'] : obj.modeValue['tag'];
			}
			if(document.getElementById(this.targetName+'_size')){
				this.setSize();
			}
		}

		this.RTELoaded = function(){
			try{
				this.rteSel = this.rteDoc.selection;
				this.rteDoc.designMode = 'on';
				if(this.isSafari){
					this.rteDoc.writeln("<body></body>");
				}else if(this.isGecko){
					this.rteDoc.open();
					this.rteDoc.writeln("<body></body>");
					this.rteDoc.close();
				}else{
					this.rteDoc.body.innerHTML = "<body></body>";
				}
				this.rteBody = this.rteDoc.body;
				this._iframe_loaded = true;
			}catch(e){
				var _this = this;
				this.rteWin.setTimeout(function(){ _this.RTELoaded(); }, 100);
			}finally{
				if(this._iframe_loaded){
					this.rteBody.style.backgroundColor = '#ffffff';
					this.rteBody.style.padding = '0px';
					this.rteBody.style.margin = '0px';
					this.rteBody.style.fontSize = '12px';
					this.rteBody.style.fontFamily = 'Verdana, "MS P Gothic"';
					//this.rteBody.style.lineHeight = '1.3em';
					this.RTEload();
				}
			}
		}

		this.RTEload = function() {
			var obj = this;

			var tListenerKeyUp = function(event){
				obj.textChange(obj.targetElt);
			};
			var iListenerKeyUp = function(event){
				obj.textChange(obj.rteElt);
			};

			var iListenerKeyDown = function(event){

				var k=event.keyCode;
				var m=event.shiftKey;

				var remove = obj.removeImagePointer();
				if(remove){
					if(k==8 || k==27 || k==35 || k==46){
						remove.parentNode.removeChild(remove);
						event.returnValue = false;
						event.cancelBubble = true;
						return false;
					}
				}

				//EnterでBR
				if(k==13){
					if (obj.isIE) { 
						event.returnValue = false;
						event.cancelBubble = true;
						var range = document.selection.createRange();
						range.pasteHTML('<br />');
						range.select();
						return false;
					}
				}
				
				//スペース 229 32 
				/*
				if(k==32){
					if (obj.isIE) { 
						event.returnValue = false;
						event.cancelBubble = true;
						var range = document.selection.createRange();
						range.pasteHTML('&nbsp;');
						range.select();
						return false;
					}else{
						event.returnValue = false;
						event.cancelBubble = true;
						var range = document.selection.createRange();
						range.pasteHTML('&nbsp;');
						range.select();
						return false;
					}
				}
				*/

				if(k == 39){ //bs
				}
				event.returnValue = true;
				event.cancelBubble = false;
			};

			//img move
			var rteMouseMove = function(e){
				function getPercent(move_y, move_x){
					if(Math.abs(move_x) > Math.abs(move_y)){
						var percent = Math.round(((obj.imgTarget._target.w + move_x) / obj.imgTarget._target.w) * 100);
					}else{
						var percent = Math.round(((obj.imgTarget._target.h + move_y) / obj.imgTarget._target.h) * 100);
					}
					return percent;
				}
				if(obj._img_draging == true){
					switch(obj.imgTarget._pointer.id){
						case 'pointer_s':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = obj.imgTarget._target.w + 'px';
							break;
						case 'pointer_n':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = obj.imgTarget._target.w + 'px';
							break;
						case 'pointer_e':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = obj.imgTarget._target.h + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						case 'pointer_w':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = obj.imgTarget._target.h + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						case 'pointer_sw':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						case 'pointer_ne':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						case 'pointer_nw':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						case 'pointer_se':
							var move_x = e.x - obj.imgTarget._mouse.x;
							var move_y = e.y - obj.imgTarget._mouse.y;

							obj.imgTarget.style.height = Math.round((obj.imgTarget._target.h * getPercent(move_y, move_x)) / 100) + 'px';
							obj.imgTarget.style.width = Math.round((obj.imgTarget._target.w * getPercent(move_y, move_x)) / 100) + 'px';
							break;
						default:
							break;
					}
					obj.setPositionImagePointer();
				}
			}
			var rteMouseDown = function(e){
				obj.mouse_down = true;
			}
			var rteMouseUp = function(e){
				obj.mouse_down = false;
				if(e.srcElement != obj.imgTarget){
					obj._img_draging = false;
					obj.removeImagePointer();
				}
			}
			
			if (obj.rteDoc.attachEvent) { //IE
				obj.rteDoc.attachEvent('onmousemove', rteMouseMove, false);
				obj.rteDoc.attachEvent('onmouseup', rteMouseUp, true);
				obj.rteDoc.attachEvent('onmousedown', rteMouseDown, true);

				if(this.debug){
					//obj.rteDoc.attachEvent('onkeyup', iListenerKeyUp);
				}
				obj.rteDoc.attachEvent('onkeydown', iListenerKeyDown);

			} else if (obj.rteDoc.addEventListener) { //Firefox, Safari
				/*
				if(this.isGecko){
					obj.rteDoc.addEventListener('mouseup', rteMouseUp, true);
				}
				*/
				obj.rteDoc.onmousemove = rteMouseMove;
				obj.rteDoc.onmouseup = rteMouseUp;
				obj.rteDoc.onblur  = function(e){
					e.returnValue = false;
					e.cancelBubble = true;
				};

				if(this.debug){
					//obj.rteDoc.addEventListener('keyup', iListenerKeyUp, false);
				}
				obj.rteDoc.addEventListener('keydown', iListenerKeyDown, false);

			}
			if(this.debug){
				//obj.rteElt.onblur = iListenerKeyUp;
				//obj.targetElt.onblur = tListenerKeyUp;
			}

			function getParentForm(el){
			    var form;
			    if(el.parentNode.tagName != "FORM"){
			        form = getParentForm(el.parentNode);
			    } else {
					form = el.parentNode;
				}
			    return form;
			}

			var FORM_SUBMIT = function(){
				obj.onsubmit();
			}
			var form = getParentForm(this.targetElt);

			if (form.attachEvent) { //IE
				form.attachEvent('onsubmit', FORM_SUBMIT, true);
			} else if (form.addEventListener) { //Firefox, Safari
				form.addEventListener('submit', FORM_SUBMIT, true);
			}

			var code = new RegExp('<\\\\/script>', 'igm');
			obj.targetElt.value = obj.targetElt.value.replace(code, '</script>');

			obj.targetElt.value = this.formatOutput(obj.targetElt.value, true, true);

			obj.textChange(obj.targetElt);
			//obj.textChange(obj.rteElt);

			if(document.getElementById(this.targetName+'_size')){
				this.setSize();
			}
		}

		this.textChange = function(elm){

			var obj = this;

			if(elm.id == this.targetName){
				//タグモードからリッチモードへ
				var tmp = elm.value;

				tmp = this.formatOutput(tmp, false, false);

				//Scriptタグ対応
				var code = new RegExp('<\\\\/script>', 'igm');
				tmp = tmp.replace(code, '</script>'); 

				var script_node = new RegExp('(<script((\n|(?:(?!/script).))*)/script>)', 'igm');
				tmp = tmp.replace(script_node, function($0, $1){
					$1 = $1.replace(/</g, "＜");
					$1 = $1.replace(/>/g, "＞");
					$1 = $1.replace(/"/g, "”");
					$1 = $1.replace(/\n/g, "￥ｎ");
					var attribute = 'width="100px" height="100px"';
					new_tag = obj.replaceObjectTagname + ' ' + obj.replaceScriptAttribute + attribute + ' title="'+$1+'"';
					return '<' + new_tag + '/>';
				});

				//Objectタグ対応
				var object_node = new RegExp('(<object((\n|(?:(?!/object).))*)/object>)', 'igm');
				tmp = tmp.replace(object_node, function($0, $1){
					var width = 0;
					var height = 0;
					var align = 0;
					var attribute = '';
					//var div = obj.rteDoc.createElement('div');
					var div = document.createElement('div');
					$0 = $0.replace('<object ', '<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" ');
					/*
					$0 = $0.replace('<object ', '<div ');
					$0 = $0.replace('</object>', '</div>');
					$0 = $0.replace('<embed ', '<p ');
					$0 = $0.replace('</embed>', '</p>');
					*/
					div.innerHTML = $0.toString();
					if(div.childNodes.length > 0){
						var object_elm = div.childNodes.item(0);
						if(object_elm.width){
							width = object_elm.width;
						}
						if(object_elm.height){
							height = object_elm.height;
						}
						if(!width || !height){
							var param_elms = object_elm.childNodes;
							for(i=0; i<param_elms.length; i++){
								param = param_elms.item(i);
								if(param.name){
									if(param.name.toLowerCase() == 'width'){
										width = param.value;
									}
									if(param.name.toLowerCase() == 'height'){
										height = param.value;
									}
									if(param.name.toLowerCase() == 'align'){
										align = param.value;
									}
								}
							}
						}
					}
					attribute += ' width="'+ width +'px"';
					attribute += ' height="'+ height +'px"';
					if(align){
						attribute.replaceObjectAttribute += ' align="'+align+'"';
					}
					$1 = $1.replace(/</g, "＜");
					$1 = $1.replace(/>/g, "＞");
					$1 = $1.replace(/"/g, "”");
					$1 = $1.replace(/\n/g, "￥ｎ");
					new_tag = '<' + obj.replaceObjectTagname + ' ' + obj.replaceObjectAttribute + attribute + ' title="'+$1+'"' + '/>';
					return new_tag;
				});

				//空タグ対応
				if(tmp.match(/^<!--/)){
					//tmp = '&nbsp;'+tmp;
					tmp = '<br />'+tmp;
				}
				if(obj.isGecko && tmp == ""){
					tmp = '<br />';
				}
				
				obj.rteBody.innerHTML = tmp;
			}else{
				//リッチモードからタグモードへ

				obj.removeImagePointer();

				var tmp = trim(obj.rteBody.innerHTML.toString());

				//空タグ対応
				if(obj.isIE && tmp.toLowerCase() == '<p>&nbsp;</p>'){ //ie
					tmp = '';
				}
				if((obj.isSafari || obj.isGecko) && (tmp.toLowerCase() == '<br>' || tmp.toLowerCase() == '<br />')){ //firefox , safari
					tmp = '';
				}
				if(obj.isSafari && (tmp.toLowerCase() == '<div><br></div>' || tmp.toLowerCase() == '<div><br /></div>')){ //safari
					tmp = '';
				}

				//scriptタグ対応
				var script_node = new RegExp('<' + obj.replaceObjectTagname + ' ([^>]*?)(＜script((\n|(?:(?!\/script＞).))*)\/script＞)((\n|(?:(?!>).))*)>', 'igm');
				tmp = tmp.replace(script_node, function($0, $1, $2, $3){
					$2 = $2.replace(/＜/g, "<");
					$2 = $2.replace(/＞/g, ">");
					$2 = $2.replace(/”/g, "\"");
					$2 = $2.replace(/￥ｎ/g, "\n");
					return $2;
				});

				//Objectタグ対応
				var object_node = new RegExp('<' + obj.replaceObjectTagname + ' ([^>]*?)(＜object((\n|(?:(?!\/object＞).))*)\/object＞)((\n|(?:(?!>).))*)>', 'igm');
				tmp = tmp.replace(object_node, function($0, $1, $2, $3){
					$2 = $2.replace(/＜/g, "<");
					$2 = $2.replace(/＞/g, ">");
					$2 = $2.replace(/”/g, "\"");
					$2 = $2.replace(/￥ｎ/g, "\n");
					return $2;
				});

				//&amp;対応
				var code = new RegExp('([^&amp;]*)&amp;([^&amp;]*)', 'igm');
				var tmp = tmp.replace(code, '$1&$2');


				tmp = this.formatOutput(tmp, true, true);
				
				obj.targetElt.value = tmp;
			}
			//ポインタイベント
			this.setEventImagePointer();

			//高さ調整
			this.SetReHeight(this.targetEltHeight);
		}
		
		this.getParentForm = function(el){
		    var parent_ref;
		    if(el.parentNode.tagName != "FORM"){
		        this.getParentForm(el.parentNode);
		    } else {
		        if(el.parentNode.name){
		            parent_ref = el.parentNode.name;
		        } else {
		            parent_ref = el.parentNode.id;
		        }   }
		    return parent_ref;
		}

		this.onsubmit = function(){
			if(this.editRichMode){
				this.textChange(this.rteElt);
			}
			html = this.formatOutput(this.targetElt.value, false)

			var code = new RegExp('</script>', 'igm');
			html = html.replace(code, '<\\/script>'); 

			this.targetElt.value = html;
			return true;
		}

		//================================================================================
		//タグ関係
		//================================================================================
		this.formatOutput = function(str, indent, whitespaceReplace) {
			if(this.browserVersion == 2){
				//return str;
			}
			
			var whitespace = " |\t|\f|\x0b|\xa0|\u2000|\u2001|\u2002|\u2003|\u2004|\u2005|\u2006|\u2007|\u2008|\u2009|\u200a|\u200b|\u2028|\u2029|\u3000";

			var RegExpCode = [
				['\r', ''],
				['>('+whitespace+'{2,})<', '> <'],
				['> <', '>&nbsp;<'],

				//['<(/?)p([^>]*?)>', '<$1div$2>'],//IEPタグ対策

				//['<(span|big|small|p|h[0-6]|center|b|font|strong)></\\1>', ''], //空タグを削除（単独タグ属性無）
				['<(span|big|small|p|h[0-6]|center|b|font|strong)([^>]*?)></\\1>', ''], //空タグを削除（単独タグ属性有）
				//['<(span|big|small|p|h[0-6]|center|b|font|strong|div)>([^<>]*)</\\1><\\1>', '<$1>$2'], //１行の中のダブりタグの削除（属性無）
				['<(span|big|small|p|h[0-6]|center|b|font|strong)([^>]*?)>([^<>]*)</\\1><\\1\\2>', '<$1$2>$3'], //１行の中のダブりタグの削除（属性有）

				//['<(span|big|small|p|h[0-6]|center|div|b|font)([^>]*?)><\\1\\2>((\n|(?:(?!\/</\\1>).))*)</\\1></\\1>', '<$1$2>$3</$1>'], //ダブりタグの削除（属性有）

				//['<(span|big|small|p|h[0-6]|center|div|b|font)>([^<>]*)<br>\n([^<>]*)</\\1><\1>', '<$1>$2<br>\n$3'],  //改行コードをまたぐダブりタグの削除（属性無）
				//['<(span|big|small|p|h[0-6]|center|div|b|font) ([^>]*?)>([^<>]*)<br>\n([^<>]*)</\\1><\\1 \\2>', '<$1 $2>$3<br>\n$4'], //改行コードをまたぐダブりタグの削除（属性有）

				//['<([^ ]*) ([^=]*)=(".)([^ >]*)(".)([^<>]*)>', '<$1 $2="$4"$6>'], //属性をダブルクォーテート

				//['</(?:(?!>)?)(.*?)>', '\n</$1>'], //閉じタグ改行
				//['<(?:(?!>)?)(.*?)/>', '<$1/>\n'], //閉じタグ改行
				//['<(?:(?!>)?)(.*?)>', '<$1>\n'], //閉じタグ改行
			];

			for(i in RegExpCode){
				var e = RegExpCode[i];
				var code = new RegExp(e[0], 'igm');
				str = str.replace(code, e[1]);
			}

			//空要素タグ
			var empty_elements = new Array(
				'area',
				'base',
				'basefont',
				'bgsound',
				'br',
				'embed',
				'frame',
				'hr',
				'img',
				'input',
				'link',
				'meta',
				'param'
			);

			var treer = new Array();

//alert();

			//HTML配列化
			//var code_node = new RegExp('(<(([^>]|\n)*?)>|(<!--(((?:(?!-->).)|\n)*?)-->)|(([^<]|\n)*))', 'igm');
			var code_node = new RegExp('(<!--(((?:(?!-->).)|\n)*?)-->|<(([^>]|\n)*?)>|(([^<]|\n)*))', 'igm');

			var tags = str.match(code_node);

			//ツリー化
			var code_tag = new RegExp('<([/|!]?)([^ ]*)( ?)(([^>]|\n)*?)(/?)>', 'i');
			//var code_tag = new RegExp('<([/|!]?)([^ ]*)( ?)(([^<>]|\n)*?)(/?)>', 'i');
			var code_comment = new RegExp('<!--(((?:(?!-->).)|\n)*?)-->', 'i');
			//var code_text = new RegExp('([^<>]*)', 'i');

			var depth = 0;
			var tag_depth = new Array();
			var treeindex = 0;
			var match;
//alert(str);
			for(var i=0; i<tags.length; i++){
//alert(tags[i] + ":" + i + ":" + depth);
				match = tags[i].match(code_tag);

				if(match){
					treer[treeindex] = new Array();
					treer[treeindex]['tagName'] = match[2].toLowerCase().replace(/\//g, ''); //不正タ(<BR/>)グ対応 2009.05.11 
					treer[treeindex]['attribute'] = match[4];
					if(match[1] == '/'){
						if(in_array(treer[treeindex]['tagName'], empty_elements)){
							continue;
						}
						tag_depth[depth] = null;
						depth--;
						treer[treeindex]['depth'] = depth;
						treer[treeindex]['tagType'] = 'end';

						if(treer[treeindex]['attribute']){
							treer[treeindex]['html'] = '</' + treer[treeindex]['tagName'] + ' ' + treer[treeindex]['attribute'] + '>';
						}else{
							treer[treeindex]['html'] = '</' + treer[treeindex]['tagName'] + '>';
						}

						if(tag_depth[depth] != treer[treeindex]['tagName']){
							if(depth > 0){
								//不足タグ補完
								treer[treeindex]['html'] = '</'+tag_depth[depth]+'>';
								treer[treeindex]['attribute'] = '';
								treer[treeindex]['tagName'] = tag_depth[depth];
								treeindex++;
								i--;
								continue;
							}else{
								//余分タグ除去
								treer[treeindex]['html'] = '';
								treer[treeindex]['tagName'] = '';
								treeindex++;
								depth++;
								continue;
							}
/*
							if(treer[treeindex]['tagName'] == tag_depth[depth-1]){
								//不足タグ補完
								treer[treeindex]['html'] = '</'+tag_depth[depth]+'>' + treer[treeindex]['html'];
							}else{
								//余分タグ除去
								treer[treeindex]['html'] = '';
							}
*/
						}

					}else if(match[1] == '!'){
						treer[treeindex]['tagName'] = '--';
						treer[treeindex]['attribute'] = '';

						treer[treeindex]['depth'] = depth;
						treer[treeindex]['tagType'] = 'comment';
						commant_match = tags[i].match(code_comment);
						treer[treeindex]['html'] = '<!--' + commant_match[1] + '-->';
						//treer[treeindex]['html'] = '<!--' + commant_match[1].replace(/--/g, '－－') + '-->';
					}else{
						if(in_array(treer[treeindex]['tagName'], empty_elements)){
							treer[treeindex]['depth'] = depth;
							treer[treeindex]['tagType'] = 'line';

							if(treer[treeindex]['attribute']){
								//属性をダブルクォーテート
								var attr = treer[treeindex]['attribute'].split('=');
								treer[treeindex]['html'] = '<' + treer[treeindex]['tagName'] + ' ' + trim(treer[treeindex]['attribute']) + ' />';
							}else{
								treer[treeindex]['html'] = '<' + trim(treer[treeindex]['tagName']) + ' />';
							}
						}else{
							treer[treeindex]['depth'] = depth;
							treer[treeindex]['tagType'] = 'start';

							tag_depth[depth] = treer[treeindex]['tagName'];
							depth++;

							if(treer[treeindex]['attribute']){
								treer[treeindex]['html'] = '<' + treer[treeindex]['tagName'] + ' ' + treer[treeindex]['attribute'] + '>';
							}else{
								treer[treeindex]['html'] = '<' + treer[treeindex]['tagName'] + '>';
							}

							/*
							//scriptタグ対応
							if(treer[treeindex]['tagName'] == 'script'){
								treer[treeindex]['html'] += '</script>';
							}
							*/

							if(treeindex > 1 && treer[treeindex]['html'] == treer[(treeindex-1)]['html']){ //親と同じタグは除外
								continue;
							}
						}
					}
					treer[treeindex]['text'] = '';

				}else{
					//インデント改行時の末尾空白除去
					var lines = tags[i].split("\n");
					var line = '';
					//for(var j in lines){
					//	if(typeof(lines[j]) != 'string') continue;
					for(var j=0; j<lines.length; j++){
						if(trim(lines[j])){
							line += lines[j];
						}
					}
					tags[i] = line;

					//改行除去
					var code = new RegExp("\n|\u000A|\r|\u000D", 'igm');
					tags[i] = tags[i].replace(code, '');

					if(whitespaceReplace){ //add 090414
						var code = new RegExp(whitespace, 'igm');
						//tags[i] = tags[i].replace(code, '&nbsp;');
						tags[i] = tags[i].replace(code, ' ');
					}

//alert("2["+tags[i]+"]");

					//インデントスペース除去
					var indentspace = '';
					for(var d=0; d<depth; d++){
						indentspace += '  ';
					}
					if(tags[i].substring(0, indentspace.length) == indentspace){
						tags[i] = tags[i].substring(indentspace.length, (tags[i].length));
					}

					//末尾のスペース除去
/*
					if(tags[i].substring(tags[i].length-1, tags[i].length) == ' '){
alert("["+tags[i]+"]");
						tags[i] = tags[i].substring(0, (tags[i].length-1));
alert("["+tags[i]+"]");
					}
*/
					
//alert("3["+tags[i]+"]");

/*
					//前後のスペース置換え
					if(tags[i].substring(0, 1) == ' '){
						tags[i] = '&nbsp;' + tags[i].substring(1, (tags[i].length));
					}
					if(tags[i].substring(tags[i].length-1, tags[i].length) == ' '){
						tags[i] = tags[i].substring(0, (tags[i].length)-1) + '&nbsp;';
					}
*/
					//連続スペース纏め
					var code = new RegExp('( {2,})', 'igm');
					//tags[i] = tags[i].replace(code, '&nbsp;');
					tags[i] = tags[i].replace(code, ' ');

					//tags[i] = trim(tags[i]);

					if(tags[i]){
						treer[treeindex] = new Array();
						treer[treeindex]['tagName'] = '';
						treer[treeindex]['attribute'] = '';
						treer[treeindex]['tagType'] = '';
						treer[treeindex]['text'] = tags[i];
						treer[treeindex]['html'] = tags[i];
						treer[treeindex]['depth'] = depth;
					}else{
						continue;
					}
				}
				treeindex++;
			}

			while(depth != 0){
				depth--;
				tagName = '';
				for(var i=0; i<treer.length; i++){
					if(treer[i]['depth'] == depth && treer[i]['tagType']=="start"){
						tagName = treer[i]['tagName'];
//alert(tagName);
						treer[treeindex] = new Array();
						treer[treeindex]['tagName'] = tagName;
						treer[treeindex]['attribute'] = '';
						treer[treeindex]['tagType'] = 'end';
						treer[treeindex]['text'] = '';
						treer[treeindex]['html'] = '</'+tagName+'>';
						treer[treeindex]['depth'] = depth;
						break;
					}
				}
				treeindex++;
			}


			var new_str = '';
			if(indent){
				for(var i=0; i<treer.length; i++){
					for(var n=0; n<treer[i]['depth']; n++){
						new_str += "  ";
					}
					new_str += treer[i]['html'];
					new_str += "\n";
				}
			}else{
				for(var i=0; i<treer.length; i++){
					new_str += treer[i]['html'];
				}
			}
//alert(new_str);
			//タグ標準化
			var RegExpCode = [
				//['<(.*?)P>|</DIV>|&nbsp;', ''],
				//['\n', ''],

				//['<(.?)syncltag>', ''], //独自タグ
				//['\r', ''],

				//['</DIV>', ''],
				//['&nbsp;', ' '],
				//['<p>&nbsp;</P>', '<br>'],
				//['<p>(.*?)<.p>', '$1'],

				['^<p><hr \/>((.|\n)*?)</p>', '<hr \/>$1<\/p>'],

				['<b>((.|\n)*?)<.b>', '<strong>$1</strong>'],
				['<i>((.|\n)*?)<.i>', '<em>$1</em>'],
				['<(.?)xml(?:(?!>).)((.|\n)*?)>', '&lt;$1xml$2&gt;'],	//XMLタグ対策
				['<(.?)o:p(.?)>', '<$1p$2>'],						//XMLタグ対策
				['<([^ >]*) ([^>]*?)apple-style-span([^>]*?)>', '<$1 $2$3>'], //アップル対応


				//['<STRONG>(.*?)<.STRONG>', '<strong>$1</strong>'],
				//['<U>(.*?)</U>', '<span style="text-decoration: underline;">$1</span>'],

				//RGB変換
				['<([^ >]*) ([^>]*?)style="((?:(?!color).)*)color:([^;"]*)([;"])([^>]*?)>', function($0, $1, $2, $3, $4, $5, $6){
					var color = new RGBColor(trim($4));
					var str = '<'+$1+' '+$2+'style="'+$3+'color:'+color.toHex()+$5+$6+'>';
					return str;
				}],

				/*
				['<span ([^(style|>)]*?)style="([^(color|>)]*?)color:([^(;|>|")]*)(;?)([^(>|")]*)"([^>]*?)>([^<]*?)</span>', '<font style="$2$5" $1color="$3"$6>$7</font>'], //カラースパンフォント化
				*/

				['<([^>]*?) style=""([^>]*?)>', '<$1$2>'], //空スタイル除去
				['<([^>]*?) class=""([^>]*?)>', '<$1$2>'], //空クラス除去

//				['<span>([^<]*)</span>', '$1']
/*
				['<span>([^<]*)</span>', function($0){
					alert($0);
					return $0;
				}] //空spanタグ除去
*/
				
				/*
				['<span style="font-style: italic;">((.|\n)*?)</span>', '<em>$1</em>'],
				['<span style="font-weight: bold;">((.|\n)*?)</span>', '<strong>$1</strong>'],
				['<span style="text-decoration: line-through;">((.|\n)*?)</span>', '<strike>$1</strike>'],
				['<span style="text-decoration: underline;">((.|\n)*?)</span>', '<u>$1</u>'],
				['<span styl.*"font-weight: normal;">((.|\n)*?)</span>', '$1'],
				*/




				//['<BR class="khtml-block-placeholder">', 'n'],
				//['<DIV>|<BR.*?>', '<br>']
			];
			
			for(i in RegExpCode){
				var e = RegExpCode[i];
				var code = new RegExp(e[0], 'igm');
				new_str = new_str.replace(code, e[1]);
			}
//alert(new_str);

/*
			var RegExpCode = [
				['(<BIG>)+(.*?)(<.BIG>)+', '<span style="font-size:%#size#%em">$2</span>','<BIG>'],
				['(<SMALL>)+(.*?)(<.SMALL>)+', '<span style="font-size:%#size#%em">$2</span>','<SMALL>']
			];
			
			for(i in RegExpCode){
				var e = RegExpCode[i];
				var tagPattern = new RegExp(e[0], 'igm');
				var tag = new RegExp(e[2], 'igm');
				new_str = new_str.replace(tagPattern, function(matchText){
					var num = matchText.split(tag).length - 1;
					var size = (e[2] == '<BIG>') ? Math.pow(1.4, num) :  Math.pow(0.85, num);
					var pattern = e[1].replace(/%#size#%/, roundMath(size));
					return matchText.replace(tagPattern, pattern);
				});
			}
*/
			return trim(new_str);
		}

		//================================================================================
		//イメージ関係
		//================================================================================
		this.setEventImagePointer = function() {
			var obj = this;
			obj.removeImagePointer();

			//イメージ
			var imgs    = obj.rteBody.getElementsByTagName('img');
			for(var i=0; i<imgs.length; i++) {
				imgs[i]._parent = imgs[i];
				imgMouseUp = function(e){
					obj.imgTarget = this;
					obj._img_draging = false;

					var object_node = new RegExp('(object((\n|(?:(?!/object).))*)/object)', 'igm');
					if(this.title && object_node.test(this.title)){
						if(obj.isGecko){
							obj.imgBlur(this);
						}else{
							obj.imgRange(this);
						}
						return false;
					}else{
						if(obj.isGecko){
							return false;
						}else{
							obj.imgRange(this);
						}
					}
					obj.createImagePointer(this);
					return false; //add kaneko
				}
				imgDragEnd = function(e){
					//obj.textChange(obj.rteElt);
					obj.imgRange(this);
					obj.removeImagePointer();
					//obj.imgRange(this);
					obj.setEventImagePointer();
				}
				imgMouseDown = function(e){
					//var range = document.selection.createRange();
					//obj.bookmark = range.getBookmark();
				};
				imgControlSelect = function(e){
					var object_node = new RegExp('(object((\n|(?:(?!/object).))*)/object)', 'igm');
					if(this.title && object_node.test(this.title)){
						obj.imgBlur(this);
						return false;
					}
					if(!obj.mouse_down){
						obj.imgRange(this);
						obj.createImagePointer(this);
					}else{
						obj.removeImagePointer();
					}
				};

				if (obj.isIE) { //IE
					imgs[i].onmouseup = imgMouseUp;
					imgs[i].ondragend = imgDragEnd;
					imgs[i].onmousedown = imgMouseDown;
					//imgs[i].oncontrolselect = imgControlSelect;

				}else if(obj.isSafari) {
					imgs[i].onmouseup = imgMouseUp;
					imgs[i].ondragend = imgDragEnd;
				}else if(obj.isGecko) {
					imgs[i].removeEventListener('mouseup', imgMouseUp, false);
					imgs[i].addEventListener('mouseup', imgMouseUp, false);
					//imgs[i].addEventListener('dragend', imgDragEnd, false);
					//imgs[i].addEventListener('draggesture', imgDragEnd, false);
					//imgs[i].addEventListener('controlselect', imgControlSelect, false);
					//imgs[i].addEventListener('mouseup', imgMouseUp, false);
					//imgs[i].addEventListener('dragover', imgDragEnd, false);

	//				imgs[i].addEventListener('dragexit', imgDragEnd, false);
					//imgs[i].addEventListener('DOMMenuItemActive', imgDragEnd, false);
	//				imgs[i].addEventListener('dragdrop', imgDragEnd, false);


					//imgs[i].contenteditable = "false";
				}
			}
		}
		this.imgBlur = function(elm) {
			//alert(var_export(elm));
				var selection = this.rteWin.getSelection();
				if(selection.rangeCount > 0) selection.removeAllRanges();

				if(selection["selectAllChildren"]){ // Mozilla 
					//selection.selectAllChildren(elm.nextSibling); 
					//selection.selectAllChildren(elm.previousSibling);

					//selection.removeAllRanges();
					//selection.removeAllRanges();
					//alert(var_export(node));
					//node.removeNode();
					//selection.containsNode(node ,true);

					node = this.rteDoc.createElement('br');
					elm.appendChild(node);
					selection.selectAllChildren(node);
					node.parentNode.removeChild(node);
				}
		}
		this.setBookmark = function(bookmark){
			var textRange = this.rteBody.createTextRange();
			textRange.moveToBookmark(bookmark);
			this.rteWin.setTimeout(function(){ textRange.select(); }, 1);
		}
		this.imgRange = function(elm, bookmark) {
			if(this.isIE){
				if(elm){
					var textRange = this.rteBody.createTextRange();
					textRange.moveToElementText(elm);
					this.rteWin.setTimeout(function(){ textRange.select(); }, 1);
				}else{
					if(bookmark){
						//textRange.moveToBookmark(bookmark);
						this.setBookmark(bookmark);
					}else{
						var textRange = this.rteBody.createTextRange();
						textRange.collapse(false);
						this.rteWin.setTimeout(function(){ textRange.select(); }, 1);
					}
				}
			}else if(this.isSafari){
				var selection = this.rteWin.getSelection();
				if(selection.rangeCount > 0) selection.removeAllRanges();
				if(this.browserVersion != 2){
					var range = this.rteDoc.createRange();
					range.selectNode(elm);
					selection.addRange(range);
				}else{
					if(selection["setBaseAndExtent"]){ // Safari 
						selection.setBaseAndExtent(elm, 0, elm, 1); 
						//selection.setBaseAndExtent(elm, 0, elm, elm.innerText.length - 1); 
					} else if(selection["selectAllChildren"]){ // Mozilla 
						selection.selectAllChildren(elm); 
					}
				}
			}
			return false;
		}

		this.setPositionImagePointer = function() {
			var obj = this;
			var pointers = new Array('nw','n','ne','w','e','sw','s','se');
			var x = 0;
			var y = 0;

			try{
				for(var i=0; i<pointers.length; i++){
					var pointer = obj.rteDoc.getElementById('pointer_'+pointers[i]);
					switch(pointers[i]){
						case 'n':
							y = obj.imgTarget.offsetTop + obj.imgTarget.offsetHeight;
							x = Math.round((obj.imgTarget.offsetWidth) / 2) + obj.imgTarget.offsetLeft - (obj.pointer_size / 2);
							break;
						case 's':
							y = obj.imgTarget.offsetTop - obj.pointer_size;
							x = Math.round((obj.imgTarget.offsetWidth) / 2) + obj.imgTarget.offsetLeft - (obj.pointer_size / 2);
							break;
						case 'e':
							y = Math.round((obj.imgTarget.offsetHeight) / 2) + obj.imgTarget.offsetTop - (obj.pointer_size / 2);
							x = obj.imgTarget.offsetLeft - obj.pointer_size;
							break;
						case 'w':
							y = Math.round((obj.imgTarget.offsetHeight) / 2) + obj.imgTarget.offsetTop - (obj.pointer_size / 2);
							x = obj.imgTarget.offsetLeft + obj.imgTarget.offsetWidth;
							break;
						case 'ne':
							y = obj.imgTarget.offsetTop + obj.imgTarget.offsetHeight;
							x = obj.imgTarget.offsetLeft - obj.pointer_size;
							break;
						case 'nw':
							y = obj.imgTarget.offsetTop + obj.imgTarget.offsetHeight;
							x = obj.imgTarget.offsetLeft + obj.imgTarget.offsetWidth;
							break;
						case 'se':
							y = obj.imgTarget.offsetTop - obj.pointer_size;
							x = obj.imgTarget.offsetLeft - obj.pointer_size;
							break;
						case 'sw':
							y = obj.imgTarget.offsetTop - obj.pointer_size;
							x = obj.imgTarget.offsetLeft + obj.imgTarget.offsetWidth;
							break;
					}
					pointer.style.top =  y + 'px';
					pointer.style.left = x + 'px';
				}
			}catch(e){
				obj.removeImagePointer();
			}
		}
		this.removeImagePointer = function() {
			var obj = this;
			var pointers = new Array('nw','n','ne','w','e','sw','s','se');
			var remove = false;
			var pointer = null;
			for(var i=0; i<pointers.length; i++){
				pointer = obj.rteDoc.getElementById('pointer_'+pointers[i]);
				if(pointer){
					remove = pointer._parent;
					//pointer.removeEvent('onmousedown');
					obj.rteBody.removeChild(pointer);
				}
			}
			return remove;
		}
		this.createImagePointer = function(target) {

			this.removeImagePointer();
			var obj = this;
			var pointers = new Array('nw','n','ne','w','e','sw','s','se');
			for(var i=0; i<pointers.length; i++){
				//var pointer = obj.rteDoc.createElement('img');
				//pointer.src = '/img/img_move_point.png';
				var pointer = obj.rteDoc.createElement('div');
				pointer.style.border = '1px solid #000000';

				pointer.id = 'pointer_' + pointers[i];
				pointer.style.position = 'absolute';
				pointer.style.top = '0px';
				pointer.style.left = '0px';
				pointer.style.height = obj.pointer_size + 'px';
				pointer.style.width = obj.pointer_size + 'px';
				pointer.style.margin = '0px';
				pointer.style.padding = '0px';
	//			pointer.style.lineHeight = '0px';
				pointer.style.fontSize = '0px';

				pointer.style.backgroundColor = '#FFFFFF';

				pointer.unselectable = 'on';
				pointer.style.cursor = pointers[i] + '-resize';
				pointer._parent = target;
				pointerMouseDwon = function(e){
					obj.imgTarget._pointer = e.srcElement;
					obj._img_draging = true;
					obj.imgTarget._mouse = new Object();
					obj.imgTarget._mouse.x = e.x;
					obj.imgTarget._mouse.y = e.y;
					obj.imgTarget._target = new Object();
					obj.imgTarget._target.h = obj.imgTarget.offsetHeight;
					obj.imgTarget._target.w = obj.imgTarget.offsetWidth;

					e.returnValue = false;
					e.cancelBubble = true;
				}
				pointerMouseUp = function(e){
					obj._img_draging = false;
				}
				pointerControlSelect = function(e){
					e.cancelBubble = true;
					e.returnValue = false;
				}
				
				if (obj.isIE) { //IE
					pointer.attachEvent('onmousedown', pointerMouseDwon, true);
					pointer.attachEvent('onmouseup', pointerMouseUp, true);
				}else{
					pointer.onmousedown = pointerMouseDwon;
					pointer.onmouseup = pointerMouseUp;
					pointer.oncontrolselect = pointerControlSelect;
				}
				obj.rteBody.appendChild(pointer);
			}
			this.setPositionImagePointer();
		}


		//================================================================================
		//ノード関係
		//================================================================================
		this.log = function(val){
			document.getElementById('debug').value = var_export(val);
		}


		this.updateNode = function(tmpElement, html){

			if(this.isIE){
				/*
				var activeElement = this.rteDoc.createElement('syncltag');
				activeElement.innerHTML = html;
				this.replaceNode(activeElement, tmpElement);
				var code = new RegExp('<(.?)syncltag>', 'igm');
				this.rteBody.innerHTML = this.rteBody.innerHTML.replace(code, '');
				*/
				var range = this.getRange();
				range.moveToElementText(tmpElement);
				tmpElement.parentNode.removeChild(tmpElement);
				range.pasteHTML(html);
			}else{
				var contener = null;
				var range = this.rteDoc.createRange();
				tmpElement.innerHTML = html;
				range.selectNodeContents(tmpElement); // tmpElementの内容を選択
				contener = range.extractContents(); // tmpElementの内容をcontenerとして抽出
//alert(var_export(tmpElement));

				range.setStartBefore(tmpElement); // 始点をtmpElementの前に設定
				range.setEndAfter(tmpElement);

				range.insertNode(contener); // 始点の位置にcontenerを挿入
				range.selectNode(tmpElement); // tmpElementを選択
				range.deleteContents(); // tmpElementを削除
			}

		}

		this.replaceNode = function(newElement, oldElement){
			oldElement.parentNode.replaceChild( newElement, oldElement);
			return newElement;
		}
		



		this.getRange = function(){
			this.rteWin.focus();
			var range = null;
			if(document.all){
				var range = this.rteSel.createRange();
			}else if(this.isGecko){
				var selection = this.rteWin.getSelection();
				var range = selection.getRangeAt(0);
			}else{
				var selection = this.rteWin.getSelection();
				var range = this.rteDoc.createRange();
			}
			return range;
		}

		this.encapHTML = function(encap_node){
			var range = this.getRange();
			if(document.all){

				encap_node.innerHTML = range.htmlText;
				var container = this.rteDoc.createElement("div");
				container.appendChild(encap_node);
//alert(range.htmlText);
				try {
					if(this.rteBody.innerHTML.replace(/[\n|\r]/g, '') == range.htmlText.replace(/[\n|\r]/g, '')){
						this.rteBody.innerHTML = container.innerHTML; //全選択時
					}else{
						range.pasteHTML(container.innerHTML);
					}
				} catch (e) {
					alert(e);
				}
			}else{
				if(this.isGecko){
					range.surroundContents(encap_node);
				}else{
					var selection = this.rteWin.getSelection();
/*
					var range = selection.getRangeAt(0);
					container = range.extractContents();
					encap_node.appendChild(container);
					range.insertNode(encap_node);

					return;
*/
					/*
					alert(var_export(selection.anchorNode));
					alert(selection.anchorOffset);
					alert(var_export(selection.focusNode));
					alert(selection.focusOffset);
					*/

					try{

/*
						range.setStart(selection.baseNode, selection.baseOffset);
						range.setEnd  (selection.extentNode,  selection.extentOffset);
*/
/*
						range.setStart(selection.anchorNode, selection.anchorOffset);
						range.setEnd  (selection.focusNode,  selection.focusOffset);
*/
						//var anchorNode = selection.anchorNode;
//alert(var_export(anchorNode));
/*
						while(anchorNode.parentNode){
							if(anchorNode.parentNode.){
							anchorNode = anchorNode.parentNode;
						}
*/
						//var focusNode = selection.focusNode;
/*
						while(focusNode.outerHMTL == focusNode.parentNode.innerHMTL){
							focusNode = focusNode.parentNode;
						}
*/
/*
						range.setStart(anchorNode.parentNode.parentNode, 0);
						range.setEnd  (focusNode,  4);
*/

/*
						range.setStart(this.rteBody, 0);
						range.setEnd  (this.rteBody,  1);
*/
/*
						if(selection.focusNode != selection.anchorNode && !selection.focusOffset){
alert('A1');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
						}else if(selection.focusNode != selection.anchorNode && !selection.anchorOffset){
alert('B1');
							range.setStart(selection.focusNode, selection.focusOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
						}else if(selection.focusNode == selection.anchorNode && selection.focusOffset > selection.anchorOffset){
*/
						if(selection.focusNode == selection.anchorNode && selection.focusOffset > selection.anchorOffset){
//alert('A');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
						}else if(selection.focusNode == selection.anchorNode && selection.focusOffset < selection.anchorOffset){
//alert('B');
							range.setStart(selection.focusNode, selection.focusOffset);
							range.setEnd(selection.anchorNode, selection.anchorOffset);
							container = range.extractContents();
						}else if(selection.focusNode == selection.anchorNode && selection.focusOffset == selection.anchorOffset){
//alert('C');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.anchorNode, selection.anchorOffset);
							container = range.extractContents();


						}else if(selection.focusNode != selection.anchorNode && selection.focusOffset > selection.anchorOffset){
//alert('D');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
						}else if(selection.focusNode != selection.anchorNode && selection.focusOffset < selection.anchorOffset){
//alert(selection.focusNode + ":" + selection.anchorNode + ":" + selection.focusOffset + ":" + selection.anchorOffset);
//alert('E');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();


						}else if(selection.focusNode != selection.anchorNode && selection.focusOffset == selection.anchorOffset){
//alert('F');
							range.setStart(selection.focusNode, selection.focusOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
						}

					}catch(e){
						if(selection.anchorOffset > selection.focusOffset){
//alert('G');
							container = selection.focusNode;
						}else if (selection.anchorOffset < selection.focusOffset){
//alert('H');
							container = selection.anchorNode;
						}
					}
					if(!container){
						try{
//alert('I');
							range.setStart(selection.anchorNode, selection.anchorOffset);
							range.setEnd(selection.focusNode, selection.focusOffset);
							container = range.extractContents();
							//alert(var_export(container));
						}catch(e){
//alert('J');
							//alert('!container2');
							container = selection.anchorNode;
						}
					}


					if(!container){
//alert('K');
						//alert('appendChild');
						//var emptyTextNode = this.rteDoc.createTextNode('AA');
						//emptyTextNode = this.rteDoc.getElementById('test');
						//container = emptyTextNode;
						this.rteBody.appendChild(encap_node);
					}else{
						clone_encap_node = encap_node.cloneNode();
						try{
							clone_encap_node.appendChild(container);
						}catch(e){
						}
						range.insertNode(clone_encap_node);
					}

					if(this.rteBody.childNodes.length == 1 && this.rteBody.childNodes.item(0).innerHTML == encap_node.outerHTML){
						this.rteBody.innerHTML = encap_node.outerHTML; //全選択時
					}

					if(this.rteBody.childNodes.length == 1 && this.rteBody.childNodes.item(0).innerHTML == encap_node.outerHTML){
						this.rteBody.innerHTML = encap_node.outerHTML; //全選択時
					}

				}
			}
		}
		this.getSelectedElements = function(){
			var date = new Date();
			var temp_id = 'tmp-syncl-' + date.getTime();
			var node = this.rteDoc.createElement('span');

			node.setAttribute("id", temp_id);
			this.encapHTML(node);

			return this.rteDoc.getElementById(temp_id);
		}

		this.getLineArea = function (tmpElement){

			while(tmpElement.previousSibling){
				if(tmpElement.previousSibling.tagName && (tmpElement.previousSibling.tagName.toLowerCase() == 'div' || tmpElement.previousSibling.tagName.toLowerCase() == 'br' || tmpElement.previousSibling.tagName.toLowerCase() == 'p')){
					break;
				}else{
					tmpElement.insertBefore(tmpElement.previousSibling, tmpElement.firstChild);
				}
			}
			while(tmpElement.nextSibling){
				if(tmpElement.nextSibling.tagName && (tmpElement.nextSibling.tagName.toLowerCase() == 'div' || tmpElement.nextSibling.tagName.toLowerCase() == 'br' || tmpElement.nextSibling.tagName.toLowerCase() == 'p')){
					break;
				}else{
					if(tmpElement.childNodes.length){
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.lastChild.nextSibling);
					}else{
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.firstChild);
					}
				}
			}

			//tmpElement = this.getArea(tmpElement);

			return tmpElement;
		}
		this.getTextArea = function (tmpElement){
			while(tmpElement.previousSibling){
				//if(tmpElement.previousSibling.tagName && (tmpElement.previousSibling.tagName.toLowerCase() == 'div' || tmpElement.previousSibling.tagName.toLowerCase() == 'br' || tmpElement.previousSibling.tagName.toLowerCase() == 'p')){
				if(tmpElement.previousSibling.tagName){
					break;
				}else{
					tmpElement.insertBefore(tmpElement.previousSibling, tmpElement.firstChild);
				}
			}
			while(tmpElement.nextSibling){
				//if(tmpElement.nextSibling.tagName && (tmpElement.nextSibling.tagName.toLowerCase() == 'div' || tmpElement.nextSibling.tagName.toLowerCase() == 'br' || tmpElement.nextSibling.tagName.toLowerCase() == 'p')){
				if(tmpElement.nextSibling.tagName){
					break;
				}else{
					if(tmpElement.childNodes.length){
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.lastChild.nextSibling);
					}else{
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.firstChild);
					}
				}
			}

			if(isSafari){
				tmpElement = this.getArea(tmpElement);
			}
			return tmpElement;
		}


		this.getArea = function (tmpElement){
//alert(tmpElement.parentNode.innerHTML);

			if(tmpElement.previousSibling){
				if(!tmpElement.previousSibling.nodeValue){
					tmpElement.insertBefore(tmpElement.previousSibling, tmpElement.firstChild);
				}
			}
			if(tmpElement.nextSibling){
				if(!tmpElement.nextSibling.nodeValue){
					if(tmpElement.childNodes.length){
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.lastChild.nextSibling);
					}else{
						tmpElement.insertBefore(tmpElement.nextSibling, tmpElement.firstChild);
					}
				}
			}
//alert(tmpElement.parentNode.innerHTML);
			return tmpElement;
		}

		this.replaceParentNode = function(tmpElement){
			//親ノード入れ替え
			
			tmpElement = this.getTextArea(tmpElement);
			
			//while(tmpElement.parentNode && tmpElement.parentNode.innerText == tmpElement.innerText && tmpElement.parentNode.tagName.toLowerCase() != 'body'){
			while(tmpElement.parentNode && tmpElement.parentNode.childNodes.length == 1 && tmpElement.parentNode.tagName.toLowerCase() != 'body'){
				cloneElement = tmpElement.cloneNode(false);
				cloneParentElement = tmpElement.parentNode.cloneNode(false);
				cloneParentElement.innerHTML = tmpElement.innerHTML;
				cloneElement.appendChild(cloneParentElement);

//alert(tmpElement.parentNode.outerHTML);
				tmpElement = this.replaceNode(cloneElement, tmpElement.parentNode);
			}

			return tmpElement;
		}
		
		this.moveCursor = function(){
			
		}
		//================================================================================
		//コマンド関係
		//================================================================================
		this.cmd = function(cmd, val, opt){
			var obj = this;
			if(opt == undefined){
				opt = false;
			}
			
			if(this.editRichMode){
				this.rteWin.focus();

				switch(cmd){
				case 'inserthtml':
					if(opt === 0){
						alert('この機能はプレビューモードではご利用できません');
						return false;
					}

					var tmpElement = this.getSelectedElements();

					this.updateNode(tmpElement, val);

					if(this.isIE){
						var range = document.selection.createRange();
						var bookmark = range.getBookmark();
						this.setBookmark(bookmark);

						//range.move('character', -1);
						//range.select();

						//return ;
					}
					
					this.moveCursor();
					
					this.textChange(this.rteElt);

					break;
				case 'selectall':
					var range = this.getRange();
					if(this.isIE){
						document.getElementById('title').focus();

						range.moveStart('character', -(this.rteBody.innerText.length));
						range.moveEnd('character', this.rteBody.innerText.length);
						range.select();

					}else if(this.isSafari){
						var selection = this.rteWin.getSelection();
						if(this.browserVersion != 2){
							range.setStart(this.rteBody, 0);
							range.setEnd  (this.rteBody, 1);

							selection.addRange(range);
						}else{
							if(selection["setBaseAndExtent"]){ // Safari 
								selection.setBaseAndExtent(this.rteBody, 0, this.rteBody, 1); 
								//selection.setBaseAndExtent(elm, 0, elm, elm.innerText.length - 1); 
							} else if(selection["selectAllChildren"]){ // Mozilla 
								selection.selectAllChildren(this.rteBody); 
							}
						}
					}else{

						range.setStart(this.rteBody, 0);
						range.setEnd  (this.rteBody, 1);
					}
					this.rteElt.focus();
					this.rteWin.focus();


					break;

				case 'allremoveformat':

					html = this.rteBody.innerHTML;

					var code = new RegExp('<(.?)[^(img|br)](([^>]|\n|\r)*)>', 'igm');
					html = html.replace(code, '');

					//IMG属性除去
					var code = new RegExp('<img([^>]*?)src([^ >]*)([^>]*?)>', 'igm');
					html = html.replace(code, '<img src$2>');

					this.rteBody.innerHTML = html;

					this.textChange(this.rteElt);
					//this.textChange(this.targetElt);

					break;

				case 'removeformat':
					var tmpElement = this.getSelectedElements();

					//tmpElement = this.getArea(tmpElement);
					tmpElement = this.getTextArea(tmpElement);
					if(tmpElement.parentNode.childNodes.length == 1){
						tmpElement = this.replaceParentNode(tmpElement);
					}

					var html = tmpElement.innerHTML;

					if(!html){
						/*
						//WinIEOK
						this.updateNode(tmpElement, html);
						this.rteWin.focus();
						*/




						//this.rteWin.blur();
						this.updateNode(tmpElement, html);
						//this.rteWin.setTimeout(function(){ this.rteWin.focus(); }, 1);
						//this.rteWin.focus();
						//this.rteElt.focus();
					this.rteElt.focus();
					this.rteWin.focus();
						
						//カーソル最後へ一旦フォーカス外すとOK
						return;
					}

					//IMG、BR以外のタグ除去

					//'<([/|!]?)([^ ]*)( ?)(([^>]|\n)*?)(/?)>'

					var code = new RegExp('<([/|!]?)[^(img|br)](([^>]|\n|\r)*?)>', 'igm');
					html = html.replace(code, function($0){
						return '';
					});

					//IMG属性除去
					/*
					var code = new RegExp('<img([^>]*?)src([^ >]*)([^>]*?)>', 'igm');
					html = html.replace(code, '<img src=$2>');
					*/
					var code = new RegExp('<img ([^>]*?)>', 'igm');
					html = html.replace(code, function($0, $1){
						var new_attributes = new Array();
						div = obj.rteDoc.createElement('div');
						div.innerHTML = $0;
						img = div.firstChild;

						for(i in img){
							if(i.toLowerCase() == 'src' || i.toLowerCase()=='alt' || i.toLowerCase()=='title'){
								if(img[i]){
									array_push(new_attributes, i + '="' + img[i].toString() + '"');
								}
							}
						}
						return '<img '+implode(' ', new_attributes)+' />';
					});

					this.updateNode(tmpElement, html);

					this.textChange(this.rteElt);

					//this.textChange(this.targetElt);

					break;
				case 'imageleft':
					var tmpElement = this.getSelectedElements();
					var code = new RegExp('^<img([^>]*?)>$', 'ig');
					if(code.test(tmpElement.innerHTML)){

						div = obj.rteDoc.createElement('div');
						div.innerHTML = tmpElement.innerHTML;
						var activeElement = div.firstChild;
						activeElement.style.marginRight	= '5px';
						activeElement.style.marginLeft	= '';
						activeElement.align				= 'left';
					}else{
						activeElement = tmpElement.firstChild;
					}
					this.replaceNode(activeElement, tmpElement);

					this.textChange(this.rteElt);
					this.textChange(this.targetElt);

					break;
				case 'imageright':
					var tmpElement = this.getSelectedElements();
					var code = new RegExp('^<img([^>]*?)>$', 'ig');
					if(code.test(tmpElement.innerHTML)){
						div = obj.rteDoc.createElement('div');
						div.innerHTML = tmpElement.innerHTML;
						var activeElement = div.firstChild;
						activeElement.style.marginLeft	= '5px';
						activeElement.style.marginRight	= '';
						activeElement.align				= 'right';
					}else{
						activeElement = tmpElement.firstChild;
					}
					this.replaceNode(activeElement, tmpElement);

					this.textChange(this.rteElt);
					this.textChange(this.targetElt);

					break;

				case 'justifycenter':
					var tmpElement = this.getSelectedElements();
					var align = 'center';

					tmpElement = this.getLineArea(tmpElement);
					tmpElement = this.replaceParentNode(tmpElement);

					var activeElement = this.rteDoc.createElement('div');

					if(tmpElement.childNodes.length == 1 && tmpElement.firstChild.align){
						activeElement.innerHTML = tmpElement.firstChild.innerHTML;
					}else{
						activeElement.innerHTML = tmpElement.innerHTML;
					}
					//activeElement.align	= align;
					//activeElement.setStyle({'text-align:'+align});
					activeElement.style.textAlign = align;

					if(activeElement.innerHTML){
						this.replaceNode(activeElement, tmpElement);

						this.textChange(this.rteElt);
						this.textChange(this.targetElt);
					}
					break;

					/*
					var tmpElement = this.getSelectedElements();
					var code = new RegExp('^<img([^>]*?)>$', 'ig');
					if(code.test(tmpElement.innerHTML)){
						var activeElement = this.rteDoc.createElement('div');

						tmpElement.childNodes.item(0).marginLeft = '';
						tmpElement.childNodes.item(0).marginRight = '';
						tmpElement.childNodes.item(0).align = '';

						activeElement.appendChild(tmpElement.childNodes.item(0));

						activeElement.align	= 'center';

					}else{
						tmpElement.marginLeft = '';
						tmpElement.marginRight = '';
						tmpElement.align = '';

						var activeElement = this.rteDoc.createElement('div');
						activeElement.innerHTML = tmpElement.innerHTML;
						activeElement.align	= 'center';
					}

					this.replaceNode(activeElement, tmpElement);

					this.textChange(this.rteElt);
					this.textChange(this.targetElt);

					break;
					*/
				case 'justifyleft':
					var tmpElement = this.getSelectedElements();
					var align = 'left';

					tmpElement = this.getLineArea(tmpElement);
					tmpElement = this.replaceParentNode(tmpElement);

					var activeElement = this.rteDoc.createElement('div');

					if(tmpElement.childNodes.length == 1 && tmpElement.firstChild.align){
						activeElement.innerHTML = tmpElement.firstChild.innerHTML;
					}else{
						activeElement.innerHTML = tmpElement.innerHTML;
					}
					activeElement.align	= align;

					if(activeElement.innerHTML){
						this.replaceNode(activeElement, tmpElement);

						this.textChange(this.rteElt);
						this.textChange(this.targetElt);
					}
					break;

					/*
					var tmpElement = this.getSelectedElements();
					var code = new RegExp('^<img([^>]*?)>$', 'ig');
					if(code.test(tmpElement.innerHTML)){
						var activeElement = tmpElement.childNodes.item(0);

						activeElement.style.marginRight	= '5px';
						activeElement.style.marginLeft	= '';
						activeElement.align				= 'left';
					}else{
						var activeElement = this.rteDoc.createElement('div');
						activeElement.innerHTML = tmpElement.innerHTML;
						activeElement.align	= 'left';
					}

					this.replaceNode(activeElement, tmpElement);

					this.textChange(this.rteElt);
					this.textChange(this.targetElt);

					break;
					*/
				case 'justifyright':
					var tmpElement = this.getSelectedElements();
					var align = 'right';

					tmpElement = this.getLineArea(tmpElement);
					tmpElement = this.replaceParentNode(tmpElement);

					var activeElement = this.rteDoc.createElement('div');

					if(tmpElement.childNodes.length == 1 && tmpElement.firstChild.align){
						activeElement.innerHTML = tmpElement.firstChild.innerHTML;
					}else{
						activeElement.innerHTML = tmpElement.innerHTML;
					}
					activeElement.align	= align;

					if(activeElement.innerHTML){
						this.replaceNode(activeElement, tmpElement);

						this.textChange(this.rteElt);
						this.textChange(this.targetElt);
					}
					break;
					/*
					var tmpElement = this.getSelectedElements();
					var code = new RegExp('^<img([^>]*?)>$', 'ig');
					if(code.test(tmpElement.innerHTML)){
						var activeElement = tmpElement.childNodes.item(0);

						activeElement.style.marginLeft	= '5px';
						activeElement.style.marginRight	= '';
						activeElement.align				= 'right';
					}else{
						var activeElement = this.rteDoc.createElement('div');
						activeElement.innerHTML = tmpElement.innerHTML;
						activeElement.align="right";
					}

					this.replaceNode(activeElement, tmpElement);

					this.textChange(this.rteElt);
					this.textChange(this.targetElt);

					break;
					*/
				default:
					if(this.isSafari){
						if(cmd == 'fontsize'){
							var fontSizes = {'1':'x-small', '2':'small', '3':'medium', '4':'large', '5':'x-large'};
							if(this.browserVersion == 2){
								val = fontSizes[val]; //safari2必要
							}
						}else if(cmd == 'forecolor'){
							val = '#' + val;
						}
					}
					if(this.rteDoc.queryCommandEnabled(cmd)){
						if(this.isIE){
							var range = document.selection.createRange();
							var bookmark = range.getBookmark();
						}

						res = this.rteDoc.execCommand(cmd, opt, val);

						if(this.isIE){
							var elms = this.rteDoc.getElementsByTagName("p");
							for (i = 0; i < elms.length; i++){
								if(elms[i].getAttribute('align')){
									var div = this.rteDoc.createElement('div');
									div.align = elms[i].getAttribute('align');
									div.innerHTML = elms[i].innerHTML;
									div = elms[i].parentNode.replaceChild( div, elms[i]);
								}
							}
							if(cmd == 'insertimage'){
								this.imgRange(null, bookmark);
							}
						}
					}else{
						if(this.isSafari){
							switch(cmd){
								case 'insertimage':
									this.cmd_createimg(val);
									break;
								case 'createlink':
									this.cmd_createlink(val);
									break;
								case 'removeformat':
									var sel = this.rteWin.getSelection();
									var range = this.rteDoc.createRange();
									break;
								default:
									this.rteDoc.execCommand(cmd, opt, val);
									break;
							}
						}else{
							this.rteDoc.execCommand(cmd, opt, val);
						}
					}
					this.textChange(this.rteElt);
				}
			}else{
				this.targetElt.focus();
				this.execCommand(cmd, val, opt);
				this.textChange(this.targetElt);
			}
		}

		this.execCommandRte = function(targetElt, cmd, val, opt) {
			
		}

		this.execCommand = function(cmd, val, opt) {
			var v = null;
			var str = this.getSelectionRange();
			switch(cmd){
				case 'bold':
					v = '<b>' + str + '</b>';
					break;
				case 'italic':
					v = '<i>' + str + '</i>';
					break;
				case 'underline':
					v = '<u>' + str + '</u>';
					break;
				case 'strikethrough':
					v = '<strike>' + str + '</strike>';
					break;
				case 'forecolor':
					v = '<span style="color:#' + val + ';">' + str + '</span>';
					break;
				case 'fontsize':
					v = '<font size="' + val + '">' + str + '</font>';
					break;
				case 'createlink':
					v = '<a href="' + val + '">' + str + '</a>';
					break;
				case 'insertimage':
					v = '<img src="' + val + '" ';
					/*
					var code = new RegExp('(.*)/img/common/pictogram/(.*)', 'ig');
					if(code.test(val)){
					}else{
						v += 'class="blogPhoto" ';
					}
					*/
					v += '/>';
					if (opt) {
						v += opt;
					}
					break;
				case 'inserthorizontalrule':
					v = '<hr />';
					break;

				case 'imageleft':
				case 'imageright':
				case 'allremoveformat':
				case 'removeformat':
				case 'justifycenter':
				case 'justifyleft':
				case 'justifyright':
					alert('この機能はタグモードではご利用できません');
					return false;
					break;

				case 'inserthtml':
					if(opt === 1){
						alert('この機能はタグモードモードではご利用できません');
						return false;
					}
					v = val;
					break;
				case 'selectall':
					
					
					
					break;
			}
		    if(document.selection) {
				var r = document.selection.createRange();
				var x = r.offsetLeft;
				var y = r.offsetTop;
				var ele = document.elementFromPoint(x, y);
				var tag = (ele.tagName);
				
				if(this.getSelectionRange(this.targetElt)){
					document.selection.createRange().text = v;
				}else{
					this.targetElt.value = this.targetElt.value + v;
				}
		    } else if(this.isGecko){
				var start = this.targetElt.selectionStart;
				var end = this.targetElt.selectionEnd;
				var len = this.targetElt.textLength;
				var str = this.targetElt.value.substring(start, end);
				var head = this.targetElt.value.substring(0, start);
				var foot = this.targetElt.value.substring(end, len);
				this.targetElt.value = head + v + foot;
		    } else {
				var start = this.targetElt.selectionStart;
				var end = this.targetElt.selectionEnd;
				var len = this.targetElt.textLength;
				var str = this.targetElt.value.substring(start, end);
				var head = this.targetElt.value.substring(0, start);
				var foot = this.targetElt.value.substring(end, len);
				this.targetElt.value = head + v + foot;
		    }
		}

		this.cmd_createimg = function(value) {
			
			var image = this.rteDoc.createElement('img');
			image.src = value;
			//image.setAttribute('class', 'blogPhoto');
			
			this.rteBody.appendChild(image, this.rteBody);

			return true;
		}

		this.cmd_createlink = function(value) {
			if(this.browserVersion == 2){
				this.rteDoc.execCommand('unlink');
				var sel = this.rteWin.getSelection();
				//var sel = obj.rteElt.contentWindow.getSelection();
				//var range = obj.rteElt.contentWindow.document.createRange();
				var range = this.rteDoc.createRange();
				if(sel.extentOffset == sel.baseOffset){
					return false
				}
				this.rteDoc.execCommand('fontname', false, 'tmp-syncl-anchor');
				var elms = this.rteDoc.getElementsByTagName("*");
				for (i = 0; i < elms.length; i++){
					if(elms[i].getAttribute('style') && elms[i].getAttribute('style').indexOf('tmp-syncl-anchor') != -1){
						var anchor = this.rteDoc.createElement('a');
					anchor.href = value;
						anchor.innerHTML = elms[i].innerHTML;
						anchor = elms[i].parentNode.replaceChild( anchor, elms[i]);
					}
				}
			}else{
				var tmpElement = this.getSelectedElements();
				var activeElement = this.rteDoc.createElement('a');
				activeElement.href = value;
				activeElement.innerHTML = tmpElement.innerHTML;
				this.replaceNode(activeElement, tmpElement);
			}

			return true;
		}

		this.getSelectionRange = function() {
		    var str;
		    if (document.selection) {
				str = document.selection.createRange().text;
		    }else if(this.isGecko){
				if(this.editRichMode){
					var start = this.targetElt.selectionStart;
					var end = this.targetElt.selectionEnd;
					str = this.targetElt.innerText.substring(start, end);
				}else{
					var start = this.targetElt.selectionStart;
					var end = this.targetElt.selectionEnd;
					str = this.targetElt.value.substring(start, end);
				}
		    }else {
				if(this.editRichMode){
					var start = this.targetElt.selectionStart;
					var end = this.targetElt.selectionEnd;
					str = this.targetElt.innerHTML.substring(start, end);
				}else{
					var start = this.targetElt.selectionStart;
					var end = this.targetElt.selectionEnd;
					str = this.targetElt.value.substring(start, end);
				}
		    }
		    return str;
		}


		//================================================================================
		//その他
		//================================================================================
		this.SetReHeight = function(h){
			this.targetEltHeight = h;

			if(!this.debug){
				if(this.isSafari){
					if(this.editRichMode){
						this.targetElt.style.height = '0px';
						this.rteElt.style.height = h + 'px';
					}else{
						this.targetElt.style.height = h + 'px';
						this.rteElt.style.height = '0px';
					}
				}else{
					this.rteElt.style.height = h + 'px';
				}
			}else{
					this.rteElt.style.height = h + 'px';
			}
		}
		//================================================================================
		// 文字数チェック
		//================================================================================
		this.setSize = function(){
			if( this.editRichMode == false ){
				var str  = '';
				var view = '';
				var ct   = 0;
				var i    = 0;
				var len  = 0;
				var over = 0;
				str = document.getElementById(this.targetName).value;
				str = str.replace( /\r?\n +/ig, "" );	// 行頭のスペースを除去
				str = str.replace( /\s\s+/g, " " );		// スペースの連続をまとめる
				str = str.replace( /\r|\n/g, "" );		// 改行を除去
				// 全角を2バイトとして計算する(半角カナは1バイト)
				ct  = 0;
				for( i = 0; i < str.length; i++ )
					( str.charAt(i).match(/[ｱ-ﾝ]/) || escape( str.charAt(i) ).length < 4 ) ? ct++ : ct += 2;
				// 10KB以上になったらアラート
				len = 10000 - ct;
				if( len < 0 ){
					over = ct - 10000;
					view = this.NumberFormat( over );
					document.getElementById(this.targetName+'_size').innerHTML = '<a href="javascript:editer[\''+this.targetName+'\'].modeChangeButtonClick();">プレビューモードにもどる</a> <img src="http://static.syncl.jp/img/common/icon/news_syncl.gif" align="absmiddle" /> <span style="font-size: 16px; font-weight: bold; text-decoration: blink;">' + view + '文字オーバー</span>';
				}else{
					view = this.NumberFormat( len );
					document.getElementById(this.targetName+'_size').innerHTML = '<a href="javascript:editer[\''+this.targetName+'\'].modeChangeButtonClick();">プレビューモードにもどる</a> <img src="http://static.syncl.jp/img/common/icon/news_syncl.gif" align="absmiddle" /> <span style="font-size: 16px; font-weight: bold;">残り' + view + '文字</span>';
				}
			}else{
				document.getElementById(this.targetName+'_size').innerHTML = '<img src="http://static.syncl.jp/img/common/icon/news_syncl.gif" align="absmiddle" /> <a href="javascript:editer[\''+this.targetName+'\'].modeChangeButtonClick();">残り文字数はHTMLタグモードで確認</a><span style="font-size: 16px; font-weight: bold;">&nbsp;</span>';
			}
			return true;
		}
		//================================================================================
		// 数値にカンマを付ける
		//================================================================================
		this.NumberFormat = function ( x ) {
			var s = "" + x;																		// 文字列型に変換
			var p = s.indexOf(".");														// 小数点の位置を特定
			if( p < 0 ){																			// 小数点が見つからなかった時
				p = s.length;																		// 仮想的な小数点の位置とする
			}
			var r = s.substring( p, s.length );								// 小数点の桁と小数点より右側の文字列。例では ".3245"
			for (var i = 0; i < p; i++) {											// (10 ^ i) の位について
				var c = s.substring(p - 1 - i, p - 1 - i + 1);	// (10 ^ i) の位のひとつの桁の数字。例では "4", "3", "7", "5", "8", "2", "9", "3", "8", "5", "9" の順になる。
				if( c < "0" || c > "9" ){												// 数字以外のもの(符合など)が見つかった
					r = s.substring(0, p - i) + r;								// 残りを全部付加する
						break;
				}
				if (i > 0 && i % 3 == 0) {											// 3 桁ごと、ただし初回は除く
					r = "," + r;																	// カンマを付加する
				}
				r = c + r;																			// 数字を一桁追加する。
			}
			return r;
		}

	}


	/**
	 * A class to parse color values
	 * @author Stoyan Stefanov <sstoo@gmail.com>
	 * @link   http://www.phpied.com/rgb-color-parser-in-javascript/
	 * @license Use it if you like it
	 */
	function RGBColor(color_string)
	{
	    this.ok = false;

	    // strip any leading #
	    if (color_string.charAt(0) == '#') { // remove # if any
	        color_string = color_string.substr(1,6);
	    }

	    color_string = color_string.replace(/ /g,'');
	    color_string = color_string.toLowerCase();

	    // before getting into regexps, try simple matches
	    // and overwrite the input
	    var simple_colors = {
	        aliceblue: 'f0f8ff',
	        antiquewhite: 'faebd7',
	        aqua: '00ffff',
	        aquamarine: '7fffd4',
	        azure: 'f0ffff',
	        beige: 'f5f5dc',
	        bisque: 'ffe4c4',
	        black: '000000',
	        blanchedalmond: 'ffebcd',
	        blue: '0000ff',
	        blueviolet: '8a2be2',
	        brown: 'a52a2a',
	        burlywood: 'deb887',
	        cadetblue: '5f9ea0',
	        chartreuse: '7fff00',
	        chocolate: 'd2691e',
	        coral: 'ff7f50',
	        cornflowerblue: '6495ed',
	        cornsilk: 'fff8dc',
	        crimson: 'dc143c',
	        cyan: '00ffff',
	        darkblue: '00008b',
	        darkcyan: '008b8b',
	        darkgoldenrod: 'b8860b',
	        darkgray: 'a9a9a9',
	        darkgreen: '006400',
	        darkkhaki: 'bdb76b',
	        darkmagenta: '8b008b',
	        darkolivegreen: '556b2f',
	        darkorange: 'ff8c00',
	        darkorchid: '9932cc',
	        darkred: '8b0000',
	        darksalmon: 'e9967a',
	        darkseagreen: '8fbc8f',
	        darkslateblue: '483d8b',
	        darkslategray: '2f4f4f',
	        darkturquoise: '00ced1',
	        darkviolet: '9400d3',
	        deeppink: 'ff1493',
	        deepskyblue: '00bfff',
	        dimgray: '696969',
	        dodgerblue: '1e90ff',
	        feldspar: 'd19275',
	        firebrick: 'b22222',
	        floralwhite: 'fffaf0',
	        forestgreen: '228b22',
	        fuchsia: 'ff00ff',
	        gainsboro: 'dcdcdc',
	        ghostwhite: 'f8f8ff',
	        gold: 'ffd700',
	        goldenrod: 'daa520',
	        gray: '808080',
	        green: '008000',
	        greenyellow: 'adff2f',
	        honeydew: 'f0fff0',
	        hotpink: 'ff69b4',
	        indianred : 'cd5c5c',
	        indigo : '4b0082',
	        ivory: 'fffff0',
	        khaki: 'f0e68c',
	        lavender: 'e6e6fa',
	        lavenderblush: 'fff0f5',
	        lawngreen: '7cfc00',
	        lemonchiffon: 'fffacd',
	        lightblue: 'add8e6',
	        lightcoral: 'f08080',
	        lightcyan: 'e0ffff',
	        lightgoldenrodyellow: 'fafad2',
	        lightgrey: 'd3d3d3',
	        lightgreen: '90ee90',
	        lightpink: 'ffb6c1',
	        lightsalmon: 'ffa07a',
	        lightseagreen: '20b2aa',
	        lightskyblue: '87cefa',
	        lightslateblue: '8470ff',
	        lightslategray: '778899',
	        lightsteelblue: 'b0c4de',
	        lightyellow: 'ffffe0',
	        lime: '00ff00',
	        limegreen: '32cd32',
	        linen: 'faf0e6',
	        magenta: 'ff00ff',
	        maroon: '800000',
	        mediumaquamarine: '66cdaa',
	        mediumblue: '0000cd',
	        mediumorchid: 'ba55d3',
	        mediumpurple: '9370d8',
	        mediumseagreen: '3cb371',
	        mediumslateblue: '7b68ee',
	        mediumspringgreen: '00fa9a',
	        mediumturquoise: '48d1cc',
	        mediumvioletred: 'c71585',
	        midnightblue: '191970',
	        mintcream: 'f5fffa',
	        mistyrose: 'ffe4e1',
	        moccasin: 'ffe4b5',
	        navajowhite: 'ffdead',
	        navy: '000080',
	        oldlace: 'fdf5e6',
	        olive: '808000',
	        olivedrab: '6b8e23',
	        orange: 'ffa500',
	        orangered: 'ff4500',
	        orchid: 'da70d6',
	        palegoldenrod: 'eee8aa',
	        palegreen: '98fb98',
	        paleturquoise: 'afeeee',
	        palevioletred: 'd87093',
	        papayawhip: 'ffefd5',
	        peachpuff: 'ffdab9',
	        peru: 'cd853f',
	        pink: 'ffc0cb',
	        plum: 'dda0dd',
	        powderblue: 'b0e0e6',
	        purple: '800080',
	        red: 'ff0000',
	        rosybrown: 'bc8f8f',
	        royalblue: '4169e1',
	        saddlebrown: '8b4513',
	        salmon: 'fa8072',
	        sandybrown: 'f4a460',
	        seagreen: '2e8b57',
	        seashell: 'fff5ee',
	        sienna: 'a0522d',
	        silver: 'c0c0c0',
	        skyblue: '87ceeb',
	        slateblue: '6a5acd',
	        slategray: '708090',
	        snow: 'fffafa',
	        springgreen: '00ff7f',
	        steelblue: '4682b4',
	        tan: 'd2b48c',
	        teal: '008080',
	        thistle: 'd8bfd8',
	        tomato: 'ff6347',
	        turquoise: '40e0d0',
	        violet: 'ee82ee',
	        violetred: 'd02090',
	        wheat: 'f5deb3',
	        white: 'ffffff',
	        whitesmoke: 'f5f5f5',
	        yellow: 'ffff00',
	        yellowgreen: '9acd32'
	    };
	    for (var key in simple_colors) {
	        if (color_string == key) {
	            color_string = simple_colors[key];
	        }
	    }
	    // emd of simple type-in colors

	    // array of color definition objects
	    var color_defs = [
	        {
	            re: /^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/,
	            example: ['rgb(123, 234, 45)', 'rgb(255,234,245)'],
	            process: function (bits){
	                return [
	                    parseInt(bits[1]),
	                    parseInt(bits[2]),
	                    parseInt(bits[3])
	                ];
	            }
	        },
	        {
	            re: /^(\w{2})(\w{2})(\w{2})$/,
	            example: ['#00ff00', '336699'],
	            process: function (bits){
	                return [
	                    parseInt(bits[1], 16),
	                    parseInt(bits[2], 16),
	                    parseInt(bits[3], 16)
	                ];
	            }
	        },
	        {
	            re: /^(\w{1})(\w{1})(\w{1})$/,
	            example: ['#fb0', 'f0f'],
	            process: function (bits){
	                return [
	                    parseInt(bits[1] + bits[1], 16),
	                    parseInt(bits[2] + bits[2], 16),
	                    parseInt(bits[3] + bits[3], 16)
	                ];
	            }
	        }
	    ];

	    // search through the definitions to find a match
	    for (var i = 0; i < color_defs.length; i++) {
	        var re = color_defs[i].re;
	        var processor = color_defs[i].process;
	        var bits = re.exec(color_string);
	        if (bits) {
	            channels = processor(bits);
	            this.r = channels[0];
	            this.g = channels[1];
	            this.b = channels[2];
	            this.ok = true;
	        }

	    }

	    // validate/cleanup values
	    this.r = (this.r < 0 || isNaN(this.r)) ? 0 : ((this.r > 255) ? 255 : this.r);
	    this.g = (this.g < 0 || isNaN(this.g)) ? 0 : ((this.g > 255) ? 255 : this.g);
	    this.b = (this.b < 0 || isNaN(this.b)) ? 0 : ((this.b > 255) ? 255 : this.b);

	    // some getters
	    this.toRGB = function () {
	        return 'rgb(' + this.r + ', ' + this.g + ', ' + this.b + ')';
	    }
	    this.toHex = function () {
	        var r = this.r.toString(16);
	        var g = this.g.toString(16);
	        var b = this.b.toString(16);
	        if (r.length == 1) r = '0' + r;
	        if (g.length == 1) g = '0' + g;
	        if (b.length == 1) b = '0' + b;
	        return '#' + r + g + b;
	    }

	    // help
	    this.getHelpXML = function () {

	        var examples = new Array();
	        // add regexps
	        for (var i = 0; i < color_defs.length; i++) {
	            var example = color_defs[i].example;
	            for (var j = 0; j < example.length; j++) {
	                examples[examples.length] = example[j];
	            }
	        }
	        // add type-in colors
	        for (var sc in simple_colors) {
	            examples[examples.length] = sc;
	        }

	        var xml = document.createElement('ul');
	        xml.setAttribute('id', 'rgbcolor-examples');
	        for (var i = 0; i < examples.length; i++) {
	            try {
	                var list_item = document.createElement('li');
	                var list_color = new RGBColor(examples[i]);
	                var example_div = document.createElement('div');
	                example_div.style.cssText =
	                        'margin: 3px; '
	                        + 'border: 1px solid black; '
	                        + 'background:' + list_color.toHex() + '; '
	                        + 'color:' + list_color.toHex()
	                ;
	                example_div.appendChild(document.createTextNode('test'));
	                var list_item_value = document.createTextNode(
	                    ' ' + examples[i] + ' -> ' + list_color.toRGB() + ' -> ' + list_color.toHex()
	                );
	                list_item.appendChild(example_div);
	                list_item.appendChild(list_item_value);
	                xml.appendChild(list_item);

	            } catch(e){}
	        }
	        return xml;

	    }

	}


	//=============================================================================================
	//
	//=============================================================================================
	var indent = 0;
	function print_r(obj){
		indent++;
		var msg = "";
		for(i in obj){
			if(typeof(obj[i]) == 'object'){
				for(var n=1; n<indent; n++){
					msg += "\t";
				}
				msg += "["+ i + "]\n";
				msg += print_r(obj[i]);
			}else{
				for(var n=1; n<indent; n++){
					msg += "\t";
				}
				msg += "["+ i + "]\n";
				for(var n=1; n<indent; n++){
					msg += "\t";
				}
				msg += "\t" + obj[i] + "\n";
			}
		}
		indent--;
		return msg;
	}

	function var_export(obj){
		var now = new Date();
		var msg = "[" + now.toLocaleString() + "]";
		for(i in obj){
			try{
				param = (obj[i]) ? obj[i] : null;
			}catch(e){
				param = null;
			}
			if(typeof(param) != 'function'){
				msg += i + ":" + param + ":" + typeof(param) + "\n";
			}
		}
		return msg;
	}
	function var_dump(obj){
		var cnt = 0;
		var msg = "";
		for(i in obj){
			cnt++;
			try{
				param = obj[i];
				type = typeof(param);
			}catch(e){
				param = 'null';
				type = 'error';
			}
			msg += i + ":" + param + ":" + type + "\n";
			if(cnt > 40){
				alert(msg);
				cnt = 0;
				msg = "";
			}
		}
		alert(msg);
	}


	//=============================================================================================
	//Array
	//=============================================================================================
	//http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_array_search/

	//array_reverse -- 要素を逆順にした配列を返す
	function array_reverse( array, preserve_keys ) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: Karol Kowalski
	    // *     example 1: array_reverse( [ 'php', '4.0', ['green', 'red'] ], true );
	    // *     returns 1: { 2: ['green', 'red'], 1: 4, 0: 'php'}
	 
	    var arr_len=array.length, newkey=0, tmp_ar = {};
	 
	    for(var key in array){
	        newkey=arr_len-key-1;
	        tmp_ar[(!!preserve_keys)?newkey:key]=array[newkey];
	    }
	 
	    return tmp_ar;
	}

	//array_search --  指定した値を配列で検索し、見つかった場合に対応するキーを返す
	function array_search( needle, haystack, strict ) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // *     example 1: array_search('zonneveld', {firstname: 'kevin', middle: 'van', surname: 'zonneveld'});
	    // *     returns 1: 'surname'
	 
	    var strict = !!strict;
	 
	    for(var key in haystack){
	        if( (strict && haystack[key] === needle) || (!strict && haystack[key] == needle) ){
	            return key;
	        }
	    }
	 
	    return false;
	}
	//array_splice -- 配列の一部を削除し、他の要素で置換する
	function array_slice(arr, offst, lgth, preserve_keys) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Brett Zamir
	    // -    depends on: is_int
	    // %          note: Relies on is_int because !isNaN accepts floats 
	    // *     example 1: array_slice(["a", "b", "c", "d", "e"], 2, -1);
	    // *     returns 1: {0: 'c', 1: 'd'}
	    // *     example 2: array_slice(["a", "b", "c", "d", "e"], 2, -1, true);
	    // *     returns 2: {2: 'c', 3: 'd'}
	 
	    /*
	    if ('callee' in arr && 'length' in arr) {
	        arr = Array.prototype.slice.call(arr);
	    }
	    */
	        
	  if (!(arr instanceof Array) || (preserve_keys && offst != 0)) { // Assoc. array as input or if required as output
	    var lgt =0, newAssoc = {};
	    for (var key in arr) {
	      //if (key !== 'length') {
	        lgt += 1;
	        newAssoc[key] = arr[key];
	      //}
	    }
	    arr = newAssoc;
	    
	    offst = (offst < 0) ? lgt + offst : offst;
	    lgth  = lgth == undefined ? lgt : (lgth < 0) ? lgt + lgth - offst : lgth;
	    
	    var assoc = {};
	    var start = false, it=-1, arrlgth=0, no_pk_idx=0;
	    for (var key in arr) {
	        ++it;
	        if (arrlgth >= lgth) {
	          break;
	        }
	        if (it == offst){
	          start = true;
	        }
	        if (!start) {
	           continue;
	        }
	        ++arrlgth;
	        if (is_int(key) && !preserve_keys) {
	                assoc[no_pk_idx++] = arr[key];
	        } else {
	            assoc[key] = arr[key];
	        }
	    }
	    //assoc.length = arrlgth; // Make as array-like object (though length will not be dynamic)
	    return assoc;
	  }
	    
	    if (lgth === undefined) {
	        return arr.slice(offst);    
	    } else if (lgth >= 0) {
	        return arr.slice(offst, offst + lgth);
	    } else {
	        return arr.slice(offst, lgth);
	    }
	    
	}


	function array_push ( array ) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // *     example 1: array_push(['kevin','van'], 'zonneveld');
	    // *     returns 1: 3
	 
	    var i, argv = arguments, argc = argv.length;
	 
	    for (i=1; i < argc; i++){
	        array[array.length++] = argv[i];
	    }
	 
	    return array.length;
	}

	//in_array -- 配列に値があるかチェックする
	function in_array(needle, haystack, strict) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
	    // *     returns 1: true
	 
	    var found = false, key, strict = !!strict;
	 
	    for (key in haystack) {
	        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
	            found = true;
	            break;
	        }
	    }
	 
	    return found;
	}

	//is_array -- 変数が配列かどうかを検査する
	function is_array( mixed_var ) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: Legaev Andrey
	    // +   bugfixed by: Cord
	    // +   bugfixed by: Manish
	    // %        note 1: In php.js, javascript objects are like php associative arrays 
	    // *     example 1: is_array(['Kevin', 'van', 'Zonneveld']);
	    // *     returns 1: true
	    // *     example 2: is_array('Kevin van Zonneveld');
	    // *     returns 2: false
	 
	    return (mixed_var instanceof Array || mixed_var instanceof Object);
	}

	function trim (str, charlist) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: mdsjack (http://www.mdsjack.bo.it)
	    // +   improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
	    // +      input by: Erkekjetter
	    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +      input by: DxGx
	    // +   improved by: Steven Levithan (http://blog.stevenlevithan.com)
	    // +    tweaked by: Jack
	    // +   bugfixed by: Onno Marsman
	    // *     example 1: trim('    Kevin van Zonneveld    ');
	    // *     returns 1: 'Kevin van Zonneveld'
	    // *     example 2: trim('Hello World', 'Hdle');
	    // *     returns 2: 'o Wor'
	    // *     example 3: trim(16, 1);
	    // *     returns 3: 6
	 
	    var whitespace, l = 0, i = 0;
	    str += '';
	    
	    if (!charlist) {
	        // default list
	        whitespace = " \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000";
	    } else {
	        // preg_quote custom list
	        charlist += '';
	        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1');
	    }
	    
	    l = str.length;
	    for (i = 0; i < l; i++) {
	        if (whitespace.indexOf(str.charAt(i)) === -1) {
	            str = str.substring(i);
	            break;
	        }
	    }
	    
	    l = str.length;
	    for (i = l - 1; i >= 0; i--) {
	        if (whitespace.indexOf(str.charAt(i)) === -1) {
	            str = str.substring(0, i + 1);
	            break;
	        }
	    }
	    
	    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
	}

	function implode( glue, pieces ) {
	    // http://kevin.vanzonneveld.net
	    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
	    // +   improved by: Waldo Malqui Silva
	    // *     example 1: implode(' ', ['Kevin', 'van', 'Zonneveld']);
	    // *     returns 1: 'Kevin van Zonneveld'
	 
	    return ( ( pieces instanceof Array ) ? pieces.join ( glue ) : pieces );
	}

	// replace callback support for safari.
	(function(){
	  var default_replace = String.prototype.replace;
	  String.prototype.replace = function(search,replace){
		// replace is not function
		if(typeof replace != "function"){
			return default_replace.apply(this,arguments)
		}
		var str = "" + this;
		var callback = replace;
		// search string is not RegExp
		if(!(search instanceof RegExp)){
			var idx = str.indexOf(search);
			return (
				idx == -1 ? str :
				default_replace.apply(str,[search,callback(search, idx, str)])
			)
		}
		var reg = search;
		var result = [];
		var lastidx = reg.lastIndex;
		var re;
		while((re = reg.exec(str)) != null){
			var idx  = re.index;
			var args = re.concat(idx, str);
			result.push(
				str.slice(lastidx,idx),
				callback.apply(null,args).toString()
			);
			if(!reg.global){
				lastidx += RegExp.lastMatch.length;
				break
			}else{
				lastidx = reg.lastIndex;
			}
		}
		result.push(str.slice(lastidx));
		return result.join("")
	  }
	})();


