Я не понимаю, как вы могли бы реально сделать это без явно обернутого текста (то есть, новых строк или <br>
элементов).
Насколько я знаю, у DOM нет способа узнать, где конкретный фрагмент текста обернут, по символам или по пикселям - включая то, что я знаю о API диапазона - не говоря уже о динамическом характере текста, который можно предположить, например, при использовании функции масштабирования текста в браузерах.
Но если вам удастся как-то сгенерировать / внедрить явные окончания строк, то, я думаю, у меня есть решение для вас.
EDIT
Благодаря потрясающей информации в ответе Пекки, я собрал функциональный прототип, но у него есть существенное предостережение - он работает только с простым текстовым контентом. Любой HTML, представленный в теле элемента, будет удален.
<script type="text/javascript" src="http://www.google.com/jsapi"></script>
<script type="text/javascript"> google.load("jquery", "1.4.1"); </script>
<script type="text/javascript">
jQuery.fn.wrapLines = function( openTag, closeTag )
{
var dummy = this.clone().css({
top: -9999,
left: -9999,
position: 'absolute',
width: this.width()
}).appendTo(this.parent())
, text = dummy.text().match(/\S+\s+/g);
var words = text.length
, lastTopOffset = 0
, lines = []
, lineText = ''
;
for ( var i = 0; i < words; ++i )
{
dummy.html(
text.slice(0,i).join('') +
text[i].replace(/(\S)/, '$1<span/>') +
text.slice(i+1).join('')
);
var topOffset = jQuery( 'span', dummy ).offset().top;
if ( topOffset !== lastTopOffset && i != 0 )
{
lines.push( lineText );
lineText = text[i];
} else {
lineText += text[i];
}
lastTopOffset = topOffset;
}
lines.push( lineText );
this.html( openTag + lines.join( closeTag + openTag ) + closeTag );
};
$(function()
{
$('p').wrapLines( '<span class="line">', '</span>' );
});
</script>
<style type="text/css">
span.line:hover {
background-color: lightblue;
}
</style>
<p style="width: 400px;">
one two three four five six seven eight nine ten eleven twelve thirteen fourteen fifteen sixteen seventeen eighteen nineteen twenty twenty-one twenty-two twenty-three
</p>