寫在前面: 網上有各種富文本編輯器,微博分享等操作,這些功能非常實用,他們就是使用 range,selection 對象來實現的,這兩個對象偏冷門,不涉及編輯器一般用不到,range 對象是對選區的操作,選區是滑鼠在頁面上按下,然後拖動選擇的內容,range 對象就是對這個選區的操作;selecti ...
寫在前面:
網上有各種富文本編輯器,微博分享等操作,這些功能非常實用,他們就是使用 range,selection 對象來實現的,這兩個對象偏冷門,不涉及編輯器一般用不到,range 對象是對選區的操作,選區是滑鼠在頁面上按下,然後拖動選擇的內容,range 對象就是對這個選區的操作;selection 是當前活動區的操作對象,selection 對象下麵可以有多個 range 對象;這篇文章寫的是標準的 selection和 range,小於 IE 9 的舊版本不在討論範圍內;
先來看一下 W3C 文檔上的 range 對象的基本屬性:
collapsed:返回一個用於判斷 Range 起始位置和終止位置是否相同的布爾值。
commonAncestorContainer:返回包含 startContainer 和 endContainer 的最深的節點。
endContainer:返回包含 Range 終點的節點。
endOffset:返回 endContainer 中表示Range終點位置的數字。
startContainer:返回包含 Range 開始的節點。
startOffset:返回 startContainer 中表示 Range 起始位置的數字。
註意:range 的這些屬性都是只讀的,看下麵這張圖,就明白這些屬性是怎麼回事了:
collapsed 為 flase,說明起始點和終點不在同一個位置,startOffset 是從0開始的,d 的索引是2,表示滑鼠按下的位置,也就是 div 元素的字元開始算的,endOffset 是 4,是從 span 標簽開始算的,i 字元在 span 標簽立面的索引是4;
註意,他們總是從包裹字元的節點的開始字元計算的;
再來看下 range 的方法和解釋:
setStart(node, index):設置 Range 的起點。
setEnd(node, index):設置 Range 的終點。
setStartBefore(node):以其它節點( Node)為基準,設置 Range 的起點。
setStartAfter():以其它節點為基準,設置 Range 的始點。
setEndBefore():以其它節點為基準,設置 Range 的終點。
setEndAfter():以其它節點為基準,設置 Range 的終點。
selectNode():設定一個包含節點和節點內容的 Range。
selectNodeContents():設定一個包含某個節點內容的 Range。
collapse():向指定端點摺疊該 Range。
這個解釋看了之後一臉蒙圈,我的感受是講的不清楚,還是上圖,加上我們的理解更直觀:
setStart setEnd 方法:
JS 操作:
1 // 創建新的 range 對象,設置 setStart setEnd 2 function setStartEnd() { 3 var box = document.getElementById('box'); 4 if (document.createRange) { 5 var range = document.createRange(); 6 var start = box.querySelector('span').firstChild; 7 var end = box.querySelector('p').firstChild; 8 9 range.setStart(start, 2); // p 標簽的第 2 個字元 10 range.setEnd(end, 3); // span 標簽的 第 3 個字元 11 console.log(range.cloneContents()); // 列印 range 的內容 12 console.log(range); // 列印 range 13 } 14 }
選區的內容和列印 range 的結果:
這個例子可以看出來,startOffset 的位置在第一個 span 標簽的 g 字元前面,endOffset 的位置在 p 標簽的 p 字元前面;
需要註意的是,如果是跨標簽的選區,沒有匹配到結束標簽時,會摺疊選區,把起點的位置設置為結束點的位置;
看下這個例子,把開始節點設置為 p 標簽,結束節點為 span 標簽,從後面向前面選擇:
var start = box.querySelector('p').firstChild; // 開始節點是 p var end = box.querySelector('span').firstChild; // 結束節點是 span
列印出來的結果:
仔細檢查會發現 collapsed: true,並且 startContainer 和 endContainer 是同一個元素,這說明這個 range 選區摺疊了,所以操作的時候需要註意;
setStartBefore setEndBefore 方法:
JS 操作:
var box = document.getElementById('box'); if (document.createRange) { var range = document.createRange(); var spans = box.querySelectorAll('span'); var refStart = spans[0].firstChild; var refEnd = spans[1].firstChild; range.setStartBefore(refStart); // 設置 p 節點的開始位置為 range 的起點 range.setEndBefore(refEnd); // 設置 span 節點的開始位置為 range 的終點 console.log(range.cloneContents()); console.log(range); }
這兩個方法的作用是以參考節點的開始位置作為參考,來設置 range 的起點和結束點;
setStartAfter,setEndAfter 方法:
JS:
var box = document.getElementById('box'); if (document.createRange) { var range = document.createRange(); var spans = box.querySelectorAll('span'); var refStart = spans[0].firstChild; var refEnd = spans[1].firstChild; range.setStartAfter(refStart); // 設置 p 節點的結束位置為 range 的起點 range.setEndAfter(refEnd); // 設置 span 節點的結束位置為 range 的終點 console.log(range.cloneContents()); console.log(range); }
這兩個方法的作用是以參考節點的結束位置作為參考,來設置 range 的起點和結束點;
selectNode 方法:
JS:
var box = document.getElementById('box'); if (document.createRange) { var range = document.createRange(); var span = box.querySelector('span').firstChild; range.selectNode(span); console.log(range.cloneContents()); console.log(range); }
selectNode 方法的操作就是 range 選擇整個節點的,預設 startOffset 是 0,endOffset 是1;
selectNodeContents 方法:
這個方法和 selectNode 很類似,區別是會預設把結束點的位置移到最後;
var box = document.getElementById('box'); if (document.createRange) { var range = document.createRange(); var span = box.querySelector('span').firstChild; range.selectNodeContents(span); console.log(range.cloneContents()); console.log(range); }
collapse 方法是設置摺疊選區的,開始位置和結束位置相同,這麼解釋就清楚多了,作用是多用來設置游標的;
下一篇看一下 selection 對象的基本屬性和用法;