欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

可自定义的编辑器

程序员文章站 2022-03-03 13:59:54
...

初学状态,根据老大的要求,结合http://www.cnblogs.com/goodness2010/archive/2010/03/25/1695241.html,写了一个可自定义的简易编辑器,goodness对编辑器的框架做了整体的解释,而我是在他的基础上,增加了一些功能

比如,我将显示源码放在的工具条中,可自定义工具条是否浮动,编辑器各个部分的高宽、背景颜色。

这里描述的不够清楚,在附件中有附加了编辑器的API,可根据API来进行设置。

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title> 简易编辑器 </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="css/css.css" rel="styleSheet" type="text/css" />
</head>
<body>
<div id="container" class="ebody"></div>
<script src="js/editor.js"></script>
<script>
	var bardata = [
		{'index': 0, 'title': '加粗', 'class': 'tag curr-bold','unselectable': 'on', 'command': 'bold' },
		{'index': 1, 'title': '斜体', 'class': 'tag curr-italic','unselectable': 'on', 'command': 'italic' },
		{'index': 2, 'title': '下划线', 'class': 'tag curr-underline','unselectable': 'on', 'command': 'underline' },
		{'index': 3, 'title': '字号', 'class': 'tag curr-fontsize', 'unselectable': 'on', 'command': 'fontSize' },
		{'index': 4, 'title': '字体', 'class': 'tag curr-fontname', 'unselectable': 'on', 'command': 'fontName' },
		{'index': 5, 'title': '文字颜色', 'class': 'tag curr-forecolor','unselectable': 'on', 'command': 'foreColor' },
		{'index': 6, 'title': '插入链接', 'class': 'tag curr-link','unselectable': 'on', 'command': 'createLink'},
		{'index': 7, 'title': '剪贴', 'class': 'tag curr-cut','unselectable': 'on', 'command': 'cut' },
		{'index': 8, 'title': '复制', 'class': 'tag curr-copy','unselectable': 'on', 'command': 'copy'},
		{'index': 9, 'title': '左对齐', 'class': 'tag curr-justifyleft','unselectable': 'on', 'command': 'justifyLeft' },
		{'index': 10, 'title': '居中对齐', 'class': 'tag curr-justifycenter','unselectable': 'on', 'command': 'justifyCenter' },
		{'index': 11, 'title': '右对齐', 'class': 'tag curr-justifyright', 'unselectable': 'on', 'command': 'justifyRight' },
		{'index': 12, 'title': '项目符号', 'class': 'tag curr-insertunorderedlist','unselectable': 'on', 'command': 'insertUnorderedList' },
		{'index': 13, 'title': '编号', 'class': 'tag curr-insertorderedlist','unselectable': 'on', 'command': 'insertOrderedList' },
		{'index': 14, 'title': '插入表格', 'class': 'tag curr-table','unselectable': 'on', 'command': 'insertHTML'},
		{'index': 15, 'title': '减少缩进', 'class': 'tag curr-outdent','unselectable': 'on', 'command': 'outdent' },
		{'index': 16, 'title': '增加缩进', 'class': 'tag curr-indent','unselectable': 'on', 'command': 'indent'},
		{'index': 17, 'title': '清除样式', 'class': 'tag curr-removeformat','unselectable': 'on', 'command': 'removeFormat'},
		{'index': 18, 'title': '插入图片', 'class': 'tag curr-image','unselectable': 'on', 'command': 'insertImage'},
		{'index': 19, 'title': '插入表情', 'class': 'tag curr-emoticons','unselectable': 'on', 'command': 'insertEmotion'},
		{'index': 20, 'title': '自动排版', 'class': 'tag curr-quickformat','unselectable': 'on', 'command': 'autoLay' },
		{'index': 21, 'title': '上标', 'class': 'tag curr-superscript','unselectable': 'on', 'command': 'superScript' },
		{'index': 22, 'title': '下标', 'class': 'tag curr-subscript','unselectable': 'on', 'command': 'subScript' },
		{'index': 23, 'title': '显示源码', 'class': 'tag curr-source','unselectable': 'on', 'command': 'showCode' }
	];

	//编辑器id,高宽、背景颜色,ebar是工具条id、高宽、背景颜色,bgcode是在显示源码时的id、高宽、背景颜色
	var setvalue = {"container":{"id":"container","width":"580px","height":"200px","color":"#fff"},"ebar":{"id":"ebar","width":"580px","height":"30px","color":""},"bgcode":{"id":"bgcode","width":"575px","height":"65px","color":""}};
	var limitnum = {"flag":1,"limitnum":2,"callback":show};//限定显示数字,并且使用回调函数
	var isfloat = {"flag":1,"callback":showit};//是否浮动,并且使用回调函数
	var e = new editor('container', bardata,setvalue,limitnum,isfloat);
	//限定字数的回调函数
	function show(id,bb){
	}
	//是否浮动的回调函数
	function showit(id){
		id.style.position="absolute";
		id.style.top="60px";
	}
