Edit in JSFiddle

/*
为什么要用iframe来开发富文本编辑器是基于多方面考虑的。以下是我个人的看法:

1.用iframe可以解决浏览器的兼容性问题。在iframe下可以很方便的获取选中的文字等。

2.在iframe下编辑可以实现所见即所得的效果。相当于是iframe下显示的是浏览器解析源码后的内容。

3.在iframe下是直接在iframe下的document中进行操作并不会影响到当前文档的document。

因此,iframe就是一种所见即所得的编辑器。
*/
window.onload = function(){
	new R_editor({
		editor: "editor",
		editorCon: "editor-con"
	})
}

//通过元素ID取得该元素
var GE = function(id){ 
	return typeof id === "string" ? document.getElementById(id) : id;
}
//添加事件监听
var EventUtil = {};
EventUtil.addHandler = function (ele, type, handler) {
    if (ele.addEventListener) {
        ele.addEventListener(type, handler, false);
    } else if (ele.attachEvent) {
        ele.attachEvent("on" + type, handler);
    } else {
        ele["on" + type] = handler;
    }
};
//移除事件监听        
EventUtil.removeHandler = function (ele, type, handler) {
    if (ele.removeEventListener) {
        ele.removeEventListener(type, handler, false);
    } else if (ele.detachEvent) {
        ele.detachEvent("on" + type, handler);
    } else { 
        ele["on" + type] = null;
    }
};
//通过className取得元素
var getClass = function(cls,pat,tag) {
    pat = pat || document;
    tag = tag || "*";
    if("getElementsByClassName" in pat) {
        return pat.getElementsByClassName(cls)
    }else {
        var _all = pat.getElementsByTagName(tag),
            reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'),
            _arr = [],
            i = 0,
            len = _all.length;
        for(; i<len; i++) {
            if(reg.test(_all[i].className)) 
            	_arr.push(_all[i]);
        }
        return _arr;
    }
}
//是否存在该类名
var hasClass = function(ele, cls) {
    return (new RegExp('(\\s|^)' + cls + '(\\s|$)')).test(ele.className);
}
//如果不存在该类名,则添加该类名
var addClass = function(ele, cls) {
    if (!this.hasClass(ele, cls)) 
    	ele.className += " " + cls;
}
//移除该类名
var removeClass = function(ele, cls) {
    if (hasClass(ele, cls)) {
        var reg = new RegExp('(\\s|^)' + cls + '');
        ele.className = ele.className.replace(reg, '');
    }
}
//R_editor函数初始化
var R_editor = function(options){
	this.editor = GE(options.editor);
	this.editorCon = GE(options.editorCon);
	
	this.weight = options.weight || "normal";
	this.decoration = options.decoration || "none";
	
	this.iframe;
	this.iframeDoc;
	this.start();//一调用R_editor,就开始执行本程序
}
//R_editor函数原型
R_editor.prototype = {
	//开始执行
	start:function(){
		//初始化-载入
		this.init();
		//绑定控制-绑定每个按钮的操作
		this.bindControl();
	},
	//初始化-载入
	init:function(){
		//创建iframe框架,用于显示解析后的内容
		this.creatIframe();
	},
	//创建框架
	//它最开始是为富文本编辑器而开发的,
	//富文本输入框最流行的做法是把要输入的内容放到iframe中,
	//这就涉及到两种document,一个主页面的document,另一个是iframe的document。iframe的document又涉及到兼容问题
	creatIframe:function(){
		var iframe = document.createElement("iframe");
		this.iframe = iframe;
		//框架大小与编辑区大小一样
		iframe.width = this.editorCon.clientWidth + "px";
		iframe.height = this.editorCon.clientHeight + "px";
		iframe.style.margin="6px";
		iframe.frameBorder = 0;
		iframe.scrolling = "auto";
		//在this.editorCon子节点前插入iframe子节点,因此需要取得this.editorCon.parentNode父节点
		this.editorCon.parentNode.insertBefore(iframe, this.editorCon);
		iframe.style.display="block";
		//textarea不显示
		this.editorCon.style.display = "none";
		//操作iframe内contentDocument中的元素
		this.iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
		//在iframe中编辑,则设置为on,如果是要想在div中编辑,设置其contentEditable = "true"
		this.iframeDoc.designMode = "on";
	},
	//取得当前窗口或父窗口
	getWindow : function (node) {
		var doc = node.ownerDocument || node;
		return doc.defaultView || doc.parentWindow;
    },
    //在父节点中查找相同的元素类型
	findParentByTagName:function(node,tagName,includeSelf){
		if(node && tagName){
			if(!includeSelf) node = node.parentNode;
			while (node && node.tagName && node.nodeType != 9) {
				//alert(node.tagName)
            	if (tagName == node.tagName.toLowerCase()) return node;
            	node = node.parentNode;
        	}
		}
		return null;
	},
	// execCommand方法是执行一个对当前文档,当前选择或者给出范围的命令
	// command:要执行的命令的名称 
	// showUI:boolean是否向用户显示命令特定的对话框或消息框 
	// value类型:string要使用该命令分配的值
	execCommand:function(command,show,value){
		//blockquote之间的所有文本都会从常规文本中分离出来,
		//经常会在左、右两边进行缩进(增加外边距),而且有时会使用斜体。
		//也就是说,块引用拥有它们自己的空间
		if(command == "blockquote"){
			var bl= this.iframeDoc.createElement("blockquote"),
				range, 
				par;
			
			if(browser.ie){
				range = document.selection.createRange();
				par = range.parentElement();
				
				if( par.getElementsByTagName("blockquote").length || this.findParentByTagName(par,"blockquote",true)){
					
				}else{
					bl.innerHTML = par.innerHTML;
					while(par.firstChild){
						alert(par.firstChild)
						par.removeChild(par.firstChild);
					}
					par.appendChild(bl);
					bl.focus();
				}
			}else{
				
				this.iframeDoc.execCommand("formatBlock",true,"<blockquote>");
			}
		}else if(command == "html"){
			
		}else if(command == "insertImage"){
			//prompt() 方法用于显示可提示用户进行输入的对话框,
			//且阻碍其他进程,即会一直停留在该对话框直到结束该操作后才继续执行其他操作
			var src = prompt("图片地址", "");
			this.iframeDoc.execCommand(command, show, src);
		}else if(command == "createLink"){
			var href = prompt("链接地址", "http://");
			this.iframeDoc.execCommand(command,show, href);
		}else{
			this.iframeDoc.execCommand(command,show,value);
		}
	},
	//绑定控制
	bindControl:function(){
		var self = this;
		// tBold,通过类名editor-toolbar-item,查找全部
		var toolBtn = getClass("editor-toolbar-item");
		
		for(var i=0, len = toolBtn.length; i<len; i++){
			//为每一个按钮添加鼠标移进去和移出去的事件响应
			EventUtil.addHandler(toolBtn[i], "mouseover", function(){
				if(!hasClass(this, "editor-toolbar-item-hover") && !hasClass(this, "editor-toolbar-item-disable")) 
					addClass(this, "editor-toolbar-item-hover");
			});
			EventUtil.addHandler(toolBtn[i], "mouseout", function(){
				if(hasClass(this, "editor-toolbar-item-hover") && !hasClass(this, "editor-toolbar-item-disable")) 
					removeClass(this, "editor-toolbar-item-hover");
			});
			//为每个按钮添加鼠标点击事件响应
			EventUtil.addHandler(toolBtn[i], "click", function(){
				//如果editor-toolbar-item关闭,则不操作
				if(hasClass(this, "editor-toolbar-item-disable")){
					return;
				}
				//文字布局区域(左、中、右)
				else if(hasClass(this, "editor-toolbar-align")){
					//如果按钮已经打开,则不操作
					if(hasClass(this, "editor-toolbar-item-on")){
						
					}
					//如果该按钮没有打开,则移除所有editor-toolbar-item-on后,再打开该按钮editor-toolbar-item-on
					//同一时刻只能打开一个该区域的按钮
					else{
						var align = getClass("editor-toolbar-align");
						for(var j=0,len = align.length; j<len; j++){
							removeClass(align[j], "editor-toolbar-item-on");
						}
						addClass(this, "editor-toolbar-item-on");
					}
				}
				//有序、无序列表区域(同一时刻只能打开一个该区域的按钮)
				else if(hasClass(this, "editor-toolbar-list")){
					//如果按钮已经打开,则不操作
					if(hasClass(this, "editor-toolbar-item-on")){
						//removeClass(this, "editor-toolbar-item-on");
					}
					else{
						var align = getClass("editor-toolbar-list");
						for(var j=0,len = align.length; j<len; j++){
							removeClass(align[j], "editor-toolbar-item-on");
						}
						addClass(this, "editor-toolbar-item-on");
					}
				}
				//图片&链接区域(如果已经打开其中的一个按钮,则不操作)
				else if(hasClass(this, "editor-toolbar-image") || hasClass(this, "editor-toolbar-link")){
					
				}
				//HTML源代码区域
				else if(hasClass(this, "editor-toolbar-html")){
					//如果已经打开该按钮,再次点击则关闭该按钮,并开放其他按钮
					if(hasClass(this, "editor-toolbar-item-on")){
						removeClass(this, "editor-toolbar-item-on");
						for(var j=0, len = toolBtn.length; j<len; j++){
							removeClass(toolBtn[j], "editor-toolbar-item-disable");
						}
						//隐藏editorCon区域面板,editorCon用于显示HTML源码文本,
						//显示iframe区域面板,iframe用于显示解析后的文本
						self.editorCon.style.display = "none";
						//如果要获取源码解析后的内容直接取它的value就行
						self.iframeDoc.body.innerHTML = self.editorCon.value;
						self.iframe.style.display="block";
						//设置鼠标焦点后,发生内容粘贴事件时就会粘贴在该焦点区域
						self.iframe.focus();
						
					}
					//如果没有打开该按钮,再次点击时,关闭其他按钮,开放本按钮
					else{
						for(var j=0, len = toolBtn.length; j<len; j++){
							addClass(toolBtn[j], "editor-toolbar-item-disable");
						}
						removeClass(this, "editor-toolbar-item-disable");
						addClass(this, "editor-toolbar-item-on");
						//editorCon显示HTML源码文本
						self.iframe.style.display = "none";
						self.editorCon.value = self.iframeDoc.body.innerHTML;
						self.editorCon.style.display="block";
						//设置鼠标焦点后,发生内容粘贴事件时就会粘贴在该焦点区域
						self.editorCon.focus();
					}
					return;
				}
				else{
					if(hasClass(this, "editor-toolbar-item-on")){
						removeClass(this, "editor-toolbar-item-on");
					}
					else{
						addClass(this, "editor-toolbar-item-on");
					}
				}
				self.execCommand(this.getAttribute("ec"), false, null);
				self.iframeDoc.body.focus();
			});
		}		
	}
}
<body>
<div class="head clearfix">
  <h1>
    <a href="http://www.cnblogs.com/twobin/">twobin’ 
      <span id="blog">blog</span>
    </a>
  </h1>
  <span id="subtitle"> | 富文本编辑器...</span>
