I am using the following script to get the position of highlighted text:
function getSelectionCharOffsetsWithin(element) {
var start = 0, end = 0;
var sel, range, priorRange;
if (typeof window.getSelection != "undefined") {
range = window.getSelection().getRangeAt(0);
priorRange = range.cloneRange();
priorRange.selectNodeContents(element);
priorRange.setEnd(range.startContainer, range.startOffset);
start = priorRange.toString().length;
end = start + range.toString().length;
} else if (typeof document.selection != "undefined" &&
(sel = document.selection).type != "Control") {
range = sel.createRange();
priorRange = document.body.createTextRange();
priorRange.moveToElementText(element);
priorRange.setEndPoint("EndToStart", range);
start = priorRange.text.length;
end = start + range.text.length;
}
return {
start: start,
end: end
};
}
function alertSelection() {
var mainDiv = document.getElementById("detailBoxParagraph");
var sel = getSelectionCharOffsetsWithin(mainDiv);
alert(sel.start + ": " + sel.end);
}
Now, if i use this on $('p').text()
, which contains
Lorem ipsum dolor sit amet, consetetur sadipscing elitr.
everything works just fine. But i also need to get the position in $('p').html()
which is obviously different because of the <b>
tag
Lorem ipsum dolor `<b>sit</b>` amet, consetetur sadipscing elitr.
How do i prevent or change this?
Edit:
I forgot to say, my first thought was to count the times the tag occures, then use that value to calculate the new position, but this is idiotic somehow.
My second approach was to replace the tag with an asterisk for the work with .text()
Edit #2
Here is a messy fiddle showing the problem. If you highlight text with the mouse, then click the button, the first time it will correctly be set to bold. Second time won't work correctly.
I will clean the fiddle up soon
Edit #3
i played around a little with the highlight plugin mentioned below but i wasn't able to limit the function to affect only the marked string. It will either highlight all matching words or just the first appearence. Can anyone help?
Here is the necessary code:
jQuery.fn.highlight = function(pat) {
this.length = 1 ;
function innerHighlight(node, pat) {
var skip = 0;
if (node.nodeType == 3) {
var pos = node.data.toUpperCase().indexOf(pat);
if (pos >= 0) {
var spannode = document.createElement('span');
spannode.className = 'highlight';
var middlebit = node.splitText(pos);
var endbit = middlebit.splitText(pat.length);
var middleclone = middlebit.cloneNode(true);
spannode.appendChild(middleclone);
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
}
else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
for (var i = 0; i < 1; ++i) { // So it will highlight only the first occurence.
i += innerHighlight(node.childNodes[i], pat);
}
}
return skip;
}
return this.length && pat && pat.length ? this.each(function() {
innerHighlight(this, pat.toUpperCase());
}) : this;
};
Edit #4
Okay, i tried to understand that javscript. As far as i see, this can not be done since highlight() is called with a simple string as a parameter. It can not know the position of this string. Could / Should i parse the position, then try to search from that position, highlight the first occurence, then abort?