다른 답변에서 해결되지 않은 몇 가지 주름 :
- 요소는 여러 수준의 자식 노드를 포함 할 수 있습니다 (예 : 자식 노드가있는 자식 노드가있는 자식 노드 ...)
- 선택은 다른 시작 및 끝 위치로 구성 될 수 있습니다 (예 : 여러 문자가 선택됨).
- 캐럿 시작 / 종료를 포함하는 노드는 요소 또는 직계 자식이 아닐 수 있습니다.
다음은 요소의 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]];
}