Pupeteer to generate pdf is rendering tables with gaps - node.js

I'm using Node Puppeteer to generate a PDF from a webpage using Chrome Headless. It works really well, apart from a small issue I'm coming across where if a table spans over more than one page sometimes one of the rows will appear larger than expected and the date column having text appear at the top of the row.
This is how it looks in the browser
This is how it is rendered on the pdf (some parts are blurred for confidentiality)
As you can see on the created column on the second page in the PDF view the date and time in the first row are distorted. There is nothing unusual about that row in the html version.
The table follows this structure;
<table>
<thead>
<tr>
<th>Project</th>
<th>Status</th>
<th>Creator</th>
<th>Created</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div>Project Name</div>
<div>Reference</div>
</td>
<td>
<img src="status.png" alt="Some Stagus"> Some Status
</td>
<td>
<div class="avatar"></div>
</td>
<td>
<div>29/10/2020</div>
<div>10:00:00</div>
</td>
</tr>
</tbody>
</table>
I'm not sure if this is a bug with chrome headless, when I print preview in chrome is shows the same issue as the generated pdf. Any suggestions or pointers would be very welcome.

This is going to sound stupid, and I hate this answer... but it worked for me.
Add a dummy row in between your normal rows. Something like ...
<tr style="height: 0px; !important"></tr>
You'll notice that the broken row has 2x height. I'm guessing the issue is triggered when the first pixel of a row lands EXACTLY on a page break, and then the renderer attempts to add the row twice, once on the previous page and once on the current page. But since it doesn't fit on the previous page, it rolls over and doubles up on the current page. ( PURELY SPECULATION )
Given this hypothesis, adding a dummy row with no height between every normal row lets you hide this issue by having the dummy row be the target of the bug. I'm assuming that since its height it 0, it can always squeeze in on the previous page without overflowing and/or it does overflow and get doubled, but since its height is 0 it doesn't matter.
Anyways, this was a nightmare to figure out a hack-fix. It worked for me, I truly hope it works for you, and I hope puppeteer releases an update one day that improves on page-break logic.

Related

Why copy/paste html table into Excel has this behavior

