I've been working on creating a print/PDF-friendly template for articles on a WordPress site by customizing the Tufte CSS template.
However, I'm facing an issue where the print preview render (and subsequent printing/saving as PDF) is extremely slow on Chrome and browsers with Chromium cores like Edge. Interestingly, this problem doesn't occur on Firefox and Safari. You can test it yourself on this link using Chrome/Edge/(Chromium based browser), Safari, and Firefox.
I suspected that perhaps the large text was causing an increase in the number of pages or maybe the JavaScript functions were to blame. However, testing these theories hasn't made any difference to how Chrome behaves. Interestingly, when loading the page in Chrome's "Emulate CSS print mode," there doesn't seem to be any delay until the actual printing process.
The mystery lies in not knowing what exactly Chrome is doing during the rendering process, which has been frustrating me.
There are a couple of JavaScript functions that execute upon page load to make the content more print-friendly for the A4 format. These functions mainly deal with handling interactive iFrames embedded within the post to ensure they are print-ready.
To address this, check if any iFrames have been replaced with static images for printing purposes. If so, substitute them back with their original iFrames. Otherwise, tag and resize each iFrame to fit within the printable area:
var iframe_exists = false;
if ($('iframe').length > 0) {
iframe_exists = true;
}
$("iframe").each(function(index){
if(typeof $("p.print-sub-img")[index] !== 'undefined'){
$(this).replaceWith($("p.print-sub-img")[index]);
}
else {
newDiv = $('<div>').append($(this).clone());
let adjusted_dims = null;
adjusted_dims = adjustFrame($(this).width(), $(this).height());
newDiv = $('<div>').append($(this).clone().removeAttr('style').attr({'style': 'width: '+adjusted_dims[0]+'px; height: '+adjusted_dims[1]+'px;'})).attr({'class': 'print-frame', 'align': 'center', 'id': 'iframe-'+index});
$(this).unwrap().replaceWith(newDiv);
}
});
Ensure that the substitution of static images for iFrames has been successfully completed:
// script from https://www.seancdavis.com/posts/wait-until-all-images-loaded/ - thanks sean!
// Images loaded is zero because we're going to process a new set of images.
var imagesLoaded = 0;
// Total images is still the total number of <img> elements on the page.
var totalImages = $("img").length;
// Step through each image in the DOM, clone it, attach an onload event
// listener, then set its source to the source of the original image. When
// that new image has loaded, fire the imageLoaded() callback.
$("img").each(function (idx, img) {
console.log('img load check', img)
$("<img>").on("load", imageLoaded).attr("src", $(img).attr("src"));
});
// Increment the loaded count for each loaded image, and trigger allImagesLoaded() when all are done loading.
function imageLoaded() {
imagesLoaded++;
if (imagesLoaded == totalImages) {
allImagesLoaded();
}
}
Generate a QR code linking to the web version of the article, and initiate the print command:
function allImagesLoaded() {
console.log('generating qr....')
if (iframe_exists == true){
var qrcode = new QRCode($("#qr-code")[0], {
text: "<?php echo get_site_url().'/'.$post_slug ?>",
width: 128,
height: 128,
correctLevel : QRCode.CorrectLevel.H
});
$('#qr-banner').show();
}
window.print();
console.log("print triggered")
}
});