编辑器基本思路

内容纲要

一、contentEditable

div的contentEditable属性可以让div进入编辑模式,禁止可以使用contentEditable=false。

二、Selection

浏览器中内置了获取用户操作的方法:

let selection = window.getSelection();

Selection 对象有anchorNodefocusNode属性,可以用来获得选中部分的开始和结束元素,不过一般会用Range代替。还有一个isCollapsed属性,为true时,代表选择区域开始和结束在相同的点,也就是没有选中内容时光标闪烁的模式。修改选择范围,主要就是对Range对象进行编辑。首先可以通过:

let range = selection.getRangeAt(0);

获取被选中的第一个区块,以此类推往后选。

获得了Range对象,就可以获得选中区域内容了。

Range对象获得选择区域的开始和结束点:

range.startContainer //开始点所在的容器(元素)
range.endOffset  // 开始点在其容器内的偏移
range.endContainer // 结束点所在的容器(元素)
range.endOffset // 结束点在其容器内的偏移

还有一个非常有用的属性:

range.commonAncestorContainer // 选择范围的共同父元素

需要注意的是,返回的Range对象是可变对象。

简单来说,如果用户的选区改变了,那么Range对象的内容也会改变。因此要记录某一时刻的Range,就要记录。

此外,Range对象还定义了各种获取内容和修改内容的函数,详见文档,这里只是一些常用的。

1) 获得选取的坐标范围

可以获得光标在网页上的精确位置,获得光标的位置或者选区的矩形边框可以使用:

let rect = range.getBoundingClientRect();

rect对象包括的属性包括矩形的top、left、right、bottom坐标。如果选取是collapsed的话,这四个属性就可以用来计算光标的位置。

2) 保存选区并恢复

如果对选择区域内的元素进行了修改,比如添加新元素、改变元素类型等等,那么原来的选区会失效。因此一个比较有用的技巧就是在修改元素之前,先保存选区Range,待修改完成后再恢复:

let selection = window.getSelection();
let range = selection.getRangeAt(0);

let startContainer = range.startContainer;
let startOffset = range.startOffset;
let endContainer = range.endContainer;
let endOffset = range.endOffset;

// ......

let newRange = document.createRange(); 
newRange.setStart(startContainer, startOffset);
newRange.setEnd(endContainer, endOffset);

selection.removeAllRanges();
selection.addRange(newRange);

但是,有些操作可能会自动修改选区,所以要为恢复选区添加延迟:

setTimeout(function(){
selection.addRange(newRange);
},  50);

三、 编辑 DOM,修改样式

如果段落中是一段即加粗又倾斜的文字等较复杂的样式,需要使用document.execCommand:

document.execCommand('bold'); // 加粗所选
document.execCommand('italic'); // 倾斜所选
document.execCommand('underline'); // 下划线所选
document.execCommand('createLink', true, 'https://indeex.club'); // 为所选文字加链接
document.execCommand('unlink'); // 取消链接
document.execCommand('formatBlock', true, 'h1');
document.execCommand('formatBlock', true, 'p');

浏览器还提供了copy、cut和paste等方法,这里不再赘述。

四、事件侦听

除了change或keyup事件,拖拽还要使用mouseup事件,但是都比较麻烦。所以要使用 Mutation Observer 机制,略。

五、兼容

然后就是不同浏览器的兼容问题了,ummmm…..

先这样吧。

code enjoy!😜😜😜

作者:indeex

链接:https://indeex.club

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


发表评论

您的电子邮箱地址不会被公开。