возможно ли, чтобы jQuery/javascript определял, где строка сломана (чтобы соответствовать ограничениям ширины CSS), чтобы вставлять элементы DOM перед началом новой строки?
обнаружение разрывов строк с помощью jQuery?
Ответы (7)
Я придумал подход, но он может быть излишним для ваших целей, поэтому примите это во внимание.
Вам нужно создать клон элемента, очистить оригинал, а затем переместить каждое слово обратно в исходный элемент. Если высота изменяется в любой точке, перед этим словом ставится разрыв строки. Это было бы довольно просто сделать с помощью $(el).text()
, но становится сложнее, если внутри могут быть другие теги, а не только текст. Я попытался объяснить, как разбить его по узлу в этом поле для ответов, но мне оказалось проще просто создать плагин jQuery в jsFiddle. Ссылка здесь: http://jsfiddle.net/nathan/qkmse/ (Gist).
Он не будет хорошо обрабатывать плавающие элементы, и есть несколько других ситуаций, когда он упадет. Дайте мне знать, если вам нужны дополнительные параметры, или если они не совсем подходят для ваших целей, или если вы не знаете, как их применять, и я постараюсь помочь.
Вот один подход. Примечание: я не вижу идеального решения без использования моноширинных шрифтов. Знак равенства с символами значительно упрощает эту задачу.
- Символы одинаковой ширины
- Рассчитать размер одного символа
- Рассчитать размер контейнера
- Найти символы в строке
- Найдите место разрыва строки (например, пробелы, тире и т. д.)
- Получить все ломаные индексы.
Взгляните на 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
1ex
за charWidth
. Или, может быть (что сложнее) создать оценку charWidth
. Но это зависит от языка, с помощью которого персонаж с большей вероятностью будет в вашем тексте. Или, если перенос слов не то, что вы ищете, было бы неплохо взять max-char
, например W, который является огромным символом. Или, может быть, рассматривать это как функцию Gaussian
с дисперсией?
- person Marnix; 13.01.2011
max-char
, потому что почти в каждом шрифте это самый большой символ. Так что да, составить оценку приятнее, чем просто взять «а» в SPAN
.
- person Marnix; 13.01.2011
это мой скрипт, который берет текст, а затем делает каждую строку диапазоном
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.
Я не знаю какой-либо встроенной функции jQuery или javascript для этого. Однако вы можете сделать это самостоятельно, но это будет потенциально медленно, если у вас много текста.
Теоретически вы можете убедиться, что высота установлена на авто, удалить текст, а затем слово за словом снова вставить его. При изменении высоты вы удаляете последнее слово и вставляете свой элемент dom. Опять же, это будет медленно, если текста много, и лучший способ сделать это — не изменять исходный элемент, а сделать это в другом элементе, который может быть скрыт, а затем заменить исходный элемент по завершении. Таким образом, ваш пользователь не увидит, как контент исчезает, а затем возвращается слово за словом.
Другой способ - использовать аналогичный принцип и начать с пустого элемента того же размера с авто высотой и вставлять новый символ и пробел, пока не получится новая строка. Оттуда вы можете использовать это как приближение с вышеупомянутой техникой, или вы можете вслепую добавить длину каждой строки, пока не найдете новую строку, принимая во внимание ширину вашего элемента dom. Однако этот метод лучше работает с моноширинными шрифтами, где его можно использовать только в качестве приблизительного значения.
Тем не менее, есть способ измерить текст с помощью холста, но это может быть экстремально. Теоретически это было бы так: создайте элемент холста, получите контекст, установите все свойства шрифта, а затем используйте метод context.measureText()
. Пример его использования можно найти здесь. а>.
Не знаю, каков именно ваш вариант использования, но http://code.google.com/p/hyphenator/ может быть решением вашей проблемы, или если вы покопаетесь в исходном коде hyphenator.js, вы сможете найти код, который ищете.
Я думаю, что было бы легче обнаружить с помощью регулярного выражения - гораздо меньше кода при сохранении эффективности.
Вот что сработало для меня:
if ((/(\r\n|\n|\r)/.test($(this).val()))) {
alert('there are line breaks here')
}
Я не уверен, что это будет работать с вашими неработающими строками, но это работает для обнаружения разрывов строк с помощью jQuery.
В качестве альтернативы вы можете сравнить ширину текстового блока с шириной его родителя. Если блок составляет не менее 98% ширины своего родителя, он почти наверняка сломается.
<br>
? - person Marnix   schedule 12.01.2011