Use jQuery to Print & Email Articles

Learn How to Style Articles for Print and Email

Apr 5th in JavaScript & AJAX by Connor Zwick

When designing websites, a commonly desired feature is the ability to dynamically print or email any section of a webpage. Unfortunately, this idea is usually scrapped later in the project due to a lack of time or knowledge. Formatting the text for printing is more difficult than it might initially seem. Today, we will use JavaScript to automatically search for certain page elements and format them correctly for a printing.

PG

Author: Connor Zwick

Hi, I'm Connor Zwick-freelance blogger and designer. I love learning and teaching new topics in areas like HTML, CSS, PHP, Ruby on Rails, and last but certainly not least, jQuery. You can follow me on twitter or visit his design blogcyberantix.

Objectives:

At the end of this tutorial, we will have accomplished the following:

  • Use jQuery to print or email any section of a page automatically when a certain element is clicked.
  • Format and change the style to optimize for print or email.
  • Add variables to the email version (To, From, Message, etc.)

The Page

Page

What's Wrong With This?

Wow...that page is colorful. I agree - it's not the greatest color scheme in the world. This design was definitely not designed for print. Although the background blue will not print out on most printers, the printer will just make it disappear. This will mess up the rest of the design though because now the bright orange and green text will print on a white background. There is no easy way for a user to print out a nice black and white formatted article from this page, short of copying it into a word processor and formatting it themselves.

Keep The Design, Fix The Problem

One solution might be to provide a print stylesheet, as Tuts+ has done. This would work if there was only one article on a page. Unfortunately, this example is in blog format. This means that there are several articles on a page; and chances are the user only wants to print out one article. We are going to use jQuery to allow the user to click a link after each article that formats the article and allows them to print or email it.

Print Email Buttons

HTML for This Page

The HTML is rather simple for this page. We'll add a couple of standard classes: One to signify a section to be printed/emailed (.printSection), one to signify the area that contains the links to print or email (.printControls), a class for all print links (.printControl), and a class for all email links (.emailControl). Notice how we also linked to Google's minified file. This allows us to use jQuery later.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Print | Email jQuery Plugin</title>
<script type="text/javascript" src="http://jqueryjs.googlecode.com/files/jquery-1.3.2.min.js">
</script>
</head>

<body>
<div class="page-wrap">
	<div class="printSection">
    	<a name="1"></a>
    	<h2>This is a Heading</h2><br />
        <img src="image.jpg" />
        <p>Article Text</p>
        <span class="printControls"><p class="printControl">Print Section</p> | 
		  <p class="emailControl">Email Section</p></span>
    </div><!-- End printSection -->
	<div class="printSection">
        <a name="2"></a>
    	<h2>This is a Different Heading</h2><p>Article Text</p>
        <p>More Article Text</p>

		  <span class="printControls"><p class="printControl">Print Section</p> | 
		<p class="emailControl">Email Section</p></span>
    </div><!-- End printSection -->
	<div class="printSection">
    	<a name="3"></a>
    	<h2>This is Another Heading</h2><p>Article Text</p>
        <p>More Article Text</p>

		<span class="printControls"><p class="printControl">Print Section</p> | 
		<p class="emailControl">Email Section</p></span>
    </div><!-- End printSection -->
	<div class="printSection">
    	<a name="4"></a>
    	<h2>This is a Heading Again</h2><p>Article Text</p>
        <p>More Article Text</p>

		<span class="printControls"><p class="printControl">Print Section</p> | 
<p class="emailControl">Email Section</p></span>
    </div><!-- End printSection -->
</div><!-- End Page Wrap -->
</body>
</html>
 

The CSS

The CSS is pretty simple too.

body{
text-align: center;
font-family: Tahoma, Arial, Helvetica, Sans Serif;
}
h2{
color: #d98841;
font-size: 48px;
padding: 0px;
margin: 0px;
font-weight: normal;
}

.page-wrap{
margin-left: auto;
margin-right: auto;
width: 550px;
background: #10222b;
padding: 15px;
text-align: left;
}
.printSection p{
color: #bdd684;
font-size: 12px;
text-align: justify;
}
p.printControl, p.emailControl, .printControls{
display: inline;
color: #f2ece4;
}
p.printControl, p.emailControl{
cursor: pointer;
}
img{
margin-left: 35px;
}

We'll also add a bit of CSS to increase usability. In case Javascript is disabled, we don't want dead links - so we hide the links:

<noscript>
<style>
.printControls{
display: none;
}
</style>
</noscript>

Script Time

What do we want to accomplish when printing?

  • add a listener to wait for a .printControl or .emailControl to be clicked.
  • change the appearance of the section to be printer friendly
  • grab the parts of the page that we want to print
  • open up a window and size it.
  • put the parts of the page that we grabbed into the window
  • open up the print dialogue box
  • close the window after done printing

How we are going to accomplish these things?

Add the Listener:

We put the print listener inside the DOM reading function:

$(document).ready(function(){
	$('.printControl').click(function(){
		//Here we will put the printing code
    });
});

Change the Appearance

We need to change the colors from the colorful scheme, to black and white. There are several ways we can accomplish this task. The method we'll use is to add a class temporarily to the affected section, take the code to print, and then immediately remove the class again. We add the class by using jQuery's CSS selector to select the divs, and then add a class to all elements inside with the children() command.

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');		
		$('.printSection').children().removeClass('printversion');	
    });
});

We also must add some more styling for the elements with printversion:

h2.printversion, p.printversion{
color: #333333;
text-align: left;
}
.printControls.printversion{
display: none;
}

Grabbing the Section

We are now going to grab the section and put it in a variable. We are going to put this after we add the class but before we remove it, so that the version in the variable is with the added class. We grab the HTML in the head to get the styling info and concatenate it with the section's HTML. The "this" allows us to only select the section that was clicked instead of all of them. Then we go up to levels from the print button and grab that.

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');	
        var printContent= $('head').html() + $(this).parent().parent().html();	
		$('.printSection').children().removeClass('printversion');	
    });
});

Opening the Window

We now need to put the variable somewhere. But first, we need to open up a new window. These lines aren't very important and are just plain JavaScript - no jQuery in this step. Basically, we open up a window, assign a unique name, and give it some basic parameters.

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');	
        var printContent= $('head').html() + $(this).parent().parent().html();	
		$('.printSection').children().removeClass('printversion');	
        var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'PrintSection' + uniqueName.getTime();
		 var printWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600,height=1000');
    });
});

Fill the Window

We now need to fill the window with what we grabbed earlier. We basically just write to the window the variable's value.

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');	
        var printContent= $('head').html() + $(this).parent().parent().html();	
		$('.printSection').children().removeClass('printversion');	
        var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'PrintSection' + uniqueName.getTime();
		 var printWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600,height=1000');
         printWindow.document.write(printContent);
    });
});

Print and Close

We need to add a few more lines before we're finished. First, we need to focus the window and then open up the print dialogue box. Then we close the window after the dialogue box has been closed.

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');	
        var printContent= $('head').html() + $(this).parent().parent().html();	
		$('.printSection').children().removeClass('printversion');	
        var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'PrintSection' + uniqueName.getTime();
		 var printWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600,height=1000');
         printWindow.document.write(printContent);
          printWindow.document.close();
		 printWindow.focus();
		 printWindow.print();
		 printWindow.close();
    });
});

That's it. We should now have a functional print button after every article. Good job, but we're not finished yet. Now we got to make the email button function correctly.

Print

What must we accomplish when emailing?

  • add a listener to wait for a .printControl or .emailControl to be clicked.
  • We need the email address they're sending it to.
  • We need their name.
  • We need their email.
  • We need a short message to be sent with.
  • put all of this info into variables through the use of prompts.
  • change the appearance of the section to be email friendly
  • We need the URL of the page, including an anchor tag to skip right to the article.
  • put all of this information into one variable.
  • put this into a new window.

Things we've already done when printing

There's no need to go over all of these steps again. We can skip the ones that we covered with printing:

$(document).ready(function(){
		$('.emailControl').click(function(){
		$('.printSection').children().addClass('printversion');	
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'emailSection' + uniqueName.getTime();
		 var emailWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600');
		 emailWindow.document.write(printContent);
		 emailWindow.document.close();
		 emailWindow.focus();
	});
});

Getting the Information

For this example, we don't need anything fancy for retrieving the required information. We're just going to raise several prompts that store the information in variables.

