Forum Discussion
Creating downloadable pdf files in Storyline - an update on earlier methods
I am late to the party, but REALLY want to pull this off. I am working on a Roles and Actions course that will culminate in a "Now go do it!" kind of sheet. I would love for them to be able to download it. I worked the JS into what I needed(Story attached). I have the document(attached as well). I think all of it looks good. I am publishing to a LMS from Storyline and telling it to create a Zip file. I have put my document ALL OVER the zip file to try to make sure it found the document. When I preview it or load it into the LMS and go through it, when I click the button nothing happens.
Now, interesting fact, I loaded your notes demo in the LMS and in preview from Storyline and nothing happens with it either. SO, I am think my code my be good, but it is not finding a file.
I have also changed the URL for the document to our SharePoint site and that does nothing too.
Help me Obi-Won Kenobi!
PS: I added triggers to fill out what you can see on the screen and then I got smart with the things your can't but are on the PDF and added it to the variable default. :)
- MichaelGallaghe7 months agoCommunity Member
Hi HunterBlake,
There were a few things wrong in your course.
In the Javascript code in the StoryLine course you tell the code that the pdf document is named "Roles_Goals.pdf" but the PDF document you created is named Goals_Actions.pdf. To fix, rename the PDF document "Roles_Goals.pdf"
Next, in the Javascript code in StoryLine you have the following code:
Body = player.GetVar("Body");
Mind = player.GetVar("Mind");
Spirit = player.GetVar("Spirit");
Heart = player.GetVar("Heart");but you named the variables in StoryLine Self_Care_Body,Self_Care_Mind, Self_Care_Spirit, and Self_Care_Heart
The fix here is to rename the variables in StoryLine to Body, Mind, Spirit, and Heart.
Cheers!
Mike G
- ToddVillari7 months agoCommunity Member
There was a Chrome security update that stopped this from working at my company. That could by why loading the demo to your LMS doesn't work either.
- Nedim7 months agoCommunity Member
Replace the following part of the code with the one below. Ensure that const formUrl = ''; exactly matches the name of the PDF file located in the root folder.
var player = GetPlayer(); Role1 = player.GetVar("Role1") ?? ""; Role2 = player.GetVar("Role2") ?? ""; Role3 = player.GetVar("Role3") ?? ""; Role4 = player.GetVar("Role4") ?? ""; Role5 = player.GetVar("Role5") ?? ""; Role6 = player.GetVar("Role6") ?? ""; Role7 = player.GetVar("Role7") ?? ""; Role8 = player.GetVar("Role8") ?? ""; RolePicked1 = player.GetVar("RolePicked1") ?? ""; RolePicked2 = player.GetVar("RolePicked2") ?? ""; RolePicked3 = player.GetVar("RolePicked3") ?? ""; Action1 = player.GetVar("Action1") ?? ""; Action2 = player.GetVar("Action2") ?? ""; Action3 = player.GetVar("Action3") ?? ""; Body = player.GetVar("Body") ?? ""; Mind = player.GetVar("Mind") ?? ""; Spirit = player.GetVar("Spirit") ?? ""; Heart = player.GetVar("Heart") ?? ""; Time1 = player.GetVar("Time1") ?? ""; Time2 = player.GetVar("Time2") ?? ""; Time3 = player.GetVar("Time3") ?? "";
- HunterBlake7 months agoCommunity Member
What does this part
?? ""
do?
- Nedim7 months agoCommunity Member
I'm pretty sure you were initially getting this error during testing. At least, that's what I saw in my console when I first tested your project.
This error shows the sequence of function calls leading to the issue. The setText() function in PDFTextField.js fails because it expects a string but receives null. This suggests that the Storyline variable may not have been initialized yet, causing player.GetVar() to return null when the script tries to retrieve it.
To prevent this, the ?? "" (Nullish Coalescing Operator) ensures that if player.GetVar() returns null, it defaults to an empty string ("") instead of breaking the setText() function. Once the actual Storyline variable values become available, they will automatically replace the empty string.
In short, this approach prevents errors when calling setText(), ensuring that the code remains functional even if a Storyline variable hasn’t been initialized yet.
- HunterBlake7 months agoCommunity Member
Thank you all for your help. With these changes, I got it to work. You guys ROCK!
- MichaelT12 months agoCommunity Member
Hi Hunter,
I got my version of this working with the PDF form included in the zip file. But I intend to embed these Storyline "forms" in some Rise courses instead of publishing the standalone Storyline projects, in which case I think the PDF document would need to be hosted externally instead of included in the zip file. Do you know what the URL would look like in the JavaScript if pointing at the file hosted on SharePoint?
Thanks!
- JohnCooper-be3c2 months agoCommunity Member
Hi MichaelT1 I tend to just include the pdf as an attachment at the end of the RISE course:
What you need to do then is open the pdf, note down the url assigned by RISE and then amend the JavaScript to point to this file in the download script.
If you don't like the attachment file sitting in the course, there's another sneaky trick you can use - although Articulate may not be so thrilled about this method - you can add the attachment block in a completely different RISE course. Yes, it really works! For demonstrations I put all my templates as attachment blocks in a course I title "Stuff I need in other courses" then I note the url of the file I want and use the template in any course I like.
(But don't tell anyone about this method as it seems like a cheap way to store files on an on-line server...) 😀
- MichaelT12 months agoCommunity Member
JohnCooper-be3c I tried this and it works, thank you!
Is there a reason to do it this way as opposed to hosting the PDFs in something like SharePoint, though? Ideally I'd point at our usual method for file hosting.
- Nedim2 months agoCommunity Member
Files hosted on SharePoint are typically not served with the correct MIME types or headers needed for direct binary access. Instead, SharePoint often wraps files in a web-based viewer or forces a download experience through a redirect. Direct binary access means that your JavaScript (or browser) can fetch and process a file as raw binary data, not as an HTML-rendered preview or download link, but as a stream of bytes. For example, when you use:
const formPdfBytes = await fetch(formUrl).then(res => res.arrayBuffer()); ...you’re telling the browser to retrieve the raw PDF file so it can be manipulated (e.g., filled with pdf-lib). However, SharePoint typically prevents this by not allowing the browser to access the file as a pure binary stream. This is why SharePoint-hosted PDFs don’t work with libraries like pdf-lib. It’s not a hosting platform in the traditional sense.I'd upload the PDF file to the Resources section and update the code to:
const formUrl = 'story_content/external_files/notes.pdf';
If this slide is run inside Rise as a Storyline block, it should work without any issues.
Related Content
- 7 months ago
- 2 months ago