I’m trying to adapt this code to my softr site, the idea being to have a button that allows you to start printing a PDF file stored in airtable, without having to preview it
I saw on the net that print histories cause a lot of trouble for browsers, but I found this site with the following code (demo available here)
<html>
<head>
<title>Print PDF using Dynamic iFrame</title>
</head>
<body>
<input type="button" id="bt"
onclick="print('../sample.pdf')"
value="Print PDF" />
</body>
<script>
let print = (doc) => {
let objFra = document.createElement('iframe'); // Create an IFrame.
objFra.style.visibility = 'hidden'; // Hide the frame.
objFra.src = doc; // Set source.
document.body.appendChild(objFra); // Add the frame to the web page.
objFra.contentWindow.focus(); // Set focus.
objFra.contentWindow.print(); // Print it.
}
// Using regular js features.
// function print(doc) {
// var objFra = document.createElement('iframe');
// objFra.style.visibility = 'hidden';
// objFra.src = doc;
// document.body.appendChild(objFra);
// objFra.contentWindow.focus();
// objFra.contentWindow.print();
// }
</script>
</html>
I’m trying to adapt a windows.records method, considering the name of the field in airtable is the.url.field I made this code
<html>
<head>
<title>Print PDF using Dynamic iFrame</title>
</head>
<body>
<input type="button" id="bt"
onclick="print(url)" //EDIT
value="Print PDF" />
</body>
<script>
var url = window.records.<record id>.record.fields.URL.<gdocs.last.version>; //EDIT
let print = (url) => {
let xhr = new XMLHttpRequest(); //EDIT
xhr.open('GET', url, true); //EDIT
xhr.responseType = 'blob'; //EDIT
xhr.onload = (e) => { //EDIT
if (xhr.status === 200) { //EDIT
// Récupération du contenu du fichier PDF dans la réponse
let file = xhr.response; //EDIT
let objFra = document.createElement('iframe');
objFra.style.visibility = 'hidden';
objFra.src = URL.createObjectURL(file);
document.body.appendChild(objFra);
objFra.contentWindow.focus();
objFra.contentWindow.print();
}
};
xhr.send(); //EDIT
}
// Using regular js features.
// function print(doc) {
// var objFra = document.createElement('iframe');
// objFra.style.visibility = 'hidden';
// objFra.src = doc;
// document.body.appendChild(objFra);
// objFra.contentWindow.focus();
// objFra.contentWindow.print();
// }
</script>
</html>
I annotated with //EDIT my edits, I’m a noob so I’m stuck and don’t know how to debug, anyone have an idea? Soon the end of my galleys
Yep i’m sure, I tried with a display function of the URL and it is the good one @dcoletta my code is probably wrong, the XMLHttpRequest() is my idea, not the idea of the original author…
Then in that case the likely error you are hitting is a cross-origin permissions issue, unless your URL is the same origin* as the one that served the page.
Do you see errors in the browser console?
*“origin” is a fancy term for the domain and port number. So if your app is at https://mygreatapp.softr.app, then the origin would be mygreatapp.softr.app:443.
The “url” that is display with my display()function is this one and looks normal as an URL from airtable. To be sure I also tried with a pdf stored in a classic CDN in another website and it’s same error 404
OK - I’m just saying that the reason you’re getting a 404 error is because the URL that the XHR request is actually hitting ends with the string undefined, which is usually the result of converting a variable with value null to a string.
Concerning the “undefined” error @dcoletta that I had with the functions using the URL of the attached airtable file, I solved the problem by integrating the variables defining the URL in the beginning of each function. Moreover, my record ID is retrieved in the first line of my script according to the well-known formula
// script for my URL
function myFunction ()
{
var string = window.records[recordId].record.fields['NameFieldAiartable'];
var urlPDF = string.match(/\(([^)]+)\)/)[1];
}
However my concern is not solved, I believe that the problem lies mainly in the fact that the javascript functions are not authorized to interact with an iframe whose content does not come from the same URL, I found this in several post stackoverflow and here is a quote from popular javascript library Print.js
PDF files must be served from the same domain as your app is hosted under. Print.js uses iframe to load files before printing them, therefore, it is limited by the Same Origin Policy. This helps preventing Cross-site scripting (XSS) attacks.
So maybe someone can help me solve this problem. How to store my pdf coming from airtable under the same URL as my softr site? I’m good at nocode, and less at CDN deployment haha. Any no code idea here?
@lea agree with @dcoletta if all you need is printing I’m sure there are ways, however we need to see the page and play with it. I will go over my DMs to see if there is anything.
Thank you for your answers, I was working on it, here is a demo page which exactly replicates the functioning of my original website, I can add you as collaborators if necessary but I this the console is what you want to see it more precisely.
Here is a little description of the view :
Name of the record
Classic softr filefield to display pdf
Button to check the URL parameter’s script is working, just displaying URL of the pdf
Button to change the src parameter and display the iframe
Button to check recordid’s script is working
Not interesting
The button that launches the script to print the PDF
Hey @artur
I tried (after updating the Airtable URL in your code, as it had expired due to their recent update)
I created 2 new buttons and 2 new functions, described in the following code. For both functions I get the same error
<body>
<input type="button" id="printJS" onclick="printJS()" value="PrintJS (from artur)" />
<input type="button" id="printJS2" onclick="printJSurl()" value="PrintJS (from artur, with url from airtable)" />
</body>
<script>
function printJS() {
printJS('https://v5.airtableusercontent.com/v1/14/14/1673186400000/7MaqgJ_GgbIsLhstQtNdjg/8MuPo8ehU2QydUf0JNyMoJkW0yqvKPSF9sfSM7IjKiJtPPJfTWva-mdDGYhAEzxova-CzJIhli3iiHcztQi0WZctf5HiXhRfmDMxrf9B9o0/INN-qwIAlaL5Jit1dtHJP0xLD10KAXjvCLisNVWN2RI');
}
function printJSurl() {
var string = window.records[recordId].record.fields['pdf'];
var urlPDF = string.match(/\(([^)]+)\)/)[1];
printJS('urlPDF')
}
<script>
Here is the error : maximum call stack size exceeded. So The printJS function calls itself endlessly, resulting in a stack call size overflow error. But I don’t know if that’s the problem that much, because the callback function isn’t mandatory, the documentation says you can omit it if you don’t want to perform any additional actions once the print completed. Anyway, the print does not start
@artur A good start, it works and confirms that you are right about my hypothesis (XSS) attacks I was talking about here
Unfortunately, as we can see on the GIF, the button that injects the urlPDF variable (calculated from window.records) into the printJS print function does not work, we see 404 errors appear with urlPDF which is found in text in the site url. I think I’m injecting the variable wrong
function printcrablyurl() {
var string = window.records[recordId].record.fields['pdf'];
var urlPDF = string.match(/\(([^)]+)\)/)[1];
printJS('urlPDF');
}