</script>
</body>
</html>

 

// JS编辑器 
// @version beta 0.2
// @date 2010-03-21
// @edit date 2014-1-11
// @author goodNess
// @editor yaolingyan
var co = co || {};
co.Root = 'images/';  // 图片的根目录
// 浏览器判断
co.browser = (function(ua) {
	var b = {
		msie: /msie/.test(ua) && !/opera/.test(ua),
		opera: /opera/.test(ua),
		safari: /webkit/.test(ua) && !/chrome/.test(ua),
		firefox: /firefox/.test(ua),
		chrome: /chrome/.test(ua)
	};
	var vMark = '';
	for(var i in b) {
		if(b[i]) { vMark = /(?:safari|opera)/.test(i) ? 'version' : i; break; }
	}
	b.version = vMark && RegExp('(?:'+ vMark +')[\\/: ]([\\d.]+)').test(ua) ? RegExp.$1 : 0;

	b.ie = b.msie;
	b.ie6 = b.msie && parseInt(b.version) == 6;
	b.ie7 = b.msie && parseInt(b.version) == 7;
	b.ie8 = b.msie && parseInt(b.version) == 8;
	return b;
})(window.navigator.userAgent.toLowerCase());

// ie6图片强制缓存
try {
	co.browser.ie6 && document.execCommand('BackgroundImageCache', true, false);
} catch(ex) {};

// 获取ID对象
co.getId = function(id) { return document.getElementById(id); };
// 获取Class对象
co.getClass = function(className){
 var classElements = [],allElements = document.getElementsByTagName('*');  
   for (var i=0; i< allElements.length; i++ )  
    {  
      if (allElements[i].className == className ) {  
           classElements[classElements.length] = allElements[i];  
        }  
   }  
   return classElements;
};
// 获取对象
co.get = function(node) {
	return typeof(node) == 'string' ? document.getElementById(node) : node;
};

// 创建DOM对象
co.append = function(parentNode, tag, attributes) {
	var o = document.createElement(tag);
	if(attributes && typeof(attributes) == 'string') {
		o.className = attributes;
	} else {
		co.setProperties(o, attributes);
	}
	co.get(parentNode).appendChild(o);
	return o;
};

// 遍历数组
co.foreach = function(arr, callback) {
	for(var i = 0, l = arr.length; i < l; i++) {
		arr[i] = callback(arr[i]);
	}
	return arr;
};

// 设置属性
co.DIRECT_ATTRIBUTE_MAP_ = {
	'cellpadding': 'cellPadding',
	'cellspacing': 'cellSpacing',
	'colspan': 'colSpan',
	'rowspan': 'rowSpan',
	'valign': 'vAlign',
	'height': 'height',
	'usemap': 'useMap',
	'frameborder': 'frameBorder',
	'type': 'type'
};

