3

Does something like -moz-background-inline-policy exist in Webkit? This property basically gives you the opportunity to specify how should background render for each line of an inline element. I attach to images of the same element on different browsers.

This is the result on firefox (with -moz-background-inline-policy: each-box;)

Firefox

This is on Google Chrome (I've tried -webkit-background-inline-policy, but it seems it doesn't exist)

Google Chrome

UPDATE

Since there is no background policy property on Webkit, I'm trying to find a different solution using jQuery. I'm adding an extra span behind each line of text. It's ok, except for the fact that text is not measured properly. You can see both examples in action here:

  1. Original solution (background inline policy): http://jsfiddle.net/notme/mCnGy/5/
  2. New solution (jQuery spans): http://jsfiddle.net/notme/my3br/1/

SOLUTION

//thanks @Peter Bailey - http://stackoverflow.com/questions/2456442/how-can-i-highlight-the-line-of-text-that-is-closest-to-the-mouse/2456582#2456582
jQuery.fn.wrapLines = function(openTag, closeTag) {
    var dummy = this.clone().css({
        top: -9999,
        left: -9999,
        position: 'absolute',
        width: this.width()
    }).appendTo(this.parent()),
        text = dummy.text().match(/\S+\s+/g);

    var words = text.length,
        lastTopOffset = 0,
        lines = [],
        lineText = '';

    for (var i = 0; i < words; ++i) {
        dummy.html(
        text.slice(0, i).join('') + text[i].replace(/(\S)/, '$1<span/>') + text.slice(i + 1).join(''));

        var topOffset = jQuery('span', dummy).offset().top;

        if (topOffset !== lastTopOffset && i != 0) {
            lines.push(lineText);
            lineText = text[i];
        } else {
            lineText += text[i];
        }

        lastTopOffset = topOffset;
    }
    lines.push(lineText);

    this.html(openTag + lines.join(closeTag + openTag) + closeTag);
    dummy.remove();
};

//thanks @thirtydot
var fixIt = function() {
    //remove previous .dummy
    $('.dummy').remove();

    $('div.node-title-text').each(function(index) {

        var dummy = $(this).clone().removeClass().addClass('dummy').appendTo($(this).parent());
        console.log(dummy);
        $(dummy).wrapLines('<span><span>', '</span></span>');

        var padding = 15;

        dummy.css({
            left: -padding,
            right: -padding
        }).find(' > span').css('padding-left', padding*2);

    });
};

$(window).load(function(){
    $(window).resize(fixIt).resize(); //trigger resize event onLoad
});
pasine
  • 11,311
  • 10
  • 49
  • 81
  • Could you create a test case using http://jsfiddle.net/? – thirtydot Apr 03 '11 at 15:52
  • http://jsfiddle.net/notme/8Ysk6/1/ here it is. – pasine Apr 04 '11 at 00:57
  • You need to explain, from the start, what the *end goal* is here. You're asking about `moz-background-inline-policy`, and you've provided a chunk of JavaScript that doesn't seem to be working properly. Also, your comment on the answer here makes little sense `"trying to create different spans and put them as background"` - why? *Massive clarification* is needed if you want your problem to be solved. Also, consider providing a jsFiddle that actually uses `-moz-background-inline-policy:each-box`, and the background image in your question (you can upload to/use it from http://imgur.com/) – thirtydot Apr 04 '11 at 01:54
  • Sorry, but since webkit has no background policy, I'm trying to find another solution to the problem by adding an extra span behind each text line with jquery. BTW, I've created another test just to show you the original solution. You can find it here http://jsfiddle.net/notme/mCnGy/5/ – pasine Apr 04 '11 at 08:59
  • http://jsfiddle.net/notme/my3br/1/ has the image background instead of the red one. – pasine Apr 04 '11 at 09:20
  • is it possible that simply using a background image, which solves the cross browser issues easily – Capitaine Apr 06 '11 at 09:41
  • If you want more input, you should retag with `jquery` and `javascript` to get some JavaScript bounty hunters to take a look. At the moment, the only high attention tag you have is `css`. – thirtydot Apr 06 '11 at 10:30

2 Answers2

1

This works, but it could probably be made more efficient:

http://jsfiddle.net/thirtydot/UGBXD/3/

Here's the complete code for posterity:

JS:

//thanks @Peter Bailey - http://stackoverflow.com/questions/2456442/how-can-i-highlight-the-line-of-text-that-is-closest-to-the-mouse/2456582#2456582
jQuery.fn.wrapLines = function(openTag, closeTag) {
    var dummy = this.clone().css({
        top: -9999,
        left: -9999,
        position: 'absolute',
        width: this.width()
    }).appendTo(this.parent()),
        text = dummy.text().match(/\S+\s+/g);

    var words = text.length,
        lastTopOffset = 0,
        lines = [],
        lineText = '';

    for (var i = 0; i < words; ++i) {
        dummy.html(
        text.slice(0, i).join('') + text[i].replace(/(\S)/, '$1<span/>') + text.slice(i + 1).join(''));

        var topOffset = jQuery('span', dummy).offset().top;

        if (topOffset !== lastTopOffset && i != 0) {
            lines.push(lineText);
            lineText = text[i];
        } else {
            lineText += text[i];
        }

        lastTopOffset = topOffset;
    }
    lines.push(lineText);

    this.html(openTag + lines.join(closeTag + openTag) + closeTag);
    dummy.remove();
};