</div> 
    
<div id="editor">
	<div id="editor-toolbar">
    	<div class="editor-toolbar-item" id="editor-toolbar-bold" title="加粗"  ec="bold" unselectable="on">
            <b>粗</b>
    	</div>
        <div class="editor-toolbar-item" id="editor-toolbar-italic" title="斜体" ec="italic" unselectable="on">
            <b>斜</b>
    	</div>
        <div class="editor-toolbar-item" id="editor-toolbar-underline" title="下划线" ec="underline" unselectable="on">
            <b>划</b>
    	</div>
        <div class="editor-toolbar-item" id="editor-toolbar-linethrough" title="删除线" ec="StrikeThrough" unselectable="on">
            <b>删</b>
    	</div>
        <div class="editor-toolbar-blank" >
        	|
    	</div>
        <div class="editor-toolbar-item editor-toolbar-align" id="editor-toolbar-justifyleft" title="左对齐" ec="justifyleft" unselectable="on">
            <b>左</b>
    	</div>
        <div class="editor-toolbar-item editor-toolbar-align" id="editor-toolbar-justifycenter" title="居中对齐" ec="justifycenter" unselectable="on">
            <b>中</b>
    	</div>
        <div class="editor-toolbar-item editor-toolbar-align" id="editor-toolbar-justifyright" title="右对齐" ec="justifyright" unselectable="on">
            <b>右</b>
    	</div>
        <div class="editor-toolbar-blank" >
        	|
    	</div>
        <div class="editor-toolbar-item editor-toolbar-list" id="editor-toolbar-ol" title="有序列表" ec="insertorderedlist" unselectable="on">
            <b>有序</b>
    	</div>
        <div class="editor-toolbar-item editor-toolbar-list" id="editor-toolbar-ul" title="无序列表" ec="insertunorderedlist" unselectable="on">
            <b>无序</b>
    	</div>
        <div style="display:none;" class="editor-toolbar-item" id="editor-toolbar-quoteright" title="引用" ec="blockquote" 
