Подтвердить что ты не робот

Могу ли я обернуть каждую строку многострочного текста в промежутке?

Я пытался выяснить, как это сделать (если это вообще возможно) и нарисовал пробел...

У меня есть текст, который будет перенесен на несколько строк. Я хочу определить каждую отдельную строку и обернуть ее в промежуток. Наконец, я хочу назначить класс каждому диапазону из циклического массива.

Например...!

<div id="quote">
    I have some text that
    wraps onto three lines
    in this container
</div>

Я хочу, чтобы мой jQuery проанализировал эти строки, определил, где он переносится, и превратил его в это:

<div id="quote">
    <span class="red-bg">I have some text that</span>
    <span class="orange-bg">wraps onto three lines</span>
    <span class="yellow-bg">in this container</span>
</div>

Причина, по которой я хочу сделать это динамически, заключается в том, что я делаю это в адаптивных шаблонах, поэтому иногда один и тот же текст будет переноситься только на две строки или, может быть, на четыре в iPhone.

Это выполнимо? Я нашел это → http://vidasp.net/tinydemos/numberOfLines.html, который вычисляет количество строк, используемых в блоке текста, но на самом деле это не распространяется на то, что мне нужно.

4b9b3361

Ответ 1

Похоже, вы спрашиваете, как разделить текст, где он, естественно, обернут браузером. К сожалению, это совсем не просто. Также он не является надежным; рассмотрим следующий сценарий:

  • Пользователь просматривает вашу страницу, выводит div и запускается событие onload,
  • 3 элемента span создаются из текста node, 1 для каждой завернутой строки текста,
  • Пользователь изменяет размер браузера и размер изменений div.

Результат состоит в том, что промежутки больше не коррелируют с тем, где начинаются и заканчиваются линии. Конечно, этот сценарий можно избежать, используя элементы фиксированной ширины, или вы можете переделать все это при изменении размера браузера, но это просто пример того, как он может сломаться.

Тем не менее, это нелегко. A аналогичный вопрос появился раньше (хотя и с другой целью), и появились два решения, которые могли бы помочь:

Решение 1: getClientRects()

На самом деле не обертывайте текст в пробелы, а получайте позицию и размеры каждой строки текста, используя getClientRects(). Затем создайте необходимое количество интервалов и поместите/измените их размер за каждой строкой текста.

Pros

  • Fast; getClientRects возвращает позицию каждой строки
  • Простой; код более элегантный, чем решение 2

против

  • Обернутый текст должен содержаться встроенным элементом.
  • Стиль не будет применяться к тексту (например, шрифт-шрифт или цвет шрифта). Только полезно для таких вещей, как background-color или border.

Представленное демо с ответом показывает, как вы можете выделить строку текста, находящуюся под мышью.

Решение 2. Сплит, объединение, цикл, слияние

Разделите текст в массив, используя метод split() со слоем границы или пробелом в качестве переданного аргумента. Вставьте массив в строку с </span><span> между каждым элементом и оберните все это с помощью <span> и </span> и замените исходный текст node на полученный HTML в содержащем элементе. Теперь перебираем по каждому из этих элементов span, проверяя его позицию y в контейнере. Когда позиция y увеличивается, вы знаете, что достигли новой строки, а предыдущие элементы могут быть объединены в один интервал.

Pros

  • Каждая строка может быть написана с использованием любого свойства CSS, такого как шрифт-вес или текстовое оформление.
  • Каждая строка может иметь свои собственные обработчики событий.

против

  • Медленный и громоздкий из-за многочисленных операций с DOM и строкой

Заключение

Могут быть другие способы достижения вашей цели, но я не уверен в себе. TextNode.splitText(n) может разбивать TextNode в twain (!), когда передается числовой индекс символа, который вы хотите разбить. Ни одно из вышеперечисленных решений не является идеальным, и оба прерываются, как только размер элемента изменяется.

Ответ 2

Я собрал скрипт, реализующий решение №2 от Andy E (см. выше). То есть Split, join, loop, merge

Здесь алгоритм:

var spanInserted = $('#someText').html().split(" ").join(" </span><span>");
var wrapped = ("<span>").concat(spanInserted, "</span>");
$('#someText').html(wrapped);
var refPos = $('#someText span:first-child').position().top;
var newPos;
$('#someText span').each(function(index) {
    newPos = $(this).position().top   
    if (index == 0){
       return;
    }
    if (newPos == refPos){
        $(this).prepend($(this).prev().text() + " ");
        $(this).prev().remove();
    } 
    refPos = newPos;
});

Enjoy...

Ответ 3

var classes = ",red-bg,orange-bg,yellow-bg".split(",")
var txt = $('#quote').html().split("\n")
//this gives you FIVE items because of the leading and trailing CRs
//so we skip the first and last item in the loop
var output = ""
for(var x=1;x<txt.length-1;x++) {
    output = output + "<span class='"+classes[x]+"'>"+txt[x]+"</span>"
}
$('#quote').html(output)

Ответ 4

Это даст вам текст node, но я не уверен, что он помогает

$("#quote")
  .contents()
  .filter(function() {
    return this.nodeType == 3;
  })