JS snippet for page numbering via WKHTMLTOPDF won't calculate page numbers, console.log throws undefined, while writing to HTML results in NaN

Viewed 55

Until now WKHTMLTOPDF documentation has served me well and I almost always found there what I was looking for. If not, there has always been an open question for all my troubles here on StackOverflow. This time however, it was different.

I am trying to adapt this page numbering snippet which I found in the WKHTMLTOPDF documentation, so that it numbers my pages when I convert the HTML with WKHTMLTOPDF.

The manual says:

  • [page] Replaced by the number of the pages currently being printed
  • [topage] Replaced by the number of the last page to be printed

However when you run the JS snippet, subst() throws 'undefined' in the console and it writes NaN in the HTML elements which are addressed in the function, instead of writing the page number, slash the total pages as expected.

Can someone explain why is that happening?

What is the way to make it display the actual page numbers, when converted to PDF? E.g. page 1: 1/4, page 2: 2/4, page 3: 3/4, page 4: 4/4

p.s. I assume, since the body is called only once in this snippet, it should display in the HTML 1/1 right? Or 0/0? One thing is sure: NaN is not what the snippet is supposed to output, right? And it does exactly the same when converting it with WKHTMLTOPDF now.

When does it actually count the page break in the converted file?

Does the converted WKHTMLTOPDF have like 4 < body> elements (if so, then there should be 4 separate html docs which the converter tool then collates (puts together) into one PDF, as each html doc supports only 1 , right?), so that the onload="subst()" is called 4 times to count the pages? Or how else does this page break work?

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="src/style.css" />
    <script src="src/script.js"></script>
    <script>
       function subst() {
        var vars = {};
        var query_strings_from_url = document.location.search.substring(1).split('&');
        for (var query_string in query_strings_from_url) {
          if (query_strings_from_url.hasOwnProperty(query_string)) {
            var temp_var = query_strings_from_url[query_string].split('=', 2);
            vars[temp_var[0]] = decodeURI(temp_var[1]);
          }
        }
        var css_selector_classes = [
          'page',
          'frompage',
          'topage',
          'webpage',
          'section',
          'subsection',
          'date',
          'isodate',
          'time',
          'title',
          'doctitle',
          'sitepage',
          'sitepages',
        ];
        for (var css_class in css_selector_classes) {
          if (css_selector_classes.hasOwnProperty(css_class)) {
            var element = document.getElementsByClassName(
              css_selector_classes[css_class]
            );
            for (var j = 0; j < element.length; ++j) {
              element[j].textContent = vars[css_selector_classes[css_class]] + 1;
            }
          }
        }

        if (vars['page'] === 1) {
          document.getElementsByTagName('html')[0].style.display = 'none';
        }
      }
    </script>
  </head>
  <body onload="subst()">
    <h1 id="header"></h1>
    <div class="rightAlign">
      Page <span class="page"></span>/<span class="topage"></span>
    </div>
  </body>
</html>

1 Answers

I assume, since the body is called only once in this snippet, it should display in the HTML 1/1 right? Or 0/0?

wkhtmltopdf does not modify the html input file, so the answer to this question is no.

If by running the JS snippet, you mean running it in stackoverflow, this will not work because the code in your question does not call the wkhtmltopdf command line executable. It might be possible to use wkhtmltopdf in Node.js, but it could be very difficult. See: A simple guide to load C/C++ code into Node.js JavaScript Applications

The code you posted must be inserted into a separate HTML file (header.html) and used on the command line like so (using Wikipedia simply as an example):

wkhtmltopdf https://en.wikipedia.org/wiki/Main_page --header-html header.html output.pdf

Screenshot of the header of output.pdf: Result of wkhtmltopdf command

Finally, The code you posted works when copied inside header.html with one minor correction. element[j].textContent = vars[css_selector_classes[css_class]] + 1; should simply be: element[j].textContent = vars[css_selector_classes[css_class]];

Related