一、使用了CKEDITOR编辑器
二、文本是使用contenteditable="true"的div容器
三、点击文本时才初始化编辑器
四、问题:编辑器初始化后光标会重置到开始处,如何将光标重置到点击处
前端
一、在点击文本的时候,在点击文本的时候,获取range
信息和 endContainer
与endOffset
;node
try { range = window.getSelection().getRangeAt(0); var endContainer = range.endContainer; var endOffset = range.endOffset; } catch (e) { console.log(e); }
二、坑:直接点击图片,没法获取到range,须要把图片加入到range中;编辑器
// 把图片加进选区 if (e.target.nodeName === 'IMG') { var range2 = document.createRange(); var selectTion = window.getSelection(); selectTion.removeAllRanges(); range2.selectNode(e.target); selectTion.addRange(range2); }
三、在初始化编辑器后,在它的instanceReady
方法回调中进行光标恢复操做ide
CKEDITOR.instances[id].once('instanceReady', () => { ... });
听起来很美好,对不对,可是在实际操做中发现,以前存储的
endContainer
已经被替换成新的range信息了。如何获取咱们原来存储的endContainer
呢?博主试了深拷贝,浅拷贝都不行,因而才用了遍历寻找的方法~~~spa
四、找到原来的endContainer
的方法code
// 获取新的endContainer getEndContainer(endContainer, tag, endContainer2) { let childNodes = self.getAllChildNodes(tag); if (childNodes && childNodes.length > 0) { for (let i = 0, len = childNodes.length; i < len; i++) { let item = childNodes[i]; if ( (item.data && item.data === endContainer.data) || (item.wholeText && item.wholeText === endContainer.wholeText) || (item.innerHTML && item.innerHTML === endContainer.innerHTML) ) { // 为了不有重复片断,必须其父亲也要相同,我这里的每行父级元素都有类名cut-check let $endContainerParent = $(endContainer).hasClass('cut-check') ? $(endContainer) : $(endContainer).parents('.cut-check'); let $itemParent = $(item).hasClass('cut-check') ? $(item) : $(item).parents('.cut-check'); if ($endContainerParent.attr('data-value') === $itemParent.attr('data-value')) { endContainer2 = item; break; } } } } return endContainer2; }
五、恢复光标:这里须要再加个延迟,否则光标尚未初始化到开头处blog
CKEDITOR.instances[id].once('instanceReady', () => { setTimeout(() => { try { var newRange = document.createRange(); var set = window.getSelection(); // 找到与 endContainer 同样的节点 let endContainer2 = null; endContainer2 = self.getEndContainer(endContainer, tag, endContainer2); newRange.setEnd(endContainer2, endOffset); newRange.collapse(false); set.removeAllRanges(); set.addRange(newRange); } catch (e) { console.log(e) } }, 500) });
六、坑:到这里,咱们已经实现了光标恢复,可是会发现光标会如今起始处闪一下,再闪到咱们点击处。做为有强迫症的前端确定不能容忍这种操做了,这个咱们使用样式就能够处理了:在开始点击的时候给目标div添加一个隐藏光标的样式,而后恢复光标的时候移除便可。
图片
.hide-caret { caret-color: transparent; }
让咱们再看下效果:
rem
至此,完成了咱们的业务需求,固然第一次点击的时候会有不可见的1-2s的延迟,可是没办法,编辑器的初始化就须要1s多的时间。若是你有更好的想法,但愿能跟我留言~get