Forum How do I...?

How do I... find out a page number of element in the flow?

Mike
I have a use-case where I need to know page number of specific element in the flow/book.

Let's say its an ad in a book. It can be anywhere. When HTML is converted into PDF I would like to save where ad is in the book, like page#32.

At the moment the only option I can think of is to actually build a ToC for these elements as the last page, parse that page to extract page numbers and cut it of from production build.

Other option, which I'm not sure if it's even possible is to use a javascript callback which would receive a page number while its being flowed and would ajax save that. (Possible?)

Any other ideas much appreciated!

Mike
Mike
Well, I managed to get a working example using JavaScript.

The element I want to track, has a span inside.
<div class="track_me"><span class="page-number"></span></div>


As far as I am ware you can only call JavaScript function with "content:" which will change your elements content with the return value. That's the need of <span> inside.

.track_me span.page-marker {
	background-color: red;
	content: prince-script(pagenumber, counter(page));
}


I use background color to see if the span marker is being displayed. From my tests I can confirm that if you return empty string element does not take any space, is basically not displayed in PDF.

Prince.addScriptFunc("pagenumber", function(n) {
	console.log("page number", n);
	return '';
});


Running this via CLI, I get
page number2
page number2
page number4
page number4
page number7
page number7
page number10
page number10
page number11
page number11
page number13
page number13
page number15
page number15
page number17
page number17
page number20
page number20


which correctly displays page number of where the element appears, however I'm not sure why it's being displayed twice? Its always giving page number twice.


Well the questions now are:

1) Is it the best way to get pagenubmer of an emelent anywhere in the book?
2) How to send this info back to back-end?
3) Why I'm getting page number displayed twice, when there's only one element on that page with "track" class.
4) Can I some how call javascript whitout "content:"?

Mike
Mike
Actually printing page number twice is wrong. After changing markup I got irregular results. Some pages printed twice, some even 22 times, 6, etc.
mikeday
The reason the JavaScript is called multiple times is Prince may need to format a span multiple times when deciding exactly where on the page to put it.

You could try using the new box tracking API available in the Prince alpha version. It works like this:
Prince.trackBoxes = true;
Prince.addEventListener("complete", check, false);

function check()
{
    var tables = document.getElementsByTagName("table");

    for (var i = 0; i < tables.length; ++i)
    {
        var bs = tables[i].getPrinceBoxes();

        console.log("first page table appears on: "+bs[0].pageNum);
    }
}

This example checks tables, but you could get any elements that you are interested in. The JavaScript code will be run after typesetting has finished.
Mike
Hi mikeday,

I guessed that Prince is visiting element more than once for typesetting reasons.

That's a cool improvement for Prince and I definetlly give it a go.

Is the changelog for new version known at this point?

Maybe a more in depth documentation is available as well? :)

Mike
mikeday
There is a roadmap which shows items we have worked on, and updated documentation, although sadly it is no more in-depth than before. :)
Mike
Cool, thanks, will take a look.
Mike
That worked, however my initial solution had a attribute on element to pass in name (string) which is used in the back-end to identify object.

content: prince-script(pagenumber, counter(page), attr(name))

Can I achieve this whit trackBoxes?

Thanks,
Mike
Mike
That's a DOM element, so no problem :)

var attr = tables[i].getAttribute("name");

Edited by Mike