У меня есть длинный текст, и я хотел бы предложить пользователю справку чтения: текущая строка должна быть выделена. Для помощи я буду просто использовать координату Y мыши (этот путь, указатель мыши не собирается мешать). У меня есть большой DIV с идентификатором content
который заполняет общую ширину и маленький DIV с классом content
для текста (см. здесь для примера).
Я использую jQuery 1.4. Как я могу выделить строку текста, который является самым близким к текущему положению мыши?
Не уверен, что Здесь вам очень поможет jQuery, но вы можете взглянуть на метод element.getClientRects
, описанный в MSDN и MDC . В частности, этот пример в MSDN в некотором роде похож на то, что вы хотите достичь, выделяя строки с помощью хитроумного z-индексированного элемента div
, который идет за текстом в координатах возвращается getClientRects ()
.
Вы должны иметь возможность достичь того же, перебирая объекты TextRectangle, возвращенные в документе onmousemove
, и проверяя, является ли значение y курсора мыши> верхним и <нижним каждый прямоугольник и перемещая умно проиндексированный по оси z div на ту же позицию / высоту.
Все основные текущие браузеры поддерживают getClientRects ()
.
ОБНОВЛЕНО - работает в Chrome, IE6 / 7/8, Firefox, Opera, Safari.Первоначальные проблемы, которые у меня были в других браузерах, были связаны с тем, что DIV
должен был быть display: inline
.
ОБНОВЛЕНИЕ СНОВА - мне пришлось обратиться к этому ответу для некоторых новых вопросов, поэтому я нашел время, чтобы обновить его, чтобы пересчитать строки при изменении размера окна.Похоже, что другие тоже играли, сейчас версия 15.
Лучший подход, который приходит на ум, это разделение каждой строки на Это было бы наименее затратным решением, так как браузер сам позаботится о выделении. Если вам нужны причудливые эффекты, вы можете добиться этого, добавив события Сложная часть, конечно, заключается в разделении содержимого на строки с разрывом строки браузера. Это нужно делать динамически, чтобы строки действительно отражали позиции, в которых браузер разрывает текст. Возможно, принятый ответ на этот вопрос - шаг в правильном направлении: Получение конкретной строки с помощью jQuery Как это работает: Он проходит через весь элемент (фактически, клон элемента), вставляя элемент в каждое слово. Верхнее смещение span'а кэшируется - когда это смещение меняется, мы можем считать, что находимся на новой строке. или
:hover
CSS класс с установленной настройкой "highlight":
span.line:hover { background-color: lightblue; }
mouseover
и mouseout
к каждой строке.
Я не понимаю, как вы могли бы сделать это без явного переноса текста (например, новых строк или элементов
).
Насколько мне известно, DOM не может обнаружить, где конкретный фрагмент текста обернут: по символам или по пикселям, включая то, что я знаю о Range API - не говоря уже о динамическом характере текста, который может принимать, например, с функцией масштабирования текста в браузерах.
Но если бы вам каким-то образом удавалось генерировать / вставлять явные окончания строк, я думаю, у меня есть решение для вас.
Благодаря потрясающей информации в ответе Пекки я собрал функциональный прототип, но у него есть существенная оговорка - работает только с текстовым контентом. Любой 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>