1

I want to implement a button to print only a certain div of my page while leaving the possibility to the user of printing the entire page. I am using this code for the print stylesheet which works fine so far: Print <div id=printarea></div> only?

Now what I am doing is including a separate stylesheet that only contains the print configuration as suggested here: https://stackoverflow.com/a/18497062/5775547 , and toggle the stylesheet that contains my @media print in the onclick function of my button:

function handlePrintRouteInstructionsClick() {
    routeInstructions.show();
    $('link[id="printCss"]').prop("href", "css/printRouteInstructions.css");
    window.print();
    $('link[id="printCss"]').prop("href", "");
}

The css is included like this:

<link rel="stylesheet" type="text/css" href="" id="printCss" media="print"/>

Now when I press the button, it still prints the entire page. Interestingly, when pressing the button a second time, it works just as expected, printing only the specified div. The dialogue triggered by Ctrl+P still prints the entire page, as it should. Any ideas why this does not work properly on the first button push?

Community
  • 1
  • 1
HLeuschn
  • 11
  • 4
  • 1
    Why not just use CSS media queries? https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries/Using_media_queries – hopkins-matt Jan 11 '16 at 21:12
  • I guess I'm just not seeing a reason to make a separate style sheet and swap them. The print media query will only be active when printing the page. – hopkins-matt Jan 11 '16 at 21:15
  • Yes, that is the problem. I need it to be active after the user has pressed the button to print that certain containter (routeInstructions). But it should not be active when the user tries to print the entire page. I'll have a look at your link, thanks. – HLeuschn Jan 11 '16 at 21:23
  • Do you have a link to the page you are attempting this on? – hopkins-matt Jan 11 '16 at 21:54
  • Only to the latest stable release - http://openrouteservice.org . I am currently working on a local server. – HLeuschn Jan 11 '16 at 21:56
  • In that case, you should probably make a fiddle that replicates the issue if the code isn't available online. – hopkins-matt Jan 12 '16 at 19:18

3 Answers3

0

Have you tried introducing a delay between the stylesheet change and firing the print function using setTimeout()? Might only need a few hundred milliseconds or less. It kind of sounds like a timing issue. I'd try something like this:

function handlePrintRouteInstructionsClick() {
    routeInstructions.show();
    $('link[id="printCss"]').prop("href", "css/printRouteInstructions.css");
    setTimeout(window.print(), 200);
    $('link[id="printCss"]').prop("href", "");
}
hopkins-matt
  • 2,763
  • 2
  • 15
  • 23
  • 1
    Matt, thanks for the answer. Yes it probably was a timing issue. See my answer below. The asynchronous ajax function seems more reliable to me than the setTimeout – HLeuschn Jan 12 '16 at 19:39
  • @HLeuschn I'm very interested in what `$(document).ready` is doing in your solution. The `handlePrintRouteInstructionsClick()` is not fired until a button click. I'd venture to say that if a user is clicking a button the document is finished loading, removing the need for `$(document).ready` as far as I can see. – hopkins-matt Jan 12 '16 at 20:24
  • @Matt, you are right, there is no need for it. Thanks for the hint. – HLeuschn Jan 12 '16 at 20:53
0

I managed to find a solution. I guess the problem was that the file was not yet loaded but window.print() was already called. Then on the second click, the file was still in cache thus the change was fast enough. I managed to overcome the problem by using $(document).ready and its success attribute like this:

function handlePrintRouteInstructionsClick() {
    $.ajax({
        url:"css/printRouteInstructions.css",
        success:function(data){
            var style = $("<style />", {
                id  : 'printCss',
                type: 'text/css',
                html: data
            }).appendTo("head");
            routeInstructions.show();
            window.print();
            style.remove();
        }
    });
}

So basically I'm loading the file, waiting for it to be loaded, add it as a style in the header, print and then remove the style again. Probably neither nice nor efficient, but it seems to work fine.

HLeuschn
  • 11
  • 4
  • My solution loads the CSS upfront and keeps it disabled, [check it out](http://stackoverflow.com/a/34753737/227299). – Ruan Mendes Jan 12 '16 at 21:03
0

I would combine media queries with the disabled feature of <link>.

  • Create a style sheet specifies the print styles when the user clicks a button, by default, it would be disabled: <link id="print-css-special" disabled="disabled" ... />
  • Once the user clicks the "print some area", you enable the style sheet, print, then disable the style sheet

Code

button.addEventListener(e => {
   var printStyleSheet = document.getElementById('print-css-special');
   printStyleSheet.removeAttribute('disabled');               
   window.print(); 
   printStyleSheet.setAttribute('disabled', 'disabled')
});
Ruan Mendes
  • 90,375
  • 31
  • 153
  • 217
  • This looks feasible, but it just does not work for me. The stylesheet is enabled all the time, though i add it like this `` and implement the button click as you proposed. – HLeuschn Jan 17 '16 at 19:41