A modest attempt at simulating a page printing script using plain JavaScript

This is a small bit of nano-project that I did recently just for fun! The whole project took no more than 5 minutes to code up, and another 10 minutes to test out (you’ll understand why when you see the code!)

The idea came about when I used to be on Quora. I had decided to quit Quora due to the fast falling quality of the site, and the clearly biased moderation in place there, especially with regards to American politics. Anyway, the details are not important.

It so happened that I had accumulated quite a few bookmarked answers and questions during my time there. I decided to download them locally (preferably in PDF format) to my local machine. Since Quora doesn’t offer any such facility, I decided to search for it online. Five minutes of Googling led to to a nice Chrome extension.

It worked well enough for my needs, but it got me thinking. How the tool operated (from a user’s perspective) was so:

  • Log on to Quora
  • Click on the timestamp on an answer
  • A “Download” link appears below the answer in a new page
  • Upon clicking this link, the Chrome print dialog pops out, allowing saving the page in PDF

Pretty nifty, isn’t it? After a couple of minutes of thought, I realised that the task wasn’t really that complicated for two reasons:

  1. This was a Chrome extension, and chrome has supported “Print to PDF” for quite some time now, and
  2. The extension required the user to explicitly click on the timestamp of an answer. It did not seem to work for questions as a whole

My reasoning went like this: simulating the script on a local system, or on a website that I own is quite easy. I can simply add event listeners to specific buttons and links, and invoke window.print() to open the Chrome print dialog.

However, modifying a third-party site wouldn’t be that easy. Since the user has to click on the timestamp of an answer to generate the “Download” link, clearly the script is trying to get some spam or div DOM node that he can append his link object to. However, there can be many such nodes with dynamically generated IDs.

This implies that Chrome’s extensions tools/APIs must provide functionality to checks for click events, and get then get a handle to the specific node currently activated. This then makes it trivial to append the node, add an event listener, and simply trigger window.print()!

Following this logic, I created a simple demo on my local system that uses a minimal static page with a button. On clicking this button, a download link appears, and then when this hyperlink it clicked, it pops out the Chrome print dialog!

Let’s see it in action!

Demo

Simply save the code into a a file with an html extension.

Now fire it up in Chrome (it works on Safari as well, haven’t tested it on other browsers, but should work on most modern browsers that at least support addEventListener).

img2

Click on the button.

img2

Nice! Try out the “Download” hyperlink.

img3

Excellent! Not only does the print dialog pop up, the “Download” link has now disappeared.

The Code

The code is absolutely dead simple, and was cooked up to demonstrate this simple demo. So, don’t go looking for loopholes! 🙂

<!DOCTYPE html>
<html lang="en">
<head>
    <title>Testing window.print()</title>
<style language="text/css">
        h1 {
            text-align:center;
        }

        #centeredDiv, .myDiv, .hidden, .visible {
            text-align:center;
        }

        .hidden {
            display:none;
        }

        .visible {
            display:block;
        }
    </style>

</head>
<body>
<h1>This is a print page demo</h1>
<div id="centeredDiv">

To generate the download link, click on the button below!

        <button id="myButton">Click me</button></div>
<script type="text/javascript">
        function init() {
            var myButton = document.getElementById("myButton");
            if (myButton) {
                myButton.addEventListener("click", function() {
        		    var centeredDiv = document.getElementById("centeredDiv");
		            if (centeredDiv) {
			            var link = document.createElement("a");
        		    	link.setAttribute("id", "myLink");
    		        	link.setAttribute("class", "visible");
            			link.setAttribute("href", "#");
                        
                              var text = document.createTextNode("Download");
                              link.appendChild(text);
                        
                              centeredDiv.appendChild(link);
		              }	
                          var myLink = document.getElementById("myLink");
                          if (myLink) {
                              myLink.addEventListener("click", function() {
                              myLink.className = "hidden";  
                             window.print();
                           });
                       }
                   });
               }
           }

       var body = document.getElementsByTagName("body")[0];
       body.onload = init();
    </script>
</body>

Explanation: The code is dead straightforward. We just have a button inside a div. Once the body of the page has been loaded, we append an event listener to the button.

When the button is clicked, we create an anchor object dynamically, set up its properties, and append it to the same div that contains the button. We also append a hyperlink to this new anchor object so that when it is clicked, we set its class to hidden, and invoke window.print() that brings out the browser’s print dialog.

The CSS rules simply define when the dynamically created anchor object is visible (when created), or hidden (once clicked). Really, that’s all there is to it!

Wrap-up

Well, this was a small fun project that didn’t take much time, and also exercised my (admittedly rusty) JavaScript skills!

I encourage you to take inspiration from daily situations and implement small and simple solutions to problems you certainly face every day. These can provide great fun and be a good refresher for your own skills. That just goes to show that the best project ideas come from personal needs rather than coding up from a list compiled by someone else.

Have fun!

A modest attempt at simulating a page printing script using plain JavaScript