co.setProperties = function(element, properties) {
	var val;
	for(var key in properties) {
		val = properties[key];
		if(key == 'style') {
			element.style.cssText = val;
		} else if(key == 'class') {
			element.className = val;
		} else if(key == 'for') {
			element.htmlFor = val;
		} else if(key in co.DIRECT_ATTRIBUTE_MAP_) {
			element.setAttribute(co.DIRECT_ATTRIBUTE_MAP_[key], val);
		} else {
			element[key] = val;
		}
	}
	return element;
};

// 属性扩展
co.extend = function(destination, source) {
	for(var property in source) {
		destination[property] = source[property];
	}
	return destination;
};

// 获取元素绝对位置
co.getPos = function(o) {
	for(var _pos = {x: 0, y: 0}; o; o = o.offsetParent) {
		_pos.x += o.offsetLeft;
		_pos.y += o.offsetTop;
	}
	return _pos;
};

// 设置透明度
co.setOpacity = function(e, opac) {
	if(co.browser.ie) {
		e.style.filter = "alpha(opacity=" + opac*100 + ")";
	} else {
		e.style.opacity = opac;
	}
}

// 事件绑定
co.addEvent = function(el, type, fn) {
	el.addEventListener ? el.addEventListener(type, fn, false) : 
	el.attachEvent('on' + type, function() { fn.call(el); })
};

co.target = function(e) {
	return e ? e.target : event.srcElement;
}

// 禁止冒泡
co.cancelBubble = function(e) {
	if(e && e.stopPropagation) {
		e.stopPropagation();
	} else {
		event.cancelBubble = true;
	}
};

/**
 * 抽象单类工厂
 * @method create(cfg{必须有一个唯一的id标识})
 */
var newFactory = function() {
	var coll = {};
	return {
		create: function(fn, cfg, content/* POP_Body*/) {
			if(coll[cfg.id]) {
				return coll[cfg.id];
			} else {
				var win = fn(cfg, content); 
				coll[cfg.id] = win;
				return win;
			}
		}
	}
}();

/**
 *  ---------------------------------- PopUp窗口辅助类 -----------------------------
 *	config:
 *	id: 容器id
 *	title: 容器标题
 *  container: 容器class
 *	concss: 标题内容样式
 *	heacss: 标题外部样式
 *	bodcss: 容器内容样式
 *	chicss: 内容子列表样式
 *	content: 子列表内容
 *  @describe clicking on an element with the unselectable attribute set to on does not destroy the current selection if one exists.
 */
var popUp = {};

popUp.create = function(config, body) {
	this.container = co.append(document.body, 'div', config['container']);
	this.container.id = config.id;
	var _head = '<div class="' + config.heacss + '"><span class="' + config.concss + '">' + config.title +'</span></div>';
	var _body = '<div class="' + config.bodcss + '">';
	_body += (body || '');
	_body += '</div>';
	this.container.innerHTML = _head + _body;
	return this.container;
};

/*--------------------------------- ColorPicker辅助组件(单独提出.松耦合) -------------------------------------------*/
var ColorPicker = {
	create: function() {
		// 定义变量
		var cl = ['00', '33', '66', '99', 'CC', 'FF'], a, b, c, d, e, f, i, j, k, T;
		// 创建整个外围容器
		this.win = co.append(document.body, 'div');
		this.win.id = 'colorPicker';
		// 创建head
		var h = '<div class="colorhead"><span class="colortitle">颜色选择</span></div>';
		// 创建body [6 x 6的色盘]
		h += '<div class="colorbody"><table cellspacing="0" cellpadding="0"><tr>';
		for(i = 0; i < 6; ++i) {
			h += '<td><table class="colorpanel" cellspacing="0" cellpadding="0">';
			for(j = 0, a = cl[i]; j < 6; ++j) {
				h += '<tr>';
				for(k = 0, c = cl[j]; k < 6; ++k) {
					b = cl[k];
					e = k == 5 && i != 2 && i != 5 ? ';border-right:none;' : '';
					f = j == 5 && i < 3 ? ';border-bottom:none': '';
					d = '#' + a + b + c;
					T = co.browser.ie ? '&nbsp;': ''
					h += '<td unselectable="on" style="background: ' + d + e + f + '" title="' + d + '">' + T + '</td>'; /* 切记设置unselectable='on'*/
				}
				h += '</tr>';
			}
			h += '</table></td>';
			if(cl[i] == '66') h += '</tr><tr>';
		}
		h += '</tr></table></div>';
		this.win.innerHTML = h;
		return this.win;
	}
};

