Need Javascript Help with Printing a Page (fixed height/width)

Aug 10, 2020

Hi there. I need to print a page in a SL 360 course (not a certificate). I found some javascript which has worked great, but there is one issue. The formatting/size of the printed page differs depending on the browser size. When the browser size is smaller (1366x768) it fits on the page perfectly and looks great. When the browser is bigger (I have a 4k monitor) only half of the page is in the printable view. 

I know you can change the scale of what is printed and I have played with that, but that doesn't seem to help when the browser is full screen on a larger monitor. I need a way to fix the height/width of the printable view or something similar. Is this possible?

Any help would be greatly appreciated. Here is the javascript I am using:

var styles = `@media print {
body, * { visibility: hidden; }
html, body { overflow: hidden; transform: translateZ(0); }
#slide {
transform: scale(1.0) !important;
}
#wrapper {
transform: scale(1.0) !important;
}
#slide,
#wrapper {
width: 100% !important;
height: 100% !important;
overflow: visible !important;
}
#frame {
overflow: visible !important;
}
.slide-transition-container {
overflow: visible !important;
}
@page {size: A4 landscape;max-height:99%; max-width:99%}
.slide-container, .slide-container * {
visibility: visible !important;
margin-top: 0px !important;
margin-left: 0px !important;
}
#outline-panel {
display: none !important;
}
}
}`
var stylesheet = document.createElement('style');
stylesheet.type = 'text/css';
stylesheet.innerText = styles;
document.head.appendChild(stylesheet);
window.print();

23 Replies
Dave Cox

Hi Lisa,

If you page consists of just text, I think just window.print(); would work just find, and should adjust to a normal size sheet of paper.

But to use your code, this should do the trick.

var sWidth = screen.width;
console.log("sWidth "+sWidth);
var ComputedStyle = getComputedStyle(document.body);
console.log("CS "+ComputedStyle);
var divW = ComputedStyle.width;
var w = divW.replace(/[^0-9]/g,'');
var wN = Number(w);
console.log("Width "+wN);
if (w > 1000) {
var styles = `@media print {
body, * { visibility: hidden; }
html, body { overflow: hidden; transform: translateZ(0); }
#slide {
transform: scale(0.75) !important;
}
#wrapper {
transform: scale(0.75) !important;
}
#slide,
#wrapper {
width: 100% !important;
height: 100% !important;
overflow: visible !important;
}
#frame {
overflow: visible !important;
}
.slide-transition-container {
overflow: visible !important;
}
@page {size: A4 landscape;max-height:99%; max-width:99%}
.slide-container, .slide-container * {
visibility: visible !important;
margin-top: 0px !important;
margin-left: 0px !important;
}
#outline-panel {
display: none !important;
}
}
}`
var stylesheet = document.createElement('style');
stylesheet.type = 'text/css';
stylesheet.innerText = styles;
document.head.appendChild(stylesheet);
} else {
var styles = `@media print {
body, * { visibility: hidden; }
html, body { overflow: hidden; transform: translateZ(0); }
#slide {
transform: scale(1.0) !important;
}
#wrapper {
transform: scale(1.0) !important;
}
#slide,
#wrapper {
width: 100% !important;
height: 100% !important;
overflow: visible !important;
}
#frame {
overflow: visible !important;
}
.slide-transition-container {
overflow: visible !important;
}
@page {size: A4 landscape;max-height:99%; max-width:99%}
.slide-container, .slide-container * {
visibility: visible !important;
margin-top: 0px !important;
margin-left: 0px !important;
}
#outline-panel {
display: none !important;
}
}
}`
var stylesheet = document.createElement('style');
stylesheet.type = 'text/css';
stylesheet.innerText = styles;
document.head.appendChild(stylesheet);
}

window.print();

 

Dave

Lisa Ogan

Thank you for looking at this! However, it's still not acting as I had hoped. It's not full screen even in a large browser, probably due to the .75 scale and in a smaller browser it's only 30% of the page. I should have attached the SL slides. Here they are. 

You can see that there is an activity on the previous slide that captures test in a variable then shows it on the next slide. The second slide is the one I'm trying to print. I have the print function/JS occurring on a layer so the instructions and button aren't included. 

Thanks!

Dave Cox

Hi Lisa,

The problem with making this work correctly, is I can't get the div size from the correct location in the project. This is because Storyline doesn't assign an ID to that div. 

Looking at your story, I think a better solution would be for you to print your values to a pre-prepared html file, that you populate with your variable values This has been done many times before as people print out certificates. I've done it before, and it worked fine but it has been a long time ago, and the method will need to be updated for HTML5. I can probably work it out for you, but I'll need to attack it at a later time.

Dave Cox

