How to find absolute or relative position of text or <br /> in HTML?
As tdammers mentions, handling all of the details of putting together a process to handle what you're suggesting has many nuances that may have to be addressed, depending on what you're doing.
The basics of what you're trying to do is:
- Wrap an element around the text you want to find the position for, ie, in the case of text, probably a
<span>
. - Get either the
$.offset()
or$.position()
of the element or elements you added. Whichever you choose is relevant to what you're trying to do; the first is relevant to thedocument
, the second to the containing element.
I created a simple demo of a script to "highlight" a term typed into a textbox in several paragraphs using div
s with position: absolute
and top
/left
offsets relative to the terms found in the paragraphs (located by the <span>
surrounding them).
Note, this is only a demonstration (of $.offset()
); it's not production-ready code. There's a link to the live fiddle demo below the code snippets.
First, I created a function to find and create a highlight <div>
for each term found.
function highlightWordPositions(word) {
var $paras = $('p'),
$spans,
_top = 0,
_left = 0;
$paras.each(function(){
var $p = $(this),
regex = new RegExp(word, 'g');
$p.html($p.text().replace(regex, '<span>' + word + '</span>'));
$spans = $p.find('span');
$spans.each(function(){
var $span = $(this),
$offset = $span.offset(),
$overlay = $('<div class="overlay"/>');
$overlay
.offset($offset)
.css({
width: $span.innerWidth(),
height: $span.innerHeight()
}).show();
$(document.body).append($overlay);
});
});
}
Then, I attached a callback to the $.keyup()
event:
$('#term').keyup(function(event){
var term = this.value;
if (term == '') {
$('.overlay').remove();
return false;
} else if (term.indexOf(' ') != -1) {
this.value = term.replace(' ', '');
return false;
}
$('.overlay').remove();
highlightWordPositions(term);
});
http://jsfiddle.net/JaN75/
Assuming that you mean the position where the character is displayed on screen, in pixels:
jQuery or the DOM do not model individual characters in their object models, so you can't read a character's position directly.
The best way I can think of is to insert a dummy element right before (or after) the character, e.g. a zero-width span with a special class, and then get its position. Alternatively, you can wrap the character in such a special element, and then get the wrapper's position, width, height, etc.
It's still not trivial, because you need to scan the HTML, and you don't want to break the HTML by inserting tags where they don't belong - for example, if you want to match the character 'd', you don't want to turn <div>
into <<span class="magic">d</span>iv>
, as that wouldn't be well-formed HTML.
Also, inserting those dummy elements may alter the layout slightly, depending on how the browser handles kerning.
There is a simpler and more lightweight way (vs other answers that suggest overlays) to find the position of letters in DOM elements: use a range.
// returns { left, top, etc } in px
function getLetterPositions(myElementWithText, myTextElementIndex, myLetterPosition) {
var range = document.createRange();
range.setStart(myElementWithText.childNodes[myTextElementIndex], myLetterPosition);
range.setEnd(myElementWithText.childNodes[myTextElementIndex], myLetterPosition+1);
return range.getBoundingClientRect();
}
- the element with the text holding the target letter is
myElementWithText
(e.g. a<div>
) - the element child with the text (i.e. the
textNode
) is at indexmyTextElementIndex
(in most cases, 0) - the position of the letter you are trying to find is
myLetterPosition
(e.g. if text is"abcd"
and you want"c"
, this will be 2)