[javascript] Print specific part of webpage

I'm trying to print a specific part of my application.

The application has a list of users, displaying their first and last name. When I click a user I get a popup with more detailed information about them.

How would I go about printing just the popup for a user I clicked? The popup looks like this:

 <div id="user<?=$user->id;?>" class="popup">
      <div class="details">
           User details...
      </div>
      <a href="#print">Print</a>
 </div>

The print button isn't working yet though.

This question is related to javascript html printing

The answer is


I wrote a tiny JavaScript module called PrintElements for dynamically printing parts of a webpage.

It works by iterating through selected node elements, and for each node, it traverses up the DOM tree until the BODY element. At each level, including the initial one (which is the to-be-printed node’s level), it attaches a marker class (pe-preserve-print) to the current node. Then attaches another marker class (pe-no-print) to all siblings of the current node, but only if there is no pe-preserve-print class on them. As a third act, it also attaches another class to preserved ancestor elements pe-preserve-ancestor.

A dead-simple supplementary print-only css will hide and show respective elements. Some benefits of this approach is that all styles are preserved, it does not open a new window, there is no need to move around a lot of DOM elements, and generally it is non-invasive with your original document.

See the demo, or read the related article for further details.


Styles

 @media print {

       .no-print{
               display : none !important;
                }
              }

Jquery

    function printInvoice()
 {
     printDiv = "#printDiv"; // id of the div you want to print
     $("*").addClass("no-print");
     $(printDiv+" *").removeClass("no-print");
     $(printDiv).removeClass("no-print");

     parent =  $(printDiv).parent();
     while($(parent).length)
     {
         $(parent).removeClass("no-print");
         parent =  $(parent).parent();
     }
     window.print();

 }

Print Button Html

<input type="button" onclick="printInvoice();" value="Print">

Just use CSS to hide the content you do not want printed. When the user selects print - the page will look to the " media="print" CSS for instructions about the layout of the page.

The media="print" CSS has instructions to hide the content that we do not want printed.

<!-- CSS for the things we want to print (print view) -->
<style type="text/css" media="print">

#SCREEN_VIEW_CONTAINER{
        display: none;
    }
.other_print_layout{
        background-color:#FFF;
    }
</style>

<!-- CSS for the things we DO NOT want to print (web view) -->
<style type="text/css" media="screen">

   #PRINT_VIEW{
      display: none;
   }
.other_web_layout{
        background-color:#E0E0E0;
    }
</style>

<div id="SCREEN_VIEW_CONTAINER">
     the stuff I DO NOT want printed is here and will be hidden - 
     and not printed when the user selects print.
</div>

<div id="PRINT_VIEW">
     the stuff I DO want printed is here.
</div>

Here is my enhanced version that when we want to load css files or there are image references in the part to print.

In these cases, we have to wait until the css files or the images are fully loaded before calling the print() function. Therefor, we'd better to move the print() and close() function calls into the html. Following is the code example:

var prtContent = document.getElementById("order-to-print");
var WinPrint = window.open('', '', 'left=0,top=0,width=384,height=900,toolbar=0,scrollbars=0,status=0');
WinPrint.document.write('<html><head>');
WinPrint.document.write('<link rel="stylesheet" href="assets/css/print/normalize.css">');
WinPrint.document.write('<link rel="stylesheet" href="assets/css/print/receipt.css">');
WinPrint.document.write('</head><body onload="print();close();">');
WinPrint.document.write(prtContent.innerHTML);
WinPrint.document.write('</body></html>');
WinPrint.document.close();
WinPrint.focus();

Instead of all the complicated JavaScript, you can actually achieve this with simple CSS: just use two CSS files, one for your normal screen display, and another for the display of ONLY the content you wish to print. In this latter file, hide everything you don't want printed, display only the pop up.

Remember to define the media attribute of both CSS files:

<link rel="stylesheet" href="screen-css.css" media="all" />
<link rel="stylesheet" href="print-css.css" media="print" />

As answered here: https://stackoverflow.com/a/1072151/421243, you can add the specific section to a hidden frame with Javascript, focus it, and print it.


I made this jQuery extension to print the HTML of the element selected: $('#div2').print();

$.fn.extend({
    print: function() {
        var frameName = 'printIframe';
        var doc = window.frames[frameName];
        if (!doc) {
            $('<iframe>').hide().attr('name', frameName).appendTo(document.body);
            doc = window.frames[frameName];
        }
        doc.document.body.innerHTML = this.html();
        doc.window.print();
        return this;
    }
});

See it in action here.


You would have to open a new window(or navigate to a new page) containing just the information you wish the user to be able to print

Javscript:

function printInfo(ele) {
    var openWindow = window.open("", "title", "attributes");
    openWindow.document.write(ele.previousSibling.innerHTML);
    openWindow.document.close();
    openWindow.focus();
    openWindow.print();
    openWindow.close();
}

HTML:

<div id="....">
    <div>
        content to print
    </div><a href="#" onclick="printInfo(this)">Print</a>
</div>

A few notes here: the anchor must NOT have whitespace between it and the div containing the content to print


I Got a better option,

First separate the printable and nonprintable section by class name or id

_x000D_
_x000D_
window.onafterprint = onAfterPrint;_x000D_
_x000D_
function print(){_x000D_
  //hide the nonPrintable div  _x000D_
}_x000D_
_x000D_
function onAfterPrint(){_x000D_
  // Visible the nonPrintable div_x000D_
}
_x000D_
<input type="button" onclick="print()" value="Print"/>
_x000D_
_x000D_
_x000D_

