1

I know I can use CSS :first-line pseudo-elmenent to target and change style of the first line in any block of text (like in this demo: http://jsfiddle.net/6H8sy/). So the first line can be found and targeted.

I was wondering if there's any way to actually select that text to reuse. Something like $(':first-line') (which doesn't work as it is).

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Yuriy Galanter
  • 38,833
  • 15
  • 69
  • 136
  • 2
    CSS pseudo-selectors are not technically part of the DOM, and therefore cannot be manipulated by JavaScript. – Blazemonger Jan 13 '14 at 17:21
  • Akin to highlighting with your mouse? – Johnston Jan 13 '14 at 17:21
  • @Johnston not really, rather to select a node for later reuse – Yuriy Galanter Jan 13 '14 at 17:28
  • 1
    @Blazemonger this can be done to retreive content of `:before` pseudo-element (e.g. http://jsfiddle.net/6H8sy/1/) I understand it's still not part of the DOM but was hoping for something similar – Yuriy Galanter Jan 13 '14 at 17:33
  • One way would be to take the entire content and place it in a hidden div that is the same width padding and margin as the original div, then remove words until the div's height is the height of 1 line. At that point you can assume that you have the correct collection of words. I wouldn't consider it to be very effective though due to differences in browser rendering, font size, etc however it might be able to get the job done. I don't have time to build a POC. Your title question simply isn't possible because document.querySelector only returns elements . – Kevin B Jan 13 '14 at 18:05
  • 2
    @Yuriy Galanter: `window.getComputedStyle()` only lets you query element and pseudo-element *styles*. The reason you are able to obtain the content of the `:before` and `:after` pseudo-elements is because they use the `content` CSS property. – BoltClock Jan 14 '14 at 03:29

2 Answers2

5

Since you can't select the pseudo element itself, you could replicate the behavior of :first-line, to determine the text. I wrote a quick JS function, similar to the one @Kevin B suggests. The function initially determines the height of the element if there is only one line of text present. A for loop is then used to remove a word from the text node until the element's new height equals the initial height. The function then returns with the first-line text.

Example Here - the function is run onLoad, therefore if the window's width changes, the text obviously won't match first-line. You could easily fix this by running the function when the screen is resized.

JavaScript function - no jQuery

function first_line(element) {
    var el = document.getElementById(element), cache = text = el.innerHTML;
    el.innerHTML = 'a'; var initial = el.offsetHeight; el.innerHTML = cache;
    arr = text.split(" ");
    for (var i = 0; i < arr.length; i++) {
        text = text.substring(0, text.lastIndexOf(" "));
        if (el.offsetHeight == initial) {
            var temp = el.innerHTML;
            el.innerHTML = cache;
            return temp;
        }
        el.innerHTML = text;
    }
}

I don't know if I'm re-inventing the wheel here, or not; but this does work. I'm not aware of any jQuery or built-in JS that is able to achieve this. Disregarding browser support, this should also work without any cross-browser styling inconsistencies. It seems to work with any types of padding/borders. (example)

Community
  • 1
  • 1
Josh Crozier
  • 233,099
  • 56
  • 391
  • 304
  • I was quite impressed wit your code here. So much so, in fact, I re-purposed it as part of my answer here (thought you might like to know): http://stackoverflow.com/questions/28845450/adding-the-link-that-makes-the-paragraph-collapse-to-the-last-visbile-line-of-th – whiterabbit25 Mar 10 '15 at 07:11
1

I guess this Stackoverflow question is what you are looking for:

getting the first line of text in an element jquery

var first_line = $("#element")
                       .contents()
                       .filter(function() { 
                           return !!$.trim( this.innerHTML || this.data ); 
                       })
                       .first();
Community
  • 1
  • 1
Uder Moreira
  • 865
  • 6
  • 17
  • 33
  • 1
    Thanks, but that's not it exactly. In that example content of the element consists of individual nodes (textnode, span, div etc.) In my case it's just a block of text – Yuriy Galanter Jan 13 '14 at 17:55