ริ้วรอยเล็กน้อยที่ฉันไม่เห็นว่ามีอยู่ในคำตอบอื่น ๆ :
- องค์ประกอบสามารถมีโหนดลูกหลายระดับ (เช่นโหนดลูกที่มีโหนดลูกที่มีโหนดลูก ... )
- การเลือกอาจประกอบด้วยตำแหน่งเริ่มต้นและตำแหน่งสิ้นสุดที่แตกต่างกัน (เช่นมีการเลือกหลายตัวอักษร)
- โหนดที่มีจุดเริ่มต้น / จุดสิ้นสุดของ Caret อาจไม่ใช่องค์ประกอบหรือลูกโดยตรง
ต่อไปนี้เป็นวิธีรับตำแหน่งเริ่มต้นและสิ้นสุดโดยชดเชยกับค่า textContent ขององค์ประกอบ:
// node_walk: walk the element tree, stop when func(node) returns false
function node_walk(node, func) {
var result = func(node);
for(node = node.firstChild; result !== false && node; node = node.nextSibling)
result = node_walk(node, func);
return result;
};
// getCaretPosition: return [start, end] as offsets to elem.textContent that
// correspond to the selected portion of text
// (if start == end, caret is at given position and no text is selected)
function getCaretPosition(elem) {
var sel = window.getSelection();
var cum_length = [0, 0];
if(sel.anchorNode == elem)
cum_length = [sel.anchorOffset, sel.extentOffset];
else {
var nodes_to_find = [sel.anchorNode, sel.extentNode];
if(!elem.contains(sel.anchorNode) || !elem.contains(sel.extentNode))
return undefined;
else {
var found = [0,0];
var i;
node_walk(elem, function(node) {
for(i = 0; i < 2; i++) {
if(node == nodes_to_find[i]) {
found[i] = true;
if(found[i == 0 ? 1 : 0])
return false; // all done
}
}
if(node.textContent && !node.firstChild) {
for(i = 0; i < 2; i++) {
if(!found[i])
cum_length[i] += node.textContent.length;
}
}
});
cum_length[0] += sel.anchorOffset;
cum_length[1] += sel.extentOffset;
}
}
if(cum_length[0] <= cum_length[1])
return cum_length;
return [cum_length[1], cum_length[0]];
}