2

Given a block of text, I'd like to chunk it into sections N pixels tall--displayed lines, as computed after applying CSS, and rounding down so you end up with an integer number of lines of text displayed.

I'd like to then display an offset of text and show, e.g., lines 100-120, lines 121-140, etc.

The lines may not all be the same height, and will be wrapping.

How can you do this from JavaScript?

Design goals:

  • Display a book, one page at a time.
  • Allow readers to jump to a particular page.
  • Keep lines together for some sections of text, and avoid widows/orphans (solitary lines at top or bottom of page)
  • Have some styles start a new page (e.g. Chapter headers).

Things that don't work:

  • splitting the text into fixed chunks by character length. This doesn't address any of the display requirements.
  • Computing height based on ems ahead of time. This can't handle wrapping lines.
  • Rendering to an off-screen area, setting overflow: hidden, and fixing it at a large negative location. Still can't compute the height correctly, so you end up with lines cut in half vertically.
Alex Feinman
  • 5,393
  • 1
  • 30
  • 48
  • 1
    With `split` counter and loop. – vaso123 Dec 22 '14 at 14:53
  • sounds like you try to put the cart before the horse. Usually you have an area of unknown height apply the `overflow: auto;` property and list as many lines as fits inside this area. Can you give a usecase for such a thing? – Nico O Dec 22 '14 at 14:56
  • I have added more detail. – Alex Feinman Dec 22 '14 at 15:05
  • You've gotta give us a little more details. I would say use `split` and a data structure that contains the number of characters and the word. Then you can cycle through the data structure and get the information as required. That may be overkill, but it's hard to tell from what you have given – Adjit Dec 22 '14 at 15:18

2 Answers2

0

This code will count the number of lines

var textContainer = $('.text');

textContainer.each(function(){
    var current = $(this);
    var text = current.text();

    var numOfLines = 0;

    var words = text.split(' ');

    current.text(words[0]);
    var height = current.height();

    // loop through text
    for(var i = 1; i < words.length; i++){

        // insert new word
        current.text(current.text() + ' ' + words[i]);

        // height increased?
        if(current.height() > height){
            numOfLines ++;
        }
    }
    console.log(numOfLines);
});

The purpose of this code was originally something else. So there might be redundant parts.

You have to append it to whereever in the DOM you want to display it. Are the "Design goals" part of this one question? Because they're different issues entirely and should be a seperate question.

Community
  • 1
  • 1
ProblemsOfSumit
  • 19,543
  • 9
  • 50
  • 61
0

Just an outline:

  1. Put everything in an overflow: hidden block.
  2. Find where lines wrap.
  3. Wrap the words for each line in spans. This may be more difficult if you have complex structures with inline elements that wrap, as you would need to split an inline element and have it replicated inside each of the artificially created lines. (If you have IDs on inline elements this may become impossible.)
  4. At this point you are sure you only have elements in your structure that are single-line and directly under your overflow: hidden block. You can check heights now and make sure you don't have broken lines showing at the bottom. Also you can do pagination by computing the offset height of the start of each page.

Have fun coding this, as it's not something you can do very quickly.

Community
  • 1
  • 1
Alin Purcaru
  • 43,655
  • 12
  • 77
  • 90