Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split html string into multiple pages

I am trying to develop eBook reader kind of android application. I need to split long html string(sent by server at run-time) into pages on fly based on the screen space available. Html content is an article which could contain text, images, videos etc.I am using WebView to display the html.

Can anyone give me direction towards how this can be achieved.

Thanks in advance.

like image 739
Harshita Avatar asked Jan 30 '26 05:01

Harshita


1 Answers

Doing any sort of HTML/DOM parsing is going to drive you up the wall, I think, and means that you're effectively starting to develop your own HTML layout engine.

It's a better idea to use the CSS3 column functions. Basically, get your content to render within a fixed width-and-height column. This becomes your page. Then shift your content position left to move between pages, and wrap it in a container that will hide overflow elements.

Our HTML will basically be:

<body>
    <div id="container">
        <div id="content">

            CONTENT GOES HERE

            <span id="endMarker"></span>
        </div>
    </div>
    <div>
        <button id="previous">Previous</button>
        <span id="page">Page N of M</span>
        <button id="next">Next</button>
    </div>
</body>

Our basic CSS is:

#container {
    width: 240px;
    overflow: hidden;
    background-color: yellow;
}
#content {
    position: relative;
    height: 30em;

    -moz-column-width: 240px;
    -webkit-column-width: 240px;
    column-width: 240px;

    -moz-column-gap: 10px;
    -webkit-column-gap: 10px;
    column-gap: 10px;
}

Now we will set the left CSS property for the #content to switch between pages, in multiples of -250px.

We've only got to work out how many columns our content takes, and we've got paging. How to get css3 multi-column count in Javascript gives a hint: we're going to find it from the left position of #endMarker.

Here's a working example http://lateral.co.za/pages.html, with the first chapter of Moby Dick. It works in Chrome and on Android, but not in Firefox - I think because of differences in the CSS columns implementations. Since we're interested in Android here, the code is good.

The important parts are:

  1. The CSS settings as above.
  2. The addition of a <span id="endMarker"></span> after the content (but within the #content div)
  3. The addition of a #previous and #next button, and a #page span, all outside the #container.
  4. This javascript after jQuery loads:

    var _column = 0;
    var _columnCount = 0;
    var _columnWidth = 240;
    var _columnGap = 10;
    $(function() {
        _columnCount = Math.floor($('#endMarker').position().left/(_columnWidth + _columnGap));
    
        setColumn = function(i) {
            _column = i;
            document.getElementById('content').style.left = -1 * _column * (_columnWidth + _columnGap);
            $('#page').html('Page ' + (_column+1) + ' of ' + (_columnCount+1));
        }
        $('#next').click(function() {
            if (_column==_columnCount) return;
            setColumn(_column+1);
        });
        $('#previous').click(function() {
            if (0==_column) return;
            setColumn(_column-1);
        });
        setColumn(0);
    });
    

That's it.

There's room for work. One might want to think about that number of columns calculation, I sort of sucked it from the referenced SO post, but haven't actually thought it through... The width of the container seems to affect the column width of the content, which doesn't entirely make sense to me.

But at least everything seems to be working without having to do any HTML parsing and own layout, at least in Chrome and on Android.

like image 114
craigmj Avatar answered Feb 03 '26 11:02

craigmj



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!