Sorry I haven't been able to get back to this for you Lisa,

What I would do would be create a WebObject to handle the printing. That's basically an HTML web page that you pass the values to, and it can print without the restrictions that you have when printing from Storyline. The WebOject then allows you to import it into Storyline so it becomes part of the project. I had planned to build a starter page for you, but I just ran out of time. I completely apologize.

Dave

Dave Cox

Hi Lisa,

I'm sorry that it took me so long to get to this, but I have a solution for you.

I've added a webobject to a layer on slide 2 for you. When that slide is selected, the variables are loaded into the webobject on that layer, and then sent to the printer. (I set some default values in the variables so I wouldn't have to keep typing them.)

The styling in the webobject are set to style the print output to fit onto a standard page. It won't matter what size the window is in the browser.

I'm also including the webobject for you to reference. You can modify this to fit your needs, and re-import it into the project. You will need to unzip the webobject into its own folder to update it.

The layout of the page is in the index.htm file.

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PrintDoc</title>
<script src="js/script.js"></script>
<link rel="stylesheet" href="./css/style.css"/>
</head>

<body onLoad="init();">

<h2>Compassion</h2>
<ol>
<li id="CompassionText1"></li>
<li id="CompassionText2"></li>
<li id="CompassionText3"></li>
</ol>
<h2>Trust</h2>
<ol>
<li id="TrustText1"></li>
<li id="TrustText2"></li>
<li id="TrustText3"></li>
</ol>
<h2>Success</h2>
<ol>
<li id="SuccessText1"></li>
<li id="SuccessText2"></li>
<li id="SuccessText3"></li>
</ol>

<hr />
<h3>I commit to taking thise steps to help our customers move forward every day:</h3>
<ol>
<li id="Text1"></li>
<li id="Text2"></li>
<li id="Text3"></li>
</ol>

</body>
</html>

The Storyline variables are loaded into the page for printing by the javascript located in the script.js file in the js folder.

// JavaScript Document


function init() {

GetFromSL();
}

function GetFromSL() {
var player = parent.GetPlayer();
var CompassionText1 = player.GetVar("CompassionText1");
var CompassionText2 = player.GetVar("CompassionText2");
var CompassionText3 = player.GetVar("CompassionText3");
var TrustText1 = player.GetVar("TrustText1");
var TrustText2 = player.GetVar("TrustText2");
var TrustText3 = player.GetVar("TrustText3");
var SuccessText1 = player.GetVar("SuccessText1");
var SuccessText2 = player.GetVar("SuccessText2");
var SuccessText3 = player.GetVar("SuccessText3");
document.getElementById("CompassionText1").innerHTML = CompassionText1; // get the value from Storyline variable and set it in HTML
document.getElementById("CompassionText2").innerHTML = CompassionText2;
document.getElementById("CompassionText3").innerHTML = CompassionText3;
document.getElementById("TrustText1").innerHTML = TrustText1;
document.getElementById("TrustText2").innerHTML = TrustText2;
document.getElementById("TrustText3").innerHTML = TrustText3;
document.getElementById("SuccessText1").innerHTML = SuccessText1;
document.getElementById("SuccessText2").innerHTML = SuccessText2;
document.getElementById("SuccessText3").innerHTML = SuccessText3;
window.print();
}

 The styling is handled by the css in the style.css file, located in the css folder.

@charset "utf-8";
/* CSS Document */

@media print {

@page {
size: A4;
margin: 1in;
}


p {
font-size: 12pt;
}


}

I hope the accomplishes what you need in your project. You should be able to add whatever additional fields that you need by following what I've already started for you.

Here is an example of the printed output.

You will want to publish this to your LMS, or a server for this to work. You won't be able to see the results when previewing, or running it locally on your PC.

Dave

 

Dave Cox

Hello Julio,

When you just attempt to use the print command, you are restricted to what windows can print based on the current window setup. That is why you are seeing the result that you see. The page laid out for on-screen display, not for printing. The code that I listed above is designed for printing.

Julio P

Hi Dave. Thanks for taking the time to review my question.

I think your solution is a bit too complex for me to understand. Perhaps with a bit of an explanation on the following points I may be able to replicate it.

Brief explanation of my goal: I’m hoping to create a floorplan map of our library. When users select pertinent accessibility features, it is highlighted on the floor plan. I’d like to provide users with the ability to download a copy of the floorplan (along with the highlighted accessibility features). I’ve added a skeletal working draft in case it helps clarify.

Deciphering your solution:

You’ve created a layer that is hosting a webobject. In your scenario the webobject is importing text via variables (Compassiontext1, 2, 3, Trusttext1, 2, 3, etc), stylization via a CSS file and then it’s sent to the printer.

