pdfmake icon indicating copy to clipboard operation
pdfmake copied to clipboard

make pageMargins dynamic

Open peetzweg opened this issue 10 years ago • 33 comments

Books are binded and therefore have different page margins for odd and even pages, so that the text on the page appears to be in the middle and not squeezed into the books fold. I searched the documentation/issues and tested it, the pageMargins seem to be static.

peetzweg avatar Jul 31 '15 11:07 peetzweg

Yes, would be very helpful to be dynamic. I'd like to generate a different report footer just for the last page. It would nice to have pageMargins accept a function just like header/footer that has two parameters of currentPage and pageCount.

nthnmldr avatar Apr 27 '16 16:04 nthnmldr

+1

Nor145 avatar Jun 07 '16 10:06 Nor145

+1

oscardz10 avatar Jul 08 '16 21:07 oscardz10

+1

max-yu avatar Jul 27 '16 02:07 max-yu

+1

difnicolas avatar Oct 17 '16 17:10 difnicolas

+1

aba-koepke avatar Mar 03 '17 15:03 aba-koepke

+1

kngchn avatar Dec 06 '17 12:12 kngchn

+1

cbernecker avatar Jan 22 '18 08:01 cbernecker

+1

steffenstolze avatar Mar 01 '18 21:03 steffenstolze

+1

tkbrady avatar Mar 13 '18 21:03 tkbrady

i solve my problem with different header heights changing follow functions in documentContext.js.

function DocumentContext(pageSize, pageMargins) {
	this.pages = [];

	this.pageMargins = pageMargins;

      this.pageMarginsFkt = null;

        if (typeof this.pageMargins === 'function'){
             this.pageMarginsFkt = this.pageMargins; 
        }

        if (this.pageMarginsFkt){
             this.pageMargins = this.pageMarginsFkt(1);
        }
	this.x =this. pageMargins.left;
	this.availableWidth = pageSize.width - this.pageMargins.left - this.pageMargins.right;
	this.availableHeight = 0;
	this.page = -1;

	this.snapshots = [];

	this.endingCell = null;

	this.tracker = new TraversalTracker();

	this.addPage(pageSize);

	this.hasBackground = false;
}
DocumentContext.prototype.initializePage = function () {
	this.y = this.getCurrentPage().pageMargins.top;
	this.availableHeight = this.getCurrentPage().pageSize.height - this.getCurrentPage().pageMargins.top                    - this.getCurrentPage().pageMargins.bottom;
	this.pageSnapshot().availableWidth = this.getCurrentPage().pageSize.width - this.getCurrentPage().pageMargins.left - this.getCurrentPage().pageMargins.right;
};
DocumentContext.prototype.addPage = function (pageSize) {
	var page = {items: [], pageSize: pageSize};
	this.pages.push(page);
	this.page = this.pages.length - 1;

        if (typeof this.pageMargins === 'function'){
             this.pageMarginsFkt = this.pageMargins; 
        }

        if (this.pageMarginsFkt){
             this.pageMargins = this.pagerMarginsFkt(this.pages.length);
        }

        page.pageMargins = Object.assign( {} , this.pageMargins );

	this.initializePage();

	this.tracker.emit('pageAdded');

	return page;
};
DocumentContext.prototype.getCurrentPosition = function () {
	var pageSize = this.getCurrentPage().pageSize;
	var innerHeight = pageSize.height - this.getCurrentPage().pageMargins.top - this.getCurrentPage().pageMargins.bottom;
	var innerWidth = pageSize.width - this.getCurrentPage().pageMargins.left - this.getCurrentPage().pageMargins.right;

	return {
               pageMargins: this.getCurrentPage().pageMargins,
		pageNumber: this.page + 1,
		pageOrientation: pageSize.orientation,
		pageInnerHeight: innerHeight,
		pageInnerWidth: innerWidth,
		left: this.x,
		top: this.y,
		verticalRatio: ((this.y - this.getCurrentPage().pageMargins.top) / innerHeight),
		horizontalRatio: ((this.x - this.getCurrentPage().pageMargins.left) / innerWidth)
	};
};
LayoutBuilder.prototype.addDynamicRepeatable = function (nodeGetter, sizeFunction) {
	
	var pages = this.writer.context().pages;
	
	for (var pageIndex = 0, l = pages.length; pageIndex < l; pageIndex++) {
		this.writer.context().page = pageIndex;

		var node = nodeGetter(pageIndex + 1, l, this.writer.context().pages[pageIndex].pageSize);

		
		
		if (node) {
			var sizes = sizeFunction(this.writer.context().getCurrentPage().pageSize, this.writer.context().getCurrentPage().pageMargins);
			this.writer.beginUnbreakableBlock(sizes.width, sizes.height);
			node = this.docPreprocessor.preprocessDocument(node);
			this.processNode(this.docMeasure.measureDocument(node));
			this.writer.commitUnbreakableBlock(sizes.x, sizes.y);
		}
	}
};

so i can set a function in docDefinition for pageMargins like:

var docDefinition = {
           ......,
           pageMargins : function(cp) {
                  if ( cp === 1 ){
                         return {left:30,top:150, right:30,bottom:60};
                  } else {
                         return {left:30,top:50, right:30,bottom:60};
                  }
           },
          .......
}

I save the pageMargins in the page object whenever a new one is created and if the parameters are needed I get them from the currentPage. I have not found any negative side effects for me and I hope to have listed all my changes (I got them from a printout). Maybe that solves the problem of one or the other. Happy Easter :-)

sorry for my english, isn't my favorit language.

icke792 avatar Apr 01 '18 17:04 icke792

@icke792 Can you create a pull-request for it?

renarsvilnis avatar May 03 '18 10:05 renarsvilnis

This was really useful for me. Please add it to the project. There seems to be a small fix to make it work with dynamic horizontal margins:

DocumentContext.prototype.initializePage = function () {
	this.y = this.getCurrentPage().pageMargins.top;
	this.x = this.getCurrentPage().pageMargins.left;
	this.availableHeight = this.getCurrentPage().pageSize.height - this.getCurrentPage().pageMargins.top                    - this.getCurrentPage().pageMargins.bottom;
	this.availableWidth = this.getCurrentPage().pageSize.width - this.getCurrentPage().pageMargins.left                    - this.getCurrentPage().pageMargins.right;
};

hobbsi avatar May 08 '18 07:05 hobbsi

+1

kunalwatkar avatar May 18 '18 20:05 kunalwatkar

+1

vitalii4reva avatar Feb 18 '19 10:02 vitalii4reva

+1

ricardocorassa avatar Apr 29 '19 15:04 ricardocorassa

This was really useful for me. Please add it to the project. There seems to be a small fix to make it work with dynamic horizontal margins:

DocumentContext.prototype.initializePage = function () {
	this.y = this.getCurrentPage().pageMargins.top;
	this.x = this.getCurrentPage().pageMargins.left;
	this.availableHeight = this.getCurrentPage().pageSize.height - this.getCurrentPage().pageMargins.top                    - this.getCurrentPage().pageMargins.bottom;
	this.availableWidth = this.getCurrentPage().pageSize.width - this.getCurrentPage().pageMargins.left                    - this.getCurrentPage().pageMargins.right;
};

@hobbsi Did you just edit the source, build it and roll your own version?

djasnowski avatar Sep 17 '20 23:09 djasnowski

@hobbsi Did you just edit the source, build it and roll your own version?

I used it while doing some experimentation on a personal project. And yes, that's what did. I believe you could also fork the project and do your modifications... I didn't.

hobbsi avatar Sep 18 '20 08:09 hobbsi

This was really useful for me. Please add it to the project. There seems to be a small fix to make it work with dynamic horizontal margins:

DocumentContext.prototype.initializePage = function () {
	this.y = this.getCurrentPage().pageMargins.top;
	this.x = this.getCurrentPage().pageMargins.left;
	this.availableHeight = this.getCurrentPage().pageSize.height - this.getCurrentPage().pageMargins.top                    - this.getCurrentPage().pageMargins.bottom;
	this.availableWidth = this.getCurrentPage().pageSize.width - this.getCurrentPage().pageMargins.left                    - this.getCurrentPage().pageMargins.right;
};

@hobbsi How would you apply this, once implemented, in the document definition?

hielfx avatar Sep 22 '20 12:09 hielfx

@liborm85 any chance the approach of @icke792 with the fix of @hobbsi gets merged if I would create a PR?

