Dynamically change margin.top for print page depending of loaded HTML in Master page

Hello!

How to dynamically change margin.top of Print page, depending of loaded HTML in Master page.

My Master page is dynamically loaded, meaning I load HTML with Standard Scripts. Sometimes I load HTML into the Master page with two <b.> elements and sometimes three:

<p. id=twoB>
<b.> user </b.>
<b.> tel</b.>
</p.>

or

<p. id=threeB>
<b.> user </b.>
<b.> tel</b.>
<b.> feature</b.>
</p.>

I want the margin.top of the Print page to increase (creating more white space) so when I load three elements in the Master page the text goes down in the Print page.

What I want to do. I want to count the amount of <b.> tags in the HTML and accordingly change the margin.top. This is how far I have come (see Control Script code below):

var HTML = loadhtml("C:/Users/HTMLwithBelements.html);

var myPrintPage = merge.template.contexts.PRINT.sections[‘Standard A4’];

var countBelements = … (I dont know how)

if(countBelements === 3 ){

myPrintPage.margins.top = “4in”;

} else {

myPrintPage.margins.top = “2in”;

}

I understand that Control script don’t have access to the DOM but Standard scripts can’t change margin.top of a page. So I don’t know if I should use a control, standard or post pagination script.

If there is a better method, that could work, please tell me as well.

Sincerely,
ABS

Hi @ABS,

Welcome to the forum.

You could change the margins of a master page in a post pagination script (with selector “body”). This would not immediately have effect, you would also need to include a merge.section.paginate call at the end to trigger pagination again.

A possibly more efficient alternative would be to modify the DOM of the master page in a control script. Control scripts do not have a convenient API to manipulate the DOM, but you can use the html function to get and set the initial HTML (i.e. the inner HTML of <body>) of a master page.

Hi Sander,

Thanks for your response!

I understand the idea of modifying the DOM in the control script and using the post-pagination script, but I just want to make sure I’m on the right track. My primary goal is to avoid the overlap of content between the master template and the print page, adjusting the top margin of print page dynamically based on the number of <b> elements loaded in master template.

So, the core idea is this:

  1. I need to count the <b> elements in the HTML (loaded into the master template).
  2. Depending on the count (two or three <b> tags), I want to set a corresponding margin-top value on the print page (like “2in” for two <b> elements and “4in” for three).
  3. I want to ensure the content doesn’t overlap, so the print page adjusts its layout to account for the dynamic change.

How can I make sure the content on the print page doesn’t overlap when these adjustments are made?

Also, could you share some sample code or further guidance on how to implement this dynamically with the control and/or post-pagination scripts?

Thanks in advance for your help!

Best regards,
ABS

Hi @ABS,

Pages are not contained in individual elements, so there is no place to apply a margin-top style. Instead, margins are controlled by properties on sections and master pages. For a master page the property we need is margins.header.

Let’s say we are doing this with a control script rather than a post pagination script. This means you will need to move the code that dynamically loads master page content to that control script. Something like this:

// Iterate over all master pages
for (let master of merge.template.masterpages) {
	// Dynamically load content
	const html = loadhtml("...");
	master.html(html);
	
	// Count <b> elements
	const count = html.filter("b").length;
	
	// Apply margins accordingly
	master.margins.header = count == 2 ? "2in" : "4in";
}

Hello @ABS,

Please wrap any blocks of code in between three backtick characters (```) as this will improve the readability and will make your post or reply look clean.

Example:

<p id="twoB">
	<b>user</b><br>
	<b>tel</b>
</p>

Thank you,I had to make a few changes but the solution seems to be working. I do run into one small issue.

This is my control script

var print = merge.template.contexts.PRINT.sections['Standard A4'];
const bCount = loadhtml("C:/Users/HTMLwithBelements.html", 'p# b').length;

if(bCount === 2 || bCount === 0) {

	print.margins.top = "4in"
}
else {
	print.margins.top = "5in"
}

My letters are 2 - 3 pages long. Now every print page start with margin.top = 4in or 5in, but I only want it to take effect on the first page. How can I accomplish this in the control script?

Best regards,
ABS

Hi @ABS,

section.margins.top applies to all pages in the section, but you can override that value with master.margins.header (the largest value wins).

In the sheet configuration for your section you can apply one master page to “Single Sheet” and “First Sheet”, and a different master page to “Middle Sheet” and “Last Sheet”:

In your control script you can then set master.margins.header for only the master page that is assigned to “Single Sheet” and “First Sheet”.