1

I am trying to create the style here http://codepen.io/timprint/pen/dumjF . I'm 99% sure this isn't possible with just CSS but if I can figure out how to wrap each line of the span with another element (another span? it doesn't really matter) I should be able to do it fairly easily. This is a responsive site so I don't have control of the line ends.

I have paragraphs with inline spans.

<p>Hong Kong Phooey, number one super guy. Hong Kong Phooey, quicker than the
human eye <span class="highlight">He's got style, a groovy style, and a car
that just won't stop. When the going gets tough, he's really rough, with a
Hong Kong Phooey chop. Hong Kong Phooey, number one super guy.</span> Hong Kong
Phooey, quicker than the human eye. Hong Kong Phooey, he's fan-riffic!</p>`

I would like to wrap each line of .highlight in a secondary span and give the first and last ones a class .first & .last. It needs to recalculate and reapply the spans if the window width changes.

There could be several of these on a page so I need some way of reusing it.

Obtain a line of a paragraph in HTML is the closest I can find but I'm struggling to modify it for this use.

Community
  • 1
  • 1
Tim Print
  • 165
  • 7
  • So you're simply having a problem applying the answer to another question. What are you having a hard time with? – Etheryte Aug 06 '14 at 21:58
  • That answer is splitting the paragraph up into lines but not wrapping them in spans. My js skills are fairly rudimentary so I'm struggling to follow the whole thing... – Tim Print Aug 06 '14 at 22:03
  • 1
    So, the paragraph above should have three spans as a final result, right? If not, please add the version of this paragraph after it has been processing. – hex494D49 Aug 06 '14 at 22:20
  • As it is shown above, yes three spans. It could be more on a narrower viewport or fewer on a wider viewport. – Tim Print Aug 06 '14 at 23:06
  • You could use @ to quote someone next time so he/she could get your response. – hex494D49 Aug 06 '14 at 23:23

1 Answers1

6

One approach is, as in the linked question, to split each word of the element into its own individual element, assess the $(el).offset().top and, if it's the same as its previous sibling, add the contents of the current word to that previous sibling.

The following works, though rather than explicitly adding specific classes for the first, and last, lines I simply use CSS' :first-child and :last-child selectors. That said, the jQuery (a simple plugin, which is a little clunky and could well be optimised):

(function ($) {
    $.fn.lines = function (opts) {
        var s = $.extend({
            'lineClass' : 'line'
        },opts);
        return this.each(function () {
            var self = this,
                $self = $(self),
                $line,
                $prev;
            $self.find('.' + s.lineClass).contents().unwrap();
            $self.html(function (i, h) {
                return h.replace(/(\b[\w']+\b)/g, '<span class="' + s.lineClass + '">$1</span>');
            });

            $self.find('.line + .line').each(function(i, el){
                $line = $(this),
                $prev = $line.prev('.line');
                if ($line.offset().top === $prev.offset().top) {
                    $prev.append(el.previousSibling, $line.contents());
                    $line.remove();
                }
            });
        });
    };
})(jQuery);

$(window).on('resize', function(){
    $('p .highlight').lines();
});
$(document).ready(function(){
    $('p .highlight').lines();
});

JS Fiddle demo.

Note that this is a simple approach, and, because it re-writes the html of the .highlight elements any event-handlers on those elements will be removed/destroyed/deleted; so if the .line elements must have an interactive nature, you'll need to use on() to provide event-delegation:

$('.highlight').on('click', '.line:first-child', function(e){
    console.log(this, e.target);
    // <span class=​"line" style=​"color:​ blue;​">​…​</span>​ <span class=​"line" style=​"color:​ blue;​">​…​</span>
    $(this).css('color','blue');
});

JS Fiddle demo.

References:

David Thomas
  • 249,100
  • 51
  • 377
  • 410