var fixIt = function() {
    $('.dummy').remove();

    $('div.node-title-text').each(function(index) {
        //remove previous .dummy
        var dummy = $(this).clone().removeClass().addClass('dummy').appendTo($(this).parent());
        $(dummy).wrapLines('<span><span>', '</span></span>');
    });
};
$(window).resize(fixIt).resize(); //trigger resize event onLoad

CSS:

.node-title {
    position: relative;
    margin-bottom: 16px
}
.node-title-text {
    position: relative;
    z-index: 2
}
.dummy {
    position: absolute;
    top: 0; left: 0;
    z-index: 1
}
.dummy > span {
    background: url('https://i.stack.imgur.com/HPofR.png') top left no-repeat,
        url('https://i.stack.imgur.com/C8ImH.png') top right no-repeat,
        url('https://i.stack.imgur.com/9is9r.png') top center repeat-x;
}
.dummy > span > span {
    visibility: hidden
}

HTML: (same as yours)

<div class="node-title">
    <div class="node-title-text">
        <a href="#">Lorem ipsum dolor sit amet, consectetur adipiscing elit.
            Sed suscipit fermentum leo eu scelerisque.</a>
    </div>
</div>
thirtydot
  • 224,678
  • 48
  • 389
  • 349
  • Your solution is similar to what I've done in one of my many tries. It works fine in the example, but it breaks with multiple elements (try duplicate the HTML code and you'll see). I guess it's cause of this that I get `text is null var words = text.length` in firebug console. – pasine Apr 08 '11 at 20:28
  • @notme: Seems to work fine with multiple elements, see: http://jsfiddle.net/thirtydot/UGBXD/3/ - perhaps if you can show me how you managed to break it, I can fix it. – thirtydot Apr 08 '11 at 21:11
  • the code in last example you gave is different from the above one. If you take the first link you posted http://jsfiddle.net/thirtydot/UGBXD/2/ and try to duplicate HTML content, it works only for the last div. I see in the next example, you put the dummy.remove outside the each loop, and that did the trick! Unfortunatly, it still doesn't work form me, because of a strange issue: ´dummy.text().match(/\S+\s+/g)´ doesn't match the all string, but it misses the last word. This is way, when I just have one word in node-title, I get "text is null" error. – pasine Apr 08 '11 at 22:27
  • ok, putting a line-break in the HTML code, solved the problem! I didn't think that writing the code on a single line could be a issue! Thanks! Your code works great! – pasine Apr 08 '11 at 22:34
  • Ah, I see, that all makes perfect sense, I'm glad you got it working. I forgot to tell you that I moved `$('.dummy').remove();`, sorry about that. – thirtydot Apr 09 '11 at 12:00
  • no problem. btw i'm working on a new solution, based on splitting in spans all the text and adding a class on the first and the last spans of each line (it's just a title, so there are no more than 10 words). this would allow me to better handle left/right padding. if you are interested i'll post here. – pasine Apr 09 '11 at 12:14
  • I didn't realise it would be so difficult to add proper padding (trying it now, *it is difficult*). I will take a look at fixing it myself. – thirtydot Apr 09 '11 at 22:47
  • Same here. I asked for this to many friends, and most of them had to throw in the towel after trying some common solution (adding padding everywhere or changing every kind of display). – pasine Apr 10 '11 at 00:27
  • I felt like properly earning the bounty you awarded, so I looked at fixing the padding issue. This seems to work nicely: http://jsfiddle.net/thirtydot/UGBXD/8/ You can also use more chaining, though I'm not sure I like the code any better: http://jsfiddle.net/thirtydot/UGBXD/9/ – thirtydot Apr 11 '11 at 04:15
  • you are great man! but I found another issue (again, sorry :) ). If you change some text attribute with css (i.e. font-size, font-family, text-transform), the span take the wrong size. I wasn't able to reproduce the issue on jsfiddle, but you can figure out by yourself that dummy spans take width from text without css applied if js loads first. Everything works fine after user resizes browser. I've tested the issue on Chrome. FF4 works fine after moving javascript to the bottom of the page. – pasine Apr 12 '11 at 15:33
  • The only thing I can think of is that you need to apply the relevant properties to `.node-title`, like this: http://jsfiddle.net/UGBXD/11/ or to `.node-title-text, .dummy`, like this: http://jsfiddle.net/UGBXD/12/ - or maybe `.node-title-text a, .dummy` will work better for you. The point is to make sure that the visible text and `.dummy` both receive the relevant text-changing properties. – thirtydot Apr 12 '11 at 15:39
  • I can see both codes fine in all browsers. My code is fine on FF4 and Safari, but not on Chrome. I think is something related to font-face and Chrome, since the issue is solved if I use an installed font. – pasine Apr 12 '11 at 18:29
  • 1
    I got it! You call window.resize() to fire the onLoad event, but I think on WebKit it takes no effects if window is not fully loaded. Adding `$(window).load(function(){ $(window).resize(fixIt).resize(); //trigger resize event onLoad });` fixIt is fired at the right moment. I'm updating my question wit the complete solution. Thank you! – pasine Apr 12 '11 at 21:47
0

This non-standard feature isn't implemented in other browsers. You'll need to wrap each line in a span, then apply the background to that span.

You could use javascript to sort out the spans for you if you needed to have dynamic text, but if it's possible to hardcode it then it shouldn't be too complex.

Rich Bradshaw
  • 71,795
  • 44
  • 182
  • 241
  • I can't wrap text in spans cause it is a link. I was trying to create different spans and put them as background, but I can't get them of the same size of the above text. – pasine Apr 04 '11 at 00:40