обнаруживать разрывы строк с помощью jQuery? - PullRequest
24 голосов
/ 12 января 2011

возможно ли, чтобы jQuery / javascript определял, где строка разбита (чтобы соответствовать ограничениям ширины CSS), чтобы вставить элементы DOM перед началом новой строки?

Ответы [ 7 ]

37 голосов
/ 15 сентября 2011

Я придумал подход, но он может быть излишним для ваших целей, поэтому примите это во внимание.

Вам необходимо создать клон элемента, очистить оригинал, а затем переместить каждое слово назадв оригинальный элемент.Если высота изменяется в любой точке, перед этим словом стоит разрыв строки.Это было бы довольно просто сделать с помощью $(el).text(), но это усложняется, если внутри могут быть другие теги, а не только текст.Я попытался объяснить, как разбить его по узлам в этом поле для ответов, но оказалось проще просто создать плагин jQuery в jsFiddle.Ссылка здесь: http://jsfiddle.net/nathan/qkmse/ ( Gist ).

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

6 голосов
/ 12 января 2011

Вот один из подходов. Примечание: я не вижу идеального решения без использования моноширинных шрифтов. Равные символы делают эту задачу намного проще.

  1. Символы равной ширины
  2. Рассчитать размер одного символа
  3. Рассчитать размер контейнера
  4. Поиск символов в строке
  5. Найдите, где строка будет разрываться (например, пробел, тире и т. Д.)
  6. Получить все индексы взлома.

Посмотрите на jsfiddle для связанного html. Я не выполнил эту функцию. При расчете индекса взлома необходимо провести больше проверок. Сейчас он использует lastIndexOf (''), но при этом игнорируется, что следующий индекс может быть пробелом или текущим. Также я не учитываю другие символы перевода строки. Однако это должно стать отличной отправной точкой.

var text = $('#text').text(),                   // "lorem ipsum ... "
    len = text.length,                          // total chars
    width = $('#text').width(),                 // container width
    span = $('<span />').append('a').appendTo('#sandbox'),
    charWidth = span.width(),                  // add single character to span and test width
    charsPerRow = Math.floor(width/charWidth); // total characters that can fit in one row

var breakingIndexes = [], // will contain indexes of all soft-breaks
    gRowStart = 0,        // global row start index
    gRowEnd = charsPerRow;// global row end index

while(gRowEnd < len){
    var rowEnd = text.substring(gRowStart, gRowEnd).lastIndexOf(' '); // add more checks for break conditions here
    breakingIndexes.push(gRowStart + rowEnd); // add breaking index to array
    gRowStart = gRowStart + rowEnd + 1; // next start is the next char
    gRowEnd = gRowStart + charsPerRow;  // global end inxex is start + charsperrow
}

var text2 = $('#text2').text();           // "lorem ipsum ... " now not width bound
var start = 0, newText = '';
for(var i=0; i < breakingIndexes.length; i++){
    newText += text2.substring(start, breakingIndexes[i]) + '<br />'; // add hard breaks
    start = breakingIndexes[i]; // update start
}

$('#text2').html(newText); // output with breaks

http://jsfiddle.net/Y5Ftn/1/

5 голосов
/ 03 апреля 2013

это мой скрипт, который берет текст, а затем переводит каждую строку в интервал

CSS:

    margin: 0;
        padding: 0;
    }

    .title{
        width: 300px;
        background-color: rgba(233,233,233,0.5);
        line-height: 20px;
    }

    span{
        color: white;
        background-color: red;
        display: inline-block;
        font-size: 30px;
    }

    a{
        text-decoration: none;
        color: black;
    }

html

<div class="title">
        <a href="">SOME TEXT LONG TEXT ANDTHISISLONG AND THIS OTHER TEXT</a>
    </div>

JS

$(function(){

        $(".title").find("a").each(function(){

            var $this = $(this);
            var originalText = $this.text();
            $this.empty();

            var sections = [];

            $.each( originalText.split(" "), function(){
                var $span = $("<span>" + this + "</span>");
                $this.append($span);

                var index = $span.position().top;

                if( sections[index] === undefined ){
                    sections[index] = "";
                }

                sections[index] += $span.text() + " ";
            });

            $this.empty();

            for(var i = 0; i< sections.length; i++){
                if( sections[i] !== undefined ){
                    var spanText = $.trim(sections[i]);                     
                    $this.append("<span>" + spanText + "</span>");
                }
            }

        });

    });

Вы должны включить JQuery.

0 голосов
/ 23 мая 2013

В качестве альтернативы вы можете сравнить ширину текстового блока с шириной родительского блока.Если блок по крайней мере 98% ширины его родителя, уверен, что он ломается

0 голосов
/ 11 февраля 2013

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

Вот кое-что, что сработало для меня:

if ((/(\r\n|\n|\r)/.test($(this).val()))) {
    alert('there are line breaks here')
}

Я не уверенесли это будет работать с вашими сломанными строками, но это работает для обнаружения строк-бреков с помощью jQuery.

0 голосов
/ 13 января 2011

Не уверен, что именно ваш вариант использования, но http://code.google.com/p/hyphenator/ может быть решением вашей проблемы, или если вы покопаетесь в исходном коде hyphenator.js, вы сможете найти код, который вы ищете.

0 голосов
/ 12 января 2011

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

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

Другой способ - использовать аналогичный принцип и начать с пустого элемента того же размера с помощью параметра height auto,и вставьте новый символ и пробел, пока не получите новую строку.Оттуда вы можете использовать это как приближение к описанному выше методу, или вы можете слепо складывать длину каждой строки, пока не найдете новую строку, принимая во внимание ширину вашего элемента dom.Этот метод работает лучше с моноширинными шрифтами, хотя использование его только в качестве приблизительного значения.

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

...