一、使用了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