/*--------------------------------- 编辑器基类 -----------------------------------------*/
var editor = function(id, bardata,setvalue,limit,isfloat,options) {
	this.container = co.getId(id);
	this.bardata = bardata;
	this.currActive = null;
	this.bookmark = null;
	this.setvalue = setvalue;
	this.limit = limit;
	this.isfloat= isfloat;

	//设置表情
	co.extend(this, this.setOptions(options));

	// 创建框架结构
	this.createStruct(isfloat);

	//限制字数
	if(this.limit.flag==1){	
		this.limitTextArea(this.limit);
	}

	//设置大小和color
	this.setValue(this.setvalue);
	// 创建快照书签
	co.browser.ie && this.saveBookMark();
};
// 静态变量https://developer.mozilla.org/en/Rich-Text_Editing_in_Mozilla
editor.NO_ARG_COMMAND = {
	BOLD: 'bold',
	ITALIC: 'italic',
	UNDERLINE: 'underline',
	CUT: 'cut',
	COPY: 'copy',
	JUSTIFYLEFT: 'justifyleft',
	JUSTIFYRIGHT: 'justifyright',
	JUSTIFYCENTER: 'justifycenter',
	INSERTUNORDEREDLIST: 'insertunorderedlist',
	INSERTORDEREDLIST: 'insertorderedlist',
	OUTDENT: 'outdent',
	INDENT: 'indent',
	REMOVEFORMAT: 'removeformat',
	SUPERSCRIPT:'superScript',
	SUBSCRIPT:'subScript'

};
// 原型扩展
editor.prototype = {
	setOptions: function(options) {
		this.options = {
			emotion: [
				{ 'title': '微笑', 'pos': '-5px -5px',  'url': co.Root + 'o_220510752_p_r2_c2.gif' }, 
				{ 'title': '大笑', 'pos': '-32px -5px', 'url': co.Root + 'o_220510752_p_r2_c3.gif' },
				{ 'title': '窃笑', 'pos': '-59px -5px', 'url': co.Root + 'o_220510752_p_r2_c4.gif' },
				{ 'title': '眨眼', 'pos': '-86px -5px', 'url': co.Root + 'o_220510752_p_r2_c5.gif' },
				{ 'title': '吐舌', 'pos': '-113px -5px','url': co.Root + 'o_220510752_p_r2_c11.gif'},
				{ 'title': '色色', 'pos': '-140px -5px','url': co.Root + 'o_220510752_p_r2_c6.gif' },
				{ 'title': '呲牙', 'pos': '-168px -5px','url': co.Root + 'o_220510752_p_r2_c7.gif' },
				{ 'title': '讨厌', 'pos': '-194px -5px','url': co.Root + 'o_220510752_p_r2_c8.gif' }
			],
			baroverOpc: 0.7
		};
		return co.extend(this.options, options || {});
	},
	setValue:function(obj){
		var _container = co.getId(obj.container.id),_ebar = co.getId(obj.ebar.id),_bgcode = co.getId(obj.bgcode.id);
		//设置container的宽度和高度
		_container.style.width = obj.container.width;
		_container.style.height = obj.container.height;
		_container.style.background = obj.container.color;

		//设置ebar的宽度和高度
		_ebar.style.width = obj.ebar.width;
		_ebar.style.height = obj.ebar.height;
		_bgcode.style.width = obj.bgcode.width;
		_bgcode.style.height = obj.bgcode.height;	
		_ebar.style.background = obj.ebar.color;
		_bgcode.style.background = obj.bgcode.color;
	},
	//limitTextArea
	limitTextArea:function(limit){
		var _this = this,len;
		this.doc =  this.ifr.contentDocument || this.ifr.contentWindow.document; // W3C || IE
		// 当doc onkeyup		
		this.doc.onkeyup = function(){
			var flag,lavenum;//判定是否超过
			len = this.body.innerText.length;
			if(len>limit.limitnum){
				flag = 1;
				lavenum = len-limitnum;
			}else{
				flag = 0;
				lavenum = limitnum - len;
			}
			arguments = {"flag":flag,"len":len,"lavenum":lavenum,"limitnum":limitnum};
			if (limit && limit.callback) {
				limit.callback(this.doc, arguments);
			}
		};
	},
	// 创建编辑器整个框架结构
	createStruct: function(isfloat) {
		// 创建工具条
		this.createToolBar(isfloat);
		// 创建隐藏textarea容器
		this.createTextArea();
		// 创建iframe容器
		this.createIframe();
	},
	// 创建工具条
	createToolBar: function(isfloat) {
		var _this = this;
		this.bar = co.append(this.container, 'div');
		this.bar.id = 'ebar'; this.bar.className = 'ebar';
		for(var i = 0, l = this.bardata.length; i < l; i++) {
			var sp = co.append(this.bar, 'span');
			co.setProperties(sp, this.bardata[i]);
		}

		//是否显示浮动
		if(isfloat.flag!=1){
			isfloat.callback(co.getId(this.bar.id));
		}
		// 事件代理
		this.bar.onmousedown = function(e) {
			var t = co.target(e), command = t['command'];
			//t.style[0] != 'opacity'代表不是在点击显示源代码的情况下
			if(t.tagName == 'SPAN' && t.style[0] != 'opacity') {
				if(!!command) {
					if(command.toUpperCase() in editor.NO_ARG_COMMAND) { // 不需要参数的命令
						if(co.browser.firefox) { /* firefox暂不提供粘贴, 剪切, 复制功能 详见http://www.mozilla.org/editor/midasdemo/securityprefs.html*/
							if(command.toUpperCase() == 'CUT' || command.toUpperCase() == 'COPY') {
								alert('为了信息安全FF暂不提供该功能');
								return false;
							}
						}
						_this.doEditCommand(command);
						_this.ifr.contentWindow.focus(); // 焦点要记住
					} else {
						switch(command) {								 // 代理分支 
							case 'fontSize': // 字号
							case 'fontName': // 字体
							case 'createLink': // 创建连接
							case 'insertImage': // 插入图片
							case 'insertEmotion': // 插入表情
							case 'insertHTML': // 插入表格
								_this.setPopInit(command, t /*被点击的控件*/); /* 需要pop类弹窗的公用初始化方法 */
								break;
							case 'foreColor': // 颜色
								_this.setFontColor(command, t);
								break;
							case 'autoLay': // 自动排版
								_this.autoLay();
								break;
							case 'showCode':
								_this.showCode();
								break;
							default:
								alert('没有提供此项功能');
								break;
						}
					}
				}
			}
		};
	},

	// 抽象需要弹窗功能的公用接口
	setPopInit: function(command, tar) {
		var cfg = '', _body = '', _td = '', S = '';
		if(command == 'fontSize') {
			cfg = {
				'id': 'fscon',
				'title': '字号',
				'container': 'fscon',
				'concss': 'fsn',
				'heacss': 'fshead',
				'bodcss': 'fsbody',
				'chicss': ['bas f1', 'bas f2', 'bas f3', 'bas f4', 'bas f5', 'bas f6', 'bas f7'],
				'content': ['字号1', '字号2', '字号3', '字号4', '字号5', '字号6', '字号7']
			};	
			for(var i = 0, l = cfg.content.length; i < l; i++) {
				_body += '<a class="' + cfg.chicss[i] + '" href="javascript:void(0);">' + cfg.content[i] + '</a>';
			}
		}
		if(command == 'fontName') {
			cfg = {
				'id': 'ffcon',
				'title': '字体',
				'container': 'ffcon',
				'concss': 'fsn',
				'heacss': 'fshead',
				'bodcss': 'fsbody',
				'chicss': ['bas', 'bas', 'bas', 'bas', 'bas', 'bas', 'bas', 'bas', 'bas'],
				'content': ['宋体', '黑体', '楷体', '隶书', '幼圆', 'Arial', 'Georgia', 'Verdana', 'Helvetica']		
			};	
			for(var i = 0, l = cfg.content.length; i < l; i++) {
				_body += '<a class="' + cfg.chicss[i] + '" href="javascript:void(0);">' + cfg.content[i] + '</a>';
			}
		}
		if(command == 'createLink' || command == 'insertImage' || command == 'insertEmotion') { // 创建链接 + 插入图片 + 插入表情形体类似. 只需要单独定制id和title即可
			cfg = {'container':'flcon', 'concss':'fsn', 'heacss':'fshead', 'bodcss':'fsbody'};
			if(command == 'createLink') { cfg.title = '插入链接';	/*title*/cfg.id = 'fflink';/*容器id*/cfg.txtId = 'lurl';	/*文本框id*/cfg.cofbtnId = 'lkcof';/* 确认按钮*/cfg.celbtnId = 'lkcel';}/*撤销按钮*/
			if(command == 'insertImage') { cfg.title = '插入图片';cfg.id = "ffimage";cfg.txtId = 'limg';cfg.cofbtnId = 'imcof';cfg.celbtnId = 'imcel';} 
			if(command == 'insertEmotion') { cfg.title = '插入表情';cfg.id = "ffemotion";cfg.container="emotionCon"; }
			if(command == 'createLink' || command == 'insertImage') {
				_body += '<div style="padding:7px;background-color:#FFF;font-size:12px;"><span>链接地址</span>';
				_body += '<input type="text" id="' + cfg.txtId + '" style="width:200px;" /></div>';
				_body += '<div style="text-align:center;">'
				_body += '<img id="' + cfg.cofbtnId + '" style="padding-right:10px;" src="'+co.Root+'o_220836549.p.gif" />';
				_body += '<img id="' + cfg.celbtnId + '" src="'+co.Root+'o_220726721.p.gif" /></div>';
			}
			if(command == 'insertEmotion') {
				for(var i = 0, l = this.emotion.length; i < l; i++) {
					S += ';background-position:' + this.emotion[i]['pos'] + ';width:21px;height:21px;'
					_td += '<td unselectable="on" url="'+this.emotion[i].url+'" title='+this.emotion[i]['title']+' style="cursor:pointer;background-image:url('+co.Root+'o_220510752_p.gif)'+S+'"></td>';
				}
				_body += '<table><tr>'+ _td +'</tr></table>';
			}
		}
		if(command == 'insertHTML') {
			cfg = {
					    'id':'fftable','title':'插入表格','container':'isbtlCon','concss':'fsn','heacss':'fshead',
				        'bodcss':'fsbody','rowId':'rowtxt','cellId':'celltxt','cfmId':'tblcfm','celId':'tblcel',
						'tblwId':'tblwid','tblhId':'tblhid'	
				  };
			_body += '<div class="tblCon">行数<input type="text" id="'+cfg.rowId+'" class="tblTxt" />列数<input type="text" id="'+cfg.cellId+'" class="tblTxt" /></div>';
			_body += '<div class="tblCon">表格的宽度<input type="text" id="'+cfg.tblwId+'" class="tblTxt" />px</div>';
			_body += '<div class="tblCon">表行的高度<input type="text" id="'+cfg.tblhId+'" class="tblTxt" />px<div class="tblbtn">';
			_body += '<img id="'+cfg.cfmId+'" style="padding-right:6px;" src="'+co.Root+'o_220836549.p.gif" />';
			_body += '<img id="'+cfg.celId+'" src="'+co.Root+'o_220726721.p.gif" /></div></div>';
		}
		this.setPopRun(command, cfg, cfg.title, tar, _body);
	},
	// 实现POP弹窗的所有功能
	setPopRun: function(command, cfg, title, tar/* 点击的控件 */, content/* POP弹窗的body内容 */) {
		var _this = this;
		var fwin = newFactory.create(popUp.create, cfg, content);
		_this.fixPop(fwin, tar);	// 定位弹窗
		if(title == '插入链接' || title == '插入图片') { /* 插入链接和插入图片需要特殊定制 */
			co.getId(cfg.cofbtnId).onclick = function() { // 此处不用addEvent添加事件.避免多次绑定
				var _val = co.getId(cfg.txtId).value;
				if(_val.length == 0) _val = ' '; // IE下链接可以为空.但其他最起码有一个空格.否则报错
				_this.doEditCommand(command, _val);
				co.getId(cfg.id).style.display = "none"; 
			}; //确认
			co.getId(cfg.celbtnId).onclick = function() { co.getId(cfg.id).style.display = "none"; }
		}
		if(title == '插入表格') {
			co.getId(cfg.cfmId).onclick = function() {
				var _html = _this.createTblHtml(cfg);
				if(!co.browser.ie) { // IE不支持insertHTML
					_this.doEditCommand(command, _html);
				} else {
					_this.ifr.contentWindow.focus(); // 注意IE下 focus问题
					_this.doc.selection.createRange().pasteHTML(_html);
				}
				co.getId(cfg.id).style.display = 'none';
			};
			co.getId(cfg.celId).onclick = function() { co.getId(cfg.id).style.display = 'none'; }
		}
		_this.hidePop(fwin, title); // bind隐藏弹窗
		fwin.onclick = function(e) {
			var t = co.target(e);
			if(title == '插入链接' || title == '插入图片' || title == '插入表格') { co.cancelBubble(e); } // 插入链接和图片禁止冒泡
			if(t.tagName == 'A') { /* 字号和字体 */
				_this.doEditCommand(command, command == 'fontSize' ? t.innerHTML.slice(-1) : t.innerHTML);
			} else if(t.tagName == 'TD') { /* 表情 */
				_this.doEditCommand('insertImage', t.getAttribute('url'));
			}
		};	
	},
	// 设置字体颜色 
	setFontColor: function(command, tar) {
		var _this = this;
		var fwin = newFactory.create(ColorPicker.create, {'id':'colorPicker'});
		_this.fixPop(fwin, tar);	// 定位弹窗
		_this.hidePop(fwin, '文字颜色');
		co.addEvent(fwin, 'click', function(e) {
			var t = co.target(e);
			if(!!t.title) {
				_this.doEditCommand(command, t.title);
			}
		});
	},
	// 自动排版
	autoLay: function() {
		var _child = this.doc.body.childNodes;
		for(var i = 0, l = _child.length; i < l; i++){
			if(_child[i].tagName == 'DIV' || _child[i].tagName == 'P') {
				_child[i].style.textIndent = _child[i].style.textIndent == '2em' ? '' : '2em'; // text-indent属性
			}
		}
	},
	//显示源码
	showCode:function(){
		var _this = this, _bgcode = co.getId('bgcode'),
			_ebar = co.getId('ebar'),_span = _ebar.getElementsByTagName("span"),_len = _span.length;
			obj = {"_this":_this,"_span":_span,"_len":_len};
		if(_bgcode.style.display == 'block'){
			_this.removeLayer(obj);
			_bgcode.style.display = 'none';
			_this.doc.body.innerHTML = _bgcode.value;
			_this.ifr.style.display = 'block';	
		}else{
			/*_layer.style.display = 'block';*/
			//遮盖工具条,除了显示源码图标
			_this.createLayer(obj);
			_bgcode.style.display = 'block';
			_this.ifr.style.display = 'none';
		}
	},
	createLayer:function(obj){
		_span = obj._span;
		_len = obj._len;
		for(i=0;i<_len;i++){
			if(_span[i].className !="tag curr-source"){
				_span[i].style.position="absoulte";
				_span[i].style.opacity = 0.3;
			}	
		}
	},
	removeLayer:function(obj){
		_span = obj._span;
		_len = obj._len;
		for(i=0;i<_len;i++){
			if(_span[i].className !="tag curr-source"){
				_span[i].style.cssText="";
			}	
		}
	},
	// 生成Table的HTML
	createTblHtml: function(cfg) {
		var _rownum = co.getId(cfg.rowId).value, _cellnum = co.getId(cfg.cellId).value,
			_tblwid = co.getId(cfg.tblwId).value, _tblhei = co.getId(cfg.tblhId).value;	
		var _html = '<table border="1" width="'+_tblwid+'">';
		for(var i = 0; i < parseInt(_rownum,10); i++) { // 行
			_html += '<tr height="'+_tblhei+'">';
			for(var j = 0; j < parseInt(_cellnum,10); j++) { // 列
				_html += '<td></td>';
			}
			_html += '</tr>';
		}	
		_html +='</table>';
		return _html;
	},
	// 保存快照用于IE定位
	saveBookMark: function() {
		var _this = this;
		co.addEvent(_this.ifr, 'beforedeactivate', function() {
			var rng = _this.doc.selection.createRange();
			if(rng.getBookmark) {
				_this.bookmark = _this.doc.selection.createRange().getBookmark(); // 保存光标用selection下的createRange();
			}
		});
		co.addEvent(_this.ifr, 'activate', function() {
			if(_this.bookmark) {
				// Moves the start and end points of the current TextRange object to the positions represented by the specified bookmark.
				// 将光标移动到 TextRange 所以需要用 body.createTextRange();
				var rng = _this.doc.body.createTextRange();				
				rng.moveToBookmark(_this.bookmark);
				rng.select();
				_this.bookmark = null;
			}
		});
	},
	// 定位弹窗 
	fixPop: function(fwin, tar) {
		co.setProperties(fwin, {'style': 'top:' + (co.getPos(tar).y + tar.offsetHeight) + 'px; left:' + co.getPos(tar).x + 'px' });
	},
	// 隐藏弹窗
	hidePop: function(fwin, title) {
		co.addEvent(document, 'click', function(e) {
			var t = co.target(e);
			fwin.style.display = t.title == title ? 'block' : 'none';
		});
		co.addEvent(this.doc, 'click', function(e) { fwin.style.display = 'none'; }); /* 注意:绑定iframe事件句柄需要用W3C接口(addEventListener) */	
	},
	// 执行命令
	doEditCommand: function(name, arg) {
		try {
			this.ifr.contentWindow.focus(); // 放置焦点要操作contentWindow
			this.doc.execCommand(name, false, arg);		
		} catch(e) {}
	},
	// 创建隐藏文本域
	createTextArea: function() {
		this.txtarea = co.append(this.container, 'textarea');
		this.txtarea.id='bgcode'; this.txtarea.style.display = 'none';
	},
	// 创建空白iframe
	createIframe: function() {
		var _this = this;
		this.ifr = co.append(this.container, 'iframe', {'frameborder': 0, 'style': 'border:0; vertical-align:bottom', 'class': 'econtent' });
		this.doc =  this.ifr.contentDocument || this.ifr.contentWindow.document; // W3C || IE
		this.doc.designMode = 'on';
		this.doc.open();
		// margin为了消除iframe中的html上部的空白
		this.doc.write('<html><head><style>body{ margin:3px; word-wrap:break-word; word-break: break-all; }</style></head><body></body></html>');
		this.ifr.contentWindow.focus();
		this.doc.close();

		// 当iframe失去焦点.偷偷将代码存入textare中
		co.addEvent(this.ifr.contentWindow, 'blur', function() {
			_this.txtarea.value = _this.doc.body.innerHTML;
		});
	}
};

 第一次发布自己改写的js,希望能够跟各位大大学习,并且进步

相关标签: js 编辑器