Twitter Bootstrap: Print content of modal window

前端 未结 10 940
走了就别回头了
走了就别回头了 2020-11-28 02:19

I\'m developing a site using Bootstrap which has 28 modal windows with information on different products. I want to be able to print the information in an open modal window.

相关标签:
10条回答
  • 2020-11-28 02:37

    This is a revised solution that will also work for modal windows rendered using a Grails template, where you can have the same modal template called multiple times (with different values) in the same body. This thread helped me immensely, so I thought I'd share it in case other Grails users found their way here.

    For those who are curious, the accepted solution didn't work for me because I am rendering a table; each row has a button that opens a modal window with more details about the record. This led to multiple printSection divs being created and printed on top of each other. Therefore I had to revise the js to clean up the div after it was done printing.

    CSS

    I added this CSS directly to my modal gsp, but adding it to the parent has the same effect.

    <style type="text/css">
       @media screen {
            #printSection {
               display: none;
            }
       }
    
       @media print {
            body > *:not(#printSection) {
               display: none;
            }
            #printSection, #printSection * {
                visibility: visible;
            }
            #printSection {
                position:absolute;
                left:0;
                top:0;
            }
       }
    </style>
    

    Adding it to the site-wide CSS killed the print functionality in other parts of the site. I got this from ComFreak's accepted answer (based on Bennett McElwee answer), but it is revised using ':not' functionality from fanfavorite's answer on Print <div id=printarea></div> only? . I opted for 'display' rather than 'visibility' because my invisible body content was creating extra blank pages, which was unacceptable to my users.

    js

    And this to my javascript, revised from ComFreak's accepted answer to this question.

    function printDiv(div) {    
        // Create and insert new print section
        var elem = document.getElementById(div);
        var domClone = elem.cloneNode(true);
        var $printSection = document.createElement("div");
        $printSection.id = "printSection";
        $printSection.appendChild(domClone);
        document.body.insertBefore($printSection, document.body.firstChild);
    
        window.print(); 
    
        // Clean up print section for future use
        var oldElem = document.getElementById("printSection");
        if (oldElem != null) { oldElem.parentNode.removeChild(oldElem); } 
                              //oldElem.remove() not supported by IE
    
        return true;
    }
    

    I had no need for appending elements, so I removed that aspect and changed the function to specifically print a div.

    HTML (gsp)

    And the modal template. This prints the modal header & body and excludes the footer, where the buttons were located.

    <div class="modal-content">
        <div id="print-me"> <!-- This is the div that is cloned and printed -->
            <div class="modal-header">
                <!-- HEADER CONTENT -->
            </div>
            <div class="modal-body">
                 <!-- BODY CONTENT -->
            </div>
        </div>
        <div class="modal-footer">
                                     <!-- This is where I specify the div to print -->
            <button type="button" class="btn btn-default" onclick="printDiv('print-me')">Print</button>
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
        </div>
    </div>
    

    I hope that helps someone!

    0 讨论(0)
  • 2020-11-28 02:39

    I just use a bit of jQuery/javascript:

    html:

    <h1>Don't Print</h1>
    
    <a data-target="#myModal" role="button" class="btn" data-toggle="modal">Launch modal</a>
    
    <div class="modal fade hide" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"      aria-hidden="true">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
         <h3 id="myModalLabel">Modal to print</h3>
      </div>
      <div class="modal-body">
        <p>Print Me</p>
      </div>
      <div class="modal-footer">
        <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
        <button class="btn btn-primary" id="printButton">Print</button>
      </div>
    </div>
    

    js:

    $('#printButton').on('click', function () {
        if ($('.modal').is(':visible')) {
            var modalId = $(event.target).closest('.modal').attr('id');
            $('body').css('visibility', 'hidden');
            $("#" + modalId).css('visibility', 'visible');
            $('#' + modalId).removeClass('modal');
            window.print();
            $('body').css('visibility', 'visible');
            $('#' + modalId).addClass('modal');
        } else {
            window.print();
        }
    });
    

    here is the fiddle

    0 讨论(0)
  • 2020-11-28 02:41

    Heres a solution with no Javascript or plugin - just some css and one extra class in the markup. This solutions uses the fact that BootStrap adds a class to the body when a dialog is open. We use this class to then hide the body, and print only the dialog.

    To ensure we can determine the main body of the page we need to contain everything within the main page content in a div - I've used id="mainContent". Sample Page layout below - with a main page and two dialogs

    <body>
     <div class="container body-content">
    
      <div id="mainContent">
           main page stuff     
      </div>
      <!-- Dialog One -->
      <div class="modal fade in">
       <div class="modal-dialog">
        <div class="modal-content">
              ...
        </div>
       </div>
      </div>
    
      <!-- Dialog Two -->
      <div class="modal fade in">
       <div class="modal-dialog">
        <div class="modal-content">
              ...
        </div>
       </div>
      </div>
    
     </div>
    </body>
    

    Then in our CSS print media queries, I use display: none to hide everything I don't want displayed - ie the mainContent when a dialog is open. I also use a specific class noPrint to be used on any parts of the page that should not be displayed - say action buttons. Here I am also hiding the headers and footers. You may need to tweak it to get exactly want you want.

    @media print {
        header, .footer, footer {
            display: none;
        }
    
        /* hide main content when dialog open */
        body.modal-open div.container.body-content div#mainContent {
            display: none;
        }
    
        .noPrint {
            display: none;
        }
    }
    
    0 讨论(0)
  • 2020-11-28 02:49

    you can download printThis lib from this source https://github.com/jasonday/printThis/blob/0a7f799693af8a8303bf0b8df0efc80c2694af81/printThis.js and include it into your html page

    Call the following jquery to print all the content including the content that is not viewable. You may include your css files in an array if you have multiple css files.

    $("#modalDiv").printThis({ 
        debug: false,              
        importCSS: true,             
        importStyle: true,         
        printContainer: true,       
        loadCSS: "../css/style.css", 
        pageTitle: "My Modal",             
        removeInline: false,        
        printDelay: 333,            
        header: null,             
        formValues: true          
    }); 
    
    0 讨论(0)
  • 2020-11-28 02:52

    With the currently accepted solution you cannot print the page which contains the dialog itself anymore. Here's a much more dynamic solution:

    JavaScript:

    $().ready(function () {
        $('.modal.printable').on('shown.bs.modal', function () {
            $('.modal-dialog', this).addClass('focused');
            $('body').addClass('modalprinter');
    
            if ($(this).hasClass('autoprint')) {
                window.print();
            }
        }).on('hidden.bs.modal', function () {
            $('.modal-dialog', this).removeClass('focused');
            $('body').removeClass('modalprinter');
        });
    });
    

    CSS:

    @media print {
        body.modalprinter * {
            visibility: hidden;
        }
    
        body.modalprinter .modal-dialog.focused {
            position: absolute;
            padding: 0;
            margin: 0;
            left: 0;
            top: 0;
        }
    
        body.modalprinter .modal-dialog.focused .modal-content {
            border-width: 0;
        }
    
        body.modalprinter .modal-dialog.focused .modal-content .modal-header .modal-title,
        body.modalprinter .modal-dialog.focused .modal-content .modal-body,
        body.modalprinter .modal-dialog.focused .modal-content .modal-body * {
            visibility: visible;
        }
    
        body.modalprinter .modal-dialog.focused .modal-content .modal-header,
        body.modalprinter .modal-dialog.focused .modal-content .modal-body {
            padding: 0;
        }
    
        body.modalprinter .modal-dialog.focused .modal-content .modal-header .modal-title {
            margin-bottom: 20px;
        }
    }
    

    Example:

    <div class="modal fade printable autoprint">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h4 class="modal-title">Modal title</h4>
          </div>
          <div class="modal-body">
            <p>One fine body&hellip;</p>
          </div>
          <div class="modal-footer">
            <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
            <button type="button" class="btn btn-primary" onclick="window.print();">Print</button>
          </div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal-dialog -->
    </div><!-- /.modal -->
    
    0 讨论(0)
  • 2020-11-28 02:53

    Another solution

    Here is a new solution based on Bennett McElwee answer in the same question as mentioned below.

    Tested with IE 9 & 10, Opera 12.01, Google Chrome 22 and Firefox 15.0.
    jsFiddle example

    1.) Add this CSS to your site:

    @media screen {
      #printSection {
          display: none;
      }
    }
    
    @media print {
      body * {
        visibility:hidden;
      }
      #printSection, #printSection * {
        visibility:visible;
      }
      #printSection {
        position:absolute;
        left:0;
        top:0;
      }
    }
    

    2.) Add my JavaScript function

    function printElement(elem, append, delimiter) {
        var domClone = elem.cloneNode(true);
    
        var $printSection = document.getElementById("printSection");
    
        if (!$printSection) {
            $printSection = document.createElement("div");
            $printSection.id = "printSection";
            document.body.appendChild($printSection);
        }
    
        if (append !== true) {
            $printSection.innerHTML = "";
        }
    
        else if (append === true) {
            if (typeof (delimiter) === "string") {
                $printSection.innerHTML += delimiter;
            }
            else if (typeof (delimiter) === "object") {
                $printSection.appendChild(delimiter);
            }
        }
    
        $printSection.appendChild(domClone);
    }​
    

    You're ready to print any element on your site!
    Just call printElement() with your element(s) and execute window.print() when you're finished.

    Note: If you want to modify the content before it is printed (and only in the print version), checkout this example (provided by waspina in the comments): http://jsfiddle.net/95ezN/121/

    One could also use CSS in order to show the additional content in the print version (and only there).


    Former solution

    I think, you have to hide all other parts of the site via CSS.

    It would be the best, to move all non-printable content into a separate DIV:

    <body>
      <div class="non-printable">
        <!-- ... -->
      </div>
    
      <div class="printable">
        <!-- Modal dialog comes here -->
      </div>
    </body>
    

    And then in your CSS:

    .printable { display: none; }
    
    @media print
    {
        .non-printable { display: none; }
        .printable { display: block; }
    }
    

    Credits go to Greg who has already answered a similar question: Print <div id="printarea"></div> only?

    There is one problem in using JavaScript: the user cannot see a preview - at least in Internet Explorer!

    0 讨论(0)
提交回复
热议问题