Also, I have the need for a dynamic margin based on a dynamic header (see #2238) which is even a step further than what we have here. Any chance a solution taking dynamic headers into account gets merged in the end?

robstoll avatar Apr 25 '21 15:04 robstoll

A work around can be setting the content margins to negative value (only top margin) and passing an empty string to the header function.

For example:

pageMargins : [30, 140, 30, 30]

Then on the page where you don't need header, after passed the empty string, you can sett:

content.margins: [0, -110, 0, 0 ]

gine avatar Aug 03 '21 13:08 gine

A work around can be setting the content margins to negative value (only top margin) and passing an empty string to the header function.

For example:

pageMargins : [30, 140, 30, 30]

Then on the page where you don't need header, after passed the empty string, you can sett:

content.margins: [0, -110, 0, 0 ]

Will it work for footers?

qasimmehdi avatar Aug 06 '21 17:08 qasimmehdi

If anyone wants to create bigger footer on a specific page you can just put your items in the footer with page condition and give it margin: [0,-100,0,0] decrease the negative value to fit your content. Note: this is just a workaround and if you have more text in your page body using negative margin might make footer and body overlap.

qasimmehdi avatar Aug 06 '21 18:08 qasimmehdi

If you have dynamic content - ie tables that span over multiple pages it can be difficult to determine where each new page header footer dimensions should be used from just the page number

I added the following code to icke792's (thanks) above

function DocumentContext(pageSize, pageMargins) {
    var _this;
    _this = _EventEmitter.call(this) || this;
    _this.pages = [];
    _this.pageMargins = pageMargins;
    _this.pageMarginsFkt = null;
    _this.sections = 1;

    if (typeof _this.pageMargins === "function") {
        _this.pageMarginsFkt = _this.pageMargins;
    }
   if (_this.pageMarginsFkt) {                     
        _this.pageMargins = _this.pageMarginsFkt(1, _this.sections);
    }

    _this.x = _this.pageMargins.left;
    _this.availableWidth = pageSize.width - _this.pageMargins.left - _this.pageMargins.right;
    _this.availableHeight = 0;
    _this.page = -1;
    _this.snapshots = [];
    _this.endingCell = null;
    _this.backgroundLength = [];
    _this.addPage(pageSize);

    return _this;
  }

  //after var _proto = DocumentContext.prototype;
  _proto.addSection = function addSection () {
        this.sections++;
  }

//in addPage

 if (this.pageMarginsFkt) {
              this.pageMargins = this.pageMarginsFkt(this.pages.length, this.sections);
 }

//at the end of function - _proto.processNode = function processNode(node) {

if (node.sectionEnd === true) {
      _this2.writer.context().addSection();
   }

//You can the add .sectionEnd = true; as a property of any section where you want to change the header/footer

{
text: "this is the end",
sectionEnd : true
}

//and when that changes the callback to pageMargins will contain the section count

docDefinition.pageMargins = function (pages, sectionCount) {
         
            if (sectionCount % 2 === 0) {
                return { left: 20, top: 50, right: 20, bottom: 50};
            } else {
                return { left: 20, top: 10, right: 20, bottom: 10 };
            }             
           
        }

tedbakers avatar Dec 01 '21 14:12 tedbakers

Books are binded and therefore have different page margins for odd and even pages, so that the text on the page appears to be in the middle and not squeezed into the books fold. I searched the documentation/issues and tested it, the pageMargins seem to be static.

Books are binded and therefore have different page margins for odd and even pages, so that the text on the page appears to be in the middle and not squeezed into the books fold. I searched the documentation/issues and tested it, the pageMargins seem to be static.

Did you solve the issue?

zhengwei16 avatar Jan 13 '22 10:01 zhengwei16

I solved this issue, contact me if someone need help ........removed....

zhengwei16 avatar Mar 18 '22 15:03 zhengwei16

I'm looking for this as well. We have a report with dynamic headers, and I need to set the page margins according to the header size. Currently, because of the limitation, I have to truncate the header in order for it to fit. But when the header is shorter, there is a gap between it and the content of the page.

I'm not sure how this can be solved since the header needs to know the left and right margins in order to render, but the content needs to know the top margins, depending on the header height, in order to render; it's the chicken and the egg problem.

Edit: this could be solved with the possibility to have a margin value of "auto", which would default to 0 for left and right, to the header height for top, and the footer height for bottom.

yanickrochon avatar Jun 01 '22 12:06 yanickrochon

Has anyone found a solution for this?

albertoLGDev avatar Jun 30 '22 14:06 albertoLGDev

Can I determine It's the last page of the pdf and assign different page margin for it?

carltin0315 avatar Aug 19 '22 07:08 carltin0315

+1

GitNomster avatar Oct 02 '24 07:10 GitNomster