$(document).ready(function(){
		$('.emailControl').click(function(){
        var sendTo = prompt('Please type who you would like to send this to');
		var fromWho = prompt('And What is Your Name?');
		var fromWhoEmail = prompt('And What is Your Email?');
		var fromMessage = prompt('Do You have a Message?');
		$('.printSection').children().addClass('printversion');	
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'emailSection' + uniqueName.getTime();
		 var emailWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600');
		 emailWindow.document.write(printContent);
		 emailWindow.document.close();
		 emailWindow.focus();
	});
});


InfoInfoInfoInfoInfo

Getting the URL and Anchor Tag

Now, we need to store the current URL and article number (via the anchor tag) in variables. We will combine them later.

$(document).ready(function(){
		$('.emailControl').click(function(){
        var sendTo = prompt('Please type who you would like to send this to');
		var fromWho = prompt('And What is Your Name?');
		var fromWhoEmail = prompt('And What is Your Email?');
		var fromMessage = prompt('Do You have a Message?');
		$('.printSection').children().addClass('printversion');	
        var emailID=$(this).parent().parent().find('a').attr('name');
		var currentURL= window.location.href;
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'emailSection' + uniqueName.getTime();
		 var emailWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600');
		 emailWindow.document.write(printContent);
		 emailWindow.document.close();
		 emailWindow.focus();
	});
});

Putting Everything Together

First we combine the URL together with the anchor tag and put it in a nice string of text. Then we combine that with everything else we need in a variable called emailContent.

$(document).ready(function(){
		$('.emailControl').click(function(){
        var sendTo = prompt('Please type who you would like to send this to');
		var fromWho = prompt('And What is Your Name?');
		var fromWhoEmail = prompt('And What is Your Email?');
		var fromMessage = prompt('Do You have a Message?');
		$('.printSection').children().addClass('printversion');	
        var emailID=$(this).parent().parent().find('a').attr('name');
		var currentURL= window.location.href;
        var emailLink='<p><b>Source:</b> <a href="' + currentURL + '#' + emailID + '">' + currentURL + '#' + emailID +'</a></p>';	
		var emailContent= $('head').html() + '<div style="text-align:left;"><p><b>To:</b>' + sendTo + '</p>' + '<p><b>From(Name):</b>' + fromWho + '</p>' + '<p><b>From(Email):</b>' + fromWhoEmail + '</p>' + '<p><b>Message:</b>' + fromMessage + '</p>' + emailLink + '</div>' + $(this).parent().parent().html();
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'emailSection' + uniqueName.getTime();
		 var emailWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600');
		 emailWindow.document.write(printContent);
		 emailWindow.document.close();
		 emailWindow.focus();
	});
});

Finished Code

$(document).ready(function(){
	$('.printControl').click(function(){
		$('.printSection').children().addClass('printversion');		
		var printContent= $('head').html() + $(this).parent().parent().html();
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'PrintSection' + uniqueName.getTime();
		 var printWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600,height=1000');
		 printWindow.document.write(printContent);
		 printWindow.document.close();
		 printWindow.focus();
		 printWindow.print();
		 printWindow.close();
	});
	$('.emailControl').click(function(){
		var sendTo = prompt('Please type who you would like to send this to');
		var fromWho = prompt('And What is Your Name?');
		var fromWhoEmail = prompt('And What is Your Email?');
		var fromMessage = prompt('Do You have a Message?');
		$('.printSection').children().addClass('printversion');	
		var emailID=$(this).parent().parent().find('a').attr('name');
		var currentURL= window.location.href;
		var emailLink='<p><b>Source:</b> <a href="' + currentURL + '#' + emailID + '">' + currentURL + '#' + emailID +'</a></p>';	
		var emailContent= $('head').html() + '<div style="text-align:left;"><p><b>To:</b>' + sendTo + '</p>' + '<p><b>From(Name):</b>' + fromWho + '</p>' + '<p><b>From(Email):</b>' + fromWhoEmail + '</p>' + '<p><b>Message:</b>' + fromMessage + '</p>' + emailLink + '</div>' + $(this).parent().parent().html();
		$('.printSection').children().removeClass('printversion');		
		var windowUrl = 'about:blank';
		 var uniqueName = new Date();
		 var windowName = 'emailSection' + uniqueName.getTime();
		 var emailWindow = window.open(windowUrl, windowName, 'left=500,top=000,width=600');
		 emailWindow.document.write(emailContent);
		 emailWindow.document.close();
		 emailWindow.focus();
	});
});

We're Done

