![]() |
#1 |
Member
![]() Posts: 18
Karma: 10
Join Date: Jul 2014
Device: none
|
Does .pdf conversion support indexOf()?
I've just discovered the ability to use javascript in headers and footers when converting EPUB to PDF. I think it's great.
So far I've been able to write simple functions with conditionals. However, I'm stuck when I introduce an indexOf(). I would like not to show headers in initial pages (TOC, title page, etc.) so I'm trying to write something like this after <p id="header">....</p> Code:
<script> function header() { if ( document.getElementById("header").indexOf("Title Page") >= 0 ){ document.getElementById("header").style.display = 'none' } } header() </script> Code:
.indexOf("Page Title") >= 0 This is why I'm suspecting Calibre may not accept indexOf(). Is this right? And if so, how to hide headers and page numbers for certain sections? Last edited by bowlins; 02-21-2015 at 10:06 AM. |
![]() |
![]() |
![]() |
#2 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
indexOf operates on strings, getElementById returns DOM nodes.
calibre uses WebKit for pdf conversion, which means it has a complete browser engine with full javascript support. You want document.getElementById("header").innerHTML.indexO f |
![]() |
![]() |
Advert | |
|
![]() |
#3 |
Member
![]() Posts: 18
Karma: 10
Join Date: Jul 2014
Device: none
|
That works like a charm!!!
![]() Having realised that, I was wondering how each page is rendered when converting into PDF. I've managed now to hide headers for certain sections, but I'm not able to hide them when page has headings with a certain class (e.g.: "chapter"). If heading is relatively big, then the header doesn't look that good. So far I've managed to check if a class exists with this: Code:
function header() { var chapter = document.getElementsByClassName("chapter"); if (chapter != 'undefined' || chapter != null ) {document.getElementById("header").style.display = 'none';} header() Is there a way of checking if class exists in the current page? |
![]() |
![]() |
![]() |
#4 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
pages are made using the css 3 columns module. So if you want to check whether a particular element is on the current page you would need to check if its position is contained in the current viewport position.
|
![]() |
![]() |
![]() |
#5 |
Member
![]() Posts: 18
Karma: 10
Join Date: Jul 2014
Device: none
|
Glad to know that there's a way but after too many hours trying I'm unable to put it in place.
Because I can't print variables on console I don't know which position (if any) my functions are returning. I've tried many variations of offsetParent and offsetTop but with no visible results. However, the most logical option to me would be to use a variation of my previous answer: Code:
if (document.getElementsByClassName("chapter").getBoundingClientRect() != null || document.getElementsByClassName("chapter").getBoundingClientRect() != 'undefined') { //Code to hide header } Would this be a correct method? Or how could I check returned values? |
![]() |
![]() |
Advert | |
|
![]() |
#6 |
Ex-Helpdesk Junkie
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 19,421
Karma: 85400180
Join Date: Nov 2012
Location: The Beaten Path, USA, Roundworld, This Side of Infinity
Device: Kindle Touch fw5.3.7 (Wifi only)
|
Well, you could always do a test run that just prints out the return value.
|
![]() |
![]() |
![]() |
#7 |
Member
![]() Posts: 18
Karma: 10
Join Date: Jul 2014
Device: none
|
I've tried many variations of document.write() but with no success. I just don't know if JS scripts in the header/footer can interact with the body element. Also using document.write() makes the pdf conversion to fail
Looking at the documentation in MDN, xhtml documents do not allow for document.write(), which makes things even more complicated https://developer.mozilla.org/en-US/...Document/write |
![]() |
![]() |
![]() |
#8 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
Why do you say there is no logging? console.log works fine, its output will be in the conversion log. As does using innerHTML to change the document contents for debugging.
|
![]() |
![]() |
![]() |
#9 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
And getElementsByClassName returns an list of elements. You want to get the bounding rect of a single element.
|
![]() |
![]() |
![]() |
#10 |
Member
![]() Posts: 18
Karma: 10
Join Date: Jul 2014
Device: none
|
It's been intense with many unexpected issues along the way, but I now have some code which removes headers from chapters' first page in pdf output files.
Print books do not normally have headers at the start of a chapter, but I'm not sure if this is something that people are actually using in Calibre. I'll post some explanations for future reference with code below just in case it helps someone. JS methods which are normally used for screen viewports were very problematic and I never got them to work correctly. I assume that this is because as a print document, viewports work differently (?). I eventually manage to print values in the pdf output document using innerHTML in the footer (sorry kovidgoyal but couldn't find where the console would be printed in the log files). This helped me to see that methods based on offset properties and getBoundingClientRect() were retrieving the position of the element fine but the position value remained the same for the whole chapter for all pages. This meant that any hiding of the header would be applied to the whole xhtml file and not just the first page. Instead of carrying through that route, I stumbled upon a set of functions based on the Pythagorean Theorem http://stackoverflow.com/questions/1...ements-centers I eventually had my Eureka moment as the triangle measures the distance between any two elements for the whole chapter/file but this time the value is updated for each page. Now that the value was changing on each page, it was finally possible to remove the header in the first page of each chapter (or any section for that matter). Code:
function hasChapter() { var chapter = document.getElementsByClassName("chapter")[0], header = document.getElementById("header"); var getPositionAtCenter = function (element) { var data = element.getBoundingClientRect(); return { x: data.left + data.width / 2, y: data.top + data.height / 2 }; }; var getDistanceBetweenElements = function(a, b) { var aPosition = getPositionAtCenter(header); var bPosition = getPositionAtCenter(chapter); return Math.sqrt( Math.pow(aPosition.x - bPosition.x, 2) + Math.pow(aPosition.y - bPosition.y, 2) ); }; var distance = getDistanceBetweenElements(document.getElementById("x"), document.getElementById("y")); if ( distance < 200 ) { document.getElementById("header").style.display = 'none'; } } hasChapter(); But overall this works!! |
![]() |
![]() |
![]() |
#11 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
Here is a simple way to test if an element is on the current screen
var br = elem.getBoundingClientRect() var on_current_page = br.left + 20 > window.pageXOffset && br.right - 20 < window.pageXOffset + window.innerWidth |
![]() |
![]() |
![]() |
#12 |
Addict
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 230
Karma: 13495
Join Date: Feb 2009
Location: SoCal
Device: Kindle 3, Kindle PW, Pocketbook 301+, Pocketbook Touch, Sony 950, 350
|
@kovidgoyal
Looks as JavaScript is disabled in command line. This header template: Code:
<div id="header" style="font-size:x-small"><p style="float:left">_TITLE_</p><p style="float:right;"><i>_AUTHOR_</i></p></div><script>document.getElementById("header").style.display = "none";</script> Exact copy of the same template used in CLI --pdf-header-template option doesn't eliminate header if style.display="none". Same about this template from Calibre website: Code:
<p id="pagenum" style="text-align:center;"></p><script>document.getElementById("pagenum").innerHTML = "" + (_PAGENUM_ + 3)</script> Same template (with all blanks, exact copy from the web page) works perfectly in GUI. Is there any way to enable JavaScript in command line? Last edited by EbokJunkie; 03-01-2015 at 11:00 PM. |
![]() |
![]() |
![]() |
#13 |
creator of calibre
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 45,207
Karma: 27110894
Join Date: Oct 2006
Location: Mumbai, India
Device: Various
|
There is no difference between command line and GUI. Make sure you are escaping command line strings properly. Remember that your shell will be interpreting all arguments you pass, so you have to quote/escape them properly.
|
![]() |
![]() |
![]() |
#14 |
Addict
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 230
Karma: 13495
Join Date: Feb 2009
Location: SoCal
Device: Kindle 3, Kindle PW, Pocketbook 301+, Pocketbook Touch, Sony 950, 350
|
Thanks for advice. I tried all imaginable (to me) combinations of escaping by quotes but exhausted my options...
This is the command line I experimented with intending to turn off the header: Code:
ebook-convert "book.epub" "book.pdf" --custom-size 78.836x108.31 --unit millimeter --override-profile-size --pdf-default-font-size 17 --margin-top 12 --pdf-header-template "<div id="header" style="font-size:x-small"><p style="float:left">_TITLE_</p><p style="float:right;"><i>_AUTHOR_</i></p></div><script>document.getElementById("header").style.display="none";</script>" Please give me a hint: How to place quotes in this line to set javascript to work? |
![]() |
![]() |
![]() |
#15 |
Addict
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() Posts: 230
Karma: 13495
Join Date: Feb 2009
Location: SoCal
Device: Kindle 3, Kindle PW, Pocketbook 301+, Pocketbook Touch, Sony 950, 350
|
Solved escaping in command line JavaScript .
Just need to escape quotes like \"header\" and \"none\". Might be useful to point this out in Calibre online documentation. |
![]() |
![]() |
![]() |
|
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
Multi-Core Conversion support? | evandy | Calibre | 5 | 09-18-2015 10:49 AM |
KF8 conversion and support in Calibre? | Rhialto | Conversion | 19 | 01-16-2012 05:45 PM |
PDF to PDF conversion creates much larger file? | rocketcat | Conversion | 11 | 09-30-2011 07:37 PM |
when will calibre support vector graphics in pdf to epub conversion | smith9 | Calibre | 5 | 11-13-2010 05:03 AM |
Any chance for chm to epub/mobi/pdf conversion support | joblack | Calibre | 4 | 11-02-2010 01:06 AM |