So this is not so much a problem solving question, more a question of why this is happening.
For context, assume you have normal html table like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Check This Out</title>
</head>
<body>
<table border="1">
<tr>
<td width="75" >This</td>
<td width="75" >is</td>
<td width="75" >row</td>
<td width="75" >one</td>
<td width="75" >Details</td>
</tr>
<tr>
<td>Now</td>
<td>this</td>
<td>is</td>
<td>TWO</td>
<td>Details</td>
</tr>
<tr>
<td>Last</td>
<td>we</td>
<td>have</td>
<td>Three</td>
<td>Details</td>
</tr>
</table>
</body>
</html>
Using Edge or Chrome, when performing a select operation on of all the data on this table you can do it two different ways (let's ignore reverse-selecting for now):
You can start selecting at the top left and move your mouse all the way until you get the the last cell and stop with your mouse cursor just after the 's' in Details. The mouse cursor looks like a text-insertion cursor until you release mouse button to end the selection.
You can start selecting at the top left and move your mouse way past all the data until it is outside the bottom right side of the data. Doing it this way, your mouse cursor stays as a mouse pointer when you release your mouse button to end the selection.
If you select the data the first way, then copy/paste into Excel, you get all your data in nice rows and columns.
If you select the data the second way, then copy/paste into Excel, all your data shows up as plain text in the one cell you selected for your paste.
Why does this happen?
This is related to your operation, and the operation description you mentioned is not very detailed. For example, these two points:
Start selecting location
End selecting location
If the Start selecting position is outside the table, the content copied and pasted into Excel will be in the correct table format. But if it is in the table, the problem you mentioned may appear, and the second point mentioned needs to be considered.
If the End selecting position is in the table, the content copied and pasted into Excel will also be in the correct table format. But if it is outside the table, the problem you mentioned will occur.
I think this is because the different selection positions will result in whether the table structure is also copied. You can even copy the code directly into Excel, and it will display the correct format.
A simple test:

How do I display list of multi-column clickable items?

I'm working on a project where I'm trying to display a list of messages. I want to have multiple fields in each row (Sent by, Message, date), and to be clickable (which then shows the thread the message is part of).
This is what I have so far. https://imgur.com/a/uU1sm64
I'm having problems aligning the data in the rows. For now, I have them as three ListItemText components under one ListItem for each row. I tried using tables but I can't get the OnClick function working on it.
What's the best way to get an aligned clickable multi-column list? Similar to gmail's web interface.
Thank you.
Is this the solution you are looking for? I used bootstrap hover table. On clicking the table row, I get the contents of the first cell. May be you should try getting the message ID or something related from the selected table row.
$("#display-table tr").click(function(){
$(this).addClass('selected').siblings().removeClass('selected');
var value=$(this).find('td:first').html();
alert(value);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/js/bootstrap.min.js"></script>
<table id="display-table" class="table table-hover">
<thead>
<th>Sent By</th>
<th>Message</th>
</thead>
<tbody>
<tr>
<td>ABC User</td>
<td>how-do-i-display-list-of-multi-column-clickable-items</td>
</tr>
<tr>
<td>ADC User</td>
<td>how-do-i-display-list-of-multi-column-clickable-items</td>
</tr>
<tr>
<td>ADE User</td>
<td>how-do-i-display-list-of-multi-column-clickable-items</td>
</tr>
</tbody>
</table>

Python Webdriver - How can I select a radio button based upon the text of a separate label?

Using Python WebDriver, how can I select a radio button based upon the text of a separate element such as this label?
My current code has the ability to click the radio button by id. But I have no idea how it is possible to click it when I am depending on text from a completely separate element.
The following is a pic of what i'm up against.
All help is greatly appreciated! =)
I've created a simplified example of your html on the screenshot, and assuming you want to get radio button which following sibling has "test text2", you need to use xpath axes:
<table>
<tbody>
<tr>
<td><input id="test_id" type="radio" value="123" /></td>
<td>test text</td>
<td>test text2</td>
<td>test text3</td>
</tr>
</tbody>
</table>
XPath would be: //tr/td[contains(text(),"test text2")]/preceding-sibling::td/input
The logic is:
get an element with specific text
go to previous sibling element (sibling == same level element)
now go deeper to td/input from there

Kentico search results showing raw macros

I have a table with column headers coming from localization keys. The table code is in an Editable Text webpart. Unfortunatly, the macro is showing in search results. is there a way to avoid this, or limit the smart search webpart? Worst case is i drop the localization implementation.
Here's my code snippet:
<thead>
<tr>
<th scope="col">{$kff.Generic-Name$}</th>
<th class="type" scope="col">{$kff.Generic-Type$}</th>
</tr>
</thead>
So those macros are page content. You can control what you're showing in search result changing appropriate transformation. Also you might try to go to the appropriate page type search fields and change Content field.
You can call the CMS.MacroEngine.MacroResolver.Resolve(string contentResult) method within your smart search transformation to get those macros resolved into text (or resource strings).

EE2 Embedded Template with Playa fields

Hopefully this is has a simple solution. I am pretty sure I am close. So here goes...
Code first.
{exp:channel:entries channel="client" url_title="{embed:client_name}"}
<tr>
{exp:playa:parents channel="project"}
<td>
{proj_name}
</td>
<td>
{proj_job_number}
{job_number}
{/proj_job_number}
</td>
<td>
{entry_date format="%m/%d/%Y"}
</td>
<td>
{proj_producer}
{producer_name}
{/proj_producer}
</td>
<td>
{proj_vendor}
{vendor_name}
{/proj_vendor}
</td>
<td>
<i class="icon-download"></i>
</td>
{/exp:playa:parents}
</tr>
{/exp:channel:entries}
This is the code from the embedded template I am using. I am trying to return each Project channel entry along with the other playa field values from the project channel entry. I am able to return the results correctly however I am trying to format returned values into a html table. So finally my question is... What do I need to do as far as markup/tagging/conditionals so I can have one Project channel entry display per html table row. Right now all entries to the playa field display in one table cell ending up with one row with all the table cells in it. I can post more code if needed and or clarify anything I am missing. Any help on this issue is much appreciated.
Cheers!
You need to place the <tr> tags inside the {exp:playa:parents} tag pair.

Resources