Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JQuery - find height of div then create loop to overlay div

I am using wkhtmltopdf to convert part of a HTML page to a PDF document that may be several pages long (depending on the text the user inputs to be converted).

The wkhtmltopdf is working correctly. I am now wanting to indicate to the user where the page breaks will occur before the user creates their PDF document.

How do I overlay a HTML div tag to replicate a hr tag (< hr />) on top of the HTML text that is to be converted to the PDF document to indicate where the page breaks are most likely to occur before the contents of the form is converted to the PDF document?

I am thinking that there will have to be a JQuery / JavaScript loop condition to overlay the HTML div tag (indicating the page break) each 5cms (for the purpose of this post, assume that the page break will occur on the PDF each 5cms).

I have tried several times to do this myself, but I cannot get the jq/js code right (and it is killing me).

Here is a fiddle of the code below without the js/jq.

Here is the HTML:

<body>
    <div id="main_area">
        <div id="text">
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        <p>
            Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet. Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet Lorem ipsum doler sit amet.
        </p>
        </div>
        <div id='page_break'></div>         
    </div>
</body>

Here is the CSS:

If I add the following no-print CSS to the HTML div tag (indicating the page break), the div tag will not be printed/converted to the PDF document by wkhtmltopdf, in case you are wondering how the page break tag will be handled in the PDF document.

@media print {
    /* prevents the element from being printed in the pdf */
   .no_print, .no_print * {
        display: none !important
    }
}
#main_area {
    padding: 2px;
    width:100%;
    background:#fff;
    color:#333;
 }
 #text {
    z-index:1;
 }
 #page_break {
    position: absolute;
    width: 100%;
    height: 5px;
    background: red;
    top: 5cm;
    z-index:0;
    opacity: 0.2;
 }
like image 359
user1261774 Avatar asked Dec 27 '16 10:12

user1261774


1 Answers

Fiddle

The simplest way to do this, is by stacking transparent <div>s that have a height of the desired distance and a visible bottom border. We can repurpose the div#page_break in the original HTML to contain these <div>s. There is no need to use z-index, because positioned elements are always layered on top of unpositioned elements. So we can start by changing the CSS into this:

#main_area {
    padding: 2px;
    width: 100%;
    background: #fff;
    color: #333;
}
#page_break {
    position: absolute;
    top: 0;
    width: 100%;
    opacity: 0.2;
}
#page_break > div {
    width: 100%;
    height: 5cm;
    border-bottom: 5px solid red;
    margin-bottom: -5px;
    /* negative margin above ensures that the distance
       between two rulers is exactly the height of the div
     */
}

If we now consider the relevant bit of the original HTML,

<div id="main_area">
    <div id="text">
        ...
    </div>
    <div id='page_break'></div>
</div>

we won't see any rulers yet, because we added the ruler container but we didn't give it any <div>s to contain yet. For every child <div> that we add, we will obtain a new ruler, where the first is positioned 5cm from the top of the #main_area and each next ruler is positioned 5cm below the previous:

<div id="main_area">
    <div id="text">
        ...
    </div>
    <div id='page_break'>
        <div></div>   <!-- first ruler,   5cm from top -->
        <div></div>   <!-- second ruler, 10cm from top -->
        <div></div>   <!-- third ruler,  15cm from top -->
    </div>
</div>

In order to append a new <div> to another element in jQuery, we can use .appendTo:

$('<div>').appendTo('#page_break');

If necessary, we can insert another method call in order to adjust properties of the new <div>, such as .height:

$('<div>').height(400).appendTo('#page_break');  // 400 pixels

Now we just have to repeat this often enough to place exactly enough rulers. .height happens to be our friend again:

var textHeight = $('#text').height();

This is a height in pixels. Fortunately, according to the CSS standard there is a fixed number of pixels in a centimeter (even in print), so we can just do some calculations:

var pixelsPerInch = 96;
var cmPerInch = 2.54;
var pixelsPerCm = pixelsPerInch / cmPerInch;

pixelsPerCm is about 37.8. @pottedmeat7's variable onePixel is the inverse of this, i.e., the number of centimeters per pixel. 5cm happens to be about 189px.

We now know enough to roll a loop that adds <div>s to the #page_break until the height of the #text has been filled. The simplest case, where all distances are fixed to 5cm, just requires us to divide the height of the #text by 5cm:

var divisions = Math.floor((textHeight / pixelsPerCm) / 5);

var breaks = $('#page_break');
for (var i = 0; i < divisions; ++i) {
    $('<div>').appendTo(breaks);
}

We floor the divisions, because otherwise you'll get a dangling ruler below the text whenever the textHeight is not an exact multiple of 5cm. breaks is an optimization so jQuery doesn't have to look up the #page_break selector on every iteration of the loop.

like image 70
Julian Avatar answered Nov 14 '22 02:11

Julian