You mentioned that the layout of the page is located in the index.htm file. Is this the same as the Story.html file that is generated by storyline? Would I need to replicate this as I am not generating a layout, but hoping to push the graphics that are on a slide to print?

You mentioned that the storyline variables are loaded into the page for printing by the javascript located in the script.js file in the js folder. Can I omit this step as I will not be bringing in variables but rather I’m looking to replicate the slide, as is?

You mentioned that Styling is handled by the CSS file located in the css folder (in my CSS folder I find a file named output.min.css). Would I be along the correct path to assume that it’s here where I should be making my modifications? Perhaps by adding the following code?

@media print {
 
 @page {
 size: A4;
 margin: 1in;
 }

Dave Cox

Hi Julio,

To work correctly, Storyline slides use a lot of features that can be incompatible with the browsers built in screen print engine. That is why just doing a screen print of the slide typically is very small, and doesn't always display everything. To get a good print, you need a page built specifically for the browser's print capabilities. That is why I used a webobject to hold the printed page. 

A Webobject is a complete webpage. It includes the index.html file, and any other supporting files, including the CSS file and the javascript that I mentioned. These files are not the same files that are included with Storyline. This article explains a bit about web objects. When you import a local webobject, these files are imported as part of the webobject.

You would not need to include the javascript code for your project, since you don't need to set any values presented on your page. You would need the index.html page, with a copy of your image that you want to print, and you would need to include the css code, either on the index.html page or as a linked file.

Give me a few minutes, and I will mock something up for you that you might be able to use.

Dave

Dave Cox

Hi Julio,

I've mocked up your project for you.

I added a layer to handle the print function to print your map. The new layer contains the webobject required to print the map When you click the button to show the layer, the layer displays. When the webobject shows, it immediately wants to print the image and opens a print dialoge to choose a printer. I've included a PDF output of the printed output. I've also included the index.html file that I created for this project. I included the javascript and CSS needed in the html file:

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>PrintDoc</title>
<style>
@media print {
@page {
size: A4;
margin: 1in;

}
}
img {width: 7in;}
</style>
<script>
function init(){
window.print();
}
</script>
</head>

<body onload="init();">
<img src="FloorPlan.png" />
</body>
</html>

I hope this helps your with your project.

Dave

Julio P

Hi Dave. Unfortunately I can't seem to access our conversation on E-Learning Heroes as the page is not loading (I'm replying to your post via email). I've already notified support. As soon as I'm able to access the post, I'll review your reply. Regardless, thank you for taking the time to assist.

Kasa Wahl-Losee

Hi Dave! My turn! lol.  I am trying to implement this.  I did it a long time ago but now I don't remember exactly how to execute it.   I can't add the course here due to restrictions, but my questions are where do I put the CSS and javascript (I see in the html file but where in there?) and then do I need to create another page and include it in the file package? 

Dave Cox

Hi Kasa,

There are three files in the example above. The .html file, a script.js file and a style.css file. The javascript goes in the script.js file, and the css code goes in the style.css file. Put all three of those file in a folder of their own, then import the folder into your project as a webobject. You should be able to download the completed project from above to see how I did it.

Dave

Kasa Wahl-Losee

Hi Dave, my apologies if this posts twice.  I thought this posted and then I didn't see anything appear in the comments.  So I got this all implemented except that the text associated with the variable is not carrying over to the webobject.  The set up is this. 

Total pages in course 39

First entry - page 5

Second entry - pg 28

Print page - page 35 

So I am carrying over the variables using the %variablename% to the print page.  I've update the index.html page to show: 

 

<h2>GOOD_Personal_Experience_in_the_Candidate_Process</h2>

<ol> <li id="GoodTextEntry"></li>

</ol>


<h2>Bad_Personal_Experience_in_the_Candidate_Process</h2>
<ol>
<li id="%BadTextEntry1%"></li>
</ol>

<h2>Reflecting_on_the_5_Questions </h2>

<ol>

<p>What is compelling about working here?<p>
<p>How would you describe what you do? <p>
<p>What is most exciting about your role here?<p>
<p>What is most challenging about working here?<p>
<p>What are Regeneron's values that resonate most with you?<p>

</ol>


<h3>Answers</h3>
<ol>
<li id="textentry"></li>
</ol>

 

I'm not sure why the variable text isn't carrying over.  Ideas?

Dave Cox

Hi Kasa,

You can't use the %variable% to print the variable on the HTML page. You have to pass then variable to a new variable on the page using var player = parent.GetPlayer(); and var SLvariablename = player.GetVar("variablename");

then you can print put the contents of your variable into your list element by using:

<script>
document.getElementById("GoodTextEntry").innerHTML = SLvariablename
<script>

Dave