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

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

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

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

<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, которое вычисляет количество строк, используемых в блоке текста, но на самом деле это не распространяется на то, что мне нужно.

Ответы [ 4 ]

10 голосов
/ 10 ноября 2010

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

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

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

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

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

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

Плюсы

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

Минусы

  • Переносимый текст должен содержаться встроенным элементом.
  • Нетстиль будет фактически применяться к тексту (например, font-weight или font-color).Полезно только для таких вещей, как цвет фона или границы.

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

Решение 2: Разделить, объединить, зациклить, объединить

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

Плюсы

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

Минусы

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

Заключение

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

6 голосов
/ 23 марта 2014

Я собрал скрипку , реализующую решение № 2 Энди Э (см. Выше).Т.е. разделение, объединение, цикл, слияние

Вот алгоритм:

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;
});

Наслаждайтесь ...

1 голос
/ 10 ноября 2010
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)
0 голосов
/ 10 ноября 2010

Это даст вам текстовый узел, но я не уверен, что это поможет

$("#quote")
  .contents()
  .filter(function() {
    return this.nodeType == 3;
  })
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...