前言
之前看quill源碼(一個(gè)富文本編輯器)的時(shí)候第一次接觸Range與Selection對象性含,之前也寫過一篇文章總結(jié)了這兩個(gè)對象虱岂,不過感覺略水鸿市,正好現(xiàn)在在重構(gòu)一個(gè)atwho的功能偿枕,特寫幾篇總結(jié)下几于。吃引、
Selection
Selection是什么
selection是對當(dāng)前激活選中區(qū)(即高亮文本)進(jìn)行操作的對象筹陵。
Selection有什么用
我遇見的比較主要的就是獲取選中區(qū)的Range
Selection例子
讀者可以選中一些文字然后控制臺(tái)輸入下列代碼
userSelection = window.getSelection();
userSelection.toString()
Range
Range是什么
所謂"Range"刽锤,是指HTML文檔中任意一段內(nèi)容。一個(gè)Range的起始點(diǎn)和結(jié)束點(diǎn)位置任意朦佩,甚至起始點(diǎn)和結(jié)束點(diǎn)可以是一樣的(也就是空Range)并思。最常見的Range是用戶文本選擇范圍(user text selection)。當(dāng)用戶選擇了頁面上的某一段文字后语稠,你就可以把這個(gè)選擇轉(zhuǎn)為Range宋彼。當(dāng)然,你也可以直接用程序定義Range仙畦。
Range有什么用
試想一下输涕,在富文本編輯器里面,有一些情況是加粗或者傾斜選中的內(nèi)容慨畸,Range指HTML文檔中任意一段內(nèi)容莱坎。
在 HTML5 中,一個(gè) Range 對象代表頁面上的一段連續(xù)區(qū)域寸士。通過 Range 對象檐什,可以獲取或修改頁面上的任何區(qū)域。包含獲取弱卡,修改乃正,刪除和替換等操作。
Range的例子
userSelection = window.getSelection();
userSelection.getRangeAt(0).toString()
Range與Selection
每一個(gè)selection對象都有一個(gè)或者多個(gè)Range對象婶博,每一個(gè)range對象代表用戶鼠標(biāo)所選取范圍內(nèi)的一段連續(xù)區(qū)域瓮具,在firefox中,可以通過ctrl鍵可以選取多個(gè)連續(xù)的區(qū)域凡人,因此在firefox中一個(gè)selection對象有多個(gè)range對象名党,在其他瀏覽器中,用戶只能選取一段連續(xù)的區(qū)域划栓,因此只有一個(gè)range對象兑巾。
所以你可以看到userSelection.getRangeAt(0)這個(gè)為什么會(huì)有個(gè)0
getRangeAt方法有一個(gè)參數(shù)index,代表該Range對象的序列號忠荞;我們可以通過Selection對象的rangeCount參數(shù)的值判斷用戶是否選取了內(nèi)容;
屬性與方法
由于這種屬性和方法的東西太多了帅掘,羅列出來沒什么用委煤,我就說一些我用過的部分屬性和方法。
Range對象的我用過的屬性與方法(待補(bǔ)充)
setStart, setEnd等
setStart方法 用于將某個(gè)節(jié)點(diǎn)中的某處位置指定為Range對象所代表區(qū)域的起點(diǎn)位置修档,使用方法如下:
rangeObj.setStart(node,curIndex);
如上代碼rangeObj代表一個(gè)Range對象碧绞,該setStart方法使用2個(gè)參數(shù),第一個(gè)參數(shù)node代表一個(gè)節(jié)點(diǎn)吱窝,第二個(gè)參數(shù)是一個(gè)數(shù)字讥邻,當(dāng)?shù)谝粋€(gè)參數(shù)node所代表的節(jié)點(diǎn)是一個(gè)內(nèi)容為一段文字的文字節(jié)點(diǎn)時(shí)迫靖,該參數(shù)值用于指定將第幾個(gè)文字的結(jié)束位置作為Range對象所代表的區(qū)域的起點(diǎn)位置;當(dāng)?shù)谝粋€(gè)參數(shù)node所代表的節(jié)點(diǎn)中包括其他子節(jié)點(diǎn)時(shí)兴使,該參數(shù)值用于將第幾個(gè)子節(jié)點(diǎn)的結(jié)束位置指定為Range對象所代表的區(qū)域的起點(diǎn)位置系宜;
Selection對象的我用過的屬性與方法(待補(bǔ)充)
getRangeAt(index)
從當(dāng)前selection對象中獲得一個(gè)range對象。
index:參考rangeCount屬性发魄。
返回:根據(jù)下標(biāo)index返回相應(yīng)的range對象盹牧。
collapse(parentNode, offset)
將開始點(diǎn)和結(jié)束點(diǎn)合并到指定節(jié)點(diǎn)(parentNode)的相應(yīng)(offset)位置。
實(shí)戰(zhàn)
需求是獲取光標(biāo)之前的內(nèi)容励幼,這個(gè)在我實(shí)現(xiàn)atwho(@)和添加標(biāo)簽(#)的時(shí)候使用過汰寓。
代碼
// 這個(gè)函數(shù)獲取用戶選擇部分的Range對象
function getRange() {
const selection = window.getSelection()
if (selection && selection.rangeCount > 0) {
return selection.getRangeAt(0)
}
}
//這個(gè)獲取光標(biāo)前的Range
function getPrecedingRange() {
const r = getRange()
if (r) {
const range = r.cloneRange()
range.collapse(true)
// var el = closest(range.endContainer, d => d.contentEditable)
// range.setStart(el, 0)
range.setStart(range.endContainer, 0)
return range
}
}
// have fun
getPrecedingRange().toString()