Friday, May 10, 2024
 Popular · Latest · Hot · Upcoming
31
rated 0 times [  36] [ 5]  / answers: 1 / hits: 94053  / 14 Years ago, thu, january 27, 2011, 12:00:00

Suppose I have this HTML element:



<div id=parent>
Hello everyone! <a>This is my home page</a>
<p>Bye!</p>
</div>


And the user selects home with his mouse.



I want to be able to determine how many characters into #parent his selection starts (and how many characters from the end of #parent his selection ends). This should work even if he selects an HTML tag. (And I need it to work in all browsers)



range.startOffset looks promising, but it is an offset relative only to the range's immediate container, and is a character offset only if the container is a text node.


More From » textrange

 Answers
11

UPDATE



As pointed out in the comments, my original answer (below) only returns the end of the selection or the caret position. It's fairly easy to adapt the code to return a start and an end offset; here's an example that does so:





function getSelectionCharacterOffsetWithin(element) {
var start = 0;
var end = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != undefined) {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.startContainer, range.startOffset);
start = preCaretRange.toString().length;
preCaretRange.setEnd(range.endContainer, range.endOffset);
end = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != Control) {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint(EndToStart, textRange);
start = preCaretTextRange.text.length;
preCaretTextRange.setEndPoint(EndToEnd, textRange);
end = preCaretTextRange.text.length;
}
return { start: start, end: end };
}

function reportSelection() {
var selOffsets = getSelectionCharacterOffsetWithin( document.getElementById(editor) );
document.getElementById(selectionLog).innerHTML = Selection offsets: + selOffsets.start + , + selOffsets.end;
}

window.onload = function() {
document.addEventListener(selectionchange, reportSelection, false);
document.addEventListener(mouseup, reportSelection, false);
document.addEventListener(mousedown, reportSelection, false);
document.addEventListener(keyup, reportSelection, false);
};

#editor {
padding: 5px;
border: solid green 1px;
}

Select something in the content below:

<div id=editor contenteditable=true>A <i>wombat</i> is a marsupial native to <b>Australia</b></div>
<div id=selectionLog></div>





Here's a function that will get the character offset of the caret within the specified element; however, this is a naive implementation that will almost certainly have inconsistencies with line breaks, and makes no attempt to deal with text hidden via CSS (I suspect IE will correctly ignore such text while other browsers will not). To handle all this stuff properly would be tricky. I've now attempted it for my Rangy library.



Live example: http://jsfiddle.net/TjXEG/900/



function getCaretCharacterOffsetWithin(element) {
var caretOffset = 0;
var doc = element.ownerDocument || element.document;
var win = doc.defaultView || doc.parentWindow;
var sel;
if (typeof win.getSelection != undefined) {
sel = win.getSelection();
if (sel.rangeCount > 0) {
var range = win.getSelection().getRangeAt(0);
var preCaretRange = range.cloneRange();
preCaretRange.selectNodeContents(element);
preCaretRange.setEnd(range.endContainer, range.endOffset);
caretOffset = preCaretRange.toString().length;
}
} else if ( (sel = doc.selection) && sel.type != Control) {
var textRange = sel.createRange();
var preCaretTextRange = doc.body.createTextRange();
preCaretTextRange.moveToElementText(element);
preCaretTextRange.setEndPoint(EndToEnd, textRange);
caretOffset = preCaretTextRange.text.length;
}
return caretOffset;
}

[#94036] Tuesday, January 25, 2011, 14 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
kamryn

Total Points: 645
Total Questions: 100
Total Answers: 118

Location: Tanzania
Member since Wed, Feb 24, 2021
3 Years ago
;