We now have an automatic way to print and email sections of a web site that degrades when JavaScript is disabled. Good job! If you enjoyed this tutorial, stay tuned; in a future tutorial, we'll cover how to turn this into a jQuery plugin. Meanwhile, if you have any questions or comments, be sure to leave them below. I'd love to hear from you!


Related Posts

Check out some more great tutorials and articles that you might like

Enjoy this Post?

Your vote will help us grow this site and provide even more awesomeness

Plus Members

Source Files, Bonus Tutorials and
More for $9 a month for all TUTS+
sites in one subscription.

Join Now

User Comments

( ADD YOURS )
  1. PG

    Hasanga April 5th

    Guys!!! I’m the first! \m/

    ( Reply )
    1. PG

      Taylor Satula April 6th

      Wow way to be an n00b.
      Only 10 year olds Yell yay im first.

      ( Reply )
      1. PG

        Wornall April 7th

        WOW way to be a kill joy
        i am a grumpy old man stay off my lawn

      2. PG

        Paris Vega April 9th

        WOW… words… of cleverness and… retort.

  2. PG

    Amir April 5th

    nice tutorial, Thanks

    ( Reply )
  3. PG

    insic April 5th

    cool tut, I’ve seen an article about printing before but its not using jQuery. thanks for sharing

    ( Reply )
  4. PG

    Mauro Accornero April 5th

    Nice ideas

    ( Reply )
  5. PG

    Tom April 6th

    This is good tutorial, Thanks

    ( Reply )
  6. PG

    zik April 6th

    Nice tutorial !

    Thanks for sharing

    ( Reply )
  7. PG

    2rock April 6th

    yeah, nice one …

    ( Reply )
  8. PG

    Jonas Bonn April 6th

    thanks for this detail tutorial…

    ( Reply )
  9. PG

    Rik Girbes April 6th

    Very nice Thanks

    Im going to use this on a project im working on now!!

    ( Reply )
  10. PG

    Patternhead April 6th

    Nice tips and tricks, thanks :)

    ( Reply )
  11. PG

    Rahul Chowdhury April 6th

    Great work, nice tutorial. Like it.

    ( Reply )
  12. PG

    Pieter Beulque April 6th

    Did not read this completely but I have one question.
    Why don’t you just use a print stylesheet? You know like media=”print” ?

    ( Reply )
    1. PG

      Taylor Satula April 6th

      I was wondering the same thing

      ( Reply )
      1. PG

        Zyend April 7th

        Me too

  13. PG

    Max Stanworth April 6th

    Pretty cool technique for sending a page to a friend but not ideal in my honest opinion, needs validation? you can enter nothing and it will still accept it, you should have to enter an email address, also when you press cancel it still goes to the next prompt, cancel should close the entire prompt and not proceed or at least go to the previous prompt.

    I might be being too critical but thats what i would improve if i could :P the “print section” is awesome tho.

    ( Reply )
  14. PG

    Martyn Web April 6th

    I have to admit this is something I overlook now and again.

    Great tutorial and maybe, just maybe I will start sorting some sites out to include this facility.

    ( Reply )
  15. PG

    rafaelrrp April 6th

    Great tutorial, Thx!!!

    ( Reply )
  16. PG

    Ragnar Þór Valgeirsson April 6th

    nice tuts…but what will cgtuts be

    ( Reply )
  17. PG

    Ferdy April 6th

    Quite a sophisticated approach here, but what is wrong with simply creating a seperate stylesheet and indicating it as “print” instead of “media”? This works in any browser, using the browser’s default print menu option.

    Most of the things you do do not require any Javascript. In fact it is a bad practise to put styling logic in Javascript. What if it is not enabled?

    Of course some of the things you are doing, such as the prompts, require javascript, but for none of the print stuff I think it is really needed.

    ( Reply )
    1. PG

      Evan Byrne April 6th

      Agreed. This could have been done easily with a print stylesheet.

      ( Reply )
  18. PG

    Jonny Haynes April 6th

    Why not just use a print stylesheet? Seems to be a long approach to something that can be done easily.

    ( Reply )
  19. PG

    chandra sekhar veera April 6th

    After clicking on “Email Section” a prompt opens, and when I hit Cancel button, it doesn’t close the prompt.

    ( Reply )
  20. PG

    Beshr April 6th

    Great tutorial!
    really helpful…

    ( Reply )
  21. PG

    cancel bubble April 6th

    I think the idea of the printing is you’re only printing a specific section, not the entire page. Of course this would not work with JS disabled so I’m with the print stylesheet campers on this one.

    The email feature…Can’t say I’m a fan of how this was implemented with multiple window.prompt. The UX/usability is not very high, IMO. There’s no validation and hit “cancel” on the first prompt – it takes you through the rest of the prompts.

    ( Reply )
  22. PG

    Connor Zwick April 6th

    Keep in mind I had to keep it relatively simple for this tutorial.

    As I believe I mentioned in the tutorial, the advantage of doing this as opposed to a normal print stylesheet is the ability to print only one section of the page without a page reload.

    ( Reply )
  23. PG

    Meshach April 6th

    Nice tut, thanks.

    ( Reply )
  24. PG

    lawrence77 April 6th

    thanks for this tutorial! ;)

    ( Reply )
  25. PG

    Sr Gabriel April 6th

    Great one, congratulations :D

    ( Reply )
  26. PG

    Taylor Satula April 6th

    What about print stylesheets just like everyone else said. Hundreds of times easier

    ( Reply )
  27. PG

    Brett April 6th

    I worked on a project for a newspaper where they wanted to print the articles, yet they loved cramming ads everywhere possible. So when users click on “Print” we had a stylesheet that stripped out everything except the article, the picture from the article, and a few adds, so the user could preview what the printed version would look like. We had yet another stylesheet on that page set to media=”print” that when the print page was actually printed, it removed the ads. Didnt want to waste the users inks, but the people we worked for loved putting ads everywhere possible

    ( Reply )
  28. PG

    Fred April 6th

    Cool! Always happy to read tuts here.

    ( Reply )
  29. PG

    James April 6th

    Even though a print stylesheet is the obvious solution it is not ideal for all situations. The code samples on this site (”SyntaxHighlighter”) use the same approach – try pressing the “print” button on any of the code samples and you’ll see. Now that could not be achieved with print stylesheets without massively confusing the user with flashing content.

    Nice tut Connor, although I would suggest using a hidden iframe instead of opening a new window.

    ( Reply )
  30. PG

    Aaron April 6th

    This is pretty awesome. It’s a step up from what I’ve been doing. Very good article. Thanks guys.

    ( Reply )
  31. Thats Great,
    I was waiting so long for this.
    I got some problems with this printing issue but now I think everything will go fine.
    Thanks Connor
    Your image(Connor Z) is also cool….

    ( Reply )
  32. PG

    Snookerman April 7th

    Wow, so much useless work when all you need is a print stylesheet. It takes a big idiot to complicate things and confuse so many beginners.

    ( Reply )
  33. PG

    g3t April 7th

    The print function is great for course material pages. excellent stuff

    ( Reply )
  34. PG

    AlfredN April 7th

    Nice tutorial, preciate’ sharing this.

    ( Reply )
  35. PG

    wolfcry April 7th

    This is lame beyond imagination. First, the print stylesheet, already mentioned countless times.

    Secondly, those js prompts … welcome back to the XX. century.

    If you use jQuery to do all these unnecessary stuff, why wouldn’t you just simply manipulate the DOM and get some proper data input in there? Not to mention graceful degradation in this case, which is better than simply hiding your broken links, when there’s no javascript.

    Cherry on top are the inline ’s inside a …

    Way to go, man.

    ( Reply )
  36. PG

    Stephanie April 8th

    Thanks for the article! I think it is great!

    I think the people who are saying that the same thing can be done with a print stylesheet need to re-read the article – especially the part where you explain why you aren’t simply using a print stylesheet in this situation.

    ( Reply )
  37. PG

    awake April 8th

    Nyce…

    Might come in handy some day.

    ( Reply )
  38. PG

    Maicon April 10th

    Very good!

    ( Reply )
  39. PG

    Srinath April 11th

    Sweet! Just the thing I was looking for! Thanks.

    ( Reply )
  40. PG

    jart23 April 24th

    yeah good idea….possibly other ways to accomplish same thing but useful none the less..and as for style sheets…yes easy to do good for whole page..and partial page (content).. like mentioned as to strip out adds and other unnecessary stuff….

    helpful…thank you

    ( Reply )
  41. Another great tutorial. Thanks.

    ( Reply )
  42. PG

    Mostafa November 5th

    Thanks
    I’m going to use this .

    ( Reply )
  1. Arrow
    Gravatar

    Your Name
    November 5th