unselectable="on">
            <b>引用</b>
    	</div>        
        <div class="editor-toolbar-blank" >
        	|
    	</div>      
        <div class="editor-toolbar-item editor-toolbar-image" id="editor-toolbar-image" title="图片" ec="insertImage" unselectable="on">
            <b>图片</b>
    	</div>
        <div class="editor-toolbar-item editor-toolbar-link" id="editor-toolbar-link" title="链接" ec="createLink" unselectable="on">
            <b>链接</b>
    	</div>
        <div class="editor-toolbar-blank" >
        	|
    	</div>       
        <div class="editor-toolbar-item editor-toolbar-html" id="editor-toolbar-html" title="源代码" ec="html" 
unselectable="on">
        	HTML
    	</div>
    </div>
    <textarea id="editor-con"  spellcheck="false" ></textarea>
</div>
</body>
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,button,textarea,p,blockquote,th,td{
	padding:0;
	margin:0;
}
body{
	font-family: "Helvetica Neue", "Hiragino Sans GB", "Segoe UI", "Microsoft Yahei", "微软雅黑", Tahoma, Arial, STHeiti, sans-serif;
	font-size:12px;
	background:#f8f8f8;
}
a{
	outline:none;
	-moz-outline:none;
	text-decoration:none;
}
.clearfix{
	zoom:1;
	_height:1px;
}
.clearfix:after{
	content:".";
	display:block;
	height:0;
	clear:both;
	visibility:hidden;
}
.head{
	height:50px;
	line-height:50px;
	padding-left:200px;
	border-bottom:1px solid #eee;
	box-shadow: 1px 1px 5px #ccc;
    background:#fff;
}
.head h1{
	float:left;
	width:200px;
	height: 51px;
	font-weight:bold;
	font-size:24px;
	background-color: rgb(31, 123, 155);
	text-align: center;
}
.head h1 a{
	color: #fff;
}
#blog{
	font-weight:normal;
	font-size:16px;
	color: #fff;
}
#subtitle{
	display:block;
	float:right;
	font-size:16px;
	color:#999;
	line-height:16px;
	margin:20px 200px 0 0;
}
#editor{
	width:600px;
	margin:100px auto 0;
	border: 1px solid #dddddd;
	border-top: 1px solid #ebebeb;
	border-bottom: 1px solid #b7b7b7;
	background-color: white;
	position: relative;
	overflow: visible;
	border-radius: 4px;
	box-shadow: 0 1px 1px #d3d1d1;
}
#editor-toolbar{
	height:25px;
	padding:10px 10px;
	border-bottom:1px solid #eee;
	-webkit-user-select: none;
}
.editor-toolbar-item{
	float:left;
	height:25px;
	line-height:25px;
	padding:0 10px;
	margin:0px auto;
	text-align: center;
	cursor:default;
	font-size:14px;
	color:rgb(20,68,101);
	-moz-user-select: none; /*火狐*/
    -webkit-user-select: none;  /*webkit浏览器*/
    -ms-user-select: none;   /*IE10*/
    -khtml-user-select: none; /*早期浏览器*/
    user-select: none;
}
.editor-toolbar-item i{
	-moz-user-select: none; /*火狐*/
	-webkit-user-select: none;  /*webkit浏览器*/
	-ms-user-select: none;   /*IE10*/
	-khtml-user-select: none; /*早期浏览器*/
	user-select: none;
}
.editor-toolbar-item-on,.editor-toolbar-item-hover{
	background:rgb(20,68,101);
	color:#fff;
}
.editor-toolbar-item-disable{
	background:#fff;
	color:rgb(20,68,101);
	opacity: 0.3;
	-ms-filter: 'alpha(opacity=30)';
	filter: alpha(opacity=30);
}
.editor-toolbar-blank{
	float:left;
	height:25px;
	line-height:25px;
	padding:0 0px;
	margin-right:4px;
	cursor:default;
	color:#e5e5e5;
	font-size:12px;
}
#editor-toolbar-html{
	font-size:12px;
}
#editor-con{
	height:220px;
	margin:6px;
	font-size:14px;
	border:0;
	outline:none;
	display:block;
	width:588px;
	overflow:auto;
}