That's all


Here what worked for me

With jQuery and https://developer.mozilla.org/en-US/docs/Web/API/Window/open

  var $linkToOpenPrintDialog = $('#tvcPrintThisLinkId');
  var windowObjectReference = null;
  var windowFeatures = 'left=0,top=0,width=800,height=900,menubar=no,toolbar=no,location=yes,resizable=no,scrollbars=no,status=no';
  var windowFeaturesStyles = '<link rel="stylesheet" media="print" href="/wp-content/themes/salient-child/dist/css/app-print.css">';

  $linkToOpenPrintDialog.on('click', function(event) {
    openPrintDialog(this.href, this.target, 'tvcInnerCalculatorDivId', event);    
    return false;
  });

  function openPrintDialog(url, windowName, elementToOpen, event) {

    var elementContent = document.getElementById(elementToOpen);

    if(windowObjectReference == null || windowObjectReference.closed) {

      windowObjectReference = window.open( url, windowName, windowFeatures);
      windowObjectReference.document.write(windowFeaturesStyles);
      windowObjectReference.document.write(elementContent.innerHTML);
      windowObjectReference.document.close();
      windowObjectReference.focus();
      windowObjectReference.print();
      windowObjectReference.close();

    } else {
      windowObjectReference.focus();
    };

    event.preventDefault();
  }

app-print.css

@media print { 

  body { 
    margin: 0; 
    color: black; 
    background-color: white;
  } 

}

try this one.

export function printSectionOfWebpage(sectionSelector) {
    const $body = jquery('body');
    const $sectionToPrint = jquery(sectionSelector);
    const $sectionToPrintParent = $sectionToPrint.parent();
    const $printContainer = jquery('<div style="position:relative;">');

    $printContainer.height($sectionToPrint.height()).append($sectionToPrint).prependTo($body);

    const $content = $body.children().not($printContainer).not('script').detach();

    /**
     * Needed for those who use Bootstrap 3.x, because some of
     * its `@media print` styles ain't play nicely when printing.
     */
    const $patchedStyle = jquery('<style media="print">')
        .text(
            `
          img { max-width: none !important; }
          a[href]:after { content: ""; }
        `
        )
        .appendTo('head');

    window.print();

    $body.prepend($content);
    $sectionToPrintParent.prepend($sectionToPrint);

    $printContainer.remove();
    $patchedStyle.remove();
}

In printPageArea() function, pass the specific div ID which you want to print. I've found this JavaScript code from codexworld.com.

function printPageArea(areaID){
    var printContent = document.getElementById(areaID);
    var WinPrint = window.open('', '', 'width=900,height=650');
    WinPrint.document.write(printContent.innerHTML);
    WinPrint.document.close();
    WinPrint.focus();
    WinPrint.print();
    WinPrint.close();
}

The complete code and tutorial can be found from here - How to Print Page Area using JavaScript.


Try this awesome ink-html library

import print from 'ink-html'
// const print = require('ink-html').default

// js
print(window.querySelector('#printable'))
// Vue.js
print(this.$refs.printable.$el)

Try this:

  1. Dump the innerHTML of the container into the iFrame (plus any print-specific CSS
  2. print the iFrame contents.

Try it out in JSFiddle (iframes don't appear to work in StackOverflow's preview)

You can see the code here, but it won't work due to what are probably security limitations in StackOverflow's renderer.

_x000D_
_x000D_
const printButton = document.getElementById('print-button');

printButton.addEventListener('click', event => {
  // build the new HTML page
  const content = document.getElementById('name-card').innerHTML;
  const printHtml = `<html>
      <head>
          <meta charset="utf-8">
          <title>Name Card</title>
      </head>
      <body>${content}</body>
  </html>`;
      
  // get the iframe
  let iFrame = document.getElementById('print-iframe');
  
  // set the iFrame contents and print
  iFrame.contentDocument.body.innerHTML = printHtml;
  iFrame.focus();
    iFrame.contentWindow.print();
  
});
_x000D_
<h1>Print your name badge</h1>
<div id="name-card" class="card">
  <p>Hello my name is</p>
  <h2>Max Powers</h2>
</div>
<p>You will be required to wear your name badge at all times</p>
<a id="print-button" class="btn btn-primary">Print</a>

<iframe id="print-iframe" width="0" height="0"></iframe>
_x000D_
_x000D_
_x000D_


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to html

Embed ruby within URL : Middleman Blog Please help me convert this script to a simple image slider Generating a list of pages (not posts) without the index file Why there is this "clear" class before footer? Is it possible to change the content HTML5 alert messages? Getting all files in directory with ajax DevTools failed to load SourceMap: Could not load content for chrome-extension How to set width of mat-table column in angular? How to open a link in new tab using angular? ERROR Error: Uncaught (in promise), Cannot match any routes. URL Segment

Examples related to printing

How do I print colored output with Python 3? Print a div content using Jquery Python 3 print without parenthesis How to find integer array size in java Differences Between vbLf, vbCrLf & vbCr Constants Printing variables in Python 3.4 Show DataFrame as table in iPython Notebook Removing display of row names from data frame Javascript window.print() in chrome, closing new window or tab instead of cancelling print leaves javascript blocked in parent window Print a div using javascript in angularJS single page application