Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

detecting line-breaks with jQuery?

is it possible to have jQuery/javascript detect where a string is broken (in order to fit into CSS width constraints) so as to insert DOM elements before the beginning of a new line?

like image 904
Mild Fuzz Avatar asked Jan 12 '11 17:01

Mild Fuzz


2 Answers

I came up with an approach, but it might be overkill for your purposes, so take this into account.

You need to create a clone of the element, empty the original, then move each word back into the original element. If the height changes at any point, there's a line-break before that word. This would be fairly simple to do using $(el).text(), but it gets more complicated if there can be other tags inside, not just text. I tried explaining how to break it down by node in this answer box, but found it easier just to create a jQuery plugin in a jsFiddle. Link here: http://jsfiddle.net/nathan/qkmse/ (Gist).

It won't handle floated elements all that well, and there are a few other situations where it'll fall over. Let me know if you'd like more options, or if it doesn't quite work for your purposes, or if you're not sure how to apply it and I'll try to help.

like image 111
Nathan MacInnes Avatar answered Nov 09 '22 05:11

Nathan MacInnes


Here is one approach. Note: I do not see a ideal solution without using monospace fonts. The equal with characters make this task much easier.

  1. Equal width characters
  2. Calculate the size of one character
  3. Calculate the size of the container
  4. Find characters per row
  5. Find where the row will break (ie whitespace, dashes, etc)
  6. Get all breaking indexes.

Have a look at the jsfiddle for associated html. I have not completed this function. More checks need to be put in when calculating the breaking index. Right now it is using lastIndexOf(' '), but this ignores that the next index could be a space, or the current. Also I am not accounting for other line-breaking characters. However this should be a great starting point.

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/

like image 6
Josiah Ruddell Avatar answered Nov 09 '22 05:11

Josiah Ruddell