手写前端简单易懂的富文本编辑器
最近由于工作需要,需要手写一个富文本编辑器,需要支持源代码粘贴和可视化下内容修改的基本功能。自己就手撸一个富文本编辑器。
基本原理:由于富文本内容不想收到所在页面或者前端框架的影响,或者说写一个完全单独的纯编辑器,采用原生iframe+js+jquery实现。
1 如果在iframe中嵌入内容,并且能够实现dom操作。
这就是dom结构部分,这里面iframe就是我们后面重点实现页面预览的地方。
$("#contentiframe").contents()
通过以上代码,我们就能拿到iframe的内容,当然设置内容也是完全可以的。我们对dom的操作基本上就要基于这个对象去实现。
还有一点很重要,就是我们如何过去这个iframe所在的window,下面会用到。
$("#contentiframe").contents().get(0);
这个就是,我们获取iframe所在dom的实现方法。
2 粘贴html代码到textarea,然后将textarea的html代码转化为dom展示到iframe中。
这就是一个基本原理,我们将在textarea中输入的html字符串,转化为dom展示在iframe的视图页面上。
this.ifrm.find("body").html($(this.codePage.val()));
以上代码,通过jquery节点的html方法,将textArea的文本内容转化为dom,病展示在html代码中。
3 让iframe中的内容可以编辑。
这个基本原理就是,让iframe中的元素具有可编辑属性。增加contentEditable属性,则dom元素当前允许编辑。我的实际需求是,只允许编辑文本。所以我只需要将含有的文本内容的元素所在dom节点设置contentEditable属性。
this.ifrm
.find("body")
.find("*")
.contents()
.filter(function () {
return this.nodeType === 3 && $.trim(this.nodeValue).length > 0;
})
.each(function (index, item) {
$(item).parent().prop("contentEditable", "true");
});
切换会源代码时,我们又需要将contentEditable移除掉。
// 去掉可编辑属性
this.ifrm
.find("body")
.find("[contentEditable='true']")
.each((index, item) => {
$(item).removeAttr("contentEditable");
});
如何在可视化视图下,粘贴内容后者插入内容
插入内容和粘贴内容,之前我们需要知道当前可编辑dom中编辑时光标所在的位置,才能知道我们在哪里插入内容,或者粘贴内容。
这里我们就需要用到window.getSelection() 这个方法,当然这里很重要的一点是,我们需要用到iframe所在的window,而不是直接当前页面所在window。这里就用到开头的方法。
$("#contentiframe").contents().get(0);
注意这里的写法。这里拿到的就是当前iframe所在的方法,然后去获取getSelecttion(),这时我们就能知道光标的位置。方便我们去插入内容和粘贴内容。
我的实际需求是可以编辑和粘贴内容,所以这里就实现了可编辑和粘贴内容。
$(item).on("paste", function (e) {
e.preventDefault();
const selection = that.ifrm.get(0).getSelection();
const range = selection.getRangeAt(0);
const pasteData = that.parseEventContent(e);
if (range.collapsed) {
// 没有选中范围
let pasteTxt = document.createTextNode(pasteData);
range.insertNode(pasteTxt);
range.collapse(false);
} else {
// 选中范围 判断开始和结束
if (range.startOffset < range.endOffset) {
range.deleteContents();
let pasteTxt = document.createTextNode(pasteData);
range.insertNode(pasteTxt);
range.collapse(false);
}
}
});
还有其他小细节
在可视化视图下,我们要防止超链接点击是跳转,在代码模式下,我们要防止html代码格式不完整的问题,jquery其实可以帮我们完成一些细节操作,完整代码(会给table增加tbody, 会补齐确实的标签等),但是最好还是要校验一下,防止js代码执行等,这里记不一一讲了。