8

I need javascript to detect each browser wrapped line of text and wrap it into <span class="line">.

I came across articles talking about measuring the y axis of each word, but have not seen a solid solution.

Here's what I have so far. See it on Jsfiddle.

HTML

<div class="inline-bg">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec cursus condimentum metus, et placerat augue rutrum vitae. Donec arcu lorem, eleifend at elementum eget, consectetur vel lacus. Nam euismod iaculis varius. Phasellus sed dui diam. Nullam facilisis, diam sit amet sagittis cursus, metus tortor gravida erat, ut fringilla risus ipsum eu nisl.</div>​

JS/jQuery

(function($){
    $.fn.inlinebackground = function() {
        $.each(this, function(i,t) {
            var split = $(t).html().split(' ');
            var output = '';
            $.each(split, function(i,o){
                output += '<span class="line">'+o+'</span>';
                if (i < (split.length - 1)) {
                    output += '<br>';
                }
            });
            $(t).html(output);
        });
    }
})(jQuery);

/* End Plugin Code */

// Run the plugin on .news-caption 
$(function(){
    $('.inline-bg').inlinebackground();
});

CSS

.inline-bg { width: 200px; line-height:3em; }
.inline-bg span.line { background-color: black; color: white; padding: 15px; }

1 Answer 1

12

I have to admit at first I thought this would be a daunting task since there is no way to task browser to tell you where auto wrap line breaks take place.

I've created a solution that first wraps each word in a span, then goes through all the spans to determine their top position in container. It then builds an array of indexes of line start and end spans and wraps each line of word spans in a wrapping span.

DEMO: http://jsfiddle.net/KVepp/2/

Possible Limitations:

  • Space added at end of each span may perhaps cause a span to break to a new line where text may not.
  • Not sure if each word span needs to be removed once lines are wrapped. ( very simple mod)
  • Assumes no other html in container other than text
  • Needs a little additional work to be turned into a plugin if needed for multiple containers
  • regex for words is simple split at space. Likely need additional regex for recurring spaces

HTML:

<div id="content">Lorem Ipsum<div> 

CSS:

#content{ position:relative}

JS:

var $cont = $('#content')

var text_arr = $cont.text().split(' ');

for (i = 0; i < text_arr.length; i++) {
    text_arr[i] = '<span>' + text_arr[i] + ' </span>';
}

$cont.html(text_arr.join(''));

$wordSpans = $cont.find('span');

var lineArray = [],
    lineIndex = 0,
    lineStart = true,
    lineEnd = false

$wordSpans.each(function(idx) {
    var pos = $(this).position();
    var top = pos.top;

    if (lineStart) {
        lineArray[lineIndex] = [idx];
        lineStart = false;

    } else {
        var $next = $(this).next();

        if ($next.length) {
            if ($next.position().top > top) {
                lineArray[lineIndex].push(idx);
                lineIndex++;
                lineStart = true
            }
        } else {
            lineArray[lineIndex].push(idx);
        }
    }

});

for (i = 0; i < lineArray.length; i++) {
var start = lineArray[i][0],
    end = lineArray[i][1] + 1;

/* no end value pushed to array if only one word last line*/
if (!end) {
    $wordSpans.eq(start).wrap('<span class="line_wrap">')
} else {
    $wordSpans.slice(start, end).wrapAll('<span class="line_wrap">');
}

}​

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for the answer. It doesn't wrap the last word from your example... or if there is only one word.
Not sure where you see last word not wrapping. I never thought of 1 word only. Will have to make adjustments tomorrow is late night here. Also..what browser? I haven't checked this cross browser..is very early stages and will possibly need adjustments
I'm in chrome, but it's like that on all browsers. Look at the source of html on your example on jsfiddle.
OK.. IN Firefox where I was testing it is working with the amount of words ... not in Chrome or IE. Will need to some tweaking tomorrow. Is not a trivial concept to make all this work.
did a quick fix for last line being one word. Editied link and code above also. Seems to work in FF,Chrome and IE jsfiddle.net/KVepp/2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.