Skip to content

Instantly share code, notes, and snippets.

@bluntelk
Created May 14, 2013 02:01
Show Gist options
  • Save bluntelk/5573089 to your computer and use it in GitHub Desktop.
Save bluntelk/5573089 to your computer and use it in GitHub Desktop.
based on https://gist.github.com/niflostancu/3683510 by Florin Stancu This is a reworked table split hack. I had problems with the original with the tables not being populated evenly (I would sometimes have empty tables with headers only, or a table with only a few rows) This version has support for tfoot tags. Your table should be laid out with…
/**
* WkHtmlToPdf table splitting hack.
*
* Script to automatically split multiple-pages-spanning HTML tables for PDF
* generation using webkit.
*
* To use, you must adjust pdfPage object's contents to reflect your PDF's
* page format.
* The tables you want to be automatically splitted when the page ends must
* have a class name of "splitForPrint" (can be changed).
* Also, it might be a good idea to update the splitThreshold value if you have
* large table rows.
*
* Dependencies: jQuery.
*
* WARNING: WorksForMe(tm)!
* If it doesn't work, first check for javascript errors using a webkit browser.
*
* @author Jason Playne <[email protected]>
* @version 1.1
*
* @author Florin Stancu <[email protected]>
* @version 1.0
*
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
/**
* PDF page settings.
* Must have the correct values for the script to work.
* All numbers must be in inches (as floats)!
* Use google to convert margins from mm to in ;)
*
* @type {Object}
*/
var pdfPage = {
width: 8.26, // inches
height: 11.69, // inches
margins: {
top: 0.393701, left: 0.393701,
right: 0.393701, bottom: 0.393701
}
};
/**
* The distance to bottom of which if the element is closer, it should moved on
* the next page. Should be at least the element (TR)'s height.
*
* @type {Number}
*/
var splitThreshold = 60;
/**
* Class name of the tables to automatically split.
* Should not contain any CSS definitions because it is automatically removed
* after the split.
*
* @type {String}
*/
var splitClassName = 'splitForPrint';
/**
* Window load event handler.
* We use this instead of DOM ready because webkit doesn't load the images yet.
*/
$(window).load(function () {
// get document resolution
var dpi = $('<div id="dpi"></div>')
.css({
height: '1in', width: '1in',
top: '-100%', left: '-100%',
position: 'absolute'
})
.appendTo('body')
.height();
// page height in pixels
var pageHeight = Math.ceil(
(pdfPage.height - pdfPage.margins.top - pdfPage.margins.bottom) * dpi);
// temporary set body's width and padding to match pdf's size
var $body = $('body');
$body.css('width', (pdfPage.width - pdfPage.margins.left - pdfPage.margins.right) + 'in');
$body.css('padding-left', pdfPage.margins.left + 'in');
$body.css('padding-right', pdfPage.margins.right + 'in');
//////
$('table.' + splitClassName).each(function () {
var $origin_table = $(this);
var $template = $origin_table.clone()
$template.find('> tbody > tr').remove();
$template.find('> tfoot > tr').remove();
var current_table = 0
var split_tables = Array()
split_tables.push($template.clone())
insertIntoDom($origin_table, split_tables[current_table])
$origin_table.find('> tbody tr').each(function () {
var $tr = $(this);
$tr.detach().appendTo(split_tables[current_table].find('> tbody'));
if ($(split_tables[current_table]).height() > (pageHeight - splitThreshold)) {
current_table++
split_tables.push($template.clone())
insertIntoDom($origin_table, split_tables[current_table])
}
});
//table footer
var $tfoot = $origin_table.find('> tfoot')
var last_table_height = $(split_tables[current_table]).height()
if (last_table_height + $tfoot.height() > (pageHeight - splitThreshold)) {
current_table++
split_tables.push($template.clone())
insertIntoDom($origin_table, split_tables[current_table])
alert('made new table for footer')
}
$tfoot.detach().appendTo($(split_tables[current_table]))
$origin_table.remove()
$('div.page-breaker').last().remove()
});
function insertIntoDom(after, what) {
var $br = $('<div class="page-breaker" style="height: 10px;"></div>').css('page-break-before', 'always');
$(what).appendTo($(after).parent());
$br.insertAfter(what);
}
// restore body's padding
$body.css('padding-left', 0);
$body.css('padding-right', 0);
});
@AAverin
Copy link

AAverin commented May 29, 2013

Here is another implementation from me, check it out!
https://github.com/AAverin/JSUtils/tree/master/wkhtmltopdfTableSplitHack

@vstefanoxx
Copy link

I did a similar script that does vertical splitting on wide tables instead of horizontal splitting.
I wrote it starting from the idea of Florin Stancu & forks.

I didn't find any satisfying solution for it on the web, so maybe you can find it helpful:
https://github.com/vstefanoxx/JSUtils/tree/master/TableVerticalSplitHack

Here is a working example:
http://jsfiddle.net/mU2Ne/

@lwen3
Copy link

lwen3 commented Jul 20, 2022

I did a similar script that does vertical splitting on wide tables instead of horizontal splitting. I wrote it starting from the idea of Florin Stancu & forks.

I didn't find any satisfying solution for it on the web, so maybe you can find it helpful: https://github.com/vstefanoxx/JSUtils/tree/master/TableVerticalSplitHack

Here is a working example: http://jsfiddle.net/mU2Ne/

This is perfect!